You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
spec: ActionEngineFacade.find accepts a caller-written context that type-checks and the runtime does not honour — declared-but-unenforced on an identity/tenant key (ADR-0049 class) #19237
Filed by the domain:specseat 2 execution seat (座位贴 #18549, session_01JbZnqu8bt6YqfJsr9vaFb3), from the ③ of the at-tier contract review of PR #19223 (record 5746635882, VERDICT: FAIL — this item was the one the FAIL explicitly routed out as not blocking). ⛔ Filed unassigned, ⛔ no priority:*, ⛔ no domain:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim.
⚠️Attribution split. Two facts this seat verified first-hand at origin/main. The override/discard mechanics are the at-tier reviewer's reading and the implementer's, ⛔ not reproduced here.
The gap
ActionEngineFacade.find now takes the engine query envelope EngineQueryOptionsby identity (PR #19223). That envelope declares context. The facade is trusted and mints its own execution context. ⇒ a handler can write a context on a call that type-checks, and the runtime does not honour it — with no signal.
That is the declared-but-unenforced shape ADR-0049 is about, and it is security-shaped: context is where identity and tenant live.
Verified by this seat (origin/main, read directly)
packages/spec/src/data/data-engine.zod.ts:73
context: ExecutionContextSchema.partial().optional(),
(:61 「Execution context (identity, tenant, transaction) — any SUBSET of the …」)
packages/runtime/src/action-execution.ts:164 (pre-PR) / :167 (PR head c5f0855f/35aad659)
const qlOpts = executionContext ? { context: executionContext } : undefined;
⇒ the key is declared and authorable on the envelope, and the facade mints its owncontext. Those two facts together are what make a caller-supplied context meaningless.
⛔ NOT reproduced by this seat
⛔ Whether the caller's context is overridden or dropped, and at which line. Both the reviewer and the implementer describe it as silently overridden; this seat read the minting site but did not trace the merge order into the find arm.
⛔ Whether any handler anywhere writes it today. No census. ⛔ Do not read 「the type allows it」 as 「someone does it」.
⛔ Whether the sibling arms (findOne, count, the write doors) have the same shape.
Two exits the review named — this card picks neither
Refuse it in the arm, with a prescription, the same way PR fix(spec,runtime): ActionEngineFacade.find takes the engine query envelope, not a bare filter #19223's patch round made the arm refuse every top-level key the envelope does not carry. ⭐ Note the asymmetry this creates if left as is: after that patch the arm refuses keys the engine would have honoured (transaction, tenantId, …) while still accepting one it will not honour. Fail-closed in one direction, fail-open in the other.
Omit the key at the type, so it cannot be written at all on this facade.
The FAIL routed this to its own card and the patch order did not carry it; the implementer states it did not fold it in, on the ground that doing so is a behaviour change no ruling covers. ⭐ That call is correct and is recorded here so nobody reads the omission as an oversight.
Dedupe
EngineQueryOptions → 3 results, all closed, none about context: #10470 (objectui unprefixed query keys), #7178 (search rejects the canonical bare string), #7170 (searchFields missing from a hand-written docs page). ⇒ the instrument fires, so the zero on THIS subject is a reading. ⚠️ Instrument note: the query shape in:body returns 0 even for tokens known to be present — a control (GalleryConfigSchema) proves it — so any zero taken that way is void. This zero was taken withoutin:body.
Path: P1 | api-backend(identity/tenant scoping) | 北极星「优先级」1 与 4
Filed by the
domain:specseat 2 execution seat (座位贴 #18549,session_01JbZnqu8bt6YqfJsr9vaFb3), from the ③ of the at-tier contract review of PR #19223 (record 5746635882, VERDICT: FAIL — this item was the one the FAIL explicitly routed out as not blocking). ⛔ Filed unassigned, ⛔ nopriority:*, ⛔ nodomain:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim.origin/main. The override/discard mechanics are the at-tier reviewer's reading and the implementer's, ⛔ not reproduced here.The gap
ActionEngineFacade.findnow takes the engine query envelopeEngineQueryOptionsby identity (PR #19223). That envelope declarescontext. The facade is trusted and mints its own execution context. ⇒ a handler can write acontexton a call that type-checks, and the runtime does not honour it — with no signal.That is the declared-but-unenforced shape ADR-0049 is about, and it is security-shaped:
contextis where identity and tenant live.Verified by this seat (
origin/main, read directly)⇒ the key is declared and authorable on the envelope, and the facade mints its own
context. Those two facts together are what make a caller-suppliedcontextmeaningless.⛔ NOT reproduced by this seat
contextis overridden or dropped, and at which line. Both the reviewer and the implementer describe it as silently overridden; this seat read the minting site but did not trace the merge order into thefindarm.findOne,count, the write doors) have the same shape.Two exits the review named — this card picks neither
ActionEngineFacade.findtakes the engine query envelope, not a bare filter #19223's patch round made the arm refuse every top-level key the envelope does not carry. ⭐ Note the asymmetry this creates if left as is: after that patch the arm refuses keys the engine would have honoured (transaction,tenantId, …) while still accepting one it will not honour. Fail-closed in one direction, fail-open in the other.Omitthe key at the type, so it cannot be written at all on this facade.The FAIL routed this to its own card and the patch order did not carry it; the implementer states it did not fold it in, on the ground that doing so is a behaviour change no ruling covers. ⭐ That call is correct and is recorded here so nobody reads the omission as an oversight.
Dedupe
EngineQueryOptions→ 3 results, all closed, none aboutcontext: #10470 (objectui unprefixed query keys), #7178 (searchrejects the canonical bare string), #7170 (searchFieldsmissing from a hand-written docs page). ⇒ the instrument fires, so the zero on THIS subject is a reading.in:bodyreturns 0 even for tokens known to be present — a control (GalleryConfigSchema) proves it — so any zero taken that way is void. This zero was taken withoutin:body.Dedupe words
ActionEngineFacadecontext ·EngineQueryOptionscontext · declared-but-unenforced · ADR-0049 · facade trusted context · silently overridden execution contextRefs
PR #19223 / 卡 #15124 · 复核记录 5746635882(FAIL,本条被它路由出去)· #19228(同一轮的另一条后续)
Generated by Claude Code