Uh oh!
There was an error while loading. Please reload this page.
docs(qa): correct the federation auth-floor texts against head's capability gate - #11582
Merged
Merged
Conversation
…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
os-steve
marked this pull request as ready for review
August 24, 2026 04:36
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#11138
The QA checklist item
integration-system.external-schema-introspectionwas authored on 2026-08-20 against79ebb37, 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.mjsis 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 base0320a52d:refuseFederationRequest—external-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 theshouldDenyAnonymous401 floor (:302).remote-tables-twin.equivalence.test.ts's describe is nowlistRemoteTables 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 mutatingpackages/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…then as the no-capability session (expect 403 on the ADMIN spelling only — the federation spelling serves, the pinned #9593 divergence)…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…is refused 403 PERMISSION_DENIED naming the capability on the ADMIN spelling only, while the federation spelling serves — a DELIBERATE, pinned divergence (#9593), not a hole to filethe auth floor holds and BOTH spellings answer it IDENTICALLY — the #9593 asymmetry this item recorded through rev 1 is CLOSED, so a federation 200 to an unentitled caller is a FAIL, not the documented behaviour: …— carrying both maintainer rulings verbatim and untranslated (2026-08-20 「其他接受你的建议。」 for security(rest): the external-datasource federation family still admits any authenticated caller, while its declared admin twin now requires a capability #9901, 「同意你的意见。」 for POST /datasources/:name/external/validate is the one federation route the #9901 ruling does not name — it stays authentication-only while its four siblings now require a capability #10255), and noting the family's writes sit onmanage_metadataso the reader does not over-generalise the read capability.3.
acceptance[4].verify— the verify text (:63of the item)…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…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 anchorspackages/rest/src/external-datasource-routes.ts:26-28, :215-260 (… capability gate deliberately absent — the file's own #9593 note)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 head —requireDatasourceAdminis at:361, its capability check at:408-413,DATASOURCE_ADMIN_CAPABILITYat:261,object-draftat: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 cases→the #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.refandknownGapswere read and deliberately not changed:automated.refalready namesremote-tables-twin.equivalence.test.ts, which is where the two[#9901]unentitled cases live, so the new clause's pin is already listed.Bookkeeping
revision1 → 2 on both items, each with ahistoryentry carrying"ref": "#11138"— the presencecheck:platform-checklistenforces (revisionmust equal the last history entry's revision).Companion
cli.datasource-introspect-codegen— confirmed, and it did need itRead 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:41→GET /external/tables,introspect.ts:45→POST /external/tables/:remote/draft,validate.ts:37→POST /external/validate. Every one is gated onmanage_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_settingsis now named in both personas and in the token fixture, and the all-403 run is recorded as a negative — thewrong-personatrap 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 at7ace45c17, exit codes captured by redirect before any pipe:pnpm check:platform-checklistcheck-platform-checklist: OK — 15 areas, 207 items (207 active); … traps: 19 documented, 19 in usepnpm check:doc-authoring✓ doc authoring guard: 389 files clean — no bare metadata literals.pnpm --filter @objectstack/lint run check:doc-formula-expressions✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 420 files / 1449 TS blocks judged cleanvitest run(the two pinning suites, read-only)Test Files 2 passed (2) · Tests 21 passed (21)check:platform-checklistwas green on the base before the edit too — the same verdict line, exit 0, on the unmodified tree at0320a52d. That gate was red onmainearlier 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-expressionsfirst failed withERR_MODULE_NOT_FOUNDfor@objectstack/formula/dist/index.mjs— an unbuilt dependency closure in a fresh worktree, not a finding. Green afterpnpm --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 reportFile 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: "(noparserOptions.project, no typed@typescript-eslintrules)"), 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 onlydocs/qa/platform-checklist/areas/*.json, an internal QA ledger that publishes nothing, which is the exemption's own stated case inlint.yml:1467("such a PR releases nothing, so by the workflow's own prescription it takes the label").dispatch-gates.mjssays the same from the other side: "write one unless this card is docs-only". The label is applied via the additivePOST /issues/{n}/labelsendpoint and read back, perscripts/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