Skip to content

docs(qa): correct the federation auth-floor texts against head's capability gate - #11582

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-11138-federation-capability-clause
Aug 24, 2026
Merged

docs(qa): correct the federation auth-floor texts against head's capability gate#11582
os-steve merged 1 commit into
mainfrom
claude/issue-11138-federation-capability-clause

Conversation

@claude

@claudeclaudeBot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Fixes#11138

The QA checklist item integration-system.external-schema-introspection was authored on 2026-08-20 against 79ebb37, when the federation route spelling served a caller holding no capability while its admin twin refused. #9901 (reads + writes, 9a1ed7a09) and #10255 (validate, 6ce58a735) closed that asymmetry. The item's auth-floor texts did not merely go stale — they inverted: a runner following them today observes the correct 403 on the federation spelling and scores it as a deviation, and the clause pre-empted the escape hatch by naming the old behaviour "a DELIBERATE, pinned divergence (#9593), not a hole to file". The two realistic outcomes were a QA run filing a regression against a landed security tightening, or someone acting on the clause and loosening the gate back.

scripts/check-platform-checklist.mjs is presence-level by its own header ("deliberately dumb"), so nothing was red and nothing would have become red.

Head re-verified first, not inherited

The card's evidence is anchored at afe1c4e0a (08-22). Re-measured at base 0320a52d:

  • All five federation routes open with refuseFederationRequestexternal-datasource-routes.ts:414 (GET /external/tables, read), :433 (POST .../draft, read), :458 (import, write), :485 (refresh-catalog, write), :513 (validate, read). FEDERATION_READ_CAPABILITY = 'manage_platform_settings' (:157), FEDERATION_WRITE_CAPABILITY = 'manage_metadata' (:172), both above the shouldDenyAnonymous 401 floor (:302).
  • Both pinning suites pass — 21/21, matching the card's count:
 Test Files 2 passed (2)
Tests 21 passed (21)
os-verify-lock: VERDICT command-exit 0 · held the lock 10s · waited 252s (4m12s)
  • remote-tables-twin.equivalence.test.ts's describe is now listRemoteTables twins agree on WHO may ask (#9686, #9593, #9901), and its two [#9901] cases compare the spellings' status and code to each other. The row the stale clause recorded as a divergence is the row that suite now asserts as agreement.

