Skip to content

fix(dogfood): the authz conformance matrix rows state each decision in words instead of a tracker number (stage 5b) - #21265

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20752-stage5b-authz-matrix-strings
Oct 2, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20752-stage5b-authz-matrix-strings

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #20752
Clause-②: no

Stage 5b, the last stage of the domain:cli lane under the maintainer's A / A ruling (5902360492): the authz conformance matrix. Stages 1 to 5a (PR #21172, PR #21188, PR #21219, PR #21231, PR #21250) emptied every other row of this lane; this PR empties the last one, so the lane's share of the ledger burn-down is zero once it lands. Text only: no row id, state, covers key, proof file or enforcement site moves, and the file's code comments are untouched.

What this does

The summary, enforcement and note strings of packages/qa/dogfood/test/authz-conformance.matrix.ts sent the reader to a tracker number for the reason behind a row. In form D, as the earlier stages applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words.

All 76 ledgered occurrences of 46 cards, at 43 string sites (claim 5942403129, ledger read at a23be7498e): 16 summary, 10 enforcement, 17 note strings. 22 sites now say something in words; 21 already stated the decision and only lose the citation.

Every cited card was read first. Six answer 404 and were read through the commit that decided them: 10243 (266436a7f), 12176 (7986d973f), 11757 (4d25d22d4), 8710 (04d03c3a0), 8711 (2ce1eb41b) and 8811 (d6e793507). The 10145 and 10243 phrases on the automation row reuse stage 3's route-ledger.ts wording for the same decisions, and the 5519 floor is named the way stage 3 named it (the domain-wide anonymous floor, refused before dispatch).

Two notes cite describe titles in other packages that carry a bracketed tag. Those titles are quoted without the tag, so each quote stays a literal substring of the real title and is still findable by search.

The 43 sites (line numbers are the same at base and head)

Site Cited Form The text now says (new fragment) Decision read from
:161 rls-by-id-write summary 1994 citation only by-id write enforcement PR 1994 (RLS re-checked on the pre-image of a by-id update/delete)
:162 rls-by-id-write enforcement 7665 citation only write-scope DERIVATION: when no update/delete-class policy applies card 7665 via PR 7792 (an empty write-class policy set derives its scope from the caller's select narrowing); the sentence after the colon already says it
:164 rls-by-id-write note 7685, 7665, 7665, 7792, 7685 words (tag dropped; three phrases worded) Re-verified ... — that was the hole through which a contributor PATCHed records it could not read, and ... since the fix that derives a missing write scope from the select narrowing, that file carries ... whose probe persona holds object read+edit narrowed by select-only RLS and so reaches this class — card 7665 (a by-id write was not gated by record visibility under select-only RLS); PR 7792 (option A: derive the write scope from the select narrowing); card 7685 comment 5264791326 (measurement first: a probe persona with object read+edit narrowed by select-only RLS; both rows stay enforced)
:174 controlled-by-parent note 7685, 7665 tag dropped; one phrase worded Re-verified as enforced on its OWN evidence ... when the select-derived write-scope derivation its master depends on is ablated. card 7685 comment 5264791326 (re-verified by measurement, not downgraded); card 7665 / PR 7792
:177 multi-tenant-write-postimage summary 2937 words (forged INSERT / Finding 1 re-point — a forged OR re-pointed organization_id cannot cross the tenant wall) card 2937 (an INSERT carrying a forged organization_id crossed the tenant wall; Layer 0 gains an insert post-image check)
:179 multi-tenant-write-postimage note 2937, 2937, 2937 citation only + suite titles named in words INSERT a forged cross-tenant organization_id or UPDATE ... (the "Layer 0 insert post-image tenant guard" suite + the Finding 1 "Layer 0 update post-image tenant guard (cross-tenant re-point)" suite) card 2937; the two describe titles in plugin-security/authz-matrix-gate.test.ts, quoted without their bracket tags so each stays a substring of the real title
:181 multi-tenant-exemption-posture enforcement 2956 citation only reads the carried ctx.posture rung (ADR-0099 D1) PR 2956 (carry the derived posture rung on ExecutionContext); the phrase 'the carried ctx.posture rung' already says it
:182 multi-tenant-exemption-posture note 2937 suite title named in words (the Finding 2 "Layer 0 cross-tenant exemption requires the platform posture" suite + "ADR-0099 P1 ...") the describe title in plugin-security/authz-matrix-gate.test.ts
:195 org-write-validation note 2937 words — the forged-organization_id INSERT defect one call site down. card 2937
:213 anonymous-deny-meta summary 2567 words (uniform anonymous posture, surface 1) card 2567 (the anonymous-deny posture must be uniform across every HTTP surface that reaches ObjectQL)
:228 anonymous-deny-meta note 11373, 12176 citation only + words For most of this row's life ... five since the retirement of slash-bearing metadata item names un-mounted the compound save card 11373 (measure first; the note goes on to state the measured refusal); card 12176 answers 404, read through landing commit 7986d97 (stage 3 of the ruled retirement of slash-bearing metadata item names: un-mounts the compound arities)
:236 anonymous-deny-actions summary 2567, 5519 words (uniform anonymous posture, surface 2: refused 401 before dispatch, as /data and /meta are) card 2567; card 5519 (anonymous /actions and /automation requests are refused 401 before dispatch, the same baseline as /data and /meta)
:244 anonymous-deny-actions note 5519 words — before the gate, an anonymous POST /actions/showcase_task/showcase_mark_done/:id was measured answering 200 with the update applied. card 5519
:245 anonymous-deny-automation summary 2567, 5519 words (uniform anonymous posture, surface 3: refused 401 before dispatch, as /data and /meta are) card 2567; card 5519
:246 anonymous-deny-automation enforcement 10145, 10243, 7900, 3801, 5561 words (stage 3 route-ledger twin wording) DELETE /:name, the definition writes on the metadata plane, plus enablement POST /:name/togglesince the 2026-08-23 ruling that enablement is an authoring write, ... the run-state reads (thesys_automation_runread grant) andresume` (keyed on the node the run is suspended on, fail-closed for a node that declares no resumeAuthority) carry their own card 10145 (flow definition writes are authored metadata, so manage_metadata gates them); card 10243 answers 404, read through landing commit 266436a (enablement is an authoring write, ruling of 2026-08-23); card 7900 via commit 627e65a (run-state reads consult the sys_automation_run read grant); card 3801 (resume gated on the suspended node); card 5561 (no declared resumeAuthority fails closed); the 10145 and 10243 phrases reuse stage 3's route-ledger.ts wording
:253 anonymous-deny-automation note 5519 words which the original anonymous-surface report did not record. card 5519
:263 anonymous-deny-packages summary 7033, 7023 citation only anonymous-deny on the package-management surface cards 7033 and 7023 (the /packages domain carried no authorization predicate; the row's enforcement already states the domain-wide gate); same shape as the sibling analytics row
:300 realtime-delivery-authz summary 2992 words (a latent surface: identity admission is owed before any client transport ships) card 2992 (GraphQL and realtime must satisfy identity admission before a client transport ships)
:302 realtime-delivery-authz note 9083, 9083 tag dropped + words Clearing that red ... Before that admission rule landed, this note promised a gate that did not exist card 9083 (a TRANSPORT-WIRED key may be classified only by an enforced row); the sentence after the tag already says it
:310 mcp-http-identity enforcement 2698 citation only (403 on none) card 2698 (OAuth 2.1 for /api/v1/mcp, scope-gated tool families); the sentence already says it
:320 mcp-http-identity note 3167 citation only proven end-to-end: the proof boots card 3167 (identity admission first); the sentence after the colon states what the proof drives
:332 readonly-static-write summary 2948, 3003, 3043 citation only + words UPDATE AND INSERT (first at the data-write ingress; in-engine ...) cards 2948 and 3003 (strip static readonly on non-system UPDATE); card 3043 (tighten the INSERT exemption, first enforced at the data-write ingress)
:333 readonly-static-write enforcement 2948, 5591 citation only (caller-supplied VALUES only — ... the caller also sent) card 2948; card 5591 (strip the caller-supplied value, never a hook stamp); the parenthetical already says both
:335 readonly-static-write note 3003, 3043, 3003 words The originating field report: ... The INSERT face followed: ... a step SHORTER than the draft-then-PATCH route, card 3003 (readonly was UI-only; a non-admin self-approved by PATCH); card 3043 (the INSERT exemption let the same caller POST an approved record)
:340 declarative-rbac-seeding summary 2077 citation only seeded at boot card 2077 (activate declarative roles + sharingRules at runtime)
:355 ownership-anchor-guard summary 3004 citation only without the transfer grant card 3004 (owner_id is system-managed for non-privileged writers)
:358 bulk-write-owner-scoping summary 2982 citation only not just single-id writes card 2982 (bulk writes owner-scoped on OWD-private objects)
:361 public-form-managed-anchors summary 3022 citation only (owner_id / organization_id / audit / id) card 3022 (a public-form submit cannot supply owner_id or other server-managed anchors)
:362 public-form-managed-anchors enforcement 3004 words complements the step 3.5 owner-anchor guard card 3004
:378 hierarchy-widening enforcement 7807 citation only the runtime was narrowed to the declaration card 7807 (business_unit expands exactly one unit, as declared)
:381 rls-compiler-fail-closed enforcement 4983 citation only hoisted out of plugin-security so lint/... card 4983 (wire the ADR-0056 D4 authoring gate to the one predicate definition)
:385 secure-by-default-posture enforcement 11757 words (the gate's other carrier, sys_scim_provider, retired once the stable SCIM line stopped deriving a provider model) card 11757 answers 404, read through landing commit 4d25d22 (retire the rc.1-era sys_scim_provider; stable @better-auth/scim derives no scimProvider model)
:387 flow-run-as summary 1888 citation only under the run's effective identity card 1888 (enforce runAs)
:390 flow-run-as note 1888 words but its enforce-or-remove decision chose ENFORCE and implemented it for flow data nodes card 1888 (decision required: enforce or remove; enforced)
:420 permission-set-active summary 8613 citation only (ADR-0049) card 8613 (the active flag on both grant catalogues is enforced)
:422 permission-set-active note 8613 citation only "the active flag on the grant catalogues (ADR-0049)" card 8613; the describe title in core/security/resolve-authz-context.test.ts, quoted without its tag so it stays a substring of the real title
:423 position-active summary 8613 citation only (ADR-0049) card 8613
:443 grant-validity-window enforcement 10982 citation only accessible_org_ids and the org-administration role projection card 10982 (window-filter the role projection too); the present-tense list already says it
:445 grant-validity-window note 8811, 8711, 8710, 10982, 11089, 10982, 9377, 7976 tags dropped + words NO covers ... Per the 2026-08-15 maintainer ruling ... by the 2026-08-15 ruling that access-conferring paths filter and addressing paths do not, because approval ROUTING ... sys_member ... last-admin-guard.ts's ... the role projection as window-filtered now; ... is now cited: ... the mutual-attribution contract (a cited proof file names the rows it proves) is satisfied. 8811 (404) via d6e7935 (adds this row); 8711 (404) via 2ce1eb4 (ruled narrowing of the completeness claim to routes); 8710 (404) via 04d03c3 (ruling 2026-08-15: access-conferring paths filter deactivated positions, addressing paths do not); card 10982; card 11089 (the last-admin-guard note went stale after 10982); card 9377 (cite delegation-of-duty as this row's proof); card 7976 (a proof file names the rows it proves, checked both ways)
:452 agent-visibility summary 1901 citation only listing scope card 1901 (agent visibility not enforceable without owner/org anchors; removed per D8)
:453 agent-visibility note 1901, 1884 citation only visibility deleted) ... at the chat route; card 1901; card 1884 (enforce access/permissions at the chat route)
:462 requireAuth-removed note 3963, 7976 words + tag dropped ADR-0056 D2, completed by deleting the switch once every session-less surface was declared: the requireAuth: false opt-out is RETIRED ... The showcase-anonymous-deny.dogfood.test.ts CITATION WAS DROPPED card 3963 (step 1: public as a declared capability; step 2: delete api.requireAuth, an auth-less stack fails at boot); card 7976 (mutual attribution, already named in the sentence)
:466 allow-transfer-restore-purge note 1883, 3004, 12497, 1883 words + citation only ADR-0049 → roadmap M2, which builds the lifecycle ops and their RBAC bits as one batch: the ops still do not exist ... owner_id door. ... RETIRED 2026-08-26 (maintainer ruling: retire the two bits now rather than carry them unenforceable until M2): card 1883 (M2: build undelete/purge and their RBAC bits in one batch); card 3004; card 12497 (ruled 2026-08-26: retire allowRestore/allowPurge, the keys return with M2)

The ledger

scripts/doc-authoring-prose-id.baseline.json, recomputed with node scripts/check-doc-authoring.mjs --census-ledger (refuses any growth):

occurrences (file, id) pairs files matrix row
base 434c6c7cab 359 251 87 76 occurrences / 46 cards
head 283 205 86 absent
  • Exactly the matrix row leaves: 48 lines deleted, 0 added. The other 86 rows compare equal as JSON.
  • Recomputed again after merging origin/main (8dea55d314): byte-identical.
  • pnpm check:doc-authoring: exit 0 before and after. Its cross-package line reads 300 pinned sites across 87 files at base and 257 across 86 at head, "no growth, no burn-down unrecorded".
  • The census's other 257 sites are the same before and after (file, line and ids).

Text only

A scratch TypeScript-AST comparison of the file at base 434c6c7cab and head: 1695 skeleton nodes on both sides, identical; 280 string literals on both sides, 43 values changed, owned by summary 16, enforcement 10, note 17 and nothing else; 255 comment trivia blocks on both sides, byte-identical. Its three controls each behave: a renamed property key reads "skeleton DIFFERS", a changed state value is reported as owned by state, and an edited comment reads "not identical".

Pins

None. Nothing mechanical reads these three fields: the companion test imports the rows for id, state, proof, covers and enforcement presence, and the census and blind-spot test read only the header docblock and the covers arrays. A whole-repo fixed-string search for the text around each of the 76 removed ids (224 fragments, docs/qa/** included) found 12 fragments with hits, every one a code comment, a release-owned CHANGELOG entry, a describe title or a liveness note, none asserting this file's text. So no pin moved and no ablation is owed.

Verification

  • Build: pnpm turbo run build --filter='@objectstack/dogfood^...' --concurrency=2: 63/63 tasks.
  • Tests: pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/authz-conformance.test.ts test/authz-probe-blind-spot.test.ts: 2 files, 90 tests passed. These are the only consumers of the module and of its text.
  • Typecheck: pnpm --filter @objectstack/dogfood typecheck exit 0; --listFilesOnly lists the matrix file and the companion test.
  • Gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at 3005a8b6d1 derives 54 commands; all 54 run, exit 0. check:dual-build-cjs-loads first answered exit 3 (PREREQUISITE NOT MET: 8 unrelated packages without dist/); after a full workspace build (72/72) it exits 0 and that rerun is the recorded result. --ran reconciliation: 54 derived, 54 run, 0 NOT-MEASURED, 0 UNRUN.
  • Lint: full pnpm lint at 3005a8b6d1: exit 0, no findings.
  • Tests and typecheck ran at 0dbdbd759b; the merge after it brought one docs/adr file and no package input.

Changeset

None, with skip-changeset: @objectstack/dogfood is private: true, and the ledger is a repository script file. No .changeset/*.md is touched.

Acceptance notes

  • Code comments in the matrix file still cite cards (33 comment lines, the bracketed tracker tags and the block-comment headers among them). They are not runtime strings and not on the ledger, so they are outside ruling 5902360492 and this claim. Noted, not filed.
  • Two describe titles the notes quote carry a bracketed tag: plugin-security/src/authz-matrix-gate.test.ts (the Layer 0 insert, update and exemption suites) and core/src/security/resolve-authz-context.test.ts (the active-flag suite). Test bodies are outside the gate's reading and belong to those packages, not to this lane. Noted, not filed.

Generated by Claude Code

claude added 3 commits October 1, 2026 23:16
…rds instead of a tracker number (stage 5b)

The matrix's summary, enforcement and note strings sent the reader to a
tracker number for the reason behind a row. In form D, as stages 1 to 5a
applied it, the number goes: where the sentence already said what was
decided, only the citation goes; where it leaned on the number, it now
says the decision in words. 76 ledgered occurrences of 46 cards at 43
string sites. Text only: no row id, state, covers key, proof file or
enforcement site moves, and code comments are untouched.

Claude-Session: https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB
Co-authored-by: Claude <noreply@anthropic.com>
…ter stage 5b

The authz conformance matrix row leaves the ledger: 76 occurrences of 46
cards. No other row moves. The ledger reads 283 occurrences, 205
(file, id) pairs, 86 files.

Claude-Session: https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/m label Oct 1, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 1, 2026
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 30c530e5c0e13ca283cde133f4e63a9503edf936 → packageMentionDocs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants