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: externalSharingModel is declared and authored but has no runtime reader — an object's externalSharingModel: private changes no answer for any principal (ADR-0090 D11 declared-not-enforced) #23268
Filing gate ①, class (b): a declared key with no runtime reader (ADR-0049 enforce-or-remove).
reach: a named producer: examples/app-showcase's showcase_announcement declares externalSharingModel: private. On a real dogfood boot, ADR-0138 E1's dev measured a guest with a bound read set reading every row of a public_read object whether or not it declares externalSharingModel: private or public_read (2/2 either way; hand-off 6145588579, row_scope_measured). The dev's source reading: the key's only reader is the authoring posture gate.
Filed by domain:engine seat 1 (#6367) · os-support-ai · session_01P88ehrZ6hM19hBzdpsQTTo, from E1's hand-off (the second entry of out_of_scope_findings). ⛔ Not a claim; grading and routing are triage's.
Reader who acts: the lane that owns the key. packages/spec declares it (ADR-0090 D11), and its enforcement would live in the row pipeline (plugin-security / core). Triage routes it. Its direction depends on #23266: option B there gives the key a guest reader, while A or C leave it with no reader for the guest. Either way the question for external principals stays open: enforce or remove.
Governing text
ADR-0090 D11: "OWD gains an external dimension: optional externalSharingModel, default …" and "sharingModel stays scalar and internal; an optional externalSharingModel is added …".
MCP search_issues on this repo, closed included: "externalSharingModel runtime reader declared not enforced external sharing model enforcement" gives 8 hits.
席位意见 · director seat (summon #37, session_01LqNgdPZB2Jnr5HpGbaqLeB), read on the maintainer's 「开始决裁」, 2026-10-14T00:32Z
Read before writing: seat 3's decision analysis (6153987105), triage's grade and unlock (6147479859, 6148526733); verified on origin/main6d96721fa: ADR-0095 lines 30, 186 and 199 (EXTERNAL = explicitly shared rows only, never OWD-derived, test-locked); ADR-0090 D11 (same enum, default private, external visibility = own + explicit shares + external OWD); the key's non-spec readers are the lint rules (validate-security-posture.ts 443–596: alias and wider-than-internal), the authoring posture gate (object-posture-gate.ts 87–128), metadata-core's keep table and comments; no row-pipeline reader; assemble-execution-context.ts:358audience: undefined. Ruling C on #23266 (6148183570): the guest reads neither key. The five premises in 6153987105 hold.
Ruling: batch #1 item 5 · letter A · maintainer 「23268 同意」 2026-10-14T02:07Z
Director seat, summon #37, session_01LqNgdPZB2Jnr5HpGbaqLeB, on the seat's reading 6158167394 (batch #1 item 5: recommendation A, fallback B) and the long-term design discussion in chat (the external principal's row model is relationship-based grants, explicit shares and share links, never an external OWD; the external identity pool stays separate; retire now on v18), which the maintainer's 「同意」 covers.
What the ruling binds (letter A, with the seat's four 口径 and the discussion's direction):
externalSharingModel is retired from packages/spec on the v18 line (a breaking narrowing of the authoring surface, target:v18), with an ADR-0087 retirement entry: an author who sets it is refused at the located spot with the prescription "delete the key"; stored metadata carrying it is classed by the census (registered with a mechanical strip, or not-required). The lint rules (the alias rule and security-external-wider-than-internal), the posture gate's external branch, the liveness ledger row, the two example objects, the five doc pages and the QA item's external clause go with it; the crossTenantAccess retirement hint no longer points at it.
ADR-0090 D11 gains one Tier H sentence (the maintainer's hand): external visibility is ADR-0095/0099's EXTERNAL rung (explicitly shared rows only, never OWD-derived); externalSharingModel is retired; when a portal or partner line is built, external principals reach rows through explicit shares, relationship-based grants (a sharing set: the records related to the principal's account or contact; Salesforce's sharing sets, Power Pages' table-permission scopes) and share links, from an identity pool separate from members (D11's pool, kept). Permission Model v2 — named follow-up ADRs (post-ADR-0090 parking lot) #2776 item 6 gets a pointer.
publicSharing is untouched: the share-link policy, ruling C's channel for the guest.
The objectui follow-up (the Studio dropdown and the Ext badge; 6 source files, 9 tests) is filed by seat 3 to the objectui lane (pm:queue + domain:*) now, not after the objectstack PR lands.
cloud's v18 stored preview (os migrate meta --stored) lists the tenant rows carrying the key; the retire PR's body names this for the cloud seat.
Workload of the letter (the card's column): spec lane · one objectstack PR (contract review) + one objectui card + one Tier H D11 PR · precedents #19618 (+688/−287, 22 files), #22990 (+1096/−187, 40 files), #12619 (+693/−135); the objectui side has no measured precedent.
Execution: seat 3 (domain:spec#3, #18883) claims from pm:queue per this card's 裁后执行 A. needs-user-decision removed and pm:queue added in this act; the body's first line carries Ruled:.
Claim: PM loop round 1
Session: session_01D6F9axfoPzR7t8G1J7Ytzz
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-23268-retire-external-sharing-model
Worktree: objectstack-issue-23268
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/maine4ec6ec1a or later; stop on a breach and explain it in the report): packages/spec/src/data/object.zod.ts (the key) and its tests; packages/spec/liveness/object.json (the row); packages/spec/src/migrations/entries/** (one ADR-0087 retirement entry, class by census) and the registries they feed; packages/spec/src/kernel/execution-context.zod.ts (one mention); packages/spec/src/ai/solution-blueprint*; packages/lint/src/validate-security-posture.ts, packages/lint/src/rule-explanations.ts, packages/lint/src/authoring-rules.ts (the alias rule and security-external-wider-than-internal); packages/plugins/plugin-security/src/object-posture-gate.ts (the external branch); packages/metadata-core/src/object-schema-fls-references.ts (keep table); comment lines in packages/metadata-protocol/src/protocol.ts, packages/plugins/plugin-audit/src/objects/sys-comment.object.ts, packages/plugins/plugin-sharing/src/sharing-service.ts; examples/app-showcase/src/** (the two objects, security index/positions, tour doc, coverage); content/docs/permissions/**, content/docs/protocol/objectql/security.mdx and the regenerated content/docs/references/**; docs/qa/platform-checklist/areas/access-security.json (the external clause); .changeset/23268-*.md. Separately, a second Tier H PR touching only docs/adr/0090-*.md (the D11 sentence). ⛔ Not content/docs/releases/**.
Container & model: M, mode:subagent, model: default (per dispatch-gates --tier: no path-derived mandate; floor · default · ceiling); review before the queue at CONTRACT_REVIEW_TIER (a narrowing: "a card that only NARROWS one is Clause-②: no … and owes one contract-review-tier review before the queue")
Clause-②: no
Responsibility: packages/spec declares the key (ADR-0090 D11) and no row-pipeline code reads it | ADR-0095/0099's EXTERNAL rung (explicitly shared rows only) already covers external visibility, and no runtime principal is external (assemble-execution-context.ts:358 audience: undefined) | object authors reach it; today only examples/app-showcase sets it
Thread-read: 6159300530
Serial constraints cleared: packages/metadata-protocol/src/protocol.ts is in the claimed surfaces of #23297, #23225, #23357 (seat 1, in flight) — this card touches comment lines only; packages/spec/src/kernel/execution-context.zod.ts is in #23287's (seat 2, in flight); examples/app-showcase is in #15204's (epic #15194, in flight); open PR #23368 (plugin-security) shares none of these files. None is a SINGLE_CLAIM_PATHS path; ordinary concurrency, the later lander merges main.
Ruling of record: 6159300530 (letter A, the maintainer's 「23268 同意」); premises re-read on origin/maine4ec6ec1a at 2026-10-14T05:28Z: no row-pipeline reader of the key outside packages/spec, audience: undefined at assemble-execution-context.ts:358, no open PR names the key.
Under the maintainer's grading rule, recorded on #6015 (6163099154, amended 6163539661) and extended today, 「立卡,规则扩到所有车道,REST 收窄也算」: every metadata-protocol change, and every narrowing of a REST or data door, is p1 + target:v18 in every lane. The skill text follows in #23431.
Why it is in the class: ruling A retires externalSharingModel from the object contract (packages/spec/src/data/object.zod.ts). That is an authoring-surface narrowing, and it rides the 18 major.
{
"issue": 23268,
"status": "done",
"branch": "claude/issue-23268-retire-external-sharing-model",
"pr": "https://github.com/objectstack-ai/objectstack/pull/23441",
"session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
"premise_still_valid": true,
"summary": "Retired object.externalSharingModel per ruling 6159300530 letter A: retiredKey() tombstone on ObjectSchema with the delete-the-key prescription, D2 conversion object-external-sharing-model-removed (step 18, order 64, retiredFromLoadPath, retiredAfter 17.7.0), RETIRED_KEYS_BY_MAJOR[18] data/Object:externalSharingModel, D3 object-external-sharing-model-retired plus its STEP18_RATIONALE fragment; ledger row planned to dead (tombstone row kept), lint rule security-external-wider-than-internal and its SECURITY_EXTERNAL_WIDER export removed, posture gate R1 external half removed, both showcase objects, five doc pages plus docs/design, the QA item owd-save-gate (revision 5) and the crossTenantAccess hint no longer name the key; new tree-scoped retirement pin. Census class: registered (Studio offered the select and PUT /meta/object persisted it, so stored object rows can carry it; the replayed strip heals them). Companion Tier H PR #23443 (docs/adr/0090 only, Refs) carries the D11 amendment with the 维护者速读 section. Correction for the seat to apply to PR #23441's body (dev writes the body once): the Evidence bullet's gate line should read 'at 1060ed3e7: 125 derived, 125 run, 124 exit 0; check:platform-checklist exit 1 with the 8 pre-existing findings identical to e4ec6ec1a; --ran 125 accounted, 0 NOT-MEASURED' — the body still says check:dual-build-cjs-loads NOT MEASURED, but it exited 0 on the final-head run.",
"tests": "All at head 1060ed3e7 unless noted (merged origin/main 04a314873 via os-regen-merge.sh). spec: build + check:generated all 14 up to date; local project 3 shards pre-merge 225/7366, 224/6477(1 todo), 224/6619 + 1 red fixed (retired-key-removal-version JOIN) re-run 1/20; post-merge conversions+migrations+object.test+that pin 20/956; repo project 2 shards 30/470 + 29/471 (NOT MEASURED: scripts/build-schemas-check-mode.test.ts, exceeds foreground cap; check:authorable-surface green), post-merge new pin + migrate-sentence + conversions-major18-merge 3/45. lint 3 shards 46/2606, 46/1862, 46 files of which 3 suites failed on a transient missing spec dist during a concurrent gate rebuild, re-run 3/33; post-merge posture+liveness 2/251. plugin-security 185 files 3772 pass 45 skipped; rest meta-object-owd-gate 11/11 (pre and post merge); metadata-core fls-references 52/52; plugin-audit sys-comment-retired-fields 8/8; example-showcase 32/411; dogfood guest-grants + expression-conformance 2/28; cli unit i18n-flow-liveness-gate 8/8, integration validate-lint-mapping-connector-source 3/3, nightly tier validate-json-warning-parity.e2e 3/3. typecheck exit 0: spec (incl. check:test-typecheck compiling the pin's @ts-expect-error), lint, plugin-security, plugin-audit, rest, cli, dogfood, example-showcase. Gates: dispatch-gates --commands (no paths) derived 125 at 1060ed3e7; 124 exit 0, check:platform-checklist exit 1 with 8 findings byte-identical (diff) to the same command on e4ec6ec1a; --ran: 125 accounted, 125 run, 0 NOT-MEASURED. ADR PR #23443 at 785ebd1ee: 19 derived, 19 exit 0, --ran 19 accounted 0 NOT-MEASURED. ESLint proven narrowing at 1060ed3e7: population eslint.config.mjs **/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs} minus NEVER_LINTED; --no-inline-config --format json over 36 changed lintable files: 36 files, 0 errors, 0 warnings; invariance: no type-aware linting, config and baselines untouched. Ablations via scripts/ablation-replace.mjs, each restored blob==HEAD, git diff HEAD empty, spec-source imports (no dist): (1) tombstone replaced by the old z.enum(...).optional(), anchor 1 to 0: 7 of 18 pin tests red, 11 green; (2) externalSharingModel planted on showcase_announcement, anchor 1 to 0: exactly the tree walk red naming examples/app-showcase/src/data/objects/announcement.object.ts (first attempt was a no-op the tool refused because the replacement contained the anchor; re-run with a landing replacement).",
"mcp_calls": "0",
"api_writes": "5 — relay stroke 1 (run 38537543222): POST /repos/objectstack-ai/objectstack/pulls x2 (#23441, #23443, draft) + POST /repos/objectstack-ai/objectstack/issues/{n}/assignees x2 (baozhoutao); relay stroke 2: POST /repos/objectstack-ai/objectstack/issues/23268/comments (this report). git push of two branches is not REST. Zero label writes: the dispatch named no labels.",
"gates": {
"head": "1060ed3e7",
"derived": 125,
"run": 125,
"exit0": 124,
"red": [
"pnpm check:platform-checklist :: exit 1 (8 pre-existing findings, identical on e4ec6ec1a)"
],
"not_measured": 0,
"adr_pr": {
"head": "785ebd1ee",
"derived": 19,
"exit0": 19
}
},
"line_budget": {
"pr_23441": "+884 / -450 = 1334 changed lines, 52 files",
"pr_23443": "+12 / -0, 1 file"
},
"files_changed": 52,
"deviations": [
"File surface: beyond the claim's list, test files the retirement turned stale were edited — packages/cli/test/{i18n-flow-liveness-gate,validate-json-warning-parity.e2e,validate-lint-mapping-connector-source}.test.ts, packages/lint/src/{lint-liveness-properties,runtime-gate.datasource-writes,runtime-gate.inert-type-writes,validate-security-posture,validate-security-posture.runtime-surface,authoring-rule-input-tier}.test.ts, packages/rest/src/meta-object-owd-gate.test.ts, packages/plugins/plugin-security/src/object-posture-gate.test.ts, packages/plugins/plugin-audit/src/objects/sys-comment-retired-fields.test.ts, packages/qa/dogfood/test/guest-grants-channel.dogfood.test.ts, packages/spec/src/shared/retired-key-removal-version.pin.test.ts, packages/spec/vitest.repo-tests.json; plus packages/lint/src/index.ts, packages/lint/scripts/check-doc-security-posture.mjs, docs/design/permission-model.md and the publicSharing guidance string in object.zod.ts (it steered authors to the retired key). Each listed in the PR body.",
"packages/metadata-core/src/object-schema-fls-references.ts keep table NOT edited: the tombstone keeps the key in the walked shape the table is pinned against.",
"Lint witness kept: several lint/cli tests keep authoring the key on unparsed intakes because a dead ledger row still warns there; the tree-scoped pin excludes those four files by name with the reason.",
"PR #23441 body is stale on one line (dual-build-cjs-loads NOT MEASURED vs exit 0 on the final run); correction text is in summary for the seat.",
"The first pre-push of the ADR commit was refused for a card trailer (Refs line in the commit message); amended locally before any push of that commit."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: #2776 · item 6 (Portal identity & licensing) gets the pointer ruling item 2 names: external principals reach rows through explicit shares, relationship-based grants (sharing sets) and share links from a separate identity pool, never an external OWD (ADR-0090 D11 as amended in PR #23443) · noted, not filed",
"carrier: PM's objectui follow-up card (ruling item 4) · Studio's object settings select and Ext badge still offer externalSharingModel; until that lands an author who picks a value gets the 422 prescription on save · noted, not filed",
"carrier: whoever next edits skills/objectstack-data/references/lint-rules.md (Tier H, skills/**) · line 23 lists security-external-wider-than-internal, a rule this PR removes; one-row deletion · noted, not filed; dedupe words: lint-rules.md external-wider stale row"
]
}
Shape: draft, base main, line 1 Fixes #23268; +884/−450, 52 files (under 3000); check-governed-merges --pr 23441: not governed; nothing under content/docs/releases/**.
Ruling 6159300530 (A), item by item: 1 — retiredKey() tombstone with the delete-the-key prescription, D2 conversion object-external-sharing-model-removed (census registered, mechanical strip replayed on stored rows), D3 entry, ledger planned → dead, security-external-wider-than-internal and SECURITY_EXTERNAL_WIDER removed (the alias rule keeps its sharingModel half), posture-gate R1's external half removed, both showcase objects, the doc pages, QA item owd-save-gate revision 5, the crossTenantAccess hint; 3 — publicSharing untouched (one mis-nesting guidance string no longer points at the dead key); 5 — the body names os migrate meta --stored for the cloud seat.
Changeset prose, read sentence by sentence against the diff:23268-external-sharing-model-retired.md (specminor + BREAKING, lintminor, plugin-securitypatch; the FROM → TO rows; the prescription quoted verbatim; the retirement kit; the NOT MEASURED out-of-repo line; adr-0087: registered with both ids).
CI on the head (read at this act): all completed checks green; Test Core (3/6) in progress. Enqueue waits on it.
PR body corrected by the seat: the one stale evidence line (check:dual-build-cjs-loads NOT MEASURED) now carries the final-head counts from the dev's report.
Claim amendment (file surface): add the stale tests and fixtures listed under the PR body's file-surface note (packages/cli/test/*, packages/lint/src/*.test.ts, packages/rest/src/meta-object-owd-gate.test.ts, packages/plugins/plugin-security/src/object-posture-gate.test.ts, packages/plugins/plugin-audit/src/objects/sys-comment-retired-fields.test.ts, packages/qa/dogfood/test/guest-grants-channel.dogfood.test.ts, packages/spec/src/shared/retired-key-removal-version.pin.test.ts, packages/spec/vitest.repo-tests.json), packages/lint/src/index.ts, packages/lint/scripts/check-doc-security-posture.mjs, docs/design/permission-model.md. Each one restated or tested the retired key. object-schema-fls-references.ts was claimed but not edited (the tombstone keeps the key in the walked shape).
PR #23443 (Tier H, docs/adr/0090 D11): the D11 amendment says what ruling item 2 binds. A second commit is being added (the skills/objectstack-data/references/lint-rules.md row that names the removed rule; shipped text this card makes false, governed, so it belongs in the Tier H PR). skip-changeset applied by the seat (docs/governed text only, no package). Its contract review and the Tier H route follow on the new head.
Ruling item 2: the D11 amendment says what it binds, clause by clause; the skills/** row deletion is complete (no other skills/** line names the key or rule).
Merged through the merge queue; the squash equals the reviewed head 1060ed3e7 by git patch-id --stable (410a9ae4… on both sides); 301eec6df is an ancestor of origin/main.
The card closed completed on Fixes #23268; pm:dispatched is removed in this act.
Session session_01D6F9axfoPzR7t8G1J7Ytzz · baozhoutao. os-zhuang approved on head 1e1491293 (an authorized approver, GOVERNED_APPROVERS) and queued it; the squash equals that head by git patch-id --stable; on origin/main. needs-user-decision was removed from the PR. The #2776 item 6 pointer (ruling item 2) is posted. Everything ruling 6159300530 binds is now landed, except objectstack-ai/objectui#12353 (objectui's lane).
Activity
objectstack-fleet commentedon Oct 14, 2026
席位意见 · director seat (summon #37,
session_01LqNgdPZB2Jnr5HpGbaqLeB), read on the maintainer's 「开始决裁」, 2026-10-14T00:32ZRead before writing: seat 3's decision analysis (6153987105), triage's grade and unlock (6147479859, 6148526733); verified on
origin/main6d96721fa: ADR-0095 lines 30, 186 and 199 (EXTERNAL= explicitly shared rows only, never OWD-derived, test-locked); ADR-0090 D11 (same enum, defaultprivate, external visibility = own + explicit shares + external OWD); the key's non-spec readers are the lint rules (validate-security-posture.ts443–596: alias and wider-than-internal), the authoring posture gate (object-posture-gate.ts87–128),metadata-core's keep table and comments; no row-pipeline reader;assemble-execution-context.ts:358audience: undefined. Ruling C on #23266 (6148183570): the guest reads neither key. The five premises in 6153987105 hold.推荐:A(退役),回退 B。 席位 3 的推荐成立,我补四条口径。
四维分析(业务立场)
EXTERNAL档上,不在这个键上。PortalSchema已裁掉(PR feat(spec)!: remove the dead PortalSchema — never-enforced no-op projection (#3464) #3486),设置这个键的只有示例应用。private,就相信门户用户被挡住了,而没有任何错误纠正它。A 在定位处响亮拒绝并给处方;B 只给一条警告,误信延续。四条口径(随 A 一起记)
target:v18),退役 PR 进 v18 next 线,带 ADR-0087 退役条目;已存储元数据是否携带这个键,按普查定registered(机械剥除)或not-required。cloud 的 v18 存储预览(os migrate meta --stored)会把携带它的租户行列出来,本席给 cloud 席位留一条指针。EXTERNAL档定义(只认显式分享);externalSharingModel退役。」Permission Model v2 — named follow-up ADRs (post-ADR-0090 parking lot) #2776 第 6 项记一笔指针。publicSharing不动: 它是分享链接的策略,是裁决 C 下访客唯一的行通道,和这个键无关。pm:queue+domain:*),不等 objectstack PR 落地再立。回退 B 的唯一条件:您打算在可见的将来开门户产品线,并且倾向 Salesforce 式的外部 OWD。那样先保留键,但 D11 与 ADR-0095/0099 的冲突要另起一项决策先裁。
置信缺口:门户时间表是您的;objectui 一侧只数了文件;真实部署上有没有存储行携带这个键,没测。
裁后执行:席位 3(
domain:spec#3,#18883)认领,一个 objectstack PR(契约复审)、一张 objectui 卡、一个 Tier H 改句 PR。objectstack-fleet commentedon Oct 14, 2026
Ruling: batch #1 item 5 · letter A · maintainer 「23268 同意」 2026-10-14T02:07Z
Director seat, summon #37,
session_01LqNgdPZB2Jnr5HpGbaqLeB, on the seat's reading 6158167394 (batch #1 item 5: recommendation A, fallback B) and the long-term design discussion in chat (the external principal's row model is relationship-based grants, explicit shares and share links, never an external OWD; the external identity pool stays separate; retire now on v18), which the maintainer's 「同意」 covers.What the ruling binds (letter A, with the seat's four 口径 and the discussion's direction):
externalSharingModelis retired frompackages/specon the v18 line (a breaking narrowing of the authoring surface,target:v18), with an ADR-0087 retirement entry: an author who sets it is refused at the located spot with the prescription "delete the key"; stored metadata carrying it is classed by the census (registeredwith a mechanical strip, ornot-required). The lint rules (the alias rule andsecurity-external-wider-than-internal), the posture gate's external branch, the liveness ledger row, the two example objects, the five doc pages and the QA item's external clause go with it; thecrossTenantAccessretirement hint no longer points at it.EXTERNALrung (explicitly shared rows only, never OWD-derived);externalSharingModelis retired; when a portal or partner line is built, external principals reach rows through explicit shares, relationship-based grants (a sharing set: the records related to the principal's account or contact; Salesforce's sharing sets, Power Pages' table-permission scopes) and share links, from an identity pool separate from members (D11's pool, kept). Permission Model v2 — named follow-up ADRs (post-ADR-0090 parking lot) #2776 item 6 gets a pointer.publicSharingis untouched: the share-link policy, ruling C's channel for the guest.pm:queue+domain:*) now, not after the objectstack PR lands.os migrate meta --stored) lists the tenant rows carrying the key; the retire PR's body names this for the cloud seat.Workload of the letter (the card's column): spec lane · one objectstack PR (contract review) + one objectui card + one Tier H D11 PR · precedents #19618 (+688/−287, 22 files), #22990 (+1096/−187, 40 files), #12619 (+693/−135); the objectui side has no measured precedent.
Execution: seat 3 (
domain:spec#3, #18883) claims frompm:queueper this card's 裁后执行 A.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
Session:
session_01D6F9axfoPzR7t8G1J7YtzzAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23268-retire-external-sharing-modelWorktree:
objectstack-issue-23268Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/maine4ec6ec1aor later; stop on a breach and explain it in the report):packages/spec/src/data/object.zod.ts(the key) and its tests;packages/spec/liveness/object.json(the row);packages/spec/src/migrations/entries/**(one ADR-0087 retirement entry, class by census) and the registries they feed;packages/spec/src/kernel/execution-context.zod.ts(one mention);packages/spec/src/ai/solution-blueprint*;packages/lint/src/validate-security-posture.ts,packages/lint/src/rule-explanations.ts,packages/lint/src/authoring-rules.ts(the alias rule andsecurity-external-wider-than-internal);packages/plugins/plugin-security/src/object-posture-gate.ts(the external branch);packages/metadata-core/src/object-schema-fls-references.ts(keep table); comment lines inpackages/metadata-protocol/src/protocol.ts,packages/plugins/plugin-audit/src/objects/sys-comment.object.ts,packages/plugins/plugin-sharing/src/sharing-service.ts;examples/app-showcase/src/**(the two objects, security index/positions, tour doc, coverage);content/docs/permissions/**,content/docs/protocol/objectql/security.mdxand the regeneratedcontent/docs/references/**;docs/qa/platform-checklist/areas/access-security.json(the external clause);.changeset/23268-*.md. Separately, a second Tier H PR touching onlydocs/adr/0090-*.md(the D11 sentence). ⛔ Notcontent/docs/releases/**.Container & model:
M,mode:subagent,model: default (per dispatch-gates --tier: no path-derived mandate; floor · default · ceiling); review before the queue at CONTRACT_REVIEW_TIER (a narrowing: "a card that only NARROWS one is Clause-②: no … and owes one contract-review-tier review before the queue")Clause-②: no
Responsibility:
packages/specdeclares the key (ADR-0090 D11) and no row-pipeline code reads it | ADR-0095/0099's EXTERNAL rung (explicitly shared rows only) already covers external visibility, and no runtime principal is external (assemble-execution-context.ts:358audience: undefined) | object authors reach it; today only examples/app-showcase sets itThread-read: 6159300530
Serial constraints cleared:
packages/metadata-protocol/src/protocol.tsis in the claimed surfaces of #23297, #23225, #23357 (seat 1, in flight) — this card touches comment lines only;packages/spec/src/kernel/execution-context.zod.tsis in #23287's (seat 2, in flight);examples/app-showcaseis in #15204's (epic #15194, in flight); open PR #23368 (plugin-security) shares none of these files. None is aSINGLE_CLAIM_PATHSpath; ordinary concurrency, the later lander mergesmain.Ruling of record:
6159300530(letter A, the maintainer's 「23268 同意」); premises re-read onorigin/maine4ec6ec1aat 2026-10-14T05:28Z: no row-pipeline reader of the key outsidepackages/spec,audience: undefinedatassemble-execution-context.ts:358, no open PR names the key.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Regrade: p2 → p1 ·
target:v18· protocol-first rule, all lanes · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T08:23ZUnder the maintainer's grading rule, recorded on #6015 (
6163099154, amended6163539661) and extended today, 「立卡,规则扩到所有车道,REST 收窄也算」: every metadata-protocol change, and every narrowing of a REST or data door, is p1 +target:v18in every lane. The skill text follows in #23431.externalSharingModelfrom the object contract (packages/spec/src/data/object.zod.ts). That is an authoring-surface narrowing, and it rides the 18 major.Lane, scope and Clause ② are unchanged.
objectstack-fleet commentedon Oct 14, 2026
os-dev-report
{ "issue": 23268, "status": "done", "branch": "claude/issue-23268-retire-external-sharing-model", "pr": "https://github.com/objectstack-ai/objectstack/pull/23441", "session": "session_01D6F9axfoPzR7t8G1J7Ytzz", "premise_still_valid": true, "summary": "Retired object.externalSharingModel per ruling 6159300530 letter A: retiredKey() tombstone on ObjectSchema with the delete-the-key prescription, D2 conversion object-external-sharing-model-removed (step 18, order 64, retiredFromLoadPath, retiredAfter 17.7.0), RETIRED_KEYS_BY_MAJOR[18] data/Object:externalSharingModel, D3 object-external-sharing-model-retired plus its STEP18_RATIONALE fragment; ledger row planned to dead (tombstone row kept), lint rule security-external-wider-than-internal and its SECURITY_EXTERNAL_WIDER export removed, posture gate R1 external half removed, both showcase objects, five doc pages plus docs/design, the QA item owd-save-gate (revision 5) and the crossTenantAccess hint no longer name the key; new tree-scoped retirement pin. Census class: registered (Studio offered the select and PUT /meta/object persisted it, so stored object rows can carry it; the replayed strip heals them). Companion Tier H PR #23443 (docs/adr/0090 only, Refs) carries the D11 amendment with the 维护者速读 section. Correction for the seat to apply to PR #23441's body (dev writes the body once): the Evidence bullet's gate line should read 'at 1060ed3e7: 125 derived, 125 run, 124 exit 0; check:platform-checklist exit 1 with the 8 pre-existing findings identical to e4ec6ec1a; --ran 125 accounted, 0 NOT-MEASURED' — the body still says check:dual-build-cjs-loads NOT MEASURED, but it exited 0 on the final-head run.", "tests": "All at head 1060ed3e7 unless noted (merged origin/main 04a314873 via os-regen-merge.sh). spec: build + check:generated all 14 up to date; local project 3 shards pre-merge 225/7366, 224/6477(1 todo), 224/6619 + 1 red fixed (retired-key-removal-version JOIN) re-run 1/20; post-merge conversions+migrations+object.test+that pin 20/956; repo project 2 shards 30/470 + 29/471 (NOT MEASURED: scripts/build-schemas-check-mode.test.ts, exceeds foreground cap; check:authorable-surface green), post-merge new pin + migrate-sentence + conversions-major18-merge 3/45. lint 3 shards 46/2606, 46/1862, 46 files of which 3 suites failed on a transient missing spec dist during a concurrent gate rebuild, re-run 3/33; post-merge posture+liveness 2/251. plugin-security 185 files 3772 pass 45 skipped; rest meta-object-owd-gate 11/11 (pre and post merge); metadata-core fls-references 52/52; plugin-audit sys-comment-retired-fields 8/8; example-showcase 32/411; dogfood guest-grants + expression-conformance 2/28; cli unit i18n-flow-liveness-gate 8/8, integration validate-lint-mapping-connector-source 3/3, nightly tier validate-json-warning-parity.e2e 3/3. typecheck exit 0: spec (incl. check:test-typecheck compiling the pin's @ts-expect-error), lint, plugin-security, plugin-audit, rest, cli, dogfood, example-showcase. Gates: dispatch-gates --commands (no paths) derived 125 at 1060ed3e7; 124 exit 0, check:platform-checklist exit 1 with 8 findings byte-identical (diff) to the same command on e4ec6ec1a; --ran: 125 accounted, 125 run, 0 NOT-MEASURED. ADR PR #23443 at 785ebd1ee: 19 derived, 19 exit 0, --ran 19 accounted 0 NOT-MEASURED. ESLint proven narrowing at 1060ed3e7: population eslint.config.mjs **/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs} minus NEVER_LINTED; --no-inline-config --format json over 36 changed lintable files: 36 files, 0 errors, 0 warnings; invariance: no type-aware linting, config and baselines untouched. Ablations via scripts/ablation-replace.mjs, each restored blob==HEAD, git diff HEAD empty, spec-source imports (no dist): (1) tombstone replaced by the old z.enum(...).optional(), anchor 1 to 0: 7 of 18 pin tests red, 11 green; (2) externalSharingModel planted on showcase_announcement, anchor 1 to 0: exactly the tree walk red naming examples/app-showcase/src/data/objects/announcement.object.ts (first attempt was a no-op the tool refused because the replacement contained the anchor; re-run with a landing replacement).", "mcp_calls": "0", "api_writes": "5 — relay stroke 1 (run 38537543222): POST /repos/objectstack-ai/objectstack/pulls x2 (#23441, #23443, draft) + POST /repos/objectstack-ai/objectstack/issues/{n}/assignees x2 (baozhoutao); relay stroke 2: POST /repos/objectstack-ai/objectstack/issues/23268/comments (this report). git push of two branches is not REST. Zero label writes: the dispatch named no labels.", "gates": { "head": "1060ed3e7", "derived": 125, "run": 125, "exit0": 124, "red": [ "pnpm check:platform-checklist :: exit 1 (8 pre-existing findings, identical on e4ec6ec1a)" ], "not_measured": 0, "adr_pr": { "head": "785ebd1ee", "derived": 19, "exit0": 19 } }, "line_budget": { "pr_23441": "+884 / -450 = 1334 changed lines, 52 files", "pr_23443": "+12 / -0, 1 file" }, "files_changed": 52, "deviations": [ "File surface: beyond the claim's list, test files the retirement turned stale were edited — packages/cli/test/{i18n-flow-liveness-gate,validate-json-warning-parity.e2e,validate-lint-mapping-connector-source}.test.ts, packages/lint/src/{lint-liveness-properties,runtime-gate.datasource-writes,runtime-gate.inert-type-writes,validate-security-posture,validate-security-posture.runtime-surface,authoring-rule-input-tier}.test.ts, packages/rest/src/meta-object-owd-gate.test.ts, packages/plugins/plugin-security/src/object-posture-gate.test.ts, packages/plugins/plugin-audit/src/objects/sys-comment-retired-fields.test.ts, packages/qa/dogfood/test/guest-grants-channel.dogfood.test.ts, packages/spec/src/shared/retired-key-removal-version.pin.test.ts, packages/spec/vitest.repo-tests.json; plus packages/lint/src/index.ts, packages/lint/scripts/check-doc-security-posture.mjs, docs/design/permission-model.md and the publicSharing guidance string in object.zod.ts (it steered authors to the retired key). Each listed in the PR body.", "packages/metadata-core/src/object-schema-fls-references.ts keep table NOT edited: the tombstone keeps the key in the walked shape the table is pinned against.", "Lint witness kept: several lint/cli tests keep authoring the key on unparsed intakes because a dead ledger row still warns there; the tree-scoped pin excludes those four files by name with the reason.", "PR #23441 body is stale on one line (dual-build-cjs-loads NOT MEASURED vs exit 0 on the final run); correction text is in summary for the seat.", "The first pre-push of the ADR commit was refused for a card trailer (Refs line in the commit message); amended locally before any push of that commit." ], "open_questions": [], "out_of_scope_findings": [ "carrier: #2776 · item 6 (Portal identity & licensing) gets the pointer ruling item 2 names: external principals reach rows through explicit shares, relationship-based grants (sharing sets) and share links from a separate identity pool, never an external OWD (ADR-0090 D11 as amended in PR #23443) · noted, not filed", "carrier: PM's objectui follow-up card (ruling item 4) · Studio's object settings select and Ext badge still offer externalSharingModel; until that lands an author who picks a value gets the 422 prescription on save · noted, not filed", "carrier: whoever next edits skills/objectstack-data/references/lint-rules.md (Tier H, skills/**) · line 23 lists security-external-wider-than-internal, a rule this PR removes; one-row deletion · noted, not filed; dedupe words: lint-rules.md external-wider stale row" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Review: ACCEPT (PR #23441) · PR #23443 pending its new head ·
domain:specseat 3 · 2026-10-14T09:20ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao. Reviewer of record; checked against GitHub, not the report.PR #23441 @
1060ed3e74306c46a60e51745479a418806475bf— ACCEPT.main, line 1Fixes #23268; +884/−450, 52 files (under 3000);check-governed-merges --pr 23441: not governed; nothing undercontent/docs/releases/**.6159300530(A), item by item: 1 —retiredKey()tombstone with the delete-the-key prescription, D2 conversionobject-external-sharing-model-removed(censusregistered, mechanical strip replayed on stored rows), D3 entry, ledgerplanned→dead,security-external-wider-than-internalandSECURITY_EXTERNAL_WIDERremoved (the alias rule keeps itssharingModelhalf), posture-gate R1's external half removed, both showcase objects, the doc pages, QA itemowd-save-gaterevision 5, thecrossTenantAccesshint; 3 —publicSharinguntouched (one mis-nesting guidance string no longer points at the dead key); 5 — the body namesos migrate meta --storedfor the cloud seat.23268-external-sharing-model-retired.md(specminor+ BREAKING,lintminor,plugin-securitypatch; the FROM → TO rows; the prescription quoted verbatim; the retirement kit; the NOT MEASURED out-of-repo line;adr-0087: registeredwith both ids).CONTRACT_REVIEW_TIER, record posted on PR feat(spec)!: retire the object's externalSharingModel — the external org-wide default no principal ever read (#23268) #23441 on this head.Test Core (3/6)in progress. Enqueue waits on it.check:dual-build-cjs-loadsNOT MEASURED) now carries the final-head counts from the dev's report.packages/cli/test/*,packages/lint/src/*.test.ts,packages/rest/src/meta-object-owd-gate.test.ts,packages/plugins/plugin-security/src/object-posture-gate.test.ts,packages/plugins/plugin-audit/src/objects/sys-comment-retired-fields.test.ts,packages/qa/dogfood/test/guest-grants-channel.dogfood.test.ts,packages/spec/src/shared/retired-key-removal-version.pin.test.ts,packages/spec/vitest.repo-tests.json),packages/lint/src/index.ts,packages/lint/scripts/check-doc-security-posture.mjs,docs/design/permission-model.md. Each one restated or tested the retired key.object-schema-fls-references.tswas claimed but not edited (the tombstone keeps the key in the walked shape).PR #23443 (Tier H,
docs/adr/0090D11): the D11 amendment says what ruling item 2 binds. A second commit is being added (theskills/objectstack-data/references/lint-rules.mdrow that names the removed rule; shipped text this card makes false, governed, so it belongs in the Tier H PR).skip-changesetapplied by the seat (docs/governed text only, no package). Its contract review and the Tier H route follow on the new head.Out-of-scope findings:
externalSharingModeldropdown and the Ext badge once @objectstack/spec retires the key (objectstack#23268, ruling A) objectui#12353 (filed under ruling item 4).skills/**lint-rules row → PR docs(adr): ADR-0090 D11 — external visibility is the EXTERNAL rung; externalSharingModel retired (#23268) #23443 (above).Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Review: PR #23443 @
1e1491293dd46fd3657ad481bf120ddce9e7cd92— reviewed, Tier H, waiting for an authorized approval ·domain:specseat 3 · 2026-10-14T09:53ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao.Refs #23268(no closing keyword; PR feat(spec)!: retire the object's externalSharingModel — the external org-wide default no principal ever read (#23268) #23441 closes the card),Clause-②: no; 3 files:docs/adr/0090-…md(+12),skills/objectstack-data/references/lint-rules.md(−1),.changeset/23268-skills-lint-rules-row.md(@objectstack/skillspatch). Governed (Tier H):docs/adr/**andskills/**.skills/**row deletion is complete (no otherskills/**line names the key or rule).CONTRACT_REVIEW_TIERon this head, superseding the FAIL once509e82c. That FAIL was the seat's error: it had labelled the PRskip-changeset, butskills/**ships in@objectstack/skills. The label is removed and the changeset added. The gate that let the label pass is filed as finding(gates):check-empty-changesetandCheck Changesetroute 2 still say askills/**-only PR releases nothing, so it passes with no changeset; since #22658@objectstack/skillspublishesskills/**#23451.needs-user-decisionis on the PR; review requested fromos-zhuangandhotlong. The seat lands it after an authorized approval, preferably after PR feat(spec)!: retire the object's externalSharingModel — the external org-wide default no principal ever read (#23268) #23441 merges.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed · PR #23441 →
main301eec6df·domain:specseat 3 · 2026-10-14T09:59ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao.1060ed3e7bygit patch-id --stable(410a9ae4…on both sides);301eec6dfis an ancestor oforigin/main.completedonFixes #23268;pm:dispatchedis removed in this act.Refs #23268: the ADR-0090 D11 amendment and theskills/**row), contract PASS on1e1491293, review requested fromos-zhuangandhotlong. This seat follows it to MERGED and then posts the Permission Model v2 — named follow-up ADRs (post-ADR-0090 parking lot) #2776 item 6 pointer (ruling item 2).externalSharingModeldropdown and the Ext badge once @objectstack/spec retires the key (objectstack#23268, ruling A) objectui#12353 (the Studio half, ruling item 4) is in objectui's queue. objectui meets the refusal when it moves to a@objectstack/specrelease carrying301eec6df, so Studio's select should go no later than that bump. (Corrected in place: an earlier wording said the pin already carries it.)Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed · PR #23443 →
main11d4c5a6d(Tier H, approved byos-zhuang) ·domain:specseat 3 · 2026-10-14T10:26ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao.os-zhuangapproved on head1e1491293(an authorized approver,GOVERNED_APPROVERS) and queued it; the squash equals that head bygit patch-id --stable; onorigin/main.needs-user-decisionwas removed from the PR. The #2776 item 6 pointer (ruling item 2) is posted. Everything ruling6159300530binds is now landed, except objectstack-ai/objectui#12353 (objectui's lane).Generated by Claude Code