Head agrees with what the card says head does, so Zone 1 rule 4's stop-and-report condition did not fire. No file under packages/rest/** is touched. The card's ablation figure ("7 of 21") is not re-measured here and is not asserted by the new text — an ablation would require mutating packages/rest/**, which this card forbids; the new clause rests on the route source, the describe, and the 21/21 pass instead.

The four texts, before and after

1. steps[7] — the step

  • before: …then as the no-capability session (expect 403 on the ADMIN spelling only — the federation spelling serves, the pinned #9593 divergence)
  • after: …then as the no-capability session (expect 403 PERMISSION_DENIED naming manage_platform_settings on BOTH spellings — #9901/#10255 CLOSED the #9593 divergence, so a 200 to that session on the federation spelling is now a FAIL, not the documented behaviour)

2. acceptance[4].clause — the acceptance clause

3. acceptance[4].verify — the verify text (:63 of the item)

  • before: …external-datasource-routes.ts refuseAnonymous (401 only, capability check deliberately absent per its #9593 note); the divergence case is pinned in the twin test's 'WHO may ask' describe
  • after: …external-datasource-routes.ts:287-324 refuseFederationRequest (the same two decisions out of ONE resolveExecutionContext call — anonymous first, then FEDERATION_READ_CAPABILITY); the agreement is pinned in the twin test's 'listRemoteTables twins agree on WHO may ask (#9686, #9593, #9901)' describe…

4. source[1] — the source entry and its stale line anchors

  • before: packages/rest/src/external-datasource-routes.ts:26-28, :215-260 (… capability gate deliberately absent — the file's own #9593 note)
  • after: packages/rest/src/external-datasource-routes.ts:409-448 (the twin family), :287-324 (refuseFederationRequest — the #9686 floor, then the #9901/#10255 capability gate), :157 (FEDERATION_READ_CAPABILITY = manage_platform_settings) + :172 (FEDERATION_WRITE_CAPABILITY = manage_metadata)

Every anchor above was re-read at base and verified by content, not by the quoted line. The sibling source[0] (admin-routes.ts:517-560, :611-623, :361-420 + :261) was checked the same way and is accurate at headrequireDatasourceAdmin is at :361, its capability check at :408-413, DATASOURCE_ADMIN_CAPABILITY at :261, object-draft at :611 — so it is left untouched.

Two further texts in the same defect class, named here rather than left live

Fixing four while leaving a fifth contradiction would repeat this card's own failure mode, so the item's remaining capability-posture texts were triaged too. Both are mechanical and pinned by the same evidence already read:

  • personas[0]: (the admin spelling's capability gate, #9391/#9593)(BOTH spellings' capability gate since #9901/#10255: admin #9391/#9593, federation FEDERATION_READ_CAPABILITY). The persona is used for the federation probes too; left as-is it would read narrower than the corrected clause.
  • steps[6]: the #9686/#9593 admission casesthe #9686/#9593/#9901 admission cases, incl. the two that pin the twins refusing an UNENTITLED caller identically — aligning the step with the describe's actual name at head.

negative[], automated.ref and knownGaps were read and deliberately not changed: automated.ref already names remote-tables-twin.equivalence.test.ts, which is where the two [#9901] unentitled cases live, so the new clause's pin is already listed.

Bookkeeping

revision 1 → 2 on both items, each with a history entry carrying "ref": "#11138" — the presence check:platform-checklist enforces (revision must equal the last history entry's revision).

Companion cli.datasource-introspect-codegen — confirmed, and it did need it

Read at head (after PR #11524's cd932772). It needs the persona spelled out. All three subcommands address federation READ routes, verified in source: list-tables.ts:41GET /external/tables, introspect.ts:45POST /external/tables/:remote/draft, validate.ts:37POST /external/validate. Every one is gated on manage_platform_settings.

The item's fixture asked only for "an admin session token … (the external-datasource routes sit behind the auth guard)" — that describes the #9686authentication floor and nothing more, and neither persona named a capability. A runner minting a merely-authenticated token gets 403 on all six acceptance clauses, with the item's own negative[] pointing at "the server's error arm" rather than at the persona. Same inversion class as the main card.

So: manage_platform_settings is now named in both personas and in the token fixture, and the all-403 run is recorded as a negative — the wrong-persona trap this item already declares — so a runner re-mints instead of filing the landed gate as a CLI regression.

Verification

Gate union derived from the real changeset (node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, no paths passed — provenance line: "gate list derived from the tree of 'objectstack-ai/objectstack' at commit 0320a52"), re-derived after the final commit and unchanged. All run at 7ace45c17, exit codes captured by redirect before any pipe:

gateexitits own verdict line
pnpm check:platform-checklist0check-platform-checklist: OK — 15 areas, 207 items (207 active); … traps: 19 documented, 19 in use
pnpm check:doc-authoring0✓ doc authoring guard: 389 files clean — no bare metadata literals.
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 420 files / 1449 TS blocks judged clean
vitest run (the two pinning suites, read-only)0Test Files 2 passed (2) · Tests 21 passed (21)

check:platform-checklist was green on the base before the edit too — the same verdict line, exit 0, on the unmodified tree at 0320a52d. That gate was red on main earlier today (#11421, fixed by PR #11524), so the after-green is only meaningful next to the before-green; both were measured here.

check:doc-formula-expressions first failed with ERR_MODULE_NOT_FOUND for @objectstack/formula/dist/index.mjs — an unbuilt dependency closure in a fresh worktree, not a finding. Green after pnpm --filter '@objectstack/formula...' run build.

Both heavy runs went through scripts/pm/os-verify-lock.sh; neither returned 99.

Repo-wide pnpm lint: a declared, measured narrowing. Ran eslint on the two changed files only, and the narrowing is proven rather than assumed: (1) the population is read from eslint's own config, not guessed — both files report File ignored because no matching configuration was supplied., so they are outside the linted population entirely; (2) the count is read from --format json — 2 files, 0 errors, 2 warnings, both being that ignore notice; (3) type-aware linting is not enabled (eslint.config.mjs:328, verbatim: "(no parserOptions.project, no typed @typescript-eslint rules)"), so no edit to these two files can move any untouched file's verdict. CI runs the full farm regardless.

Changeset

None — skip-changeset. This PR touches only docs/qa/platform-checklist/areas/*.json, an internal QA ledger that publishes nothing, which is the exemption's own stated case in lint.yml:1467 ("such a PR releases nothing, so by the workflow's own prescription it takes the label"). dispatch-gates.mjs says the same from the other side: "write one unless this card is docs-only". The label is applied via the additive POST /issues/{n}/labels endpoint and read back, per scripts/pr-labels.mjs.

Control-byte scan

grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' over both changed files: no hits. No raw control bytes; the one escaped \u-form em dash left by the edit script was normalised to the file's existing raw UTF-8 spelling, and both files re-parse as JSON.

Generated by Claude Code


Generated by Claude Code

…bility gate
`integration-system.external-schema-introspection` was authored 2026-08-20
against `79ebb37`, when the federation route spelling served a caller holding
no capability while its admin twin refused. #9901 (reads + writes) and #10255
(validate) closed that asymmetry, so the item's auth-floor texts do not merely
go stale — they invert: a runner following them today observes the correct 403
on the federation spelling, and the clause names the old behaviour "a
DELIBERATE, pinned divergence (#9593), not a hole to file", pre-empting the
escape hatch.
Rewrite the four texts to the twin-agreement posture (step 8, the auth-floor
clause, its verify, and the `external-datasource-routes.ts` source entry whose
`:26-28`/`:215-260` anchors were stale), plus persona 1 and step 7, which
attributed the capability to the admin spelling alone.
Companion `cli.datasource-introspect-codegen`: all three `os datasource`
subcommands address federation READ routes, so a merely-authenticated token now
403s every clause. Name `manage_platform_settings` in both personas and in the
token fixture, and record the all-403 run as a negative so a runner re-mints
instead of filing the landed gate as a CLI regression.
Both items take a `revision` bump and a `history` entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 24, 2026
@os-steve
os-steve marked this pull request as ready for review August 24, 2026 04:36
@os-steve
os-steve added this pull request to the merge queueAug 24, 2026
Merged via the queue into main with commit 4afd3c8Aug 24, 2026
27 checks passed
@os-steve
os-steve deleted the claude/issue-11138-federation-capability-clause branch August 24, 2026 04:54
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

QA checklist item integration-system.external-schema-introspection still documents the federation spelling as ungated — four texts contradict head

2 participants

@os-steve@claude