Skip to content

feat: mark a declared secret sensitive, and warn on a deprecated attribute - #93

Merged
ShocOne merged 1 commit into
mainfrom
feat/sensitive-and-deprecated
Aug 14, 2026
Merged

feat: mark a declared secret sensitive, and warn on a deprecated attribute#93
ShocOne merged 1 commit into
mainfrom
feat/sensitive-and-deprecated

Conversation

@ShocOne

@ShocOne ShocOne commented Aug 14, 2026

Copy link
Copy Markdown
Member

mapping.md row 4. A property the document declares writeOnly or formats as
password generated as a plain, visible attribute — terraform printed it in
plan output and wrote it to logs. That is the security-visible defect
handoff.md:107 names, and #91 put the facts in place to fix it.

What changed

  • ir.Attribute.Sensitive = writeOnly || format == "password", read from
    both sides. Either declaration is enough on its own: format: password names
    what the value is, and writeOnly says the API takes it and never gives it
    back, which is what a credential does.
  • attributeDecl emits Sensitive: true and
    DeprecationMessage: "This attribute is deprecated and may be removed in a future API version."
    Both are plain fields on the attribute type, so unlike a validator or a plan
    modifier they need no import to travel with them.
  • attributes.go decomposes. It crossed the 800-line ceiling, so it splits
    by protocol into attribute_types.go (how a declared type becomes an
    attribute kind, and the refusals that follow) and attribute_addressing.go
    (the attributes that address an object rather than describe it). 529 / 141 /
    142 lines.

One thing the framework does not allow

action/schema and list/schema attribute types have no Sensitive field
I checked every attribute type in v1.19.0; they carry DeprecationMessage but
not Sensitive. Emitting it there would not compile, and postcheck would have
caught it only after the fact. rendersSensitive() gates it to the resource and
datasource packages.

So a secret passed as an action argument or a list filter stays unmarked. That is
the framework's limit rather than a choice made here, and it is stated as such in
the code. TestUnit_AttributeDecl_OmitsSensitiveWhereThePackageLacksIt holds it.

Measured effect

Refusals unchanged on all three pilots — 817 / 290 / 343. provider verify
reports no drift. This adds fields to attributes that already generated; it
recovers nothing and loses nothing.

What moved is the schema itself, counting entity code only (the three
provider-block occurrences are excluded):

Sensitive before after DeprecationMessage before after
github 0 0 0 25
jamfpro 0 26 0 38
thousandeyes 0 24 0 55

github stays at zero for Sensitive because it declares neither writeOnly nor
format: password anywhere — which is what #91 measured, so this is the expected
answer rather than a miss.

"plain_password": schema.StringAttribute{
    Optional:            true,
    MarkdownDescription: "The plainPassword property.",
    Sensitive:           true,
},

Why 50 sensitive attributes in the IR become 26 in jamfpro's schema

The IR marks more than the schema emits, and the difference is honest: a
write-only field has no getter on the read model, so sdkbind prunes it with
carries no GetPasswordEscaped to read "password" from. Those attributes never
reach a schema at all — that is mapping.md row 1, which needs WriteOnly support
and is not attempted here.

Gates

  • gofmt -l internal cmd — empty
  • scripts/repo_hygiene_gate.sh — pass (it is what forced the decomposition)
  • golangci-lint run — 0 issues
  • go build ./... && go vet ./... — pass
  • go test ./... — pass, coverage 91.4% total
  • provider generate (postcheck) + provider verify on all three — no drift

New tests: internal/emit/render_schema_test.go (3, one per schema package
family) and TestUnit_Attribute_MarksADeclaredSecretSensitive.

🤖 Generated with Claude Code

…ibute

A property the document declares writeOnly or formats as a password
generated as a plain, visible attribute: terraform printed it in plan
output and wrote it to logs. Either declaration now marks the attribute
Sensitive, and a deprecated one carries the framework's warning.

The action and list schema packages declare no Sensitive field, so
nothing is emitted there; a secret passed as an action argument stays
unmarked, which is the framework's limit rather than a choice made here.
All four packages declare DeprecationMessage.

attributes.go crossed the 800-line ceiling, so it decomposes by
protocol: how a declared type becomes an attribute kind, and the
attributes that address an object rather than describe it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ShocOne
ShocOne merged commit 1829d76 into main Aug 14, 2026
1 of 2 checks passed
@ShocOne
ShocOne deleted the feat/sensitive-and-deprecated branch August 14, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant