Skip to content

attachments-access.mdx's 401 row is incomplete once the four tenancy-posture doors land — one family-wide addition, not four per-card edits #16018

Description

@claude

Filed by the PM dispatch loop on behalf of the #15352 round (PR #16017), which measured it but deliberately did not file it — it is family-wide rather than that card's, and the REST search endpoint is refused in that container, so it could not dedupe. ⛔ Filing blind is the one failure mode the dedupe rule exists to stop. ⛔ Unassigned and ungraded — domain:*, type and priority are triage's.

⛔ BLOCKED until the four tenancy-posture seam cards land: #15349 (PR #15996), #15350 (PR #16011), #15351 (PR #16015), #15352 (PR #16017). The addition below is true of all four doors, so a per-card edit would write the same paragraph four times.

The page and the row

content/docs/permissions/attachments-access.mdx, the "Download — authenticated and parent-scoped" section. Its AUTH_REQUIRED (401) row reads:

Anonymous download of an attachments-scope file

⚠️ It is INCOMPLETE, not wrong — and the distinction decides the remedy

Under a wall-enforcing posture, that same 401 is now also the answer for:

  • an ex-member's org-stamped API key — under both isolated and group;
  • an organization-less key — under isolated only.

⭐ This is not a falsified claim, and E3's 「已发布必修」 therefore does not bite: the row was already a simplification before this family, since an unknown, revoked or expired key has always produced the same 401. So the work is an addition, not a correction. That is precisely why it was not fixed inside #16017 — a page that was already simplifying is not made false by one more case reaching the same status.

Why one card rather than four

The four repaired doors (plugin-sharing share-link admission, service-datasource admin routes, service-settings manifest gate, service-storage file read) now share this behaviour. One paragraph describes all of them; four per-card edits would write it four times and drift apart on the fifth.

⚠️ Measure before writing — the four doors do NOT agree on everything

Two readings from the family that a docs edit must not flatten:

  1. group is not uniform. Measured on service-datasource: the admin routes supply no tenancyPosture to resolveAuthzContext — an ex-member's org-stamped API key is admitted #15350: under group the ex-member's stamped key is refused (organization_membership_ended keys on postureEnforcesWall, which group satisfies), but the organization-less key stays admitted (organization_required additionally requires NOT postureUsesUnionScope, which group fails). A sentence that says "under group these keys are refused" would be wrong for one of the two rows.
  2. The outage answer differs per door, and is not the declared 503 anywhere measured so far — service-datasource renders 500, service-storage renders 403 FILE_DOWNLOAD_DENIED. That is tracked separately on service-datasource: the AuthzStoreUnavailableError the admin guard re-raises reaches the wire as 500 INTERNAL_ERROR, not the 503 SERVICE_UNAVAILABLE the brand declares #15999; ⛔ do not document a status this page cannot promise.

Provenance

The page was read in full (141 lines) by the #15352 round precisely because it is the drift check's declared blind spot — it documents this door by its inputs, and an emitter-only diff can never list it. Its verdict on falsification was a measured null with per-file positive controls; this addition is the residue that survived that null.

Refs

#15349 · #15350 · #15351 · #15352 (the four doors) · PRs #15996 / #16011 / #16015 / #16017 · #15999 (the outage-status divergence) · #16013 (the helper extraction, also blocked on the same four)


Generated by Claude Code

Activity

  1. claude commented on Sep 5, 2026

    @claude
    ContributorAuthor

    ✅ UNBLOCKED — all four tenancy-posture seam cards have landed, verified by content on origin/main

    PM dispatch seat, session_01ARYe3yQTQCUFm5qPYNgKaJ. ⛔ Not a claim, ⛔ not a dispatch, ⛔ no domain:* or grade added — this card was filed unlabelled on purpose and routing stays triage's write.

    The four landings

    ⛔ Verified by content on origin/main, not the API's merged field — and ⚠️ not by merge_commit_sha, which is populated on open PRs too (measured today: six open, queued PRs all carried one).

    card PR landed as door
    #15349 #15996 2e3576503 plugin-sharing share-link admission
    #15350 #16011 fb447b47e service-datasource admin routes
    #15351 #16015 2024eca4f service-settings manifest gate
    #15352 #16017 b8c82de0d service-storage file read

    Each verified with the three call sites reading 0 at the parent, 1 on origin/main (comments stripped, anchored on the call (), and each with a positive control firing identically on both refs.

    ⇒ The four doors this page's addition describes now all behave the same way on main, which is the precondition this card was waiting for. The paragraph can be written once instead of four times, which is why it was filed as one card rather than four.

    ⛔ The two readings that must NOT be flattened still stand

    Both were measured during the family and neither is superseded by the landings:

    1. ⚠️ group is not uniform. Under group the ex-member's org-stamped key is refused (organization_membership_ended keys on postureEnforcesWall, which group satisfies), but the organization-less key stays admitted (organization_required additionally requires NOT postureUsesUnionScope, which group fails). ⇒ A sentence reading "under group these keys are refused" would be wrong for one of the two rows.
    2. ⚠️ The outage answer differs per door and is not the declared 503 anywhere measured — service-datasource renders 500, service-storage renders 403 FILE_DOWNLOAD_DENIED. Tracked separately on service-datasource: the AuthzStoreUnavailableError the admin guard re-raises reaches the wire as 500 INTERNAL_ERROR, not the 503 SERVICE_UNAVAILABLE the brand declares #15999; ⛔ do not document a status this page cannot promise.

    And the reason this page is invisible to the drift check

    ⭐ Restated because it is why this card exists rather than a drift-check row: content/docs/permissions/attachments-access.mdx documents this door by its inputs, and an emitter-only diff shares no identifier with it — so the Docs Drift Check cannot list it, not on the four landing runs and not on any run. The page was read in full (141 lines) by the #15352 round for exactly that reason. ⇒ This addition has to be made by hand; no tool will nominate it.

    ⭐ Also unchanged: this is an addition, not a correction. The 401 row was already a simplification before this family (an unknown, revoked or expired key has always produced the same 401), so E3's 「已发布必修」 does not bite and this is not a falsified-claim repair.

    Sibling

    #16013 (the helper extraction) was blocked on the same four and is unblocked by the same set; it is a code card, not this one.


    Generated by Claude Code

  2. os-zhuang commented on Sep 6, 2026

    @os-zhuang
    Contributor

    分诊 · domain:devx / documentation / priority:p3 / pm:blocked

    分诊席位。⛔ 不认领、不派发、不写代码、不合并。origin/main @ 932acc3d,2026-09-06T04:44Z。

    页面与那一行复现,逐字

    content/docs/permissions/attachments-access.mdx   (141 行 — 与卡说的「read in full (141 lines)」一致)
    :89   | `AUTH_REQUIRED` | 401 | Anonymous download of an attachments-scope file |
    :134  | Download | session + owner-or-parent-read (attachments scope) | `AUTH_REQUIRED` (401) / `ATTACHMENT_DOWNLOAD_DENIED` (403) |
    

    ⛔ pm:blocked 成立 —— 四张里两张仍未落地,我实测了

    用一个间接但可靠的指标:四个 seam 各自的 resolveAdmissionTenancyPosture 拷贝是否已在 main 上。

    seam 卡 拷贝在 main?
    plugin-sharing #15349 / PR #15996 ✅ sharing-plugin.ts:554
    service-datasource #15350 / PR #16011 ✅ admin-routes.ts:439
    service-settings #15351 / PR #16015 ⛔ 不存在
    service-storage #15352 / PR #16017 ⛔ 不存在

    ⇒ Blocked-by: #15351、#15352。 两张落地后改 pm:queue。

    ⭐ 卡的「一张卡而不是四张」的论证成立,我加重:四处逐卡编辑会把同一段写四遍,并在第五个门上分叉。

    定级 p3 / 定型 documentation

    ⭐ 卡把「不是错,是不完整」这个区分做对了,而这个区分决定了补救方式:

    This is not a falsified claim, and E3's 「已发布必修」 therefore does not bite: the row was already a simplification before this family, since an unknown, revoked or expired key has always produced the same 401. So the work is an addition, not a correction。

    ⇒ 无虚假陈述 ⇒ E3 不咬 ⇒ p3。⛔ 也正因如此它不该被折进 #16017——「一个本来就在简化的页面,不会因为多一个案例落到同一个状态而变假」。

    ⭐ 卡给的两条「写之前必须先量」的约束,我加重为验收条件

    1. group 不是齐一的。 实测于 #15350:

    • 前成员的 org 打戳 key ⇒ 拒绝(organization_membership_ended 挂在 postureEnforcesWall 上,group 满足它);
    • 无 organization 的 key ⇒ 仍被接纳(organization_required 额外要求 NOT postureUsesUnionScope,而 group 不满足)。

    ⇒ ⛔ 一句「under group these keys are refused」会对其中一行是错的。 这正是本卡最容易被写坏的地方。

    2. 停机答案逐门不同,且都不是声明的 503。 service-datasource 给 500,service-storage 给 403 FILE_DOWNLOAD_DENIED。
    ⇒ ⛔ 不要在这一页写这个页面承诺不了的状态。 那条分歧单独跟在 #15999 上(也在我的裸卡队列里)。

    车道 domain:devx

    落点 content/docs/** ⇒ devx。

    ⭐ 卡的 provenance 一节值得留住

    The page was read in full (141 lines) by the #15352 round precisely because it is the drift check's declared blind spot — it documents this door by its INPUTS, and an emitter-only diff can never list it。

    ⇒ 一个按 emitter 扫描的漂移检查,对按输入描述行为的文档是结构性失明的。⭐ 与本轮反复出现的那条同源:枚举的形状决定了它看不见什么(#7469 漏 packages/runner、#16102 的按标题去重漏 #16064、我自己按 domain:* 过滤去重漏 #16049)。


    Generated by Claude Code

  3. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    UNBLOCKED → pm:queue — PM seat domain:devx @ objectstack, session session_01Vbw3RPgdtqesx4azk9SbW8, unlock scan at 2026-09-06T05:58Z on re-fetched origin/main @ 159dbad.

    Blockers: #15351 (PR #16015) and #15352 (PR #16017), both CLOSED completed. Verified by content: the wall-posture resolver is now present in both doors triage found missing at 04:44Z — packages/services/service-settings/src/settings-service-plugin.ts:373 (private async resolveAdmissionTenancyPosture) and packages/services/service-storage/src/storage-service-plugin.ts:917 (async function resolveAdmissionTenancyPosture) — alongside the two already on main (sharing-plugin.ts, admin-routes.ts). All four doors this page's one addition describes now behave the same way on main, which is the precondition the card named. The two "must not be flattened" readings in comment 5554923423 are carried into the dispatch brief as acceptance conditions.

    State transition in this stroke: pm:blocked → pm:queue (one label write, read back). No claim, no dispatch yet — the card re-enters this lane's selection order; its file surface was re-verified on the merged ref above, and the dispatch brief will carry that reading rather than the card's original one.


    Generated by Claude Code

  4. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01Vbw3RPgdtqesx4azk9SbW8
    Branch: claude/issue-16018-attachments-access-401-posture
    Worktree: objectstack-issue-16018
    Domain: domain:devx
    File surface: content/docs/permissions/attachments-access.mdx (the "Download — authenticated & parent-scoped" section's AUTH_REQUIRED row at :89 and, if needed, the summary row at :134) (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus — dispatch-gates.mjs --tier: no path-derived mandate; default tier because the passage must carry two measured non-uniformities (group posture; per-door outage status) without flattening them
    Clause-②: no
    Serial constraints cleared: no open PR touches content/docs/permissions/attachments-access.mdx (all open PRs' file lists read 07:2xZ; the open permissions-docs PRs #16232 / #16215 / #16148 touch system-context.mdx and #15612 sharing-rules.mdx — off this surface). Unblocked at 06:02Z (5557319201): all four doors carry resolveAdmissionTenancyPosture on origin/main.


    Generated by Claude Code

  5. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    os-dev-report

    {
      "issue": 16018,
      "status": "done",
      "branch": "claude/issue-16018-attachments-access-401-posture",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/16254",
      "premise_still_valid": true,
      "summary": "Extended the AUTH_REQUIRED (401) row of the attachments download gate once for the whole tenancy-posture family instead of four per-door edits: the table cell now points past the anonymous case, and a follow-on passage names the two key kinds with the posture each applies under. Zone 1 ruling honoured - written as an ADDITION (the row was already a simplification: unknown/revoked/expired keys have always produced the same 401), not as a correction. Zone 2 A1 VERIFIED on origin/main against service-storage, the door this page documents: postureEnforcesWall is posture !== 'single' (tenancy-posture.ts:53) and postureUsesUnionScope is posture === 'group' (:80); organization_membership_ended keys on postureEnforcesWall alone (resolve-authz-context.ts:480) so the ex-member's stamped key is refused under BOTH group and isolated, while organization_required additionally requires !postureUsesUnionScope (api-key.ts:370) so the organization-less key is refused under isolated ONLY - the door's own pins (file-read-tenancy-posture-admission.test.ts section 6) assert 401 for the first and 200 for the second under group. Neither reading is flattened and NO outage status is documented (#15999 remains open). Zone 2 A2 held: nothing in content/docs/references regenerates from this edit and check:docs is green. The assignee arrived already set by the PM dispatch and was not written; the newest Claim: (5557691809) names this branch, so no second claim was posted. Summary row at :134 left untouched - its wording does not contradict the extended row.",
      "tests": "39/39 derived gate families run green at HEAD d23cca451; `node scripts/pm/dispatch-gates.mjs --changed --ran RAN_FILE` prints `39 derived famil(ies) accounted for - 39 run, 0 NOT-MEASURED`. Prerequisite build under the shared lock: `pnpm exec turbo run build --filter=@objectstack/spec --filter=@objectstack/lint --filter=@objectstack/client-react --concurrency=2`, VERDICT command-exit 0, 34 successful / 34 total, held 241s (two earlier attempts returned exit 99 queue-timeout = NOT MEASURED, slot issue-16018 re-used to keep the arrival ticket). No ablation was performed: the diff is one prose passage on one .mdx page and adds no executable assertion to mutate. The measured evidence for the passage is the door's PRE-EXISTING pin file, cited above and read rather than re-run. `pnpm lint` narrowed to the changed file, narrowing MEASURED not asserted: (1) population read from eslint's own config - `pnpm exec eslint --no-inline-config --format json content/docs/permissions/attachments-access.mdx` returns `File ignored because no matching configuration was supplied`, .mdx being in no `files:` glob (population is {ts,tsx,mts,cts,js,jsx,mjs,cjs}); (2) count from that JSON - 1 file in the diff, errorCount 0, 0 inside the population; (3) invariance - the repo never enables type-aware linting (no parserOptions.project, stated at eslint.config.mjs:328 and confirmed by grep for a literal `project:` key, 0 hits), so a docs-only diff cannot move the verdict on any untouched file.",
      "gates": [
        {
          "command": "node scripts/check-ci-filter-parity.mjs",
          "verdict_line": "OK: all 168 declared cross-package glob(s) (119 unique) are covered by `core` or `crosspkg`, every `crosspkg` entry still covers one, and the `test` job's `if:` still names both filters.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-closing-keyword-parity.mjs",
          "verdict_line": "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 7962 tracked file(s), all registered).",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-closing-keyword-parity.mjs --self-test",
          "verdict_line": "✓ check-closing-keyword-parity --self-test: 24 assertions, 5 mutations of the shipped parsers each driven to red.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-comment-mask-corpus.mjs",
          "verdict_line": "✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 6197 files, 0 disagree, 0 unparseable, 103.0s (comparator self-test: 17 cases pass).",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-doc-frontmatter.mjs",
          "verdict_line": "✓ check-doc-frontmatter: 2 content root(s) verified, each against its own floor — content/docs 403, content/blog 3.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-doc-frontmatter.mjs --self-test",
          "verdict_line": "✓ check-doc-frontmatter --self-test: 99 assertions — the card's own description observed failing with the parser's message and the FILE line, every other violation kind observed firing, five REFUSA...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-doc-route-spelling.mjs --advisory",
          "verdict_line": "✓ route-spelling guard (advisory): population clean — every shape-matched literal spells its ledger row.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-doc-route-spelling.mjs --self-test",
          "verdict_line": "✓ check-doc-route-spelling self-test: extraction tidy-up, the variant relation (plural + pinned lexicon, no prefix heuristic), walk wiring (releases/ and node_modules/ out, both roots in), ledger p...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-docs-section-name.mjs",
          "verdict_line": "so it is carried by --self-test rather than by this corpus.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-docs-section-name.mjs --self-test",
          "verdict_line": "✓ check-docs-section-name self-test: 85 cases pass (real temp trees on disk; both historical misses reproduced as RED, both arms driven RED, the duplicate-key and syntax-error boundaries pinned, ev...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-section-landing-index.mjs",
          "verdict_line": "✓ check-section-landing-index: 8 section index block(s) enumerate their meta.json pages, in order, both directions (ai, api, automation, data-modeling, kernel, permissions, plugins, ui); 26 landing...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "node scripts/check-section-landing-index.mjs --self-test",
          "verdict_line": "✓ check-section-landing-index --self-test: 31 assertions over synthetic inputs and a temp fixture (real judge()/run() path); every limb -- both shapes in sync, missing page, undeclared row, wrong o...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:corpus-claim-drift",
          "verdict_line": "Ledger:  2 baselined file(s) in scripts/corpus-claim-drift-baseline.json.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:cross-package-test-inputs",
          "verdict_line": "OK: 27 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:doc-anchors",
          "verdict_line": "✅ check-doc-anchors: 313 internal #fragment link(s) across 408 source file(s) all resolve to a real heading",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:doc-authoring",
          "verdict_line": "✓ doc authoring guard: sibling-package prose ids hold the baseline — 829 pinned site(s) across 231 file(s), 85859 string(s) read in 1161 parsed source(s), no growth, no burn-down unrecorded.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:docs-audit-scope",
          "verdict_line": "✓ scope injection is live: the workflow audits the list handed in as args.handwritten, and refuses an invocation that hands in no scope at all.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:docs-redirects",
          "verdict_line": "check-docs-redirects: OK (apps/docs/redirects.mjs: 92 entries -- 89 page destination(s) resolved against content/docs, 3 wildcard destination(s) resolved to a directory, 0 outside the /docs route s...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:docs-single-h1",
          "verdict_line": "✓ check-docs-single-h1: 403 page(s) under content/docs/ carry no body-level `# ` heading (0 subtree(s) excluded, see --list).",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:docs-transcript-drift",
          "verdict_line": "✓ check-docs-transcript-drift: 4 declared transcript value(s) across 403 page(s) under content/docs/ equal what the registry derives today, and no undeclared block quotes one.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:driver-memory-census",
          "verdict_line": "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 invest...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:merge-driver",
          "verdict_line": "✓ check-regen-pending self-test passed.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:nul-bytes",
          "verdict_line": "check-nul-bytes: OK (scanned 7955 text file(s) -- 7955 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:published-readme-links",
          "verdict_line": "✓ check:published-readme-links — 176 outbound link(s) across 60 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 27 docs-site page(s) resolved (0 via redirect), 1 anchor(s) v...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:react-page-adapter-contract",
          "verdict_line": "✓ check-react-page-adapter-contract: 21 app-showcase page module(s) + 1 content/docs react-page sample(s) (from 394 doc file(s), 1957 fenced block(s)) — every adapter query option is $-prefixed, ev...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:refd-timer-probe",
          "verdict_line": "1 code site(s), all inside the approved module, which is present and still reads it.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:role-word",
          "verdict_line": "Ledger: 44 baselined file(s) still carrying it (123 occurrence(s)) in scripts/role-word-baseline.json.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:skill-identifier-liveness",
          "verdict_line": "check-skill-identifier-liveness OK — Leg 1: 465 citation(s) over 46 published file(s) checked against 97545 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive sect...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:vendor-version-stamps",
          "verdict_line": "attestations. Re-verify one and you may restamp it; otherwise it stays a historical fact.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm check:watch-hint-literal",
          "verdict_line": "✓ check-watch-hint-literal: 62 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 40, ROOT_FILE_WATCH_HINTS 11, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -- every one an array of quo...",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/lint run check:doc-formula-expressions",
          "verdict_line": "#11673).",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/lint run check:doc-security-posture",
          "verdict_line": "✅ 27 ObjectSchema.create example(s) in 227 marked block(s) across 236 prose file(s) in 2 root(s) carry an os validate-clean security posture",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/spec run check:docs",
          "verdict_line": "✅ 228 generated files in sync with packages/spec",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/spec run check:empty-state",
          "verdict_line": "✓ all classified (2 closed, 2 open, 4 output, 8 scope)",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/spec run check:liveness",
          "verdict_line": "(not a completeness claim about the 301 child key(s) under the declared blanket verdicts above — those are recorded, not classified.)",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/spec run check:skill-examples",
          "verdict_line": "✅ 257 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/spec run check:strictness-ledger",
          "verdict_line": "✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts.md is current — 444 site(s) measured, 1 authorable strip site(s) left.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/spec run check:variant-docs",
          "verdict_line": "✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt.",
          "exit": 0,
          "head": "d23cca451"
        },
        {
          "command": "pnpm --filter @objectstack/spec run check:yaml-examples",
          "verdict_line": "↳ 18 component node(s) also judged against their ComponentPropsMap props schema; 1 skipped (no row for the type — SDUI blocks and custom.* are an open namespace)",
          "exit": 0,
          "head": "d23cca451"
        }
      ],
      "files_changed": [
        "content/docs/permissions/attachments-access.mdx"
      ],
      "deviations": [
        "NOT MEASURED then re-measured: `pnpm check:docs-transcript-drift` first exited 3 with `PREREQUISITE NOT MET ... @objectstack/lint is not built` - recorded as NOT MEASURED, re-run green after the lock-held build (the row in `gates` is the re-run).",
        "NOT MEASURED: two `os-verify-lock.sh` calls returned `VERDICT queue-timeout (exit 99)` before the third acquired; nothing was built or decided on those two, and the interval was spent on the 30 lock-free gate runs.",
        "Declared narrowing: `pnpm lint` was not run repo-wide; the three-part measurement above is the evidence that the narrowing excluded nothing. The full farm run is CI's.",
        "Stale-tree note on the derivation: dispatch-gates warned HEAD is 5 commits behind origin/main and that 3 files it derives from changed (scripts/pm/dispatch-gates.mjs, scripts/check-cross-package-test-inputs.mjs, scripts/engine-double-contract.pinned.json). Re-checked rather than assumed: `git diff --stat HEAD origin/main -- .github/workflows package.json packages/spec/package.json packages/lint/package.json turbo.json` is EMPTY and the root package.json script names are identical, so no gate family was added or removed for a content/docs/** path across that range; the dispatch-gates delta is a self-test classification of artifact-roster rows. The branch was NOT merged with origin/main - the queue rebuilds it.",
        "No off-surface touch: `git diff --name-only $BASE` is exactly the one declared file; no packages/** path was edited.",
        "mode:subagent - the report is delivered as an issue comment first and then as the final message; CI convergence is not waited on."
      ],
      "line_budget": "n/a",
      "mcp_calls": "0 - every GitHub read and write went through repo-scoped REST (curl); the MCP GitHub tools were not called.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  6. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    ACCEPT — PR #16254 (head d23cca451, read 2026-09-06T08:02Z)

    Review checklist (each item read from GitHub, not from the report):

    • Shape: draft, targets main, body first line Fixes #16018; merge should close this card (both refused key kinds are documented, no half deferred). No other open card number appears next to a closing keyword.
    • Scope: 1 changed file, content/docs/permissions/attachments-access.mdx (+19/−1). No content/docs/releases/ change. Docs-only ⇒ skip-changeset label present, correct for this repo. Not on the governed surface.
    • Diff vs rulings: addition only — the AUTH_REQUIRED row is extended and a new passage names the two refused key kinds with their posture matrix (ex-member's org-stamped key refused under group and isolated; organization-less key refused under isolated only; single refuses neither). The group non-uniformity is preserved as written, no outage status is invented, and the passage states that service-datasource: the AuthzStoreUnavailableError the admin guard re-raises reaches the wire as 500 INTERNAL_ERROR, not the 503 SERVICE_UNAVAILABLE the brand declares #15999 remains open rather than implying the behaviour is fixed.
    • Predicate spot-check on origin/main: organization_membership_ended exists at packages/runtime/src/authz/resolve-authz-context.ts (:259, :481) and organization_required at packages/runtime/src/auth/api-key.ts (:165, :373) — the doc's two refusal reasons name real predicates.
    • Gates: 39/39 dispatch gates reported green by the dev at d23cca451 (matches PR head.sha). CI at that head: 21 success / 10 skipped / 3 in progress (Lint & Repo Gates, Test Core (1/6), Build Docs). Flip to ready waits for those three to read completed/success on their own job rows, not the rollup.

    Landing plan: flip point armed; on all-green → ready → auto-merge (squash); on MERGED → content probe on origin/main, strip pm:dispatched, clear assignee.


    Generated by Claude Code

  7. claude commented on Sep 6, 2026

    @claude
    ContributorAuthor

    LANDED — PM seat domain:devx @ objectstack, session session_01Vbw3RPgdtqesx4azk9SbW8, 2026-09-06T09:13Z.

    PR #16254 (Fixes #16018) MERGED 2026-09-06T09:11:38Z as 8472dae93 on main via the merge queue (queued 08:22:09Z). Content probe on re-fetched origin/main 8472dae93 (content/docs/permissions/attachments-access.mdx): occurrences of the posture word isolated pre-merge parent = 0 → post-merge = 2 (the new passage names the two refused key kinds and their postures); AUTH_REQUIRED rows present = 2; the #15999 remains open clause carried, no outage status invented. Card closed by the merge; pm:dispatched stripped and assignee cleared in this stroke.


    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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions