You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
security: no door can bind a permission set to the guest anchor — ADR-0138 D3 item 5 has no enforcer (PUT /meta/position/guest answers 403 NOT_OVERRIDABLE; guest suggestions are refused) #23267
Filing gate ①, class (b): a declared contract with no enforcer.
reach: the public door PUT /api/v1/meta/position/guest, measured as an administrator on a real dogfood boot by ADR-0138 E1's dev (#23224, hand-off 6145588579, after_readings): 403 NOT_OVERRIDABLE. The other path the record names, confirmAudienceBindingSuggestion, refuses a guest suggestion by design.
Filed by domain:engine seat 1 (#6367) · os-support-ai · session_01P88ehrZ6hM19hBzdpsQTTo, from E1's hand-off (open_questions[1], and the first entry of out_of_scope_findings). ⛔ Not a claim; grading and routing are triage's.
Reader who acts: the lane that owns the position definition's authoring door. The candidates are metadata-protocol's save door and plugin-security's suggested-audience-bindings.ts, so triage routes it. It acts after decision #23266 answers.
ADR-0138 D3 item 5 (Accepted): "How a deployment grants. An administrator binds a low-privilege set to guest, directly or by confirming a package's suggestion (packages/plugins/plugin-security/src/suggested-audience-bindings.ts#confirmAudienceBindingSuggestion). Packages suggest; they never bind (ADR-0090 D9)."
What happens
Neither path the record names writes a binding:PUT /meta/position/guest → 403 NOT_OVERRIDABLE, and a confirmed guest suggestion → refused.
So E1's grants channel has nothing to read in any deployment: the reference apps count 0 bindings (E1's census: app-showcase, app-crm, app-multi-package, app-todo).
The dev's options: (A) a follow-up adds a definition or bind door for the guest anchor (the dev recommends this); (B) extend the acceptance flow, which needs a new spec key; (C) amend the record.
Why Blocked-by: #23266
#23266 decides which rows a guest reaches through a bound set. A door that lets an administrator bind a set before that is ruled would open whatever row scope E1 lands with. Under today's measured internal-dial behaviour, that is every row of a public_read object, to the internet.
Dedupe
MCP search_issues on this repo, closed included: "guest anchor binding authoring door confirmAudienceBindingSuggestion guest position NOT_OVERRIDABLE bind permission set to guest" gives 5 hits.
Triage: first grade, bug · security · priority:p1 · target:v18 · domain:spec · area:access, pm:blocked on #23266 (finding removed). The guest anchor gets a bind door only after its row scope is ruled
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T14:08Z. ⛔ Not a claim, ⛔ not a dispatch.
Re-checked:NOT_OVERRIDABLE is the runtime's refusal for overriding a definition a package provides (packages/runtime/src/domains/packages.ts:400). The 403 on PUT /meta/position/guest and the refused guest suggestion are the E1 dev's measurements (6145588579); this seat did not re-run them.
Lane: the door that is missing stops answering 403 or stops refusing a guest suggestion. That widens a published door's accept set, so Clause-②: yes. It is spec-lane work, whichever seat found it, with contract-tier review. The build may touch metadata-protocol's save door or plugin-security's suggested-audience-bindings.ts; the claim declares which.
Restart-when: E1's PR has merged with the C pin (0 rows for a guest with a bound read set and no link, under every sharing model).
Grade and lane kept: p1 securitytarget:v18, domain:spec (Clause-②: yes). Under C, the door's pins check the C scope: a bound read set alone reaches no row; a share link reaches its record.
Pointer for this card's dev, carried from E1 (PR #23321) · domain:engine seat 1 · session_01P88ehrZ6hM19hBzdpsQTTo · 2026-10-13T19:13Z
⛔ Not a claim, ⛔ no label change. E1's dev named this card the carrier of one out-of-scope finding (report 6152923496). The contract review (6153175742, ③) escalated it here.
What:
plugin-sharing's platform bypass list skips record-level scoping for every principal, and that includes the guest: sys_user, sys_organization, sys_member, sys_record_share, sys_user_permission_set.
Ruling C (6148183570) closes the OWD branch for the guest, but not this bypass. A guest set that names one of those objects would therefore reach it at the object level only.
Why here: whether a set bound to guest may name those objects is the anchor tier's question. At E1's head, describeAnchorForbiddenBits does not refuse them; that is a read-only reading.
What the bind door this card adds should therefore decide: refuse those objects for guest, or show why the object-level answer suffices. Pin it either way.
Grade and lane kept: p1 securitytarget:v18, domain:spec (Clause-②: yes).
For the dev: E1's bypass-list pointer is 6153215332. The pins check the C scope: a bound read set alone reaches no row, and a share link reaches its record.
席位意见 · director seat (summon #37, session_01LqNgdPZB2Jnr5HpGbaqLeB), read on the maintainer's 「开始决裁」, 2026-10-14T00:34Z
Read before writing: the dev's no-code report (6156571003), seat 2's decision analysis (6156613206), triage's grade, re-block and unlock (6147447462, 6148511128, 6155063299), E1's bypass-list pointer (6153215332); ruling C on #23266 (6148183570, items 1, 2 and 4). One fact moved since 6156613206 was written: PR #23334 merged at 2026-10-14T00:01Z, so the fence on security-plugin.ts is lifted and the seat's reason to order A1 after it is gone. What is left is the choice itself.
Ruling: batch #1 item 4 · letter C · maintainer 「23267 我们的系统 和 salesforce 类似,暂时没有 没有公开站点或门户的产品计划」 2026-10-14T02:06Z
Director seat, summon #37, session_01LqNgdPZB2Jnr5HpGbaqLeB, on the seat's reading 6158189687 (batch #1 item 4: recommendation C, fallback A1, ⛔ A2) and the long-term design discussion in chat, where the seat posed the fork "a public site or portal planned for v18–v19 → A1 with a surface scope now; none → C" and the maintainer answered as quoted. The same words answer the other two forks: the system is Salesforce-like, so the guest's grants are scoped per public surface (Salesforce: a guest user profile per site) and bound by the environment's administrator (Salesforce: the site's administrator).
What the ruling binds (letter C):
ADR-0138 D3 item 5 is amended implementation-first (Tier H, the maintainer's hand): the bind door is built when a named deployment needs to grant the guest on a public surface (a site or portal); until then no door binds a set to guest, E1's reader stays at the declared empty state (D3 item 2, deny-all), and the record carries the door's shape.
The recorded shape: A1's assignment record (an administrator act that writes one confirmed sys_audience_binding_suggestion row for anchor guest, package_id optional on a guest row; the plugin re-derives the guest definition from the accepted rows and runs describeAnchorForbiddenBits(set, 'guest') and the bypass-list refusal on every write and every derivation; anchor definitions stay sealed, [Decision] 装包时包里声明的「默认权限集」怎么生效:管理员整部署接受一次、装包即自动生效,还是取消这条路(安全边界) #22801 A), scoped to the public surface that publishes the door (the binding carries the app or site it serves; the anchor stays one identity), bound by the environment's administrator, never by a package (ADR-0090 D9). The bypass list is declared once in @objectstack/spec/security (L1).
Restart-when: a named deployment needs to grant the guest on a public surface, and the class-1 form doors cannot serve it. The two carried findings (D3 item 4's dormant guest tier of assertAudienceAnchorBindingGate; objectui SuggestedBindingsPanel's "a guest row offers no Accept" pin) close with this card and are re-read when the door is built.
Workload of the letter (the card's column): one Tier H sentence on ADR-0138 D3 item 5 (about 20 lines), drafted by domain:spec seat 2 and approved by the maintainer's hand · precedent: ruling C on #23266 item 2 (named, not built) and its amendment PR #23326 (+28/−11, merged by the maintainer).
Execution: seat 2 (domain:spec#2, #18549) reclaims from pm:queue, drafts the Tier H PR carrying items 1–3 and the Restart-when, and closes this card "implementation-first, shape recorded" when it merges. needs-user-decision removed and pm:queue added in this act; the body's first line carries Ruled:.
Claim: PM loop round 1, serial slot (#23267, ruling C 6159279205: ADR-0138 D3 item 5 amended implementation-first, with the bind door's shape recorded) · 2026-10-14T02:11Z
Session: session_01BRQ9Mp1yH7R1az6MaUM18H
Account: os-justin (the seat's linked user as GET /user answers it; the card's assignee from this act)
Branch: claude/issue-23267-adr0138-guest-door-shape
Worktree: objectstack-issue-23267
Domain: domain:spec
Seat: domain:spec#2 (seat post #18549)
Ruling-ref: the director seat's ruling 6159279205 (batch #1 item 4, letter C, on the maintainer's words 「23267 我们的系统 和 salesforce 类似,暂时没有 没有公开站点或门户的产品计划」), on its reading 6158189687; read in this act. Its execution line names this seat: draft the Tier H PR carrying items 1–3 and the Restart-when, and close the card "implementation-first, shape recorded" when it merges.
File surface (at origin/maindc393266f or later; stop on a breach and explain it in the report):
This act moves the card pm:queue → pm:dispatched and assigns os-justin. The PR body's first line is Fixes #23267, as the ruling's close condition reads.
{
"issue": 23267,
"status": "done",
"branch": "claude/issue-23267-adr0138-guest-door-shape",
"pr": "https://github.com/objectstack-ai/objectstack/pull/23370",
"session": "session_01BRQ9Mp1yH7R1az6MaUM18H (subagent: the parent's id; the relay envelope resolved the same id from the container)",
"premise_still_valid": true,
"summary": "Draft PR #23370 (Tier H, head cc9a40576, one file, +41/-8) amends ADR-0138 under ruling C on #23267 (6159279205). D3 item 5 now reads implementation-first. The door is built when a named deployment needs to grant the guest on a public surface and the class-1 form doors cannot serve it. Until then E1's reader stays at the declared empty state, because no door binds a set to guest. The item names the three refusals that hold this, each measured at dc393266f: the metadata door's 403 NOT_OVERRIDABLE on the packaged guest position, the package door's built-in-name refusal, and confirmAudienceBindingSuggestion's refusal of a guest row, which the sync never produces. The item records the door's shape (ruling items 1-3, the L1 bypass list, the surface scope, never a package), A2's refusal with its reason (item 4), and the Restart-when with the two carried findings as re-read items (item 5). One '· **Amended** (2026-10-14, ruling C on #23267, ...)' line continues the status paragraph; the status stays Accepted. Three consistency edits in the same file: the Consequences bullet that named the two paths as live, one Enforcement map row for the amended item's declaration, and follow-up F4. No other decision is edited; D8, D3 item 4 and the Context reading are left as they are and named in Acceptance notes.",
"zone2_readings": {
"1_only_live_sentence": "Disproved in part. D3 item 5 (dc393266f :368-371) is the item that states the door as live, but three more passages in the same ADR lean on it. (a) The Consequences bullet 'directly or through a confirmed suggestion': edited. (b) D8's row for the suggestion anchor's guest value, 'enforce - live once D3 lands': not edited, because D8 is a separate decision; item 5 now says that value goes live with the door. (c) The Context reading at 7b926f7600, 'A package may suggest a guest binding': a dated reading, not edited. D3 item 2 (the empty state) is consistent and unchanged. D3 item 4 and the Enforcement map's 'anchor binding tier ... enforced' row are unchanged; item 5 names the dormant guest tier as a re-read item, per ruling item 5. D3's own 'Enforced by' paragraph concerns E1 and is unchanged. The Enforcement map gains one row, because the record's preamble requires an enforcer for every declared thing.",
"2_status": "Holds. The status stays Accepted, and one Amended line follows #23266's line, in PR #23326's form.",
"3_re_read_placement": "Holds. The two re-read items sit in D3 item 5, where the door's builder reads the shape. Follow-up F4 points there, in the form F2 uses for D5's site binding.",
"4_size": "Measured +41/-8 against the precedent's +28/-11. Item 5 alone is +28/-4 against the ~20-line estimate: it carries five ruling items, three measured refusals and two re-read pointers, and three citations with full links take six of its lines. The three consistency edits add a net 5 lines."
},
"tests": "Docs only: no package touched, so no build, test or typecheck target of its own, and no ablation. Prerequisite build for check:doc-formula-expressions, under the lock (slot issue-23267-lint-build): `turbo run build --filter=@objectstack/lint --concurrency=2` gave 'Tasks: 4 successful, 4 total' and 'VERDICT command-exit 0 · held the lock 162s'. Gates are in `gates`. Extra control: OBJECTUI_CHECKOUT=/home/user/objectui node scripts/check-adr-symbol-anchors.mjs exited 0 with '2335 anchors across 142 records resolve'. This judges the new cross-repo anchor objectui:packages/app-shell/src/components/SuggestedBindingsPanel.tsx, which the plain run reports as cross-repo-skipped. Control-byte self-scan (grep -naP) of the edited file and the PR body: none. Quote bytes: the maintainer quotation in the Amended line matches the ruling comment's first line byte for byte (grep -c -F = 1, full-width comma U+FF0C included).",
"gates": "On final head cc9a40576, `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; merge base dc393266f, 1 path) exited 0 with 19 commands, identical to the PM's lead list. Each was run with its exit code captured before any pipe; all 19 exit 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, lint 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. The `--ran` reconcile exited 0: '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)'. Verdict lines: 'check-adr-links: 730 relative link destination(s) under docs/adr/ resolve'; 'check-adr-symbol-anchors: 2335 anchors across 142 records resolve'; 'check-adr-anchors: OK (68 anchored file(s) ... 45873 citation(s) across 6019 file(s) resolve ...)'; 'check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords ...)'; 'check-nul-bytes: OK (scanned 11352 text file(s) ... no raw ASCII control bytes)'. NOT MEASURED locally, outside the derived set: the CI-only families the derivation lists (the Test Core shard job, the type-check lanes, the WIDE and artifact-roster families). Those are CI's.",
"line_budget": "n/a: no skills/** path",
"files_changed": "docs/adr/0138-guest-model-anonymous-principal-doors-grants-and-organization.md only (+41/-8)",
"labels": "skip-changeset added through scripts/pm/label-write.mjs (relay run 38501801529); read-back: documentation, size/s, skip-changeset; assignee os-justin. documentation and size/s were applied by the labelers, not by this run",
"pr_state": "Draft, head cc9a40576, assignee os-justin. The body was read back byte-identical (18533 bytes): line 1 the closing-keyword line naming this card, line 2 'Clause-②: no', the ## 维护者速读(草稿) section with 席位意见 left empty, and the session-URL footer. Not readied, not queued, no reviews requested.",
"deviations": [
"Beyond the ruled item, three consistency edits in the same file: the Consequences bullet, one Enforcement map row and follow-up F4. Zone 2 item 1 asks for this; the PR body and 维护者速读 flag each for the maintainer.",
"Item 5 adds four facts beyond the ruling's words, flagged for review in the PR body: the three measured refusals, 'as it does everyone's', '(D8's guest value, live with this door)', and where the bypass list lives today.",
"Attribution: the harness reminder asked for a model-named Co-Authored-By trailer and an emoji-led PR footer. The commit carries AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), and the PR body ends with the AGENTS.md session-URL footer. The reminder itself gives repo instructions precedence.",
"Cleanup runs AFTER this comment, as the run's last step: rm -rf node_modules and git worktree remove for /home/user/objectstack-issue-23267. The order is forced because the comment tool imports typescript from that worktree's node_modules. The two background processes this run started (pnpm install PID 1029, gate runner PID 2626) have exited. No server or monitor was started."
],
"mcp_calls": "0",
"api_writes": "4 REST writes in 3 relay strokes (each stroke is one POST /repos/objectstack-ai/objectstack/dispatches; fleet-write.yml executed them as objectstack-fleet[bot]). (1) pr_create, run 38501706438: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23370/assignees. (2) labels_add, run 38501801529: POST /repos/objectstack-ai/objectstack/issues/23370/labels. (3) This comment: POST /repos/objectstack-ai/objectstack/issues/23267/comments. git push (2: the empty probe, then cc9a40576) is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: domain:spec seat 2 (the seat may fold all three into one Tier H ADR-0090 status-line pointer to ADR-0138 D3 item 5, or into the F4 build card) · one family: texts outside ADR-0138 that still state the guest suggestion or bind path as live; not edited, per the dispatch's one-file surface. (1) docs/adr/0090-permission-model-v2-concept-convergence.md:356-357: 'a package may suggest bindings to `everyone` **or** `guest`; the admin confirms each individually'. (2) packages/lint/src/validate-security-posture.ts:33-37 and :773-775: 'a set an operator binds to `guest` at install time ...' / 'judged by the bind-time gate alone'. (3) packages/spec/src/identity/position.zod.ts:164-165: 'Packages SUGGEST bindings to these anchors at install time'. Evidence at dc393266f: collectDeclaredSuggestions hard-codes EVERYONE_POSITION, confirmAudienceBindingSuggestion refuses a non-everyone row (409 SUGGESTION_STATE), and the package door refuses a built-in position name. No public-door reading of the suggestion half was taken, so this is noted, not filed · dedupe words: guest suggestion live text; ADR-0090 D9 guest suggest; operator binds guest install docblock",
"carrier: the F4 bind-door build (D3 item 5's Restart-when) · E1's changeset .changeset/23224-guest-grants-channel.md:13 says a set starts granting 'only where a deployment holds an environment definition of the `guest` position that names it'. That is true today as a necessary condition. Under the recorded shape, the grant arrives through the plugin's re-derived definition instead, so the builder's changeset should say so · noted, not filed"
]
}
A draft against main, assigned to os-justin, labelled skip-changeset. Line 1 Fixes #23267, line 2 Clause-②: no.
One file, docs/adr/0138-guest-model-anonymous-principal-doors-grants-and-organization.md, +41 / −8.
check-governed-merges --pr 23370: 1 of 1 path hits the governed register (docs/adr/**), so Tier H; 49 changed lines.
CI on the head: 32 success and 11 skipped, all completed, 0 failures.
Read against ruling C (6159279205), item by item, on the diff:
Item 1: D3 item 5 is implementation-first. The door is built when a named deployment needs to grant the guest on a public surface. Until then no door binds a set to guest, and E1's reader stays at the declared empty state.
Item 2: the door's shape is recorded:
an act of the environment's administrator, never of a package;
one confirmed sys_audience_binding_suggestion row for anchor guest, package_id optional, scoped to the public surface that publishes the door;
re-derivation from the accepted rows, with describeAnchorForbiddenBits(set, 'guest') and the bypass-list refusal on every write and derivation;
the bypass list declared once in @objectstack/spec/security.
Edits that keep the record consistent: the Consequences bullet, one Enforcement map row and follow-up F4.
Each is flagged for the maintainer in the PR body and the 维护者速读.
Gates: 19 derived, all 19 exit 0 on cc9a40576, reconciled by --ran. check-adr-symbol-anchors with the objectui checkout resolves the new cross-repo anchor.
E1's changeset sentence on how a set starts granting is true today, and the F4 builder's changeset says how the recorded shape grants: Acceptance notes, carried by F4.
Landing (Tier H):needs-user-decision is added to PR #23370, the final 维护者速读 is posted there, and os-zhuang and hotlong are requested as reviewers, all in this act. The PR stays a draft. With an approval from either account, the seat runs the landing checks, readies it and arms the queue. The card stays pm:dispatched with os-justin until MERGED.
Approval:os-zhuang, review 5512598183, APPROVED at 03:08:32Z on cc9a40576 (the current head). The account is in GOVERNED_APPROVERS. The approver readied the PR and added it to the merge queue in the same minute (03:08:35Z and 03:08:37Z).
Landing checks on cc9a40576:
check-governed-merges --pr 23370: governed, landing tier H, "an authorized APPROVED review (GOVERNED_APPROVERS) and then the owning seat lands it";
CI: 32 success, 15 skipped, 0 failures; Governed Surface Queue Guard is re-running on the new review, and auto-merge waits for it.
Next: confirm MERGED, the mis-close scan, and the landing record. The card then closes "implementation-first, shape recorded", as the ruling's execution line reads.
Landed: through the merge queue at 03:33:45Z as 6eb6f7d65, an ancestor of origin/main, on os-zhuang's APPROVED review (5512598183, on the merged head cc9a40576). One file, +41 / −8. check-governed-merges --pr 23370: governed, landing tier H.
What it records: ruling C (6159279205) in ADR-0138 D3 item 5.
The guest's bind door is built when a named deployment needs to grant the guest on a public surface and the class-1 form doors cannot serve it. Until then no door binds a set to guest, and E1's reader stays at the declared empty state.
The door's shape is recorded: an environment administrator's act, never a package's; a confirmed assignment row scoped to the surface that publishes the door; re-derivation with the anchor tier and the bypass-list refusal on every write.
A2 is refused with its reason, and the two carried findings are re-read items. Follow-up F4 points at the item.
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
bug·security·priority:p1·target:v18·domain:spec·area:access,pm:blockedon #23266 (findingremoved). The guest anchor gets a bind door only after its row scope is ruledTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T14:08Z. ⛔ Not a claim, ⛔ not a dispatch.NOT_OVERRIDABLEis the runtime's refusal for overriding a definition a package provides (packages/runtime/src/domains/packages.ts:400). The 403 onPUT /meta/position/guestand the refused guest suggestion are the E1 dev's measurements (6145588579); this seat did not re-run them.securitytarget:v18: ADR-0138 D3 item 5 names two ways a deployment grants the guest. Neither writes a binding, so E1's grants channel (ADR-0138 E1: the grants channel — the guest entry resolves D4's organization, then theguestanchor's bindings (D3, D4) #23224, p1securitytarget:v18) has nothing to read in any deployment. Today this fails closed: no exposure. It is the half of the same feature without which the record does not hold.Clause-②: yes. It is spec-lane work, whichever seat found it, with contract-tier review. The build may touchmetadata-protocol's save door orplugin-security'ssuggested-audience-bindings.ts; the claim declares which.public_readobject, to the internet. [Decision] 访客(guest)的行可见范围:沿用对象的内部共享模型(A,现状,公开对象全部行可见)、按 externalSharingModel 判(B)、还是只经分享链接(C) #23266 itself says this card is not dispatched before it answers.guestthrough the door; the guest's reach follows the [Decision] 访客(guest)的行可见范围:沿用对象的内部共享模型(A,现状,公开对象全部行可见)、按 externalSharingModel 判(B)、还是只经分享链接(C) #23266 letter; a package suggestion still never binds by itself (ADR-0090 D9).domain:spec, Clause-② yes); rationale: ADR-0138 D3 item 5 has no enforcer.objectstack-fleet commentedon Oct 13, 2026
Triage: the blocker moves from #23266 to #23224 (E1). Ruling C's order says no bind door before E1 lands with the C pin
Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T14:59Z. ⛔ Not a claim, ⛔ not a dispatch.6148183570, the maintainer's 「同意」 at 2026-10-13T14:43Z): a guest reaches rows through share links only, never through the object's sharing model.guest; the binding-door finding stays undispatched until then."guestanchor's bindings (D3, D4) #23224securitytarget:v18,domain:spec(Clause-②: yes). Under C, the door's pins check the C scope: a bound read set alone reaches no row; a share link reaches its record.objectstack-fleet commentedon Oct 13, 2026
Pointer for this card's dev, carried from E1 (PR #23321) ·
domain:engineseat 1 ·session_01P88ehrZ6hM19hBzdpsQTTo· 2026-10-13T19:13Z⛔ Not a claim, ⛔ no label change. E1's dev named this card the carrier of one out-of-scope finding (report 6152923496). The contract review (6153175742, ③) escalated it here.
plugin-sharing's platform bypass list skips record-level scoping for every principal, and that includes the guest:sys_user,sys_organization,sys_member,sys_record_share,sys_user_permission_set.guestset that names one of those objects would therefore reach it at the object level only.guestmay name those objects is the anchor tier's question. At E1's head,describeAnchorForbiddenBitsdoes not refuse them; that is a read-only reading.guest, or show why the object-level answer suffices. Pin it either way.Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Unlock scan:
pm:blocked→pm:queue. Ruling C's order is met: E1 (#23224) landed with the C pin as PR #23321 →37510aa0f9Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T20:57Z. ⛔ Not a claim, ⛔ not a dispatch.guestanchor's bindings (D3, D4) #23224 closedcompletedat 2026-10-13T20:02Z. Its landing record (6154108093) reads the C deny-all onmain, so a door that binds a set toguestno longer opens rows through the object's sharing model.securitytarget:v18,domain:spec(Clause-②: yes).6153215332. The pins check the C scope: a bound read set alone reaches no row, and a share link reaches its record.8 remaining items
objectstack-fleet commentedon Oct 14, 2026
席位意见 · director seat (summon #37,
session_01LqNgdPZB2Jnr5HpGbaqLeB), read on the maintainer's 「开始决裁」, 2026-10-14T00:34ZRead before writing: the dev's no-code report (6156571003), seat 2's decision analysis (6156613206), triage's grade, re-block and unlock (6147447462, 6148511128, 6155063299), E1's bypass-list pointer (6153215332); ruling C on #23266 (6148183570, items 1, 2 and 4). One fact moved since 6156613206 was written: PR #23334 merged at 2026-10-14T00:01Z, so the fence on
security-plugin.tsis lifted and the seat's reason to order A1 after it is gone. What is left is the choice itself.推荐:C(先改记录,形状记下,按需再建),回退 A1;⛔ 不选 A2。 这里我和席位 2 的字母不同,理由如下。
四维分析(业务立场)
anon角色),席位 2 说得对。但 ① 问的是「两年后的样子」,不是「今天就建」:C 把 A1 的形状(everyone同款的赋权记录、R1+b1 的公开形状、L1 的一份绕行名单声明)写进 ADR-0138 D3 item 5,将来建的时候一次建对;两个锚点「定义封存、记录赋权、派生再验」的规则在 C 下原样保留([Decision] 装包时包里声明的「默认权限集」怎么生效:管理员整部署接受一次、装包即自动生效,还是取消这条路(安全边界) #22801 裁 A),只有 A2 会推翻它。所以 ① 在 C 和 A1 之间不分高下,分高下的是 ②③④。guest仍然绑不上,E1 的读取方保持全拒的声明空态。A1 虽然守卫严密,但在 v18 发版压力下新增约 1000 行、一条公开路由、一个服务方法、一处记录格式放宽和一个 objectui 面板,每一处都是以后要防的面。四条口径(随 C 一起记)
sys_audience_binding_suggestion行(anchorguest,package_id在 guest 行上可选),插件按已接受的行重新派生 guest 的定义并每次过describeAnchorForbiddenBits(set, 'guest');绕行名单只声明一份,放在@objectstack/spec/security;锚点定义始终不可写。」Restart-when: 出现具名部署需要给访客绑权限集,且 class-1 表单门不能满足它。assertAudienceAnchorBindingGateguest 档今天没有活的写入会跑到它(休眠);objectuiSuggestedBindingsPanel钉着「guest 行不提供接受」。都在 A1 建时一并处理。回退 A1 的唯一条件:您知道 cloud 或某个客户正在等匿名门户。那时按席位 2 的两个子答案(R1+b1、L1)立即派发,围栏已经不在了。
置信缺口:cloud 或客户是否在等匿名门户,席位看不到;class-4/5 端点的行为是 dev 的读数,本席未复测。
裁后执行:席位 2 起草 D3 item 5 的改句 Tier H PR 交您批准;本卡按「实现优先、形状已记录」关闭,
Restart-when如上;E1 保持全拒的声明空态(D3 item 2)。objectstack-fleet commentedon Oct 14, 2026
Ruling: batch #1 item 4 · letter C · maintainer 「23267 我们的系统 和 salesforce 类似,暂时没有 没有公开站点或门户的产品计划」 2026-10-14T02:06Z
Director seat, summon #37,
session_01LqNgdPZB2Jnr5HpGbaqLeB, on the seat's reading 6158189687 (batch #1 item 4: recommendation C, fallback A1, ⛔ A2) and the long-term design discussion in chat, where the seat posed the fork "a public site or portal planned for v18–v19 → A1 with a surface scope now; none → C" and the maintainer answered as quoted. The same words answer the other two forks: the system is Salesforce-like, so the guest's grants are scoped per public surface (Salesforce: a guest user profile per site) and bound by the environment's administrator (Salesforce: the site's administrator).What the ruling binds (letter C):
guest, E1's reader stays at the declared empty state (D3 item 2, deny-all), and the record carries the door's shape.sys_audience_binding_suggestionrow for anchorguest,package_idoptional on a guest row; the plugin re-derives the guest definition from the accepted rows and runsdescribeAnchorForbiddenBits(set, 'guest')and the bypass-list refusal on every write and every derivation; anchor definitions stay sealed, [Decision] 装包时包里声明的「默认权限集」怎么生效:管理员整部署接受一次、装包即自动生效,还是取消这条路(安全边界) #22801 A), scoped to the public surface that publishes the door (the binding carries the app or site it serves; the anchor stays one identity), bound by the environment's administrator, never by a package (ADR-0090 D9). The bypass list is declared once in@objectstack/spec/security(L1).guestrecipient (D8) returning only in that stricter shape; not built now.assertAudienceAnchorBindingGate; objectuiSuggestedBindingsPanel's "a guest row offers no Accept" pin) close with this card and are re-read when the door is built.Workload of the letter (the card's column): one Tier H sentence on ADR-0138 D3 item 5 (about 20 lines), drafted by
domain:specseat 2 and approved by the maintainer's hand · precedent: ruling C on #23266 item 2 (named, not built) and its amendment PR #23326 (+28/−11, merged by the maintainer).Execution: seat 2 (
domain:spec#2, #18549) reclaims frompm:queue, drafts the Tier H PR carrying items 1–3 and the Restart-when, and closes this card "implementation-first, shape recorded" when it merges.needs-user-decisionremoved andpm:queueadded in this act; the body's first line carriesRuled:.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1, serial slot (#23267, ruling C
6159279205: ADR-0138 D3 item 5 amended implementation-first, with the bind door's shape recorded) · 2026-10-14T02:11ZSession:
session_01BRQ9Mp1yH7R1az6MaUM18HAccount:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-23267-adr0138-guest-door-shapeWorktree:
objectstack-issue-23267Domain:
domain:specSeat:
domain:spec#2(seat post #18549)Ruling-ref: the director seat's ruling
6159279205(batch #1 item 4, letter C, on the maintainer's words 「23267 我们的系统 和 salesforce 类似,暂时没有 没有公开站点或门户的产品计划」), on its reading6158189687; read in this act. Its execution line names this seat: draft the Tier H PR carrying items 1–3 and the Restart-when, and close the card "implementation-first, shape recorded" when it merges.File surface (at
origin/maindc393266for later; stop on a breach and explain it in the report):docs/adr/0138-guest-model-anonymous-principal-doors-grants-and-organization.mdonly: D3 item 5, plus an amendment line in the ADR's convention (AGENTS.md rule 13: a status or amendment line, never a rewritten decision). The precedent is PR docs(adr-0138): the guest reaches rows through share links only, never the object's sharing model (D3 item 6, ruling C) #23326 ([Decision] 访客(guest)的行可见范围:沿用对象的内部共享模型(A,现状,公开对象全部行可见)、按 externalSharingModel 判(B)、还是只经分享链接(C) #23266), one file, +28 / −11.content/docs/**, noskills/**. E1's reader stays at the declared empty state, and nothing inpackages/**moves.Container & model:
S,mode:subagent,model: default tier(dispatch-gates --tierondc393266f: "no path-derived mandate: the surface hits none of the 3 declared glob(s)"). Landing is Tier H: the PR stays a draft until an authorized approval byos-zhuangorhotlong.Clause-②: no (an ADR record amendment; no door, schema or published surface moves), as on PR docs(adr-0138): the guest reaches rows through share links only, never the object's sharing model (D3 item 6, ruling C) #23326
Responsibility: ADR-0138 D3 item 5 declares a bind door that no code enforces | the platform path that covers it: E1's reader at the declared empty state (deny-all) and the class-1 form doors for anonymous collection | who reaches it: no named deployment (E1's census: 0 guest bindings in the reference apps; hotcrm's guest set serves a form door)
Thread-read:
6159279205Serial constraints cleared: no open PR touches
docs/adr/0138-*(every open PR's file list read in this act). The in-flight claims that name ADR-0138 are disjoint: C3 #15204 ADR sweep: ten ADRs cite the four catalog row objects that stage 8 retires; record the retirement per the ADR convention after stage 8 (governed, Tier H) #22978 edits eleven other ADRs, not 0138; ADR-0138 E2: the closed list of doors recorded in the conformance matrix, denial by domain, and D2b's publish refusal (D2, D2b) #23225 edits code and only cites the record. Serial dispatch is in force for this seat (seat post [PM seat] domain:spec · seat 2 — 🟢 os-justin · session_01BRQ9Mp1yH7R1az6MaUM18H #18549, Terms).This act moves the card
pm:queue→pm:dispatchedand assignsos-justin. The PR body's first line isFixes #23267, as the ruling's close condition reads.objectstack-fleet commentedon Oct 14, 2026
os-dev-report
{ "issue": 23267, "status": "done", "branch": "claude/issue-23267-adr0138-guest-door-shape", "pr": "https://github.com/objectstack-ai/objectstack/pull/23370", "session": "session_01BRQ9Mp1yH7R1az6MaUM18H (subagent: the parent's id; the relay envelope resolved the same id from the container)", "premise_still_valid": true, "summary": "Draft PR #23370 (Tier H, head cc9a40576, one file, +41/-8) amends ADR-0138 under ruling C on #23267 (6159279205). D3 item 5 now reads implementation-first. The door is built when a named deployment needs to grant the guest on a public surface and the class-1 form doors cannot serve it. Until then E1's reader stays at the declared empty state, because no door binds a set to guest. The item names the three refusals that hold this, each measured at dc393266f: the metadata door's 403 NOT_OVERRIDABLE on the packaged guest position, the package door's built-in-name refusal, and confirmAudienceBindingSuggestion's refusal of a guest row, which the sync never produces. The item records the door's shape (ruling items 1-3, the L1 bypass list, the surface scope, never a package), A2's refusal with its reason (item 4), and the Restart-when with the two carried findings as re-read items (item 5). One '· **Amended** (2026-10-14, ruling C on #23267, ...)' line continues the status paragraph; the status stays Accepted. Three consistency edits in the same file: the Consequences bullet that named the two paths as live, one Enforcement map row for the amended item's declaration, and follow-up F4. No other decision is edited; D8, D3 item 4 and the Context reading are left as they are and named in Acceptance notes.", "zone2_readings": { "1_only_live_sentence": "Disproved in part. D3 item 5 (dc393266f :368-371) is the item that states the door as live, but three more passages in the same ADR lean on it. (a) The Consequences bullet 'directly or through a confirmed suggestion': edited. (b) D8's row for the suggestion anchor's guest value, 'enforce - live once D3 lands': not edited, because D8 is a separate decision; item 5 now says that value goes live with the door. (c) The Context reading at 7b926f7600, 'A package may suggest a guest binding': a dated reading, not edited. D3 item 2 (the empty state) is consistent and unchanged. D3 item 4 and the Enforcement map's 'anchor binding tier ... enforced' row are unchanged; item 5 names the dormant guest tier as a re-read item, per ruling item 5. D3's own 'Enforced by' paragraph concerns E1 and is unchanged. The Enforcement map gains one row, because the record's preamble requires an enforcer for every declared thing.", "2_status": "Holds. The status stays Accepted, and one Amended line follows #23266's line, in PR #23326's form.", "3_re_read_placement": "Holds. The two re-read items sit in D3 item 5, where the door's builder reads the shape. Follow-up F4 points there, in the form F2 uses for D5's site binding.", "4_size": "Measured +41/-8 against the precedent's +28/-11. Item 5 alone is +28/-4 against the ~20-line estimate: it carries five ruling items, three measured refusals and two re-read pointers, and three citations with full links take six of its lines. The three consistency edits add a net 5 lines." }, "tests": "Docs only: no package touched, so no build, test or typecheck target of its own, and no ablation. Prerequisite build for check:doc-formula-expressions, under the lock (slot issue-23267-lint-build): `turbo run build --filter=@objectstack/lint --concurrency=2` gave 'Tasks: 4 successful, 4 total' and 'VERDICT command-exit 0 · held the lock 162s'. Gates are in `gates`. Extra control: OBJECTUI_CHECKOUT=/home/user/objectui node scripts/check-adr-symbol-anchors.mjs exited 0 with '2335 anchors across 142 records resolve'. This judges the new cross-repo anchor objectui:packages/app-shell/src/components/SuggestedBindingsPanel.tsx, which the plain run reports as cross-repo-skipped. Control-byte self-scan (grep -naP) of the edited file and the PR body: none. Quote bytes: the maintainer quotation in the Amended line matches the ruling comment's first line byte for byte (grep -c -F = 1, full-width comma U+FF0C included).", "gates": "On final head cc9a40576, `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; merge base dc393266f, 1 path) exited 0 with 19 commands, identical to the PM's lead list. Each was run with its exit code captured before any pipe; all 19 exit 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, lint 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. The `--ran` reconcile exited 0: '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)'. Verdict lines: 'check-adr-links: 730 relative link destination(s) under docs/adr/ resolve'; 'check-adr-symbol-anchors: 2335 anchors across 142 records resolve'; 'check-adr-anchors: OK (68 anchored file(s) ... 45873 citation(s) across 6019 file(s) resolve ...)'; 'check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords ...)'; 'check-nul-bytes: OK (scanned 11352 text file(s) ... no raw ASCII control bytes)'. NOT MEASURED locally, outside the derived set: the CI-only families the derivation lists (the Test Core shard job, the type-check lanes, the WIDE and artifact-roster families). Those are CI's.", "line_budget": "n/a: no skills/** path", "files_changed": "docs/adr/0138-guest-model-anonymous-principal-doors-grants-and-organization.md only (+41/-8)", "labels": "skip-changeset added through scripts/pm/label-write.mjs (relay run 38501801529); read-back: documentation, size/s, skip-changeset; assignee os-justin. documentation and size/s were applied by the labelers, not by this run", "pr_state": "Draft, head cc9a40576, assignee os-justin. The body was read back byte-identical (18533 bytes): line 1 the closing-keyword line naming this card, line 2 'Clause-②: no', the ## 维护者速读(草稿) section with 席位意见 left empty, and the session-URL footer. Not readied, not queued, no reviews requested.", "deviations": [ "Beyond the ruled item, three consistency edits in the same file: the Consequences bullet, one Enforcement map row and follow-up F4. Zone 2 item 1 asks for this; the PR body and 维护者速读 flag each for the maintainer.", "Item 5 adds four facts beyond the ruling's words, flagged for review in the PR body: the three measured refusals, 'as it does everyone's', '(D8's guest value, live with this door)', and where the bypass list lives today.", "Attribution: the harness reminder asked for a model-named Co-Authored-By trailer and an emoji-led PR footer. The commit carries AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), and the PR body ends with the AGENTS.md session-URL footer. The reminder itself gives repo instructions precedence.", "Cleanup runs AFTER this comment, as the run's last step: rm -rf node_modules and git worktree remove for /home/user/objectstack-issue-23267. The order is forced because the comment tool imports typescript from that worktree's node_modules. The two background processes this run started (pnpm install PID 1029, gate runner PID 2626) have exited. No server or monitor was started." ], "mcp_calls": "0", "api_writes": "4 REST writes in 3 relay strokes (each stroke is one POST /repos/objectstack-ai/objectstack/dispatches; fleet-write.yml executed them as objectstack-fleet[bot]). (1) pr_create, run 38501706438: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23370/assignees. (2) labels_add, run 38501801529: POST /repos/objectstack-ai/objectstack/issues/23370/labels. (3) This comment: POST /repos/objectstack-ai/objectstack/issues/23267/comments. git push (2: the empty probe, then cc9a40576) is not a REST write.", "open_questions": [], "out_of_scope_findings": [ "carrier: domain:spec seat 2 (the seat may fold all three into one Tier H ADR-0090 status-line pointer to ADR-0138 D3 item 5, or into the F4 build card) · one family: texts outside ADR-0138 that still state the guest suggestion or bind path as live; not edited, per the dispatch's one-file surface. (1) docs/adr/0090-permission-model-v2-concept-convergence.md:356-357: 'a package may suggest bindings to `everyone` **or** `guest`; the admin confirms each individually'. (2) packages/lint/src/validate-security-posture.ts:33-37 and :773-775: 'a set an operator binds to `guest` at install time ...' / 'judged by the bind-time gate alone'. (3) packages/spec/src/identity/position.zod.ts:164-165: 'Packages SUGGEST bindings to these anchors at install time'. Evidence at dc393266f: collectDeclaredSuggestions hard-codes EVERYONE_POSITION, confirmAudienceBindingSuggestion refuses a non-everyone row (409 SUGGESTION_STATE), and the package door refuses a built-in position name. No public-door reading of the suggestion half was taken, so this is noted, not filed · dedupe words: guest suggestion live text; ADR-0090 D9 guest suggest; operator binds guest install docblock", "carrier: the F4 bind-door build (D3 item 5's Restart-when) · E1's changeset .changeset/23224-guest-grants-channel.md:13 says a set starts granting 'only where a deployment holds an environment definition of the `guest` position that names it'. That is true today as a necessary condition. Under the recorded shape, the grant arrives through the plugin's re-derived definition instead, so the builder's changeset should say so · noted, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
✅ ACCEPT: PR #23370 at
cc9a40576(Fixes #23267), Tier H. It waits for an authorized approval, then the seat lands itdomain:specseat 2 (#18549) ·os-justin· sessionsession_01BRQ9Mp1yH7R1az6MaUM18H· 2026-10-14T02:41Z · holder of claim6159342669. Report:6159642131. Thread-read: the report.Read on GitHub:
main, assigned toos-justin, labelledskip-changeset. Line 1Fixes #23267, line 2Clause-②: no.docs/adr/0138-guest-model-anonymous-principal-doors-grants-and-organization.md, +41 / −8.check-governed-merges --pr 23370: 1 of 1 path hits the governed register (docs/adr/**), so Tier H; 49 changed lines.Read against ruling C (
6159279205), item by item, on the diff:guest, and E1's reader stays at the declared empty state.sys_audience_binding_suggestionrow for anchorguest,package_idoptional, scoped to the public surface that publishes the door;describeAnchorForbiddenBits(set, 'guest')and the bypass-list refusal on every write and derivation;@objectstack/spec/security.Restart-when, with the two carried findings as re-read items. Follow-up F4 points at them.· **Amended**line is in PR docs(adr-0138): the guest reaches rows through share links only, never the object's sharing model (D3 item 6, ruling C) #23326's form, the status staysAccepted, and the maintainer's words are quoted byte for byte.The additions beyond the ruling's words, accepted:
dc393266f: the three refusals that hold the door shut today (the anchors'NOT_OVERRIDABLE, the package door's built-in names, andconfirmAudienceBindingSuggestion's refusal of aguestrow); "as it doeseveryone's", which matches the acceptance-record path security: no door can bind a permission set to theguestanchor — ADR-0138 D3 item 5 has no enforcer (PUT /meta/position/guestanswers 403 NOT_OVERRIDABLE; guest suggestions are refused) #23267's first dev measured; and where the bypass list lives today.Gates: 19 derived, all 19 exit 0 on
cc9a40576, reconciled by--ran.check-adr-symbol-anchorswith the objectui checkout resolves the new cross-repo anchor.Report items:
:375-376),packages/lint/src/validate-security-posture.ts(:33-37,:773-775) andpackages/spec/src/identity/position.zod.ts(:164-165). Filed as one family card, docs/docblocks: ADR-0090 D9,validate-security-posture.tsandposition.zod.tsstill say a package suggests, or an operator binds, aguestset; after ruling C on #23267 no door bindsguestuntil ADR-0138 D3 item 5's door is built #23373.Landing (Tier H):
needs-user-decisionis added to PR #23370, the final 维护者速读 is posted there, andos-zhuangandhotlongare requested as reviewers, all in this act. The PR stays a draft. With an approval from either account, the seat runs the landing checks, readies it and arms the queue. The card stayspm:dispatchedwithos-justinuntil MERGED.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
✅ Authorized approval in; PR #23370 at
cc9a40576is in the merge queue (Fixes #23267, Tier H)domain:specseat 2 (#18549) ·os-justin· sessionsession_01BRQ9Mp1yH7R1az6MaUM18H· 2026-10-14T03:09Z · holder of claim6159342669. Thread-read:6159686556.os-zhuang, review5512598183, APPROVED at 03:08:32Z oncc9a40576(the current head). The account is inGOVERNED_APPROVERS. The approver readied the PR and added it to the merge queue in the same minute (03:08:35Z and 03:08:37Z).cc9a40576:check-governed-merges --pr 23370: governed, landing tier H, "an authorized APPROVED review (GOVERNED_APPROVERS) and then the owning seat lands it";Governed Surface Queue Guardis re-running on the new review, and auto-merge waits for it.needs-user-decisionremoved from PR docs(adr-0138): the guest's bind door is built implementation-first, with its shape recorded (D3 item 5, ruling C) #23370 (the maintainer's review is done). The seat'sautomerge_enablefound the PR already queued by the approver.Next: confirm MERGED, the mis-close scan, and the landing record. The card then closes "implementation-first, shape recorded", as the ruling's execution line reads.
Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed: PR #23370 →
6eb6f7d65(Fixes #23267), Tier H onos-zhuang's approval. The card closedcompleted: implementation-first, shape recordeddomain:specseat 2 (#18549) ·os-justin· sessionsession_01BRQ9Mp1yH7R1az6MaUM18H· 2026-10-14T03:35Z · holder of claim6159342669. Thread-read:6160003145.6eb6f7d65, an ancestor oforigin/main, onos-zhuang's APPROVED review (5512598183, on the merged headcc9a40576). One file, +41 / −8.check-governed-merges --pr 23370: governed, landing tier H.6159279205) in ADR-0138 D3 item 5.guest, and E1's reader stays at the declared empty state.Fixes #23267. One other issue closed in the same queue batch, automation: a stored flow the engine refuses at cold boot is withdrawn with a warn, while the metadata read keeps serving it asstatus: 'active'— after the v18 upgrade, every refused flow reads as running #23316, by its own PR fix(automation,metadata-protocol,rest,spec): a stored flow the engine refuses is served beside its verdict, not as running #23358 (Fixes #23316).pm:dispatchedis removed in this act.validate-security-posture.tsandposition.zod.tsstill say a package suggests, or an operator binds, aguestset; after ruling C on #23267 no door bindsguestuntil ADR-0138 D3 item 5's door is built #23373 (three texts outside ADR-0138 still state the old guest path as live). The ruling's close condition is met by this merge.Generated by Claude Code