Skip to content

fix(ir): keep the redaction an overridden declaration asks for - #1355

Open
OmarAlJarrah wants to merge 8 commits into
feat/irfacts-correlation-keysfrom
fix/ir-flattened-secret
Open

OmarAlJarrah wants to merge 8 commits into
feat/irfacts-correlation-keysfrom
fix/ir-flattened-secret

Conversation

@OmarAlJarrah

@OmarAlJarrah OmarAlJarrah commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Summary

ir.FlattenedProperties gives a composed model one member per wire name, and the member took every facet but Required from the one declaration it took. A redaction is such a facet. So a model whose later conjunct redeclares a field without one printed that field in the clear, though an earlier conjunct asked for it to be hidden:

M1: {type: object, properties: {f: {type: string, format: password}}}
M2: {type: object, properties: {f: {type: string}}}
Both: {allOf: [{$ref: '#/components/schemas/M1'}, {$ref: '#/components/schemas/M2'}]}

Both's member f took M2's declaration and was not secret.

FlatProperty gains Secret, computed as Required is: true where any of the member's declarations asks for redaction. A declaration asks for it when it is Secret, or when its type is Sensitive or has a Base that reaches a sensitive type. That second clause carries out Property.Secret's own contract, that a value of a sensitive type is redacted whether or not the use says so. docs/ir/models.md#the-flattening states the rule beside requiredness, so a consumer reads the member's Secret instead of conjoining Overridden itself, which is the alternative the issue weighed and which leaves every emitter to remember it.

FlatProperty is a derived value, not part of the encoded document, so IRVersion does not move and no golden changes.

On the golden spec at main this case does not occur. On #1229's branch, which gives a $ref the redaction its target asks for, the issue's comment counts four members where an overridden declaration redacts and the taken one does not. Each is a failure envelope's result taking a token declaration's place.

Closes #1211

Stack

Base: #1354 (correlation keys), on #1351 and the emitter-design stack. Merge in order.

#1340 (redaction and stability tiers in the emitter design, based on #1229) read the declarations itself because the flattening did not carry this. It now reads FlatProperty.Secret (commit 5fb3d7a there), and its body names this PR.

#1229 (open) adds an extension-promotion status item to docs/compilers/openapi.md saying a flattened member reads no redaction off a declaration it overrides (#1211). That stops being true here. Whichever of the two lands second drops the item.

Test plan

  • go test ./ir -run TestFlattenedProperties. The new TestFlattenedProperties_Secret covers four cases: an overridden Secret declaration; a declaration of a sensitive scalar; sensitivity reached through a scalar's and a model's Base; and a Base cycle, a list, a missing type and a typed-nil entry, which ask for none.
  • Mutants, each reddening the test: the declaration's own Secret dropped, its type's sensitivity dropped, only the taken declaration read, the model Base not followed, and the chain bound cut to one step.
  • Probe: the spec above compiled, then flattened. f is owned by M2, has one overridden declaration, and is secret=true.
  • Push checklist: subjects within 72 characters with the number, no artifact hits, no conflict with main or the base.
  • CI.

A flattened member took every facet but Required from the one
declaration it took, so a composed model whose later conjunct
redeclared a field without a redaction printed it in the clear, though
an earlier conjunct asked for it to be hidden. For allOf of M1 (f, a
password) and M2 (f, a string), the member f took M2's declaration and
was not secret.

FlatProperty gains Secret, computed as Required is: true where any
declaration is Secret, or is of a type that is Sensitive or whose Base
reaches one, since Property.Secret already says a value of a sensitive
type is redacted whether or not it is set. docs/ir/models.md states the
rule beside requiredness. FlatProperty is not part of the encoded
document, so IRVersion does not move.
OmarAlJarrah added a commit that referenced this pull request Nov 2, 2026
The plan read a member's declarations itself because the flattening
dropped a redaction an overridden declaration asked for. #1355 gives
ir.FlatProperty a Secret that accumulates as Required does, so
TypePlan.Redacted reads that instead.
#1229 listed, under extension-promotion's status, that a flattened member
reads no redaction off a declaration it overrides. FlatProperty.Secret
now accumulates over every declaration, so the item no longer holds.
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.

ir: a flattened member drops a redaction an overridden declaration asks for

1 participant