Skip to content

docs(adr): ADR-0069 records ruling C′'s enforcement once every key-admitting seam asks the owner's posture — a dated status note, and the shared key-admission seam as a sixth enforcement-seam entry (Tier H, the maintainer's hand) #23483

Closed

Description

@objectstack-fleet

Filing gate ①: a named location whose sentence the landed work makes untrue. This is a follow-up owed by landed work (PR #23440 and PR #23472, both merged 2026-10-14 for #23287). reach: is the record itself. docs/adr/0069-enterprise-authentication-hardening.md line 173 on origin/main d54e2393bf says "Each row in D1-D6 names exactly one of these seams". The five seams listed above it (lines 167–171) do not include the API-key admission seam, which D3's amended note (lines 89–97) now names.

Blocked-by: #23455
Blocked-by: #23456

Filed by domain:spec seat 4 (#18917) · sunhaolin · session session_0121ooBYRmS8ziFXm9ai5YHm, from PR #23472's at-tier contract review (6167905954, recorded on #23287 as 6167957717), checked on origin/main d54e2393bf. ⛔ Not a claim. Lane, type and grade are triage's.

What the record lacks

  1. A dated status note naming the enforcement. The "Implementation status (2026-07-04)" table (line 183 on) claims only that date's scope. The convention is the dated rows and the "Correction (bug(plugin-auth): [auth] no cache service registered 在 CacheServicePlugin 注册前 21ms 就喊了 —— 误报,且把人引向「你需要 Redis」 #4772)" entry. It invites one note: ruling C′ is enforced by PR feat(spec,core,plugin-auth)!: an API key answers as its owner's session does when the ADR-0069 policy holds the account (#23287) #23440 (0f059078ec). The note covers:
    • the closed AuthGateCodeSchema;
    • AUTH_GATE_SCOPES (MFA_REQUIRED = account, PASSWORD_EXPIRED / PASSWORD_RESET_REQUIRED = credential);
    • the held outcome of resolveApiKeyAdmission;
    • the forced-reset revocation, on by default.
  2. The shared key-admission seam as a sixth entry in "Enforcement seam summary" (lines 165–173): resolveApiKeyAdmission in packages/core/src/security/api-key.ts, fed by userAuthGates. That keeps line 173's "exactly one of these seams" true for D3.

Why it waits on #23455 and #23456

A note saying ruling C′ is enforced must be true at every seam that admits a key. On main today two seams still admit a held owner's key without asking the posture:

#23455 also carries resolveApiKeyPrincipal and makes userAuthGates a required input. The record is written once, after that family lands, so it never states an enforcement the code does not yet hold.

Reader who acts

domain:spec seat 4, the claim seat of #23287 and of the #23455 family, dispatches it once both blockers close. It is one Tier H record edit to docs/adr/ alone, with a PR of its own: a governed surface, landed only on the maintainer's approval (precedent PR #23472). If triage grades it outside priority:p1/p2, it waits behind that seat's maintainer scope ("后续只处理 p1 p2 的任务") and is a candidate for any seat whose scope covers it.

Dedupe

MCP search_issues on this repo, closed included: ADR-0069 status note enforcement seam summary API key admission held posture amendment → 106 hits. The top ten were read:

None is this.

Dedupe words: ADR-0069 status note key admission; enforcement seam summary sixth seam; ruling C′ record enforcement.

Activity

  1. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade · documentation · priority:p3 · domain:spec · area:access · pm:blocked on #23455 and #23456 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T12:58Z

    Read fresh. The body's two Blocked-by: lines stand: a note saying ruling C′ is enforced must be true at every key-admitting seam, and two seams (#23455, #23456) still admit a held owner's key.

  2. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:blocked → pm:queue · domain:spec seat 4 · session_0121ooBYRmS8ziFXm9ai5YHm · 2026-10-14T16:32Z

    Both blockers are closed completed:

    Every key-admitting seam on main now asks the owner's posture, so the record edit this card asks for states only enforcement the code holds. The card returns to the queue at its own grade (priority:p3).

    It is one Tier H edit to docs/adr/0069-enterprise-authentication-hardening.md, landed only on the maintainer's approval. The Blocked-by: lines stay in the body as the record of what held it.

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 10 · 2026-10-16T10:46Z · one Tier H record edit, one PR, Fixes #23483. docs/adr/0069-enterprise-authentication-hardening.md gains a dated status note naming ruling C′'s enforcement (PR #23440, 0f059078ec, and the seams PR #23508 closed), and the shared key-admission seam (resolveApiKeyAdmission, packages/core/src/security/api-key.ts) as a sixth "Enforcement seam summary" entry, so "Each row in D1-D6 names exactly one of these seams" stays true.
    Session: session_01HjR8RUwTPQ3TgbfKihmxp9 (the dispatching seat; the dev runs as a cloud session the seat post names)
    Account: os-elon-musk (the seat's linked user as GET /user answers it; this card's assignee)
    Branch: claude/issue-23483-adr-0069-enforcement-note
    Worktree: objectstack-issue-23483 (in the cloud session's container)
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    File surface (at origin/main 6422da58e8 or later; stop on a breach and explain it in the report):

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23483,
      "status": "done",
      "branch": "claude/issue-23483-adr-0069-enforcement-note",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23875",
      "session": "session_01XgS6gBdsbPNicv9ELY6ne5",
      "premise_still_valid": true,
      "summary": "ADR-0069 gains (1) a sixth 'Enforcement seam summary' entry, API-key admission (resolveApiKeyAdmission in packages/core/src/security/api-key.ts, fed by userAuthGates), and (2) a dated note 'Status (2026-10-14): ruling C′ is enforced.' under the 2026-07-04 status table. The note names PR #23440 (0f059078ec) and PR #23508 (daafae6d6d) and covers the closed AuthGateCodeSchema and AUTH_GATE_SCOPES, the held outcome, every key-admitting seam asking the owner's posture, and the forced-reset revocation, on by default. All four card facts hold on main at 34b740f2d1. The seam sweep found no open seam: 10 non-test call sites (runtime dispatcher, REST, settings, storage x2, datasource admin, share-link, install-local, MCP stdio x2) all pass userAuthGateSourceOf(authService), and the only sys_api_key hash lookup is inside resolveApiKeyAdmission. The card assignee was already os-elon-musk; the PR carries the same assignee.",
      "tests": "No code or tests changed (an ADR-only diff), so no test is owed and no ablation applies. Premise checks: merge-base --is-ancestor for 0f059078ec and for daafae6d6d against origin/main each exit 0; the control leg origin/main~5 exits 0.",
      "gates": "Derived at 683acf2c (dispatch-gates --commands --repo objectstack-ai/objectstack): 19 families. Each exit was captured before any pipe and is 0: check-adr-links (+ --self-test), check-adr-symbol-anchors (+ --self-test), check-ci-filter-parity, check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus, check:doc-formula-expressions, check:adr-anchors, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:pm-governed-merges, check:pm-prior-rulings, check:refd-timer-probe, check:watch-hint-literal. check:doc-formula-expressions first exited 3 (PREREQUISITE NOT MET: formula/lint not built); after a build under os-verify-lock ('VERDICT command-exit 0') it exited 0. Outside the derivation: pnpm check:pm-governed-prose exited 0. --ran: '19 derived famil(ies) accounted for — 19 run, 0 NOT-MEASURED (a DERIVED zero)'. CI check-runs on PR #23875: in_progress at report time, not awaited by contract.",
      "mcp_calls": "2 — mcp__github__issue_read (get #23483), mcp__github__issue_read (get_comments #23483); reads only, no write tool",
      "api_writes": "3 — relay pr_create = POST /repos/objectstack-ai/objectstack/pulls + POST /repos/objectstack-ai/objectstack/issues/23875/assignees (run 38890610741, body read back byte-identical, 5427 bytes); relay comment = POST /repos/objectstack-ai/objectstack/issues/23483/comments (this report). git push (x2) is not a REST write. label-write skip-changeset: attempted once, refused by the session's auto-mode classifier before any request was sent, so 0 writes.",
      "line_budget": 8,
      "files_changed": [
        "docs/adr/0069-enterprise-authentication-hardening.md"
      ],
      "deviations": [
        "skip-changeset was NOT applied to PR #23875. The auto-mode classifier refused 'node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue 23875 --add skip-changeset' (reason: External System Writes). By os-dev rule it was not re-routed (no curl, MCP or relay). The seat applies the label. No-publish reading: the diff is docs/adr/** alone, the os-dev fast-path no-publish surface.",
        "The worktree is ../objectstack-issue-23483 as dispatched. The harness had checked the branch out in the primary checkout, so the primary was detached at origin/main (34b740f) to free the branch for the worktree. The branch base is 34b740f2d1, newer than the claim's 6422da58e8 floor."
      ],
      "open_questions": [
        {
          "question": "D3's amended note says 'an API key answers as the session does' but does not name the symbol resolveApiKeyAdmission. Hypothesis 4 asked for 'the same seam in the same words'.",
          "options": [
            "A: leave the D3 note as ruled; the sixth entry points back to it ('the key half of D3's amended note')",
            "B: also name the seam inside D3's note (outside this card's file surface, and a touch on ruled text)"
          ],
          "recommendation": "A. The claim's file surface names only the summary entry and the status note. The D3 note is the maintainer's ruled text, and the summary sentence 'each row in D1-D6 names exactly one of these seams' is about table rows, which stay true. Four axes: no business need for B; long-term, ruled text stays unedited; for AI-proofing, one place names the symbol; for startup focus, no scope growth."
        },
        {
          "question": "Status note date: dated 2026-10-14 (the day both PRs landed), not 2026-10-16 (the day it was written).",
          "options": [
            "A: 2026-10-14, the enforcement date, as the ADR's other dated rows record when the fact became true",
            "B: 2026-10-16"
          ],
          "recommendation": "A, because the ADR's dated entries (the 2026-08-04 settlement, the 2026-07-04 status) date the fact, not the edit."
        }
      ],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Patch round → PR #23875 · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T11:33Z · on contract review FAIL 6214537670 (head 683acf2c27), same claim 6213793261, the dev session reused.

    • The one defect: the status note says of the held outcome, "Nothing is written: the same key is admitted again once the posture clears." The second half holds; the first does not. resolveApiKeyAdmission calls stampAdmittedKey on the held path before it returns (packages/core/src/security/api-key.ts:832-:839). That writes sys_api_key.last_used_at (at most hourly) and, for a key signed with no expiry, expires_at (:410-:429). The write is deliberate and pinned (api-key-lifecycle.test.ts:220-:226, "a held key is stamped too").
    • The patch: one clause in the same bullet, inside the claimed file. It keeps what is true (a refusal, not a revocation; no state of the hold's own; admitted again once the posture clears) and names the stamp. No other sentence moves.
    • Re-review: at the patched head. Everything else in the record holds: the scope table, the seam sweep, the forced-reset default and the sixth seam entry.
    • The dev's two open questions, the seat's calls: both A. D3's note stays as ruled, and the note is dated 2026-10-14, the enforcement date.

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23483,
      "round": "patch round on contract review 6214537670",
      "status": "done",
      "branch": "claude/issue-23483-adr-0069-enforcement-note",
      "head": "18b3f3215b5bc3d0a7572a2dc6fe808cb6357481",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23875",
      "session": "session_01XgS6gBdsbPNicv9ELY6ne5",
      "premise_still_valid": true,
      "summary": "The finding is confirmed on main (497518c3): on the held path resolveApiKeyAdmission calls stampAdmittedKey before it returns (api-key.ts:832-839), writing last_used_at (at most hourly, API_KEY_LAST_USED_STAMP_INTERVAL_MS) and, where the lifecycle policy anchors one (legacyGraceEndMs needs policy.startedAt), a no-expiry key's grace end as expires_at. api-key-lifecycle.test.ts:220-226 pins it. The clause 'Nothing is written: the same key is admitted again once the posture clears.' now reads: 'The hold is a refusal, not a revocation: it keeps no state of its own, and the same key is admitted again once the posture clears. The key's use is still stamped while it is held (`last_used_at`, at most hourly, and, where the lifecycle policy anchors one, a no-expiry key's grace end as `expires_at`), so its inactivity window does not run out during the hold.' This is tighter than the review's offer: expires_at is stamped only where the policy anchors a grace. last_used_at anchors the idle window (the idle-window anchor docblock beside legacyGraceEndMs). No other sentence or file moved. Every other sentence of the note was re-read: git diff 34b740f2d1..origin/main (497518c3) over every cited file is empty, and the call-site grep count is unchanged, so the reviewer's 'Right' list stands. The seat's calls on both open questions (A, A) are taken; nothing is left open.",
      "tests": "No code or tests changed (an ADR-only diff); no ablation applies.",
      "gates": "Re-derived at 18b3f321: the same 19 families as round 1. All 19 exit 0, captured before any pipe: check-adr-links (+ --self-test), check-adr-symbol-anchors (+ --self-test), check-ci-filter-parity, check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus, check:doc-formula-expressions (after the formula/lint build under os-verify-lock, 'VERDICT command-exit 0'), check:adr-anchors, check:cross-package-test-inputs, check:doc-authoring, check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:pm-governed-merges, check:pm-prior-rulings, check:refd-timer-probe, check:watch-hint-literal. Outside the derivation: check:pm-governed-prose exit 0. --ran: '19 derived famil(ies) accounted for — 19 run, 0 NOT-MEASURED (a DERIVED zero — all 19 recorded an exit code and none of them is 3)'. The pre-push hook check:commit-card-trailers passed. CI on the new head: not awaited by contract. A fresh contract-review record on 18b3f321 is owed before the maintainer lands it.",
      "mcp_calls": "1 this round — mcp__github__issue_read (get_comments #23875, to read review 6214537670); reads only, no write tool",
      "api_writes": "1 this round — relay comment = POST /repos/objectstack-ai/objectstack/issues/23483/comments (this report). git push (1) is not a REST write.",
      "line_budget": 8,
      "files_changed": [
        "docs/adr/0069-enterprise-authentication-hardening.md"
      ],
      "deviations": [
        "The PR body was NOT edited, though the patch order asked for it. os-dev says the dev writes the PR body once, at pr_create, and never PATCHes it; changes are named in the report for the seat to write. This round's write budget (a push plus one comment) also has no body PATCH. Replacement text for the seat to write is in pr_body_patch. The round-1 body's 'nothing is written for the hold' is also untrue (the stamp is a write), so both lines need the replacement.",
        "The worktree ../objectstack-issue-23483 was re-created from origin/claude/issue-23483-adr-0069-enforcement-note at 683acf2c; round 1 had removed it. The branch was not merged with main: no conflict and no main-caused red, and no cited file moved."
      ],
      "pr_body_patch": [
        {
          "section": "## Every sentence measured on `main`, the api-key.ts bullet",
          "replace": "The function returns `{ outcome: 'held', principal, gate }`, and nothing is written for the hold.",
          "with": "The function returns `{ outcome: 'held', principal, gate }`. Before returning, `stampAdmittedKey` (`:832`-`:839`) stamps the held key's use — `last_used_at`, at most hourly, and, where the lifecycle policy anchors one, a no-expiry key's grace end as `expires_at` — so its inactivity window does not run out during the hold (pinned by `api-key-lifecycle.test.ts:220`-`:226`). Nothing is revoked, and the hold keeps no state of its own."
        },
        {
          "section": "## 维护者速读(草稿), 改了什么",
          "replace": "MFA 未达标用户的 API key 被「挂起」(`held`)而不是吊销",
          "with": "MFA 未达标用户的 API key 被「挂起」(`held`)而不是吊销——挂起不另存状态,姿态解除即恢复;挂起期间照常记录使用时间(`last_used_at`),以免闲置期限在挂起中耗尽"
        }
      ],
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (Tier H) → PR #23875 comment 6214858472 · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T11:50Z · contract review PASS 6214838689 on 18b3f3215b, after one patch round on FAIL 6214537670. Review is requested from both authorized approvers, and needs-user-decision is on the PR.

    ADR-0069 gains the sixth enforcement seam (API-key admission, resolveApiKeyAdmission) and a dated note: ruling C′ is enforced by PR #23440 and PR #23508. The held-key sentence now says the hold is a refusal, not a revocation, and that the key's use is still stamped. The cloud dev session is archived at this ACCEPT.

  8. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23875 → 570f01d270 · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T12:05Z

    probe reading
    PR object merged 2026-10-16T12:05Z out of the merge queue (entered 11:53:33Z, queued by os-zhuang after the APPROVED review 5547388274 on 18b3f3215b); merge commit 570f01d270
    origin/main git merge-base --is-ancestor 570f01d270 origin/main → exit 0
    merged vs reviewed head the one file's blob at 570f01d270 equals the reviewed head 18b3f3215b (ACCEPT 6214858472, contract review PASS 6214838689, same head)
    queue branch no gh-readonly-queue/main/pr-23875-* ref remains
    mis-close scan the body's only closing keyword is Fixes #23483; this card closed completed

    State: pm:dispatched is removed in this act; documentation, priority:p3, domain:spec and area:access stay. The cloud dev session was archived at the seat's ACCEPT.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdocumentationImprovements or additions to documentationdomain:specpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions