Repository navigation
rest: the API-description endpoints (RestServer.registerOpenApiEndpoints) answer an anonymous caller with the whole object model; ADR-0056 D2 and ADR-0138 D2 require 401 #22430
Description
Activity
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsTriage: first grade,
priority:p1·security·target:v18·domain:cli·area:access·pm:queue. Execution of ruling6074960686item 2Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-09T06:57Z. ⛔ Not a claim, ⛔ not a dispatch. ⛔ Function level only, as the ruling requires.Triage: lands in
packages/rest/src/rest-server.ts(RestServer.registerOpenApiEndpoints) ⇒domain:cli. Rationale:packages/restbelongs to that lane.- Why p1, security, v18: an anonymous caller reads the whole object model, against ADR-0056 D2's default-deny. The card blocks the acceptance of design(v18): the complete guest model in one ADR — identity, doors, grants channel, organization, public-site binding, disclosure, rate limits, and each declared guest key's fate (ADR-0090 D9 enforce-or-remove) #22146 (p1
target:v18), the guest model, and release-priority work is p1. - Execution, not a decision: the maintainer ruled the direction (batch Bump version to 0.3.4 #300 item 1, A): the API-description endpoints refuse an anonymous caller with
401. - Order: independent of service-storage: a file with no scope and no field owner is downloadable by an anonymous caller who has its id; the download should require a signed-in caller, while
acl: 'public_read'stays anonymous (ADR-0104) #22431 and runtime: the/i18ndispatcher domain answers an anonymous caller —handleI18nRequestmakes noshouldDenyAnonymouscall, unlike every other dispatcher domain (ADR-0056 D2); with an objectui companion for the Console sign-in page #22432. All three close design(v18): the complete guest model in one ADR — identity, doors, grants channel, organization, public-site binding, disclosure, rate limits, and each declared guest key's fate (ADR-0090 D9 enforce-or-remove) #22146's criterion 2.
- Why p1, security, v18: an anonymous caller reads the whole object model, against ADR-0056 D2's default-deny. The card blocks the acceptance of design(v18): the complete guest model in one ADR — identity, doors, grants channel, organization, public-site binding, disclosure, rate limits, and each declared guest key's fate (ADR-0090 D9 enforce-or-remove) #22146 (p1
- addedarea:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsPermissions that actually hold — RLS/FLS, sharing model, write-path guardspriority:p1High: required for production / M2High: required for production / M2and removed
on Oct 9, 2026 objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsClaim: PM loop round 2
Session:session_01BmsuLyUeuG5CNpZFMH1jzS
Account:os-elon-musk(the seat's linked user asGET /useranswers it; always the card's assignee)
Branch:claude/issue-22430-api-description-anonymous-deny
Worktree:objectstack-issue-22430
Domain:domain:cli
Seat:domain:cli#1
File surface (read atorigin/mainb9222dc70):packages/rest/src/rest-server.ts: onlyRestServer.registerOpenApiEndpoints(the API-description document handler and its viewer handler), so that each refuses an anonymous caller with the existing anonymous-deny envelope;packages/rest/src/openapi-builtin-paths.ts: only the docblock that says these routes answer anonymously "deliberately", plus the document's own security statement for them if the change makes it false;- tests beside the routes in
packages/rest(reject path:code+status; a signed-in control served as today); packages/qa/dogfood/test/authz-ledger-population.baseline.tsandauthz-conformance.matrix.ts: the API-description family moves from unclassified to classified;- the pins a repo-wide sweep finds asserting an anonymous answer from these endpoints, and the hand-written docs pages that state it (
domain:devx's pages, declared on [PM seat] domain:devx @ objectstack — ⏳ vacant #6023 when the PR shows them); .changeset/22430-*.md(@objectstack/restpatch).
Stop on breach; explain in the report.
Container & model:M,mode:subagent,model: default (opus).dispatch-gates --tierprints "no path-derived mandate". The floor is raised to default because this card implements a ruling on an access boundary.
Clause-②: no (narrowing)
Responsibility:packages/rest/src/rest-server.ts#RestServer.registerOpenApiEndpointsserves the API-description document and viewer with no anonymous check | none: ADR-0138 D2's five classes and the control-plane allowlist do not name these endpoints, andenforceAuthis not called on them | any anonymous HTTP caller reaches it (measured on a booted reference deployment, G26074331185); whether a real anonymous consumer exists (a public API portal) is the ruling's open confidence gap, which the dev measures in the tree
Thread-read: 6076053737
Serial constraints cleared: no open PR touchespackages/rest/or the two authz ledger files (REST file lists of all 13 open PRs, read in this act). The siblings under the same ruling are disjoint. #22431 (domain:services, in flight,os-bill) holdsservice-storageand one new dogfood pin file. #22432 (this lane) ispm:blockedon objectstack-ai/objectui#12034. If a sibling also classifies its family inauthz-ledger-population.baseline.ts, the second to land mergesmain. PR #22381 (held draft) moves dogfood showcase boots ontoshared-showcase.ts; a new dogfood file uses that helper if #22381 has landed first. PR #22433 (#22146's record revision) touchesdocs/adr/**only.Ruling-ref:
6074960686item 2 (#22146, retrieved in this act): "The API-description endpoints refuse an anonymous caller (401)." Disclosure: function level only on this card, in the PR and in the changeset; the route-level G2 readings stay private. Review of record: the seat's ACCEPT and CI. This card declaresClause-②: noand touches neitherpackages/specnor governed text, so no contract-tier review is owed. The refusal reuses the existing anonymous-deny code; a new error code would beClause-②: yesanddomain:spec's work.
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsSerial constraints, correction to claim
6076369421· seatdomain:cli#1·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T07:23Z
Thread-read: 6076369421The claim's last line missed one in-flight hold on
packages/rest/src/rest-server.ts. The seat had not read the newest comment on its post before writing the claim, which is a seat error.- feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 stage S3 (domain:engineseat 2, claim6076144407, branchclaude/issue-15206-s3-doors-env-only,mode:cloud; declaration6076170214on [PM seat] domain:cli — 🟢 os-elon-musk · session_01BmsuLyUeuG5CNpZFMH1jzS #6024). It may write the/metaread and write doors inrest-server.ts, plusmeta-item-read-gate.ts,rest-route-ledger.tsnotes,runtime/src/domains/meta.ts,runtime/src/route-ledger.ts, and tests inpackages/rest,packages/runtimeandpackages/qa/dogfoodthat pin organization-scoped metadata doors. - Overlap: the same file, but a different region. This card stays inside
RestServer.registerOpenApiEndpoints; S3 holds the/metadoors.rest-server.tsis not a single-claim path (SINGLE_CLAIM_PATHSnames.objectui-shaonly), so this is ordinary concurrency: whichever lands second mergesmainand resolves. If both touch the authz conformance matrix, the same rule applies. - This card's dev is told in this act: keep every
rest-server.tshunk insideregisterOpenApiEndpoints, and mergemainbefore opening the PR if S3 has landed.
Generated by Claude Code
- feat(metadata-core,metadata-protocol,objectql,plugin-security): the
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 22430, "status": "done", "branch": "claude/issue-22430-api-description-anonymous-deny", "pr": "https://github.com/objectstack-ai/objectstack/pull/22446", "session": "session_01BmsuLyUeuG5CNpZFMH1jzS — the dispatching session's id (subagent run; the harness reminder names it for commits and the PR)", "premise_still_valid": true, "summary": "RestServer.registerOpenApiEndpoints: both handlers (the document and its viewer, every base) now open with the package's existing enforceAuth floor before any work, so an anonymous caller gets 401 UNAUTHENTICATED with ANONYMOUS_DENY_BODY (byte-identical to the data routes'), a signed-in caller is served as before, an ADR-0069-gated session gets its 403. The API-description family is classified by a new enforced matrix row (anonymous-deny-api-description) whose proof drives both endpoints on the booted showcase; the baseline drops to 31. openapi-builtin-paths.ts's 'answer anonymously' sentence is corrected, five rest suites read the document as a signed-in caller, the execctx census counts the two new bare sites, and a @objectstack/rest patch changeset carries the operator line. H1-H5 held as stated; H6 held but was incomplete (the classified-keys pin in authz-conformance.test.ts also lists the family).", "tests": "MEASURE-FIRST (real boot, `pnpm dev -- --fresh`, the showcase, before = base b9222dc70, after = this branch; statuses and callers only). Callers: anonymous; a member created by the admin and still under the ADR-0069 must-change-password gate (probed before the password change); the same member after it; the dev admin. The document, unscoped base: anonymous 200 -> 401 UNAUTHENTICATED; gated 200 -> 403 PASSWORD_EXPIRED; member 200 -> 200; admin 200 -> 200. The viewer, unscoped base: anonymous 200 -> 401 UNAUTHENTICATED; gated 200 -> 403 PASSWORD_EXPIRED; member 200 -> 200; admin 200 -> 200. Both endpoints, environment-scoped base: 404 ENDPOINT_NOT_FOUND for every caller before and after (the showcase does not enable project scoping, so the scoped twin is not mounted on this boot); the scoped twin is measured at handler level instead (below). Control on the same boot: a data route answered anonymous 401 / gated 403 / member 200, before and after. H4 (viewer carries the session), Chromium /opt/pw-browsers with the real viewer bundle (@scalar/api-reference 1.73.1, served from its npm tarball because the CDN the page names answers the container proxy 403): before, anonymous navigation 200 and the viewer's fetch of the document went with NO cookie and got 200; after, anonymous navigation 401 and the viewer never ran; after, signed in by cookie, navigation 200 and the viewer's fetch of the document carried the session cookie and got 200. H5 (anonymous consumers in the tree): zero. Searched objectstack (packages/client, packages/cli, scripts, .github, apps, examples, packages/qa, packages/verify, packages/runtime, packages/adapters, packages/plugins, content/docs) and objectui at origin/main 049012bf and at the pin a58626c88: no fetch of the document or the viewer. The one in-tree reader, showcase-declarative-endpoints.dogfood.test.ts, reads it with an admin token; the platform checklist route-parity item probes it as admin; /discovery does not advertise its URL; objectui's /docs routes are the Console book portal. A deployed public API portal outside the repo is NOT MEASURED. REVERSE VERIFICATION (unit): rest-api-description-anonymous-deny.test.ts against the base rest-server.ts blob 89fae0b5e: 7 failed | 4 passed, the four anonymous cells (document and viewer, unscoped and scoped) reading `expected 200 to be 401`, signed-in controls green; restored to HEAD blob 32bb64d05, git diff HEAD empty. After: 13/13. ABLATION through dist/ (scripts/ablation-replace.mjs, anchor x1 -> x0, blob 32bb64d05 -> a0e01ffb6; `pnpm --filter @objectstack/rest build`; ablation-dist-preflight: marker present in dist/index.js and dist/index.cjs): only the document's floor removed; showcase-anonymous-deny-surfaces.dogfood.test.ts went 2 failed | 65 passed, exactly the two document-anonymous cases; viewer cases and member controls green. Restore leg: blob == HEAD 32bb64d05, git diff HEAD empty, rest rebuilt, preflight --absent: marker absent from all 6 built files, tree clean. SUITES at 1d4ad614f: rest full 271 files / 5164 passed / 327 skipped; dogfood authz-conformance + anonymous-deny proof 122/122; rest + dogfood typecheck exit 0; pnpm lint (full) exit 0; 69/69 derived gates exit 0, --ran reconciles 69/69.", "mcp_calls": "0 — no MCP GitHub tool called", "api_writes": "3 — all through the fleet-write relay as objectstack-fleet[bot], each carried by one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (#22446, draft forced; read-back 8449/8449 bytes identical); (2) label-write assign -> POST /repos/objectstack-ai/objectstack/issues/22446/assignees (os-elon-musk; read-back matches); (3) this os-dev-report -> POST /repos/objectstack-ai/objectstack/issues/22430/comments. Plus git push (not REST). Reads: REST GET only.", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed — On the environment-scoped twin a signed-in caller is judged by the auth service of the environment the URL names; these handlers do not add the enforceEnvironmentOwnership comparison the UI-view route makes. Not measured (the showcase mounts no scoped base); outside ruling item 2 (anonymous only). Recorded in the PR's Acceptance notes for whoever re-measures ADR-0138's everything-else class.", "carrier: 承接者:无 · noted, not filed — The viewer page loads its script from a CDN with no version pinned, on the API's own origin; pre-existing and unchanged by this PR (observation, no defect reproduced). In Acceptance notes.", "carrier: 承接者:无 · noted, not filed — rest-route-ledger.ts's two openapi-family rows could carry the optional `authz: 'anonymous-deny-api-description'` field; left alone because #15206 S3 holds that file's notes. In Acceptance notes.", "carrier: 承接者:无 · noted, not filed — a comment inside rest-server.ts's UI-view handler still speaks of '52 sites' behind the shared floor; the census reads 47 bare after this PR (45 before). Drift in prose outside registerOpenApiEndpoints, left alone under the seat's hunk fence." ], "gates": [ { "command": "node scripts/check-adr-0087-registration.mjs --base origin/main", "exit": 0, "verdict": "✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)." }, { "command": "node scripts/check-adr-0087-registration.mjs --self-test", "exit": 0, "verdict": "✓ check-adr-0087-registration --self-test: 441 assertions over real temp git repos (real scan()/assertInputs() path)" }, { "command": "node scripts/check-changeset-no-major.mjs --base origin/main", "exit": 0, "verdict": "✓ This diff introduces no `major` bump." }, { "command": "node scripts/check-changeset-no-major.mjs --self-test", "exit": 0, "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff scoping over real te" }, { "command": "node scripts/check-ci-filter-parity.mjs", "exit": 0, "verdict": "OK: all 20 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11 script(s) the `build-core` job's" }, { "command": "node scripts/check-closing-keyword-parity.mjs", "exit": 0, "verdict": "check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10424 tracked file(s), all registered)." }, { "command": "node scripts/check-closing-keyword-parity.mjs --self-test", "exit": 0, "verdict": "✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red." }, { "command": "node scripts/check-comment-mask-adoption.mjs", "exit": 0, "verdict": "OK check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/**, all 14 recorded and every recorded row still reached (13 unconverted, 1 specimen). A new one reds here" }, { "command": "node scripts/check-comment-mask-adoption.mjs --self-test", "exit": 0, "verdict": "PASS check-comment-mask-adoption --self-test (0 failure(s))" }, { "command": "node scripts/check-comment-mask-corpus.mjs", "exit": 0, "verdict": "✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8520 files, 0 disagree, 0 unparseable, 155.1s (comparator self-test: 26 cases pass)." }, { "command": "node scripts/check-dts-emitted.mjs --self-test", "exit": 0, "verdict": "check-dts-emitted self-test: all assertions passed." }, { "command": "node scripts/check-empty-changeset.mjs --base origin/main", "exit": 0, "verdict": "✓ No changeset from the merge base modified or deleted by this diff (#17712)." }, { "command": "node scripts/check-empty-changeset.mjs --self-test", "exit": 0, "verdict": "✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)" }, { "command": "node scripts/check-issue-citations.mjs", "exit": 0, "verdict": "✅ check-issue-citations: every citation this change adds resolves (or is a declared cross-repo reference)." }, { "command": "node scripts/check-keyed-text-bounds.mjs", "exit": 0, "verdict": "✓ check:keyed-text-bounds: 111 *.object.ts files under packages/** + apps/** + examples/** (walk is repo-wide; 0 outside), 116 object declarations, 241 declared index entries, 588 text-family fields; " }, { "command": "node scripts/check-keyed-text-bounds.mjs --self-test", "exit": 0, "verdict": "PASS check-keyed-text-bounds --self-test (0 failure(s))" }, { "command": "node scripts/check-platform-object-tenancy-census.mjs", "exit": 0, "verdict": "✓ platform-object tenancy census matches the tree: 83 platform-namespace objects, 48 in the machinery's reach, 35 outside it, every exclusion explained by a declaration on its own schema." }, { "command": "node scripts/check-platform-object-tenancy-census.mjs --self-test", "exit": 0, "verdict": "✓ check-platform-object-tenancy-census self-test: all checks pass (83 objects, 35 outside the machinery)" }, { "command": "node scripts/check-plugin-teardown-shape.mjs", "exit": 0, "verdict": "✓ check:plugin-teardown-shape: 69 Plugin implementation(s) across 7944 source(s) under packages/**; every teardown-shaped method (stop / shutdown / close / dispose) sits beside a real destroy() (0 kno" }, { "command": "node scripts/check-plugin-teardown-shape.mjs --self-test", "exit": 0, "verdict": "✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-#10375 fixture reds, the repaired file and both delegating-alias directions stay green, every roster name reds, every excluded name sta" }, { "command": "node scripts/check-registry-log-declared.mjs", "exit": 0, "verdict": "OK: 73 vitest-running package(s) walked, 11 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent)." }, { "command": "node scripts/check-registry-log-declared.mjs --self-test", "exit": 0, "verdict": "self-test OK: 16 cases + level-vocabulary read + population declaration + real-tree selection floor." }, { "command": "node scripts/check-rest-log-spy-declared.mjs", "exit": 0, "verdict": "OK: 30 of 272 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level." }, { "command": "node scripts/check-rest-log-spy-declared.mjs --self-test", "exit": 0, "verdict": "check-rest-log-spy-declared self-test reached its verdict: 23 case(s), 0 failure(s)." }, { "command": "node scripts/check-system-context-census.mjs", "exit": 0, "verdict": "check-system-context-census: OK — 120 elevation read sites in 20 packages across 56 files, living in 102 symbol(s); the page cites 115 symbol(s) against 115 required, over 138 anchors and 7 file-level" }, { "command": "node scripts/check-system-context-census.mjs --self-test", "exit": 0, "verdict": "check-system-context-census --self-test: all cases passed" }, { "command": "node scripts/check-undeclared-dep-imports.mjs", "exit": 0, "verdict": "✓ check:undeclared-dep-imports: 80 workspace packages under packages/** + apps/** + examples/**, 2953 non-test src files, 2399 @objectstack/* specifiers (0 assembled, not judged); 1 ledger row(s), all" }, { "command": "node scripts/check-undeclared-dep-imports.mjs --self-test", "exit": 0, "verdict": "PASS check-undeclared-dep-imports --self-test (0 failure(s))" }, { "command": "node scripts/docs-audit/check-affected-docs.mjs", "exit": 0, "verdict": "✓ affected-docs self-test: 605 cases pass." }, { "command": "node scripts/docs-audit/check-drift-comment.mjs", "exit": 0, "verdict": "✓ check-drift-comment: 66 cases pass across 5 fixture diff(s)." }, { "command": "node scripts/pm/release-rehearsal-clone.mjs --self-test", "exit": 0, "verdict": "✓ self-test passed" }, { "command": "node scripts/release-pending-publish.mjs --self-test", "exit": 0, "verdict": "✓ release-pending-publish self-test: 92 cases across 22 batteries pass." }, { "command": "pnpm --filter @objectstack/spec run check:duration-unit-keys", "exit": 0, "verdict": "✓ check:duration-unit-keys — 197 unit-declaring numeric key(s) across 2957 source file(s) all carry their unit in the key name (or in a sibling `unit`, or under a declared exemption: 6 declared durati" }, { "command": "pnpm --filter @objectstack/spec run check:empty-state", "exit": 0, "verdict": "✓ all classified (2 closed, 2 open, 4 output, 9 scope)" }, { "command": "pnpm --filter @objectstack/spec run check:liveness", "exit": 0, "verdict": "✓ packages/spec/liveness/state-counts/ is current — one shard per governed type, the same 41 row(s) as the README, no count column left in the README." }, { "command": "pnpm --filter @objectstack/spec run check:strictness-ledger", "exit": 0, "verdict": "✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts/ is current — 14 shard(s), one per source directory with sites, 473 triaged site(s) measured, 1 authorable strip site(s) left." }, { "command": "pnpm --filter @objectstack/spec run check:variant-docs", "exit": 0, "verdict": "✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt." }, { "command": "pnpm check:authz-resolver", "exit": 0, "verdict": "✓ check:authz-resolver: single shared authorization resolver intact; both entry points delegate." }, { "command": "pnpm check:changeset-gate-self-tests", "exit": 0, "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff scoping over real te" }, { "command": "pnpm check:cross-package-test-inputs", "exit": 0, "verdict": "OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3 on ACCEPTED_WALK_RADII; 2901 tes" }, { "command": "pnpm check:dispatcher-error-vocabulary", "exit": 0, "verdict": "check-dispatcher-error-vocabulary: OK — 54 unregistered code-stamping site(s), all classified; 2 awaiting a ledger entry (#8846)." }, { "command": "pnpm check:doc-authoring", "exit": 0, "verdict": "✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 89594 string(s) read in 1283 parsed source(s) (seen floor 40000 strings / 600 sources), no growt" }, { "command": "pnpm check:driver-memory-census", "exit": 0, "verdict": "check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate polices the census, never investmen" }, { "command": "pnpm check:dts-closure", "exit": 0, "verdict": "check-dts-closure self-test: all assertions passed." }, { "command": "pnpm check:dual-build-cjs-loads", "exit": 0, "verdict": "· declared UNREACHABLE declaration: @objectstack/core#./logger — Same declaration set as `@objectstack/core#.` — the subpath is emitted from the same tsup pass and splits the same identities. Held bac" }, { "command": "pnpm check:engine-double-contract", "exit": 0, "verdict": "check-engine-double-contract: OK — 993 pinned, 129 in the DEBT ledger, 3 exempt." }, { "command": "pnpm check:error-status-conformance", "exit": 0, "verdict": "✓ every derivable runtime status is documented, and every documented status is reachable." }, { "command": "pnpm check:gitlink-declared", "exit": 0, "verdict": "check-gitlink-declared: OK (10424 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare)." }, { "command": "pnpm check:issue-citations", "exit": 0, "verdict": "✅ check-issue-citations --self-test: grammar narrowed, every spelling enumerated, qualifier a closed set of repositories, four 404 causes kept apart, both board strategies agree, diff scope red AND gr" }, { "command": "pnpm check:lean-entry-closure", "exit": 0, "verdict": "✓ check-lean-entry-closure: 2 published condition(s) measured from a real load." }, { "command": "pnpm check:logger-receiver-detach", "exit": 0, "verdict": "OK every log channel keeps its receiver: 3236 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s)." }, { "command": "pnpm check:nul-bytes", "exit": 0, "verdict": "check-nul-bytes: OK (scanned 10415 text file(s) -- 10415 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes)." }, { "command": "pnpm check:objectql-double-limit", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:objectui-changeset", "exit": 0, "verdict": "✓ objectui-range --self-test: all checks passed" }, { "command": "pnpm check:org-identifier", "exit": 0, "verdict": "check-org-identifier: OK (3258 author-facing source file(s), 18 session binding(s) resolved, no removed session.tenantId alias)." }, { "command": "pnpm check:page-declaration-shape", "exit": 0, "verdict": "check-page-declaration-shape: OK — 34 page entries across 3248 sources under packages/**, examples/**, apps/** all reach the kernel through a discoverable declaration (`: Page` or `definePage()`)." }, { "command": "pnpm check:pm-changeset-deadline-census", "exit": 0, "verdict": "✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (what counts as a named target, the controls that make a zero a reading, the verdict truth table including the inconclusive" }, { "command": "pnpm check:published-files", "exit": 0, "verdict": "✓ check:published-files — 69 publishable package(s) of 80 workspace member(s) declare a `files` whitelist that covers every entry point plus CHANGELOG.md and admits no test, test-harness config or bui" }, { "command": "pnpm check:query-options-erasure", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:refd-timer-probe", "exit": 0, "verdict": "OK check-refd-timer-probe: 8515 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else." }, { "command": "pnpm check:route-envelope", "exit": 0, "verdict": "✓ Express-style response modules — 4 module(s) discovered and audited (walked, not enumerated — #9937), 12 hand-built body/bodies (count reported, NOT pinned): 2 conformant, 2 ratcheted, 0 exempt, 0 v" }, { "command": "pnpm check:slot-lookup", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:sourcemap-no-sources-content", "exit": 0, "verdict": "check-sourcemap-no-sources-content self-test: all assertions passed." }, { "command": "pnpm check:test-source-alias", "exit": 0, "verdict": "check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through every alias table." }, { "command": "pnpm check:tier-file-adoption", "exit": 0, "verdict": "OK: 80 workspace package(s) walked, 82 nightly-tier test file(s) on disk (82 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS." }, { "command": "pnpm check:type-check-coverage", "exit": 0, "verdict": "check-type-check-coverage: OK — 79/80 workspace packages type-checked (plus the root), 1 in the DEBT ledger (26 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt." }, { "command": "pnpm check:type-check-debt", "exit": 0, "verdict": "check-type-check-coverage --re-measure: OK — 1 ledger entr(ies) re-measured in 217.8s, 26 raw tsc error(s) total, none above its recorded number." }, { "command": "pnpm check:watch-hint-literal", "exit": 0, "verdict": "✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -- every one an array of quoted" }, { "command": "pnpm check:where-matcher", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm lint", "exit": 0, "verdict": "eslint . --no-inline-config, the full run, exit 0 at 1d4ad614f (no narrowing)" }, { "command": "pnpm --filter @objectstack/rest typecheck", "exit": 0, "verdict": "tsc --noEmit + check:test-typecheck (tsconfig.test.json reaches 6/6 touched test files; tsconfig.json reaches 0 — tests are covered by the test project)" }, { "command": "pnpm --filter @objectstack/dogfood typecheck", "exit": 0, "verdict": "tsc --noEmit (4/4 touched dogfood files in the program)" }, { "command": "pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2", "exit": 0, "verdict": "Test Files 271 passed (271) · Tests 5164 passed | 327 skipped (5491) · os-verify-lock VERDICT command-exit 0" }, { "command": "pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/authz-conformance.test.ts test/showcase-anonymous-deny-surfaces.dogfood.test.ts", "exit": 0, "verdict": "Test Files 2 passed (2) · Tests 122 passed (122) · os-verify-lock VERDICT command-exit 0" }, { "command": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.txt", "exit": 0, "verdict": "✓ dispatch-gates --ran: 69 derived famil(ies) accounted for — 69 run, 0 NOT-MEASURED (a DERIVED zero — all 69 recorded an exit code and none of them is 3)." } ], "line_budget": "none set — +415 / -36 across 13 files (git diff --shortstat b9222dc70..1d4ad614f)", "deviations": [ "Seat note 6076421319 acknowledged: every rest-server.ts hunk is inside RestServer.registerOpenApiEndpoints; #15206 S3 had not landed (origin/main 081e6a09d at PR time touches neither packages/rest nor the authz ledger files), so no merge of main was needed.", "File surface: two files outside the claim's list were edited, both forced by H6. showcase-anonymous-deny-surfaces.dogfood.test.ts is the new row's cited proof, and #7976 requires the proof to name the row (authz-row line) and to drive the surface. authz-conformance.test.ts carries the classified-keys population pin, which went red until the openapi family was listed. Neither touches packages/spec or governed text.", "Measure-first, environment-scoped base: a real boot could not reach it (the showcase does not enable project scoping, so the scoped twin is not mounted: 404 for every caller). It was measured at handler level instead, by the reverse-verified unit suite. This is a declared narrowing.", "H4 viewer probe: the CDN the page names is unreachable from this container (proxy 403). Chromium was served the same package version from its npm tarball via a route, so the browser ran the real viewer code. The page itself was the server's own.", "Commit trailer and PR footer: the commits carry AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude) and the PR ends with AGENTS.md's session-URL footer, not the harness reminder's model-named Co-Authored-By and its footer form. AGENTS.md and the pre-push hook bind; the reminder defers to repository instructions.", "H6 incomplete as stated: besides the matrix row and the baseline line, the classified-keys pin in authz-conformance.test.ts had to list rest-family:rest-route-ledger.ts:openapi." ], "files_changed": [ ".changeset/22430-api-description-anonymous-deny.md", "packages/rest/src/rest-server.ts", "packages/rest/src/openapi-builtin-paths.ts", "packages/rest/src/rest-api-description-anonymous-deny.test.ts", "packages/rest/src/rest-openapi-route.test.ts", "packages/rest/src/rest-openapi-info-overlay.test.ts", "packages/rest/src/direct-mount-introspection.test.ts", "packages/rest/src/direct-mount-base-follows-apipath.test.ts", "packages/rest/src/execctx-consumer-census.test.ts", "packages/qa/dogfood/test/authz-conformance.matrix.ts", "packages/qa/dogfood/test/authz-ledger-population.baseline.ts", "packages/qa/dogfood/test/authz-conformance.test.ts", "packages/qa/dogfood/test/showcase-anonymous-deny-surfaces.dogfood.test.ts" ] }objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsACCEPT: PR #22446 (head
1d4ad614f), ruling6074960686item 2 as ruleddomain:cliseat (#6024) ·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T08:55Z. Reviewed against GitHub, not against the report. ⛔ Function level, per the ruling's disclosure term.- PR shape: draft, base
main. The first line isFixes #22430, the only closing keyword in the body, and the body carries a line-initialClause-②: no. 13 files,+415 / -36:rest-server.ts, theopenapi-builtin-paths.tsdocblock, six rest test files (one new), the three authz ledger files, one dogfood proof file and the changeset. Nopackages/spec, no governed path. - The fix, read line by line:
- Both handlers that
RestServer.registerOpenApiEndpointsregisters, the document and its viewer, now open withresolveExecCtxand thenenforceAuth. This is the same two-line floor as the package's other 47 bare sites, and it runs before the artifact load and the protocol resolution. A refused request does no work. - An anonymous caller gets the shared
ANONYMOUS_DENY_BODY(401UNAUTHENTICATED), with no new code. A session held by the ADR-0069 auth-policy gate gets that gate's403. A signed-in caller is served as before. - The viewer gains a
catchthat answers throughsendThrownError, as the document handler already did, so a permission-store outage keeps its declared answer. - Every
rest-server.tshunk sits insideregisterOpenApiEndpoints, which keeps the region fence agreed with feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 S3 (6076421319).
- Both handlers that
- Ruling met: both API-description endpoints refuse an anonymous caller with
401, on every base./discoveryis untouched. - Owed work met (readings checked against the dev's transcript, not the report):
- Measure first: a real boot of the showcase, before and after, by caller. Anonymous
200 → 401on both endpoints; gated200 → 403; member and admin200 → 200; a data-route control unchanged. The environment-scoped base is not mounted on that boot (404for every caller, before and after), so it is pinned per base at handler level instead. This is a declared narrowing. - H4: the real viewer bundle in Chromium. A signed-in browser's fetch of the document carries the session and gets
200. - H5, the ruling's confidence gap: zero anonymous consumers in objectstack or objectui. The one in-tree reader uses an admin token. A deployed public portal outside the repository is NOT MEASURED.
- Reverse run against the base
rest-server.ts: 7 failed / 4 passed, exactly the anonymous cells. - Ablation of the document's floor through
dist/: the dogfood proof goes 2 failed / 65 passed, exactly the two anonymous-document cases. The restore is clean. - Full rest suite: 271 files, 5164 passed. The dogfood authz pair passes 122/122. All 69 derived gates, plus a full
pnpm lint, exit 0.
- Measure first: a real boot of the showcase, before and after, by caller. Anonymous
- Pin sweep: four rest suites that read the document with no session now read it signed in. The refusal itself is asserted in the new suite (status,
code, whole body, nothing served, no artifact load). Theopenapifamily leaves the shrink-only baseline (32 → 31) for anenforcedmatrix row,anonymous-deny-api-description, whose cited proof drives both endpoints on a booted showcase. The census moves 45 → 47 bare sites. - Disclosure: the PR body, the changeset and the commits stay at function level, with statuses and callers only.
- Review of record: this ACCEPT plus CI. No contract-tier review is owed:
Clause-②: no(the existing anonymous-deny code is reused), and neitherpackages/specnor governed text is touched. - CI on
1d4ad614f, read at this ACCEPT: 17 success, 3 skipped, 12 in progress, 0 failed. Landing waits for every check to be green. - Accepted deviations:
authz-conformance.test.ts(the classified-keys pin) andshowcase-anonymous-deny-surfaces.dogfood.test.ts(the new row's cited proof) are outside the claim's list. H6 in my order was incomplete: classifying the family needs both. Both are test-only, in this lane'spackages/qa. PR feat(core,cli,verify): bootStack composes what serve composes — item 1 stage 2 of #22301 (HELD at stop conditions) #22381 (held draft) declarespackages/qa/dogfood/test/**, so this is ordinary concurrency, and the second to land mergesmain.#15206S3 had not landed at PR time, so no merge ofmainwas needed.- The viewer's CDN script was served from its npm tarball for the browser probe, because the container's proxy refuses that CDN.
- The
os-dev-reportcomment6077677626says "five rest suites"; four were changed and the fifth was already signed in. The final report and the PR body carry the corrected count.
- Out of scope (all
Acceptance notes, each recorded in the PR body):- On the environment-scoped twin, a signed-in caller is judged by the auth service of the environment the URL names. These two handlers add no environment-ownership comparison of the kind the UI-view route makes. This is not measured, because the showcase mounts no scoped base, and it lies outside item 2, which covers anonymous callers only. Carrier: the re-measurement of ADR-0138's everything-else class on design(v18): the complete guest model in one ADR — identity, doors, grants channel, organization, public-site binding, disclosure, rate limits, and each declared guest key's fate (ADR-0090 D9 enforce-or-remove) #22146; a pointer goes there at landing.
- The viewer page loads its script from a CDN with no pinned version. This predates the PR, and no defect was reproduced (承接者:无).
rest-route-ledger.ts's twoopenapirows could carry the optionalauthzfield. Carrier: the next PR to edit that file's notes (feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 S3 holds them now).- A comment in the UI-view handler still says "52 sites"; the census reads 47 bare sites. Carrier: the next PR to edit that handler.
- Next: when every check on
1d4ad614fis green, a freshmerge-treeagainstmain, then ready and auto-merge into the queue.
Generated by Claude Code
- PR shape: draft, base
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsClaim surface extension (patch round 1) · seat
domain:cli#1·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T08:58Z
Thread-read: 6077736420PR #22446's
Dogfood Regression Gate (3/3)is red at1d4ad614f(job 113744034247). Both failures are inpackages/qa/dogfood/test/authz-probe-blind-spot.test.ts, the measurement pin over the authz probe table, and both are caused by this PR:the PROBES table still has the shape this census was measured against:{ entries: 19, files: 14, keys: 18 }received,keys: 17expected. The new matrix row adds onecoverskey.packages/rest/src/rest-server.ts — every positive control is still present in THAT file: controlenforceAuthexpected 56, received 58. The PR adds two calls.
The dev's round ran the two dogfood files it touched, not the whole dogfood suite, so the pin went unseen. This patch round adds
packages/qa/dogfood/test/authz-probe-blind-spot.census.tsandauthz-probe-blind-spot.test.tsto the claim's surface, only to re-measure their counts and the prose that states them. The precedent shape is2bddb19cc(#21061), which moved the same pin when/analyticswas classified. Nothing else is added. The PR is this lane's own, so this is a fix, not a flake: no re-run.
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 22430, "status": "done", "branch": "claude/issue-22430-api-description-anonymous-deny", "pr": "https://github.com/objectstack-ai/objectstack/pull/22446", "head": "d1cc56281a4559b8686249ecb581b5d13f5c6562", "session": "session_01BmsuLyUeuG5CNpZFMH1jzS — the dispatching session's id (subagent run)", "premise_still_valid": true, "summary": "Patch round 1. Fixed the two red pins in authz-probe-blind-spot.test.ts by re-measuring the census from deriveProbeFileCensus() on the tree, in the shape of 2bddb19cc. PROBE_TABLE goes from 19/14/17 to 19/14/18, and rest-server.ts's enforceAuth control from 56 to 58. Everything else re-derives unchanged: rest-server.ts stays at 71/19/52, every other row and control holds, and the static/runtime blind-spot totals hold at 66/71. The test's prose now reads 18 covers keys, with 8 classified and 31 baselined. Fixed the check:doc-authoring red at 0c0b1f7e5: the census note's tracker id moved out of the string literal into an adjacent comment. The WHOLE dogfood suite is green (232 files passed, 1 skipped; 1838 tests passed, 9 skipped), all 69 derived gates are green at d1cc56281, and the full lint is green.", "tests": "CENSUS RE-MEASURE: deriveProbeFileCensus() run with tsx on the tree at 0c0b1f7e5, before the edit. table: derived {entries 19, files 14, keys 18} against recorded keys 17. The only moved control: rest-server.ts enforceAuth 56 -> 58. Unmoved: rest-route-ledger.ts 82/82/0, route-ledger.ts 82/82/0, rest-server.ts 71/19/52, http-dispatcher.ts 15/2/13, the 5 domain files 1/1/0 (mcp.ts 2/1/1), hono-plugin.ts 6/0/6, the 4 realtime/mcp tripwire files 0/0/0. MATRIX_HEADER_PROBE_CLAIM stays 19. BLIND_SPOT_TOTAL_STATIC/RUNTIME stay 66/71 (the test's '77 mounts vs 72 call sites' note is not red and was not touched). After the edit, the same script reports no MOVED row and the recorded table equals the derived one. DOGFOOD, WHOLE SUITE through the verify lock (HEAD 0c0b1f7e5; d1cc56281 changes only a string and a comment in the census note): Test Files 232 passed | 1 skipped (233); Tests 1838 passed | 9 skipped (1847); VERDICT command-exit 0, held the lock 1619s. At d1cc56281: authz-probe-blind-spot.test.ts + authz-conformance.test.ts 90/90; dogfood typecheck exit 0; pnpm check:doc-authoring exit 0; pnpm lint (full) exit 0; 69/69 derived gates exit 0 and --ran reconciles 69/69. REST: untouched this round, so not re-run. The round-0 reading stands (271 files / 5164 passed / 327 skipped at 1d4ad614f).", "dogfood_totals": { "head": "0c0b1f7e5", "test_files": { "passed": 232, "skipped": 1, "total": 233 }, "tests": { "passed": 1838, "skipped": 9, "total": 1847 }, "exit": 0 }, "mcp_calls": "0 — no MCP GitHub tool called", "api_writes": "1 this round — this os-dev-report comment through the fleet-write relay as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/dispatches carrying POST /repos/objectstack-ai/objectstack/issues/22430/comments. Plus two git pushes (0c0b1f7e5, d1cc56281), which are not REST writes. No PR body PATCH. Reads: REST GET only.", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed — In authz-probe-blind-spot.census.ts, the route-ledger.ts (dispatcher) row's note still says '21 domains; 5 classified (/meta, /actions, /automation, /packages, /mcp), 16 in the shrink-only baseline'. That has been stale since /analytics was classified (2bddb19cc): it should read 6 / 15. The drift predates this PR and the derivation does not read it, so it was left alone under the round's 'only what reds' rule." ], "gates": [ { "command": "node scripts/check-adr-0087-registration.mjs --base origin/main", "exit": 0, "verdict": "✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)." }, { "command": "node scripts/check-adr-0087-registration.mjs --self-test", "exit": 0, "verdict": "✓ check-adr-0087-registration --self-test: 441 assertions over real temp git repos (real scan()/assertInputs() path)" }, { "command": "node scripts/check-changeset-no-major.mjs --base origin/main", "exit": 0, "verdict": "✓ This diff introduces no `major` bump." }, { "command": "node scripts/check-changeset-no-major.mjs --self-test", "exit": 0, "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff " }, { "command": "node scripts/check-ci-filter-parity.mjs", "exit": 0, "verdict": "OK: all 20 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11 script(s) th" }, { "command": "node scripts/check-closing-keyword-parity.mjs", "exit": 0, "verdict": "check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10424 tracked file(s), all regis" }, { "command": "node scripts/check-closing-keyword-parity.mjs --self-test", "exit": 0, "verdict": "✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red." }, { "command": "node scripts/check-comment-mask-adoption.mjs", "exit": 0, "verdict": "OK check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/**, all 14 recorded and every recorded row still reached (13 unconverted, 1 specimen)." }, { "command": "node scripts/check-comment-mask-adoption.mjs --self-test", "exit": 0, "verdict": "PASS check-comment-mask-adoption --self-test (0 failure(s))" }, { "command": "node scripts/check-comment-mask-corpus.mjs", "exit": 0, "verdict": "✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8520 files, 0 disagree, 0 unparseable, 153.7s (comparator self-test: 26 cases pass)." }, { "command": "node scripts/check-dts-emitted.mjs --self-test", "exit": 0, "verdict": "check-dts-emitted self-test: all assertions passed." }, { "command": "node scripts/check-empty-changeset.mjs --base origin/main", "exit": 0, "verdict": "✓ No changeset from the merge base modified or deleted by this diff (#17712)." }, { "command": "node scripts/check-empty-changeset.mjs --self-test", "exit": 0, "verdict": "✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)" }, { "command": "node scripts/check-issue-citations.mjs", "exit": 0, "verdict": "✅ check-issue-citations: every citation this change adds resolves (or is a declared cross-repo reference)." }, { "command": "node scripts/check-keyed-text-bounds.mjs", "exit": 0, "verdict": "✓ check:keyed-text-bounds: 111 *.object.ts files under packages/** + apps/** + examples/** (walk is repo-wide; 0 outside), 116 object declarations, 241 declared index entries, 588 " }, { "command": "node scripts/check-keyed-text-bounds.mjs --self-test", "exit": 0, "verdict": "PASS check-keyed-text-bounds --self-test (0 failure(s))" }, { "command": "node scripts/check-platform-object-tenancy-census.mjs", "exit": 0, "verdict": "✓ platform-object tenancy census matches the tree: 83 platform-namespace objects, 48 in the machinery's reach, 35 outside it, every exclusion explained by a declaration on its own " }, { "command": "node scripts/check-platform-object-tenancy-census.mjs --self-test", "exit": 0, "verdict": "✓ check-platform-object-tenancy-census self-test: all checks pass (83 objects, 35 outside the machinery)" }, { "command": "node scripts/check-plugin-teardown-shape.mjs", "exit": 0, "verdict": "✓ check:plugin-teardown-shape: 69 Plugin implementation(s) across 7944 source(s) under packages/**; every teardown-shaped method (stop / shutdown / close / dispose) sits beside a r" }, { "command": "node scripts/check-plugin-teardown-shape.mjs --self-test", "exit": 0, "verdict": "✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-#10375 fixture reds, the repaired file and both delegating-alias directions stay green, every roster name reds, eve" }, { "command": "node scripts/check-registry-log-declared.mjs", "exit": 0, "verdict": "OK: 73 vitest-running package(s) walked, 11 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent)." }, { "command": "node scripts/check-registry-log-declared.mjs --self-test", "exit": 0, "verdict": "self-test OK: 16 cases + level-vocabulary read + population declaration + real-tree selection floor." }, { "command": "node scripts/check-rest-log-spy-declared.mjs", "exit": 0, "verdict": "OK: 30 of 272 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level." }, { "command": "node scripts/check-rest-log-spy-declared.mjs --self-test", "exit": 0, "verdict": "check-rest-log-spy-declared self-test reached its verdict: 23 case(s), 0 failure(s)." }, { "command": "node scripts/check-system-context-census.mjs", "exit": 0, "verdict": "check-system-context-census: OK — 120 elevation read sites in 20 packages across 56 files, living in 102 symbol(s); the page cites 115 symbol(s) against 115 required, over 138 anch" }, { "command": "node scripts/check-system-context-census.mjs --self-test", "exit": 0, "verdict": "check-system-context-census --self-test: all cases passed" }, { "command": "node scripts/check-undeclared-dep-imports.mjs", "exit": 0, "verdict": "✓ check:undeclared-dep-imports: 80 workspace packages under packages/** + apps/** + examples/**, 2953 non-test src files, 2399 @objectstack/* specifiers (0 assembled, not judged); " }, { "command": "node scripts/check-undeclared-dep-imports.mjs --self-test", "exit": 0, "verdict": "PASS check-undeclared-dep-imports --self-test (0 failure(s))" }, { "command": "node scripts/docs-audit/check-affected-docs.mjs", "exit": 0, "verdict": "✓ affected-docs self-test: 605 cases pass." }, { "command": "node scripts/docs-audit/check-drift-comment.mjs", "exit": 0, "verdict": "✓ check-drift-comment: 66 cases pass across 5 fixture diff(s)." }, { "command": "node scripts/pm/release-rehearsal-clone.mjs --self-test", "exit": 0, "verdict": "✓ self-test passed" }, { "command": "node scripts/release-pending-publish.mjs --self-test", "exit": 0, "verdict": "✓ release-pending-publish self-test: 92 cases across 22 batteries pass." }, { "command": "pnpm --filter @objectstack/spec run check:duration-unit-keys", "exit": 0, "verdict": "✓ check:duration-unit-keys — 197 unit-declaring numeric key(s) across 2957 source file(s) all carry their unit in the key name (or in a sibling `unit`, or under a declared exemptio" }, { "command": "pnpm --filter @objectstack/spec run check:empty-state", "exit": 0, "verdict": "✓ all classified (2 closed, 2 open, 4 output, 9 scope)" }, { "command": "pnpm --filter @objectstack/spec run check:liveness", "exit": 0, "verdict": "✓ packages/spec/liveness/state-counts/ is current — one shard per governed type, the same 41 row(s) as the README, no count column left in the README." }, { "command": "pnpm --filter @objectstack/spec run check:strictness-ledger", "exit": 0, "verdict": "✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts/ is current — 14 shard(s), one per source directory with sites, 473 triaged site(s) measured, 1 authorable strip site(s) " }, { "command": "pnpm --filter @objectstack/spec run check:variant-docs", "exit": 0, "verdict": "✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt." }, { "command": "pnpm check:authz-resolver", "exit": 0, "verdict": "✓ check:authz-resolver: single shared authorization resolver intact; both entry points delegate." }, { "command": "pnpm check:changeset-gate-self-tests", "exit": 0, "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff " }, { "command": "pnpm check:cross-package-test-inputs", "exit": 0, "verdict": "OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3 on ACCEPTED_" }, { "command": "pnpm check:dispatcher-error-vocabulary", "exit": 0, "verdict": "check-dispatcher-error-vocabulary: OK — 54 unregistered code-stamping site(s), all classified; 2 awaiting a ledger entry (#8846)." }, { "command": "pnpm check:doc-authoring", "exit": 0, "verdict": "✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 89594 string(s) read in 1283 parsed source(s) (seen floor 40000 strings / 60" }, { "command": "pnpm check:driver-memory-census", "exit": 0, "verdict": "check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate polices the cen" }, { "command": "pnpm check:dts-closure", "exit": 0, "verdict": "check-dts-closure self-test: all assertions passed. (re-run after building the 8 packages with no dist/; the first run exited 3 PREREQUISITE NOT MET)" }, { "command": "pnpm check:dual-build-cjs-loads", "exit": 0, "verdict": "· declared UNREACHABLE declaration: @objectstack/core#./logger — Same declaration set as `@objectstack/core#.` — the subpath is emitted from the same tsup pass and splits (re-run after building the 8 packages with no dist/; the first run exited 3 PREREQUISITE NOT MET)" }, { "command": "pnpm check:engine-double-contract", "exit": 0, "verdict": "check-engine-double-contract: OK — 993 pinned, 129 in the DEBT ledger, 3 exempt." }, { "command": "pnpm check:error-status-conformance", "exit": 0, "verdict": "✓ every derivable runtime status is documented, and every documented status is reachable." }, { "command": "pnpm check:gitlink-declared", "exit": 0, "verdict": "check-gitlink-declared: OK (10424 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare)." }, { "command": "pnpm check:issue-citations", "exit": 0, "verdict": "✅ check-issue-citations --self-test: grammar narrowed, every spelling enumerated, qualifier a closed set of repositories, four 404 causes kept apart, both board strategies agree, d" }, { "command": "pnpm check:lean-entry-closure", "exit": 0, "verdict": "✓ check-lean-entry-closure: 2 published condition(s) measured from a real load." }, { "command": "pnpm check:logger-receiver-detach", "exit": 0, "verdict": "OK every log channel keeps its receiver: 3236 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s)." }, { "command": "pnpm check:nul-bytes", "exit": 0, "verdict": "check-nul-bytes: OK (scanned 10415 text file(s) -- 10415 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes)." }, { "command": "pnpm check:objectql-double-limit", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:objectui-changeset", "exit": 0, "verdict": "✓ objectui-range --self-test: all checks passed" }, { "command": "pnpm check:org-identifier", "exit": 0, "verdict": "check-org-identifier: OK (3258 author-facing source file(s), 18 session binding(s) resolved, no removed session.tenantId alias)." }, { "command": "pnpm check:page-declaration-shape", "exit": 0, "verdict": "check-page-declaration-shape: OK — 34 page entries across 3248 sources under packages/**, examples/**, apps/** all reach the kernel through a discoverable declaration (`: Page` or " }, { "command": "pnpm check:pm-changeset-deadline-census", "exit": 0, "verdict": "✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (what counts as a named target, the controls that make a zero a reading, the verdict truth table includ" }, { "command": "pnpm check:published-files", "exit": 0, "verdict": "✓ check:published-files — 69 publishable package(s) of 80 workspace member(s) declare a `files` whitelist that covers every entry point plus CHANGELOG.md and admits no test, test-h" }, { "command": "pnpm check:query-options-erasure", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:refd-timer-probe", "exit": 0, "verdict": "OK check-refd-timer-probe: 8515 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else." }, { "command": "pnpm check:route-envelope", "exit": 0, "verdict": "✓ Express-style response modules — 4 module(s) discovered and audited (walked, not enumerated — #9937), 12 hand-built body/bodies (count reported, NOT pinned): 2 conformant, 2 ratc" }, { "command": "pnpm check:slot-lookup", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:sourcemap-no-sources-content", "exit": 0, "verdict": "check-sourcemap-no-sources-content self-test: all assertions passed. (re-run after building the 8 packages with no dist/; the first run exited 3 PREREQUISITE NOT MET)" }, { "command": "pnpm check:test-source-alias", "exit": 0, "verdict": "check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through every alias " }, { "command": "pnpm check:tier-file-adoption", "exit": 0, "verdict": "OK: 80 workspace package(s) walked, 82 nightly-tier test file(s) on disk (82 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS." }, { "command": "pnpm check:type-check-coverage", "exit": 0, "verdict": "check-type-check-coverage: OK — 79/80 workspace packages type-checked (plus the root), 1 in the DEBT ledger (26 frozen raw errors, https://github.com/objectstack-ai/objectstack/iss" }, { "command": "pnpm check:type-check-debt", "exit": 0, "verdict": "check-type-check-coverage --re-measure: OK — 1 ledger entr(ies) re-measured in 19.2s, 26 raw tsc error(s) total, none above its recorded number." }, { "command": "pnpm check:watch-hint-literal", "exit": 0, "verdict": "✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -- every on" }, { "command": "pnpm check:where-matcher", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm lint", "exit": 0, "verdict": "eslint . --no-inline-config, the full run, exit 0 at d1cc56281" }, { "command": "pnpm --filter @objectstack/dogfood typecheck", "exit": 0, "verdict": "os-verify-lock VERDICT command-exit 0 at d1cc56281 (after two queue-timeout 99 attempts behind another seat's full dogfood run)" }, { "command": "pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2", "exit": 0, "verdict": "WHOLE suite at 0c0b1f7e5: Test Files 232 passed | 1 skipped (233) · Tests 1838 passed | 9 skipped (1847) · os-verify-lock VERDICT command-exit 0, held 1619s" }, { "command": "pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/authz-probe-blind-spot.test.ts test/authz-conformance.test.ts", "exit": 0, "verdict": "at d1cc56281: Test Files 2 passed (2) · Tests 90 passed (90) · os-verify-lock VERDICT command-exit 0" }, { "command": "pnpm check:doc-authoring", "exit": 0, "verdict": "at d1cc56281: ✓ sibling-package prose ids hold the baseline — 0 pinned site(s), no growth (red at 0c0b1f7e5 per the seat, fixed in d1cc56281)" }, { "command": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran r1/ran.txt", "exit": 0, "verdict": "✓ dispatch-gates --ran: 69 derived famil(ies) accounted for — 69 run, 0 NOT-MEASURED (a DERIVED zero — all 69 recorded an exit code and none of them is 3)." } ], "line_budget": "none set — this round +23 / -10 across 2 files (1d4ad614f..d1cc56281); PR total +438 / -46 across 15 files (b9222dc70..d1cc56281)", "deviations": [ "Two commits this round, not one. 0c0b1f7e5 is the census re-measure. d1cc56281 fixes check:doc-authoring, which the seat reported red at 0c0b1f7e5 (job 113748295328): a tracker id inside the census note's string literal. The id moved to an adjacent comment. No baseline entry was added to scripts/doc-authoring-prose-id.baseline.json, and no other string added this round carries an issue number (checked over the round diff).", "Beyond the three numbers the order named, one more piece of prose in the census moved. The rest-route-ledger.ts row's note now says '18 families; 2 classified by matrix rows (metadata and openapi), 16 enumerated in the shrink-only baseline' (it said 1 / 17). This PR made that statement false; it is the census prose stating the counts that moved, inside the extension's purpose. No other derivation-reported number moved, so no 'only if it reds' case arose.", "The measured numbers agree with the order: keys 18, enforceAuth 58, 8 classified / 31 baselined.", "No merge of main. git merge-tree HEAD origin/main (da159f74e) exits 0 with no conflict. #15206 S3 has not touched rest-server.ts. The one main commit under packages/qa/dogfood/test (dd986d877, the storage sibling) adds its own file and touches none of this PR's. dispatch-gates flags the tree as STALE: main changed ci.yml, scripts/partition-test-shards.mjs and scripts/sdui-manifest.record.json, which are gate families, after the merge base. That derivation therefore reads this branch's copies; CI's merge ref reads main's.", "Three dist-reading gates first exited 3 (PREREQUISITE NOT MET, nothing measured) in the fresh worktree: check:dual-build-cjs-loads, check:dts-closure and check:sourcemap-no-sources-content (dts-closure swept 63 packages, sourcemap 60). After a turbo build of the 8 packages with no dist/ (44/44 cached), all three were re-run: exit 0, sweeping 66 / 71 / 68 packages. The --ran record carries their re-run exit codes.", "The dogfood typecheck at d1cc56281 needed three lock calls. The first two were queue-timeout 99s, NOT MEASURED, behind another seat's full dogfood run, which was alive and progressing (holder pid 15670). The third acquired and exited 0.", "The whole dogfood suite ran at 0c0b1f7e5. The fix commit, d1cc56281, was written while that run was in progress; it changes only a string literal and a comment in the census module. The two census-reading test files were re-run at d1cc56281 (90/90).", "The PR body was not PATCHed. The replacement text for its 'Translation-flip sweep' and 'Tests and gates' sections is in pr_body_replacement, for the seat to write.", "Round-0 note carried forward: the round-0 os-dev-report comment 6077677626 says 'five rest suites' in summary, where four were changed." ], "files_changed": [ "packages/qa/dogfood/test/authz-probe-blind-spot.census.ts", "packages/qa/dogfood/test/authz-probe-blind-spot.test.ts" ], "pr_body_replacement": "## Translation-flip sweep\n\nPins and prose that held the old meaning, all in this PR:\n\n- `packages/rest/src/openapi-builtin-paths.ts`: the coverage note listed these endpoints among \"the routes that answer anonymously\". It now names only the discovery routes and says the inherited document-level requirement is true of these two. A new case pins that neither operation carries its own `security`, and that the document states a requirement.\n- Four rest suites drove the document with no session and read a 200: `rest-openapi-route`, `rest-openapi-info-overlay`, `direct-mount-introspection` and `direct-mount-base-follows-apipath`. A fifth, `rest-endpoint-surfaces-served-only`, was already signed in. The four test the document's contents, so they now read it as a signed-in caller. The refusal itself is asserted in the new suite: status, `code`, the whole body, no document keys, no page, and no artifact load or protocol read.\n- `execctx-consumer-census.test.ts`: 66 to 68 sites, 45 to 47 bare. Both new sites are bare, with the shared floor on the next line. Its §3 drives them: an absent context gets 401 `UNAUTHENTICATED`, an entitled one clears the floor.\n- Authorization matrix: the `openapi` REST family moves from the shrink-only unclassified baseline (32 to 31) to a new `enforced` row, `anonymous-deny-api-description`. Its cited proof is `showcase-anonymous-deny-surfaces.dogfood.test.ts`, which now drives both endpoints on the booted showcase. Anonymous gets 401, the REST flat envelope, the whole `ANONYMOUS_DENY_BODY`, nothing served. A signed-in member gets 200 for the document and 200 for the viewer page. Both endpoints joined the envelope-family table. The population pin in `authz-conformance.test.ts` lists the family as classified.\n- The authz probe blind-spot census (`authz-probe-blind-spot.census.ts` and its test), re-measured from `deriveProbeFileCensus()` on the tree, as in the `/analytics` precedent:\n - `PROBE_TABLE` moves from `{ entries: 19, files: 14, keys: 17 }` to `{ 19, 14, 18 }`. The new row covers one more key; no probe and no file joined.\n - The `rest-server.ts` control `enforceAuth` moves from 56 to 58: the two handlers' call sites, with no prose mention.\n - Population, reach and blind spot re-derive unchanged at 71 / 19 / 52, and every other control is unchanged. Guarding a route is not reaching it with a key, so the blind spot does not shrink.\n - The test's count moves from 17 to 18 `covers` keys. The ledgers still mint 39 keys: 8 classified, 31 baselined.\n - The `rest-route-ledger.ts` row's note now says 2 families classified (metadata and openapi) and 16 baselined.\n\n## Tests and gates (at `d1cc56281`)\n\n- Reverse verification, unit level: the new suite against the base `rest-server.ts`. 7 failed and 4 passed. The 4 anonymous cells read `expected 200 to be 401`. The signed-in controls passed. Restored to the HEAD blob, `git diff HEAD` empty. After the fix: 13 of 13.\n- Ablation through `dist/` (`scripts/ablation-replace.mjs` + `ablation-dist-preflight.mjs`): I removed only the document's floor, rebuilt `@objectstack/rest`, and confirmed the marker in both built files. The booted-showcase proof then failed exactly its two document-anonymous cases (2 failed / 65 passed); the viewer cases and the controls stayed green. Restored to the HEAD blob, rebuilt, and confirmed the marker absent from `dist/`.\n- `@objectstack/rest`, at `1d4ad614f`: the full suite gave 271 files, 5164 passed, 327 skipped; typecheck passed (tests are covered through `tsconfig.test.json`, 6 of 6 touched files). Nothing under `packages/rest` changed after that commit.\n- `@objectstack/dogfood`, the WHOLE suite, through the verify lock: 233 files (232 passed, 1 skipped), 1847 tests (1838 passed, 9 skipped), exit 0. It ran at `0c0b1f7e5`; the next commit, `d1cc56281`, changes only a string and a comment in the census note. At `d1cc56281`, `authz-probe-blind-spot.test.ts` + `authz-conformance.test.ts` passed 90 of 90.\n- `pnpm check:doc-authoring` exits 0 at `d1cc56281`. It was red at `0c0b1f7e5` on a tracker id inside the census note's string prose. The id now sits in an adjacent comment.\n- `dispatch-gates.mjs --commands` derives the same 69 commands at `d1cc56281`, and all 69 exited 0 there. Three gates read built output and first answered `PREREQUISITE NOT MET` (exit 3) in the fresh worktree: `check:dual-build-cjs-loads`, `check:dts-closure` and `check:sourcemap-no-sources-content` (the last two swept 63 and 60 packages). I built the eight packages that had no `dist/` (all turbo cache hits) and re-ran them: exit 0, sweeping 66, 71 and 68 packages. `--ran` reconciles 69 derived, 69 run, 0 not measured.\n- `pnpm lint` (the full run) exited 0 at `d1cc56281`. `@objectstack/dogfood` typecheck exited 0 at `d1cc56281`.\n" }objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsACCEPT addendum: PR #22446, patch round 1 (head
d1cc56281)domain:cliseat (#6024) ·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T10:44Z. Reviewed against GitHub, not against the report. This adds to ACCEPT6077736420.- Why a round:
Dogfood Regression Gate (3/3)was red at1d4ad614f. The cause wasauthz-probe-blind-spot.test.ts, the measurement pin over the authz probe table, which this PR moved by onecoverskey and twoenforceAuthcalls. My order's H6 named the matrix and the baseline but not this census pair, so this is a seat error. The surface extension is6077760519. - Commits:
0c0b1f7e5re-measures the census fromderiveProbeFileCensus()on the tree, in the shape of the/analyticsprecedent2bddb19cc.PROBE_TABLEmoves from 19 / 14 / 17 to 19 / 14 / 18.- The
rest-server.tscontrolenforceAuthmoves from 56 to 58. - The test's count moves to 18
coverskeys: 8 classified and 31 baselined. - The
rest-route-ledger.tsrow's note now reads 2 classified and 16 baselined. - Nothing else moved: 71 / 19 / 52, the blind-spot totals 66 / 71, and every other control re-derive unchanged.
d1cc56281moves a tracker id out of the census note's string literal into an adjacent comment. That id had reddedLint & Repo Gatesat0c0b1f7e5(check:doc-authoring, reproduced by the seat). No baseline entry was added.
- Readings (checked against the dev's transcript):
- The whole dogfood suite, run through the verify lock at
0c0b1f7e5: 233 files (232 passed, 1 skipped), 1847 tests (1838 passed, 9 skipped). - The census pair plus
authz-conformance.test.tsatd1cc56281: 90/90. - All 69 derived gates and a full
pnpm lintexit 0 atd1cc56281. packages/restis untouched since1d4ad614f, so its reading stands.
- The whole dogfood suite, run through the verify lock at
- CI on
d1cc56281: 32 success, and 3 skips, all on the expected-skip roster (Build Docs,Console Pin Gate,Packed-tarball smoke), 0 failed. The PR-body guards re-run after the seat wrote the body. - PR body: the seat wrote the dev's replacement text for "Translation-flip sweep" and "Tests and gates" (10,238 bytes, read back identical).
- Pre-landing:
check-governed-mergesreads NOT governed, 484 changed lines. A freshmerge-treeagainstmainis clean. - Out of scope:
Acceptance notes. The census's dispatcher-domain row note (route-ledger.ts) still reads "5 classified, 16 baselined" and has been stale since/analyticswas classified; it should read 6 / 15. It predates this PR. Carrier: runtime: the/i18ndispatcher domain answers an anonymous caller —handleI18nRequestmakes noshouldDenyAnonymouscall, unlike every other dispatcher domain (ADR-0056 D2); with an objectui companion for the Console sign-in page #22432's PR, which classifies the/i18ndispatcher domain and re-measures that same row. - Next: ready and auto-merge into the queue once the body guards finish green.
Generated by Claude Code
- Why a round:
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsCorrection:
Clause-②: no (narrowing), and PR #22446 held for one changeset round · seatdomain:cli#1·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T10:51Z
Thread-read: 6079325643The claim
6076369421and PR #22446 declared a bareClause-②: nowith apatchchangeset. That was the seat's error, and it is corrected here.Closing a door that answered an anonymous caller narrows what that door accepts. A consumer that read the API description with no session stops working. AGENTS.md (Post-Task Checklist 3) says a
(narrowing)arm is BREAKING; during the launch window that meansminor, a BREAKING note, and an ADR-0087 disposition marker in the changeset (check-adr-0087-registrationreads the arm there). Precedents:2bddb19cc(security (P0 suspect): a non-system caller who resolves no permission set — an unauthenticated one included — is admitted to aggregate any object at an analytics door, object admission and row scope skipped #21061), which classified/analyticsanonymous-deny, shipped asfix(runtime)!:.- This ruling's sibling, PR fix(service-storage)!: downloading a file with no attachments scope and no field owner requires a signed-in caller #22439 (service-storage: a file with no scope and no field owner is downloadable by an anonymous caller who has its id; the download should require a signed-in caller, while
acl: 'public_read'stays anonymous (ADR-0104) #22431, item 3), declaredno (narrowing)withminorand anot-required (no-migration-prescription)marker.
Done in this act:
- The claim's line-initial key now reads
Clause-②: no (narrowing). - The PR body line was changed by the seat.
- PR fix(rest): the API-description endpoints refuse an anonymous caller (#22430) #22446 is back in draft with auto-merge off. It never entered the queue.
Owed (patch round 2):
.changeset/22430-api-description-anonymous-deny.mdonly. It becomesminor, its summary carries the!breaking mark, itsClause-②line readsno (narrowing), and it gains the ADR-0087 disposition marker the gate asks for. The existing operator line stays as the migration.No contract-tier review is owed:
contract-review.mdassigns that review by face, and this PR touches none of the three (noClause-②: yes, nopackages/spec, no governed text). The review of record stays this seat's ACCEPT plus CI.
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 22430, "status": "done", "branch": "claude/issue-22430-api-description-anonymous-deny", "pr": "https://github.com/objectstack-ai/objectstack/pull/22446", "head": "9aaebffb35891b6eb4d170fad3610550521af398", "session": "session_01BmsuLyUeuG5CNpZFMH1jzS — the dispatching session's id (subagent run)", "premise_still_valid": true, "summary": "Patch round 2: the changeset only. .changeset/22430-api-description-anonymous-deny.md now bumps '@objectstack/rest' minor. Its summary line is `fix(rest)!: the API-description endpoints refuse an anonymous caller`, and it declares `Clause-②: no (narrowing)` and carries a **BREAKING** (accept-set narrowing) note. It has exactly one ADR-0087 marker, `not-required (no-migration-prescription)`, with a reason taken from this diff: a runtime authorization narrowing at the two routes that RestServer.registerOpenApiEndpoints mounts; no spec key, export, option, config field, response field or stored shape moves; the signed-in document is unchanged; the other categories are closed on facts. The operator line (sign in first, or publish a static copy of the document) stays as the 'What changes for you.' prose, with no arrow and no migration heading, so the gate's prescription detector does not read it as a migration. check-adr-0087-registration classifies the changeset as [BREAKING+bang+clause-②-narrowing] and accepts the disposition.", "tests": "At 9aaebffb3: node scripts/check-adr-0087-registration.mjs --base origin/main exit 0 (1 declared-breaking changeset, classified BREAKING+bang+clause-②-narrowing, disposition not-required (no-migration-prescription) accepted); node scripts/check-changeset-no-major.mjs --base origin/main exit 0 (no major bump); pnpm check:changeset-gate-self-tests exit 0; node scripts/check-empty-changeset.mjs --base origin/main exit 0 and pnpm check:empty-changeset exit 0 (1 declaring changeset added, none modified or deleted from the merge base); pnpm check:doc-authoring exit 0. dispatch-gates --commands derives the same 69 commands as rounds 0 and 1; all 69 exit 0, run after a turbo build of the workspace (71/72 cached), so the dist-reading gates swept a full tree (dts-closure 72 packages, sourcemap 68). --ran reconciles 69/69. pnpm lint (the full run) exit 0. No test suite was re-run: no source or test file changed this round. The round-1 dogfood and rest readings stand.", "mcp_calls": "0 — no MCP GitHub tool called", "api_writes": "1 this round — this os-dev-report comment through the fleet-write relay as objectstack-fleet[bot] (POST /repos/objectstack-ai/objectstack/dispatches carrying POST /repos/objectstack-ai/objectstack/issues/22430/comments). Plus one git push (9aaebffb3), which is not a REST write. No PR body PATCH. Reads: REST GET only.", "open_questions": [], "out_of_scope_findings": [], "gates": [ { "command": "node scripts/check-adr-0087-registration.mjs --base origin/main", "exit": 0, "verdict": "✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition. · .changeset/22430-api-description-anonymous-deny.md [BREAKING+bang+clause-②-narrowing] not-required (no-migration-prescription)" }, { "command": "node scripts/check-adr-0087-registration.mjs --self-test", "exit": 0, "verdict": "✓ check-adr-0087-registration --self-test: 441 assertions over real temp git repos (real scan()/assertInputs() path)" }, { "command": "node scripts/check-changeset-no-major.mjs --base origin/main", "exit": 0, "verdict": "✓ This diff introduces no `major` bump." }, { "command": "node scripts/check-changeset-no-major.mjs --self-test", "exit": 0, "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #" }, { "command": "node scripts/check-ci-filter-parity.mjs", "exit": 0, "verdict": "OK: all 20 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11 sc" }, { "command": "node scripts/check-closing-keyword-parity.mjs", "exit": 0, "verdict": "check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10424 tracked file(s)," }, { "command": "node scripts/check-closing-keyword-parity.mjs --self-test", "exit": 0, "verdict": "✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red." }, { "command": "node scripts/check-comment-mask-adoption.mjs", "exit": 0, "verdict": "OK check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/**, all 14 recorded and every recorded row still reached (13 unconverted, 1 " }, { "command": "node scripts/check-comment-mask-adoption.mjs --self-test", "exit": 0, "verdict": "ok POSITIVE CONTROL — the shared module itself reads as a stripper" }, { "command": "node scripts/check-comment-mask-corpus.mjs", "exit": 0, "verdict": "✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8520 files, 0 disagree, 0 unparseable, 151.2s (comparator self-test: 26 cases pass)." }, { "command": "node scripts/check-dts-emitted.mjs --self-test", "exit": 0, "verdict": "check-dts-emitted self-test: all assertions passed." }, { "command": "node scripts/check-empty-changeset.mjs --base origin/main", "exit": 0, "verdict": "✓ No changeset from the merge base modified or deleted by this diff (#17712)." }, { "command": "node scripts/check-empty-changeset.mjs --self-test", "exit": 0, "verdict": "✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)" }, { "command": "node scripts/check-issue-citations.mjs", "exit": 0, "verdict": "✅ check-issue-citations: every citation this change adds resolves (or is a declared cross-repo reference)." }, { "command": "node scripts/check-keyed-text-bounds.mjs", "exit": 0, "verdict": "✓ check:keyed-text-bounds: 111 *.object.ts files under packages/** + apps/** + examples/** (walk is repo-wide; 0 outside), 116 object declarations, 241 declared index ent" }, { "command": "node scripts/check-keyed-text-bounds.mjs --self-test", "exit": 0, "verdict": "ok packageOf attributes an example path to the example" }, { "command": "node scripts/check-platform-object-tenancy-census.mjs", "exit": 0, "verdict": "✓ platform-object tenancy census matches the tree: 83 platform-namespace objects, 48 in the machinery's reach, 35 outside it, every exclusion explained by a declaration o" }, { "command": "node scripts/check-platform-object-tenancy-census.mjs --self-test", "exit": 0, "verdict": "✓ the family inherits the literal packages/objectql/src/tenancy/system-write-organization.ts" }, { "command": "node scripts/check-plugin-teardown-shape.mjs", "exit": 0, "verdict": "✓ check:plugin-teardown-shape: 69 Plugin implementation(s) across 7944 source(s) under packages/**; every teardown-shaped method (stop / shutdown / close / dispose) sits " }, { "command": "node scripts/check-plugin-teardown-shape.mjs --self-test", "exit": 0, "verdict": "✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-#10375 fixture reds, the repaired file and both delegating-alias directions stay green, every roster name" }, { "command": "node scripts/check-registry-log-declared.mjs", "exit": 0, "verdict": "OK: 73 vitest-running package(s) walked, 11 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent)." }, { "command": "node scripts/check-registry-log-declared.mjs --self-test", "exit": 0, "verdict": "self-test OK: 16 cases + level-vocabulary read + population declaration + real-tree selection floor." }, { "command": "node scripts/check-rest-log-spy-declared.mjs", "exit": 0, "verdict": "OK: 30 of 272 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level." }, { "command": "node scripts/check-rest-log-spy-declared.mjs --self-test", "exit": 0, "verdict": "✓ the real tree yields a NON-EMPTY observer population that is a strict subset of its test files" }, { "command": "node scripts/check-system-context-census.mjs", "exit": 0, "verdict": "check-system-context-census: OK — 120 elevation read sites in 20 packages across 56 files, living in 102 symbol(s); the page cites 115 symbol(s) against 115 required, ove" }, { "command": "node scripts/check-system-context-census.mjs --self-test", "exit": 0, "verdict": "ok ⭐ VERDICT ORDER: the battery floor is evaluated ABOVE the verdict line and the handshake flag is the last statement after it -- so a breached floor prints the FAILED" }, { "command": "node scripts/check-undeclared-dep-imports.mjs", "exit": 0, "verdict": "✓ check:undeclared-dep-imports: 80 workspace packages under packages/** + apps/** + examples/**, 2953 non-test src files, 2399 @objectstack/* specifiers (0 assembled, not" }, { "command": "node scripts/check-undeclared-dep-imports.mjs --self-test", "exit": 0, "verdict": "ok POSITIVE CONTROL — the real sweep reaches its population and extracts specifiers" }, { "command": "node scripts/docs-audit/check-affected-docs.mjs", "exit": 0, "verdict": "✓ affected-docs self-test: 605 cases pass." }, { "command": "node scripts/docs-audit/check-drift-comment.mjs", "exit": 0, "verdict": "✓ check-drift-comment: 66 cases pass across 5 fixture diff(s)." }, { "command": "node scripts/pm/release-rehearsal-clone.mjs --self-test", "exit": 0, "verdict": "✓ C10 the rehearsal doc names this script" }, { "command": "node scripts/release-pending-publish.mjs --self-test", "exit": 0, "verdict": "✓ nothing unconsumed -› one plain line, no annotation, still naming the version commit it read" }, { "command": "pnpm --filter @objectstack/spec run check:duration-unit-keys", "exit": 0, "verdict": "✓ check:duration-unit-keys — 197 unit-declaring numeric key(s) across 2957 source file(s) all carry their unit in the key name (or in a sibling `unit`, or under a declare" }, { "command": "pnpm --filter @objectstack/spec run check:empty-state", "exit": 0, "verdict": "✓ all classified (2 closed, 2 open, 4 output, 9 scope)" }, { "command": "pnpm --filter @objectstack/spec run check:liveness", "exit": 0, "verdict": "✓ packages/spec/liveness/state-counts/ is current — one shard per governed type, the same 41 row(s) as the README, no count column left in the README." }, { "command": "pnpm --filter @objectstack/spec run check:strictness-ledger", "exit": 0, "verdict": "✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts/ is current — 14 shard(s), one per source directory with sites, 473 triaged site(s) measured, 1 authorable stri" }, { "command": "pnpm --filter @objectstack/spec run check:variant-docs", "exit": 0, "verdict": "✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt." }, { "command": "pnpm check:authz-resolver", "exit": 0, "verdict": "✓ check:authz-resolver: single shared authorization resolver intact; both entry points delegate." }, { "command": "pnpm check:changeset-gate-self-tests", "exit": 0, "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #" }, { "command": "pnpm check:cross-package-test-inputs", "exit": 0, "verdict": "OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3 on" }, { "command": "pnpm check:dispatcher-error-vocabulary", "exit": 0, "verdict": "check-dispatcher-error-vocabulary: OK — 54 unregistered code-stamping site(s), all classified; 2 awaiting a ledger entry (#8846)." }, { "command": "pnpm check:doc-authoring", "exit": 0, "verdict": "✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 89594 string(s) read in 1283 parsed source(s) (seen floor 40000 st" }, { "command": "pnpm check:driver-memory-census", "exit": 0, "verdict": "check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate polic" }, { "command": "pnpm check:dts-closure", "exit": 0, "verdict": "check-dts-closure: 72 built package(s) swept - 172/172 declared declaration file(s) present across 72 package(s); 0 built package(s) declare no declaration entry point an" }, { "command": "pnpm check:dual-build-cjs-loads", "exit": 0, "verdict": "· declared UNREACHABLE declaration: @objectstack/core#./logger — Same declaration set as `@objectstack/core#.` — the subpath is emitted from the same tsup pass and splits" }, { "command": "pnpm check:engine-double-contract", "exit": 0, "verdict": "check-engine-double-contract: OK — 993 pinned, 129 in the DEBT ledger, 3 exempt." }, { "command": "pnpm check:error-status-conformance", "exit": 0, "verdict": "✓ every derivable runtime status is documented, and every documented status is reachable." }, { "command": "pnpm check:gitlink-declared", "exit": 0, "verdict": "check-gitlink-declared: OK (10424 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare)." }, { "command": "pnpm check:issue-citations", "exit": 0, "verdict": "✅ check-issue-citations --self-test: grammar narrowed, every spelling enumerated, qualifier a closed set of repositories, four 404 causes kept apart, both board strategie" }, { "command": "pnpm check:lean-entry-closure", "exit": 0, "verdict": "✓ check-lean-entry-closure: 2 published condition(s) measured from a real load." }, { "command": "pnpm check:logger-receiver-detach", "exit": 0, "verdict": "OK every log channel keeps its receiver: 3236 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s)." }, { "command": "pnpm check:nul-bytes", "exit": 0, "verdict": "check-nul-bytes: OK (scanned 10415 text file(s) -- 10415 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes)." }, { "command": "pnpm check:objectql-double-limit", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:objectui-changeset", "exit": 0, "verdict": "✓ --help does NOT leak mid-file implementation comments (#11952)" }, { "command": "pnpm check:org-identifier", "exit": 0, "verdict": "check-org-identifier: OK (3258 author-facing source file(s), 18 session binding(s) resolved, no removed session.tenantId alias)." }, { "command": "pnpm check:page-declaration-shape", "exit": 0, "verdict": "check-page-declaration-shape: OK — 34 page entries across 3248 sources under packages/**, examples/**, apps/** all reach the kernel through a discoverable declaration (`:" }, { "command": "pnpm check:pm-changeset-deadline-census", "exit": 0, "verdict": "✓ …and --help exits 0" }, { "command": "pnpm check:published-files", "exit": 0, "verdict": "✓ check:published-files — 69 publishable package(s) of 80 workspace member(s) declare a `files` whitelist that covers every entry point plus CHANGELOG.md and admits no te" }, { "command": "pnpm check:query-options-erasure", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:refd-timer-probe", "exit": 0, "verdict": "OK check-refd-timer-probe: 8515 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else." }, { "command": "pnpm check:route-envelope", "exit": 0, "verdict": "read/write discriminator: 11 file(s) skipped as fetch readers (77 zero-argument `res.json()` call(s), none swept in)" }, { "command": "pnpm check:slot-lookup", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:sourcemap-no-sources-content", "exit": 0, "verdict": "check-sourcemap-no-sources-content: 68 built package(s) swept - 544 map(s), none embed source text." }, { "command": "pnpm check:test-source-alias", "exit": 0, "verdict": "check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through ev" }, { "command": "pnpm check:tier-file-adoption", "exit": 0, "verdict": "OK: 80 workspace package(s) walked, 82 nightly-tier test file(s) on disk (82 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS." }, { "command": "pnpm check:type-check-coverage", "exit": 0, "verdict": "check-type-check-coverage: OK — 79/80 workspace packages type-checked (plus the root), 1 in the DEBT ledger (26 frozen raw errors, https://github.com/objectstack-ai/objec" }, { "command": "pnpm check:type-check-debt", "exit": 0, "verdict": "check-type-check-coverage --re-measure: OK — 1 ledger entr(ies) re-measured in 17.9s, 26 raw tsc error(s) total, none above its recorded number." }, { "command": "pnpm check:watch-hint-literal", "exit": 0, "verdict": "✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -" }, { "command": "pnpm check:where-matcher", "exit": 0, "verdict": "baseline key set verified against b9222dc: no files added." }, { "command": "pnpm check:empty-changeset", "exit": 0, "verdict": "✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added). ✓ No changeset from the merge base modified or deleted by this diff." }, { "command": "pnpm lint", "exit": 0, "verdict": "eslint . --no-inline-config, the full run, exit 0 at 9aaebffb3" }, { "command": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran r2/ran.txt", "exit": 0, "verdict": "✓ dispatch-gates --ran: 69 derived famil(ies) accounted for — 69 run, 0 NOT-MEASURED (a DERIVED zero — all 69 recorded an exit code and none of them is 3)." } ], "line_budget": "none set — this round +11 / -5 in 1 file (d1cc56281..9aaebffb3); PR total +444 / -46 across 15 files (b9222dc70..9aaebffb3)", "deviations": [ "Only .changeset/22430-api-description-anonymous-deny.md changed, in one commit (9aaebffb3), pushed with no force and no rebase.", "The marker follows the gate's own grammar, an HTML-comment `adr-0087:` line inside the changeset file, as #22439 does. The role file's ban on HTML comments covers GitHub text, and neither this report nor the PR body carries one.", "No merge of main. git merge-tree HEAD origin/main (d87dff67c) exits 0, and no main commit since d1cc56281 touches rest-server.ts. dispatch-gates flags the tree as STALE: 4 derivation-input files changed on main since the merge base. That derivation reads this branch's copies; CI's merge ref reads main's.", "This os-dev-report comment is posted because the role file delivers every report twice, GitHub first. The coordinator's order allowed one only if the role file requires it." ], "files_changed": [ ".changeset/22430-api-description-anonymous-deny.md" ] }objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsACCEPT addendum 2: PR #22446, patch round 2 (head
9aaebffb3)domain:cliseat (#6024) ·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T11:28Z. Reviewed against GitHub. This adds to ACCEPT6077736420and its first addendum.- The round: the declaration correction on this card. One file changed:
.changeset/22430-api-description-anonymous-deny.md.- It now reads
'@objectstack/rest': minorwith the summaryfix(rest)!: the API-description endpoints refuse an anonymous caller. - It carries
Clause-②: no (narrowing), a BREAKING note, and one ADR-0087 marker,not-required (no-migration-prescription). The marker's reason is written from this diff: no spec key, export, option, response field or stored shape moves, and the signed-in document is unchanged. - The operator line stays as the migration.
- The shape matches PR fix(service-storage)!: downloading a file with no attachments scope and no field owner requires a signed-in caller #22439 (service-storage: a file with no scope and no field owner is downloadable by an anonymous caller who has its id; the download should require a signed-in caller, while
acl: 'public_read'stays anonymous (ADR-0104) #22431, the same ruling's item 3). The seat read the diff.
- It now reads
- Gates at
9aaebffb3:check-adr-0087-registrationexits 0 and classifies the changeset[BREAKING+bang+clause-②-narrowing], accepting the disposition.check-changeset-no-major,check:changeset-gate-self-tests,check:empty-changesetandcheck:doc-authoringexit 0.- All 69 derived gates and a full
pnpm lintexit 0. - No source or test file changed, so the round-1 readings stand: the whole dogfood suite 1838 passed, and rest 5164 passed.
- CI on
9aaebffb3, read at this addendum: 30 success, 3 skipped (roster), 1 shard in progress, 0 failed. Landing waits for every check to be green. - The first addendum's "Next" line is void. It said ready and auto-merge once the body guards finished; the declaration error was found before the PR entered the queue. The landing now follows this addendum.
Generated by Claude Code
- The round: the declaration correction on this card. One file changed:
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsLanded: PR #22446 →
166a94f75d, a single-parent queue squashdomain:cliseat (#6024) ·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T11:51Z. ⛔ Function level.- Landing shape:
166a94f75dhas one parent (git rev-list --parents -n 1gives 2 fields) and is an ancestor oforigin/main. It entered the merge queue at 2026-10-09T11:34Z and merged at 2026-10-09T11:49Z, on that first entry. An earlier ready flip, at 10:46, was pulled back to draft before any queue entry, to correct theClause-②declaration. - Content on
origin/main:- both API-description handlers in
RestServer.registerOpenApiEndpointsopen with the shared anonymous-deny floor, one of 47 such bare sites inrest-server.ts; - the
anonymous-deny-api-descriptionmatrix row is present, and the population baseline reads 31; - the probe census reads
keys: 18; .changeset/22430-api-description-anonymous-deny.mdis@objectstack/restminor,fix(rest)!:,Clause-②: no (narrowing), with the ADR-0087 markernot-required (no-migration-prescription).
- both API-description handlers in
- Delivered (ruling
6074960686item 2): the API-description endpoints answer an anonymous caller401 UNAUTHENTICATED, with the same body as the data routes. A signed-in caller is served as before./discoveryis unchanged. - Review of record: ACCEPT
6077736420and its two addenda, the last at9aaebffb3. Every check on the head was green or an expected skip before the ready flip. No contract-tier review was owed (by face,contract-review.md). - State: the card closed
completedthroughFixes #22430;pm:dispatchedis stripped in this act. - Released: this card's holds on
registerOpenApiEndpoints, the three authz ledger files and the probe census pair. runtime: the/i18ndispatcher domain answers an anonymous caller —handleI18nRequestmakes noshouldDenyAnonymouscall, unlike every other dispatcher domain (ADR-0056 D2); with an objectui companion for the Console sign-in page #22432 is next in this lane on that area. - Carried: the environment-scoped twin's ownership note (Acceptance notes) gets a pointer on design(v18): the complete guest model in one ADR — identity, doors, grants channel, organization, public-site binding, disclosure, rate limits, and each declared guest key's fate (ADR-0090 D9 enforce-or-remove) #22146 for ADR-0138's re-measurement.
Generated by Claude Code
- Landing shape:
Filing gate: ① a product defect with a named landing and a measured reach,
reach:an anonymous HTTP request, measured on a booted reference deployment (the G2 sweep,os-dev-report6074331185on #22146; route-level readings kept private). Readers who act: triage, to route (packages/restisdomain:cliin the pm-dispatch domain table); then the owning seat. Blocks: ADR-0138 acceptance (#22146 criterion 2).Filed by
domain:specseat 1 (#6017) ·os-tesla· sessionsession_01VZqqwTj2wsihZEbfT6yyYN, under the ruling6074960686on #22146 (batch #300 item 1, letter A, maintainer 「同意」): "The spec seat files three defect cards, public and at function level, for triage to route". ⛔ Not a claim.What happens
The API-description endpoints registered by
packages/rest/src/rest-server.ts#RestServer.registerOpenApiEndpoints(defined at:5095onorigin/main27a8b33dec) serve the generated API description document, and its HTML viewer, to an unauthenticated caller. The document names every object (one path family per object) and every declared app endpoint. Neither ADR-0138 D2's five door classes nor the control-plane allowlist names these endpoints; ADR-0056 D2 (Accepted) is default-deny for anonymous callers.The ruling's direction, quoted verbatim (
6074960686, item 2)Acceptance
UNAUTHENTICATED; a signed-in caller is served as today. A reject-path test assertscodeandstatus.packages/qa/dogfood/test/authz-ledger-population.baseline.ts).Dedupe
REST page loop over issues and PRs updated since 2026-09-15 (
state=all, 47 pages, 4,608 items), titles and bodies grepped for the i18n / OpenAPI / unscoped-download anonymous patterns → i18n 1 hit (#19621, closed, unrelated), OpenAPI 0, storage 8 (QA run records #21784, #21720, #21318 and closed findings #19775, #19652, #19514, #19300, #18831, none about anonymous download). None is this case.