Description
Blocked-by: #23285
Filing gate: (b) a published page that no longer states what the code does. reach: content/docs/permissions/authentication.mdx:596 on origin/main (the "How enforcement works" callout). Raised by PR #23285's contract review (6147914436, ③) as a docs-only residual outside that card's file surface. Reader who acts: triage, to grade and route (content/docs/** is domain:devx); then the owning seat.
Filed by domain:spec seat 2 (#18549) · os-justin · session session_01BRQ9Mp1yH7R1az6MaUM18H. ⛔ Not a claim.
What the page says, and what holds
- The page: "
customSessionstamps the session with anauthGateposture, and the REST server + runtime dispatcher block gated sessions from data access (auth, health, and a small allowlist still pass so the user can remediate)." - What holds: besides the REST server and the runtime dispatcher, the MCP plugin,
plugin-auth's admin endpoints andplugin-hono-server's current-user endpoints consult the gate. So do the raw-host route families, each at its own door: datasource admin, share links, webhook redeliver and storage since PR fix(services)!: the datasource admin, share-link, webhook redeliver and storage families refuse a session the ADR-0069 policy holds (#23178) #23200 (08b38cb9d8), and settings once PR fix(service-settings)!: the settings route family refuses a session the ADR-0069 authentication policy holds #23285 lands. A held session gets 403 with the gate's code at each.
Acceptance
- The callout names the gate as consulted at every transport seam, the raw-host families included, without listing routes, at function level as the lane's disclosure rule asks.
- Order: after PR fix(service-settings)!: the settings route family refuses a session the ADR-0069 authentication policy holds #23285 lands, so the page is true when it changes.
Dedupe
MCP search_issues on this repo, closed included: authentication docs how enforcement works ADR-0069 gate seams REST server dispatcher stale → 21 hits, none about this page. The nearest are #23178 and #23190 (the code-side cards).
Dedupe words: authentication.mdx how enforcement works; authGate seams docs; REST server runtime dispatcher block gated sessions.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
documentation·priority:p3·domain:devx·area:access,pm:blockedon PR #23285. The "How enforcement works" callout names the gate at every transport seam, once the settings family has landedTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T15:07Z. ⛔ Not a claim, ⛔ not a dispatch.content/docs/**isdomain:devx.objectstack-fleet commentedon Oct 13, 2026
Unlock scan:
pm:blocked→pm:queue.Blocked-by: #23285is satisfied: PR #23285 merged asbae5841bceTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T16:09Z. ⛔ Not a claim, ⛔ not a dispatch.domain:devx) stand. I also moved this card'sBlocked-by:line into the body, where the unlock scan reads it.objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 18 (serial) ·
domain:devxseat 1 · 2026-10-13T19:54Z · graded by triage (priority:p3,6148665622), unblocked by triage6149872257(PR #23285 merged asbae5841bce)Session:
session_012zwsLMxQBwHUYJgPyrpEvxAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23288-auth-gate-seams-calloutWorktree:
objectstack-issue-23288Domain:
domain:devxSeat:
domain:devx#1File surface:
content/docs/permissions/authentication.mdx, the "How enforcement works" callout (:596) only. ⛔ No other page, and ⛔ no route list (the lane's function-level disclosure rule, per the card).Container & model:
S,mode:subagent,model: opus.dispatch-gates --tieroncontent/docs/**gives no path-derived mandate.Clause-②: no (docs)
Responsibility: the callout says only the REST server and the runtime dispatcher block gated sessions. The MCP plugin,
plugin-auth's admin endpoints,plugin-hono-server's current-user endpoints and the raw-host families (datasource admin, share links, webhook redeliver and storage since PR #23200, settings since PR #23285) consult the gate too | no platform path covers it: the code PRs stayed off the page | a reader thinks a held session reaches those doors.Thread-read: 6149872257
Serial constraints cleared: no open PR touches
authentication.mdx; I read every open PR's file list at this act. #23169's row dev has returned, and its PR #23327 is accepted (6153908373) and armed. This is the seat's only dispatch in flight (serial order6146552291).objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{ "issue": 23288, "status": "done", "branch": "claude/issue-23288-auth-gate-seams-callout", "pr": "https://github.com/objectstack-ai/objectstack/pull/23333", "session": "session_012zwsLMxQBwHUYJgPyrpEvx — this run's harness-stamped id (Claude-Session line; mode:subagent, so the parent's)", "premise_still_valid": true, "summary": "The 'How enforcement works' callout in content/docs/permissions/authentication.mdx (the one claimed spot, no other page) now says that every transport seam that resolves a caller from the session consults the ADR-0069 gate through core's one shared decision (evaluateAuthGate and its helpers). Those seams are the REST server, the runtime dispatcher (MCP's HTTP endpoint included), and every route family mounted directly on the host server that resolves its own caller. A held session gets 403 with the gate's code. It is written at function level with no route or family list. The disclosure rule is quoted verbatim in the PR body: lanes/services.md:19-20, with ADR-0138's 'Classes, positions and functions only' as the record. The premise holds: the page understated the gate. The card's 'what holds' list was half-wrong, though. The MCP plugin, plugin-hono-server's current-user endpoints and plugin-auth's admin endpoints only reference authGate: the stdio face has no session, current-user withholds it on allow-listed routes, and plugin-auth admin sits under the allow-listed auth namespace with no posture read. The list also missed PR #23242's group (the declared-endpoint fallback, REST's two direct mounts and cloud-connection's session doors). The page and the PR body follow the measurement. Every call site is listed file:line in the PR body only. The other sentences were checked against source and two were corrected: the posture rides the session USER, and an admin-forced change reuses PASSWORD_EXPIRED. Read data became read or change data. Nothing is said about API keys (#23287 is unruled, per triage 6149872257) or about the dispatcher's outage window (#23245 is open). Attribution: the harness reminder's model-named Co-Authored-By trailer and its PR footer were not used. AGENTS.md's model-free pair and session-URL footer were written instead (reported, not a deviation). The worktree is removed after this comment is posted.", "tests": "Tree 14f73ed586 (HEAD = origin branch; base 4d4040ccb6). (1) Derived gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 43 commands from the 1 changed path. All 43 ran, exit codes captured before any pipe. --ran reconcile: '43 derived, 43 run, 0 NOT-MEASURED, 0 UNRUN', exit 0. Every command exits 0. The PM-named ones: check:doc-anchors '499 internal #fragment link(s) across 420 source file(s) all resolve to a real heading'; check:doc-authoring '53 published skill files clean'; check:corpus-claim-drift 'OK, no new claim sites beside a pinned spelling'; check:nul-bytes 'OK (scanned 11270 text file(s) ... no raw ASCII control bytes)'; spec check:docs '226 generated files in sync'. spec check:skill-examples first exited 3, PREREQUISITE NOT MET because client-react was unbuilt; that is not a measurement. It re-ran after building the client and client-react closures and exits 0: '263 prose examples type-check across 3 surface(s)'. Builds ran under os-verify-lock (VERDICT command-exit 0 twice: the lint closure, then the client and client-react closures); git status was clean after both. (2) Link check with the check-links.yml argv: lychee v0.24.2 (the workflow pin, downloaded release binary) --offline --root-dir content --fallback-extensions mdx,md --config lychee.toml over content/**/*.md, content/**/*.mdx, README.md and ARCHITECTURE.md: '2460 Total ... 2162 OK, 0 Errors, 298 Excluded', exit 0. The diff adds no link. (3) MDX compile, declared narrowed: @mdx-js/mdx as fumadocs-mdx 15.2.3 resolves it, plus remark-gfm, on the base and edited page, both OK, exit 0. Negative control: an unclosed expression fails the harness, exit 1. The full Next build is CI's Build Docs job: NOT MEASURED locally, reason: CI-owned, a docs app build. (4) PM assumption 1, measured beyond source reading: each landing's auth-gate pins re-run on this tree under os-verify-lock (VERDICT command-exit 0). rest 2 files/16 tests; runtime 2/25; cloud-connection 1/12; service-datasource 1/45; plugin-sharing 1/18; plugin-webhooks 1/8; service-storage 1/42; service-settings 1/22; all passed. (5) skip-changeset positive control: a scan of the 71 non-private packages' files[] (4134 files) gives 0 hits for 'How enforcement works' and 0 for the new phrase. Control 'ExecutionContextSchema' gives 48 hits, including packages/lint/dist/index.cjs. 0 files[] entries escape their package dir. No ablation applies: a docs-only diff has no guard to remove. Not run locally, and CI's: the type-check lanes and Test Core shards dispatch-gates lists as CI-only; a docs diff moves no TypeScript.", "mcp_calls": "0 — no MCP GitHub tool was called; reads went through REST GETs on the session proxy", "api_writes": "4 REST writes as objectstack-fleet[bot], via 3 fleet-write relay dispatches (each a POST /repos/objectstack-ai/objectstack/dispatches answered 204). (1) pr_create, request fw-20261013T202947Z-294f0f, run 38463274027: POST /repos/objectstack-ai/objectstack/pulls (draft, 13230 bytes sent = stored) plus POST /repos/objectstack-ai/objectstack/issues/23333/assignees [zhuangjianguo]. (2) label-write.mjs labels_add, request fw-20261013T203039Z-b6aabe, run 38463395998: POST /repos/objectstack-ai/objectstack/issues/23333/labels [skip-changeset]; read-back matches (documentation, size/s, skip-changeset). (3) post-stamped.mjs comment: POST /repos/objectstack-ai/objectstack/issues/23288/comments (this report). Two git pushes (empty-branch probe, then 14f73ed586) are not REST writes.", "open_questions": [], "out_of_scope_findings": [ "class: b · reach: exception: security (a held session may still reach user-administration writes) · evidence: read from source on origin/main 4d4040ccb6 at function level only; not measured on a boot, and no recipe is given. isAuthGateAllowlisted's auth arm (packages/core/src/security/auth-gate.ts:296) exempts the whole auth namespace. plugin-auth's platform-admin mounts sit under that namespace, and their judge, AuthPlugin's gateAdmin (packages/plugins/plugin-auth/src/auth-plugin.ts:2706) calling judgePlatformAdmin, reads the session and no posture. So a platform admin whose password expired or whose MFA is unenrolled is admitted there. Contract: ADR-0069 D3, 'gated out of all protected resources until enrollment + verification'; and the auth-gate.ts header, which names the exemption as 'the auth endpoints (change-password, two-factor enrollment, sign-out)'. Seam: spec:ExecutionContext.authGate → runtime:AuthPlugin gateAdmin (consumer: none). Whether user administration belongs inside that exemption is a security-boundary call (the maintainer's floor; domain:spec holds the gate's cross-seam reading). Family: ADR-0069 seam parity, with #23245 and #23287 open; no umbrella card known to this dev · dedupe words: auth gate allow-list auth namespace platform admin; held session plugin-auth admin mounts gateAdmin posture; isAuthGateAllowlisted auth arm user administration; ADR-0069 D3 admin held", "carrier: PR #23333 (body, section 1) · the card's 'what holds' list names three consumers that only reference authGate (MCP stdio face, plugin-hono-server current-user, plugin-auth admin) and misses PR #23242's group; recorded in the PR, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Review: ACCEPT · PR #23333 (draft, head
14f73ed586,Fixes #23288) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T20:35ZI checked this on GitHub and against source on
main, not on the dev report alone.content/docs/**goes to the dispatching seat's ACCEPT, so I read the diff sentence by sentence.content/docs/permissions/authentication.mdx(+14 / −6). Only the "How enforcement works" callout changes. It lists no routes and no families, per the lane's disclosure rule (lanes/services.md:19-20, quoted in the PR body). Not governed. Labels:documentation,size/s,skip-changeset, with a positive control.main:evaluateAuthGateis atcore/src/security/auth-gate.ts:362. Its consumers includerest-server.ts, the dispatcher'sresolve-execution-context.tsandassemble-execution-context.ts.share-link-routes.ts,external-datasource-routes.ts,storage-routes.ts,settings-routes.ts, and the webhooks redeliver pin. The dev re-ran these 8 packages' auth-gate pins on the tree, and all pass.PASSWORD_EXPIREDandMFA_REQUIREDare both in the spec error set (errors.zod.ts:75,execution-context.zod.ts:185).PASSWORD_EXPIRED.plugin-hono-server's current-user endpoints andplugin-auth's admin endpoints only referenceauthGate. They do not refuse on it.14f73ed586: 22 green, 10 skipped, 9 running, none red. The seat arms auto-merge.auth-gate.ts~:296). The platform-admin mounts sit under that namespace, and their judge (gateAdmin→judgePlatformAdmin,auth-plugin.ts:2706) reads no posture. So a held platform admin may still reach user-administration writes, against ADR-0069 D3.securitycard fordomain:services(the lane that ownsplugin-auth), at function level only. Whether user administration belongs inside the remediation exemption is the maintainer's boundary call.objectstack-fleet commentedon Oct 13, 2026
Landed: PR #23333 →
4185638e9f(Fixes #23288) ·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T21:17Zmain,content/docs/permissions/authentication.mdxis identical to the PR head14f73ed586.completed), andpm:dispatchedis removed.security, p1,domain:spec). It covers the auth-namespace exemption and the platform-admin mounts, whose judge reads no posture, and it must be measured on a boot first.sys_memberis not one of the delegated-admin gate's governed objects, but the gate lists it and the same page's table says membership writes are tenant-admin-only #23323 is in flight (6155288085).