Repository navigation
[decision] once ADR-0131 C5 makes package metadata environment-wide, does deletePackage's organization-scope guard (organizationId / allTenants, TENANT_SCOPE_REQUIRED, #7780) retire? #22350
Description
Activity
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsTriage: graded
priority:p1·security·target:v18·domain:engine·area:access(needs-user-decisionkept)Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-08T20:13Z. ⛔ Not a claim, ⛔ not a dispatch.- Why p1 and v18: it gates the uninstall half of feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206's S4, and feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 is p1target:v18. Release-priority work is p1. - Why
security, and why it is the maintainer's: Product question: an uninstall with no organizationId deletes EVERY organization's rows for that package (measured 5 of 5, including a foreign org's) #7780 ruled this guard after a measured cross-organization deletion. The ruling's words are 「跨租户卸载必须显式声明,缺省缺参永远不等于「全部租户」。」. Retiring a ruled security guard is a loosening, so it escalates. - Lane: the answer rides feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206's S4 inmetadata-protocol⇒domain:engine. Under any letter, the spec half stays with S4 as declared cross-lane paths, per stage 0's F12 and F13 reading. That half is a narrowing: the request keys, the error-code ledger rows and the semantic entry. - No other card waits on it. Nothing before S4 does either.
- Why p1 and v18: it gates the uninstall half of feat(metadata-core,metadata-protocol,objectql,plugin-security): the
- addedarea:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsPermissions that actually hold — RLS/FLS, sharing model, write-path guardspriority:p1High: required for production / M2High: required for production / M2
on Oct 8, 2026 objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsRuling: batch #294 item 2 · letter A · maintainer 「其他同意」 2026-10-08T23:01Z
Director seat, summon #35,
session_01VYToj6PQehTEKNrjGM9akg(GitHubos-zhuang; written asobjectstack-fleet[bot]via the relay). Presented in batch #294 from thedomain:engineseat's decision card (the body; triage grade 6068216919): A retire the organization-scope guard in #15206's S4, B keepallTenants: trueas a mandatory confirmation, C keep the current-organization requirement. The seat recommended A; the maintainer answered 「其他同意」. Thread-read: 6068216919. Freshness: no comment since the presentation. Premises re-read onorigin/main43fc50051c:TENANT_SCOPE_REQUIREDatprotocol.ts:24165and:24180; the runtime door's comment that it never sendsallTenants(packages.ts:452-454); the semantic entry17.package-uninstall-explicit-all-tenants.The ruling
A. Once ADR-0131 C5's S4 makes every package-owned
sys_metadatarow environment-wide, an uninstall is environment-wide by construction and an organization names nothing. S4 retires theorganizationIdandallTenantsrequest keys and bothTENANT_SCOPE_REQUIREDrefusals; who may uninstall stays with the package door's operator gate (ADR-0131 D6, D12). A request still carrying the retired keys is refused by the strict request body, with an ADR-0087 entry stating the retirement and the remedy. #7780's guard was ruled for the era in which rows were organization-scoped; C5 removes that premise, so the guard retires with it, which is not a loosening of anything the wall protects. ⛔ Not taken: B (a key kept under a new meaning, the shape #22007 B refused), C (a gate that guards nothing).Prior rulings read: #7780 (the ruled guard; closed),
17.package-uninstall-explicit-all-tenants, #22007 B (no re-meaning of a key), ADR-0131 D6 / D12, ADR-0049, #20492 (closed, a defect of the same guard) → 6 hits; thread: 1 comment. 自检: 只看①选 A;②③④ 是否翻转:否。置信缺口:「HTTP 门从不发allTenants」是读码未经真实请求实测;仓外调用方是否传allTenants测不到。State
needs-user-decision→pm:queue(domain:engine,priority:p1,target:v18) in this act; theRuled:line added to the body. The answer rides feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206's S4 PR: the two keys removed from the request schema (packages/spec, declared cross-lane), the two refusals removed, the ADR-0087 entry, the changeset, the contract review at tier. Nothing before S4 waits for it.
Generated by Claude Code
- added and removed
on Oct 8, 2026 objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsClaim: PM loop round 67 · 2026-10-09T00:26Z
Session:session_01EUBvqtauTDmHi2ZgY759p2
Account:os-litant(the seat's linked user, asGET /useranswers it; always the card's assignee)
Branch:claude/issue-15206-s4-package-environment-wide(#15206's S4, to be dispatched)
Worktree:objectstack-issue-15206-s4
Domain:domain:engine
Seat:domain:engine#1
Provenance:- Filed by this seat as feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206's Q4. - Triage graded it p1
securitytarget:v18(6068216919). - The maintainer ruled A through the director seat's batch 🔗 Broken links detected in documentation #294 (6070750378).
- The ruling's State line puts the answer on feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206's S4 PR. This card has no PR of its own and no dev of its own.
File surface (per ruling 6070750378, riding feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206's S4): - S4 retires the
organizationIdandallTenantsrequest keys fromdeletePackage(packages/spec, declared cross-lane), and bothTENANT_SCOPE_REQUIREDrefusals inmetadata-protocol(protocol.ts). - It adds an ADR-0087 entry that states the retirement and the remedy. A request still carrying a retired key is refused by the strict request body.
- Who may uninstall stays with the package door's operator gate (ADR-0131 D6, D12).
- S4's PR carries this card as a second
Refsline. The seat closes this card with S4's landing record.
Container & model: S4's dispatch (L,mode:subagent).
Clause-②: no - Triage read the spec half (the request keys, the error-code ledger rows and the semantic entry) as a narrowing that stays in this lane (6068216919).
- One refusal does lift. A request carrying neither key, refused today with
TENANT_SCOPE_REQUIRED, is accepted once C5 makes the rows environment-wide. The ruling decides that directly: an organization names nothing there. - S4's contract review at tier re-judges this line on S4's diff.
Responsibility: an organization-scope guard ruled for organization-scoped package rows (Product question: an uninstall with no organizationId deletes EVERY organization's rows for that package (measured 5 of 5, including a foreign org's) #7780) | C5 makes package-ownedsys_metadatarows environment-wide | the guard would then name nothing and refuse a legitimate uninstall
Thread-read: 6070750378
Serial constraints cleared: S4 waits for S2 (in dev) and S3, per the stage plan (6067844889). Nothing before S4 waits for this card.
- Filed by this seat as feat(metadata-core,metadata-protocol,objectql,plugin-security): the
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsRelease:
session_01EUBvqtauTDmHi2ZgY759p2(os-litant,domain:engine#1), releasing claim 6071732822 · 2026-10-09T05:19Z · reason: the seat is clocking off on the maintainer's order in chat (「当前任务处理完,合并后就下班」) · destination:pm:queue, unassigned. This card still rides #15206's S4 PR, as ruling A says (6070750378). The next seat claims it together with S4. No work was started on it.
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsClaim: PM loop round 2 · 2026-10-09T13:42Z
Session:session_01Bw3y2DWhT9RPnrmDsNqEVG
Account:os-tesla(the seat's linked user, asget_meanswers it; the card's assignee)
Branch:claude/issue-15206-s4-protocol-env-only(#15206's S4; this card has no PR or dev of its own)
Worktree: S4's cloud session
Domain:domain:engine
Seat:domain:engine#2(seat post #20966)
Provenance: the ruling is A (6070750378). Seat 1's claim 6071732822 was released at 6074820322, with this card left to ride #15206's S4. The S4 claim on #15206 is posted in the same act.
File surface: per the ruling, within S4. TheorganizationIdandallTenantsrequest keys retire from the package delete request (packages/spec, declared cross-lane). BothTENANT_SCOPE_REQUIREDrefusals go: inprotocol.ts(deletePackage) and inruntime'srequireUninstallOrganizationScope. Theerror-code-ledgerrows follow. An ADR-0087 entry states the retirement and the remedy. Who may uninstall stays with the package door's operator gate.
Container & model: S4's dispatch (L,mode:cloud,model: default).
Clause-②: yes (narrowing)- A package delete with neither key, refused today, is accepted. The ruling decides it, and S4's contract review at tier judges it on the diff.
Responsibility: n/a — a ruled decision card carried by a stage
Thread-read: 6074820322
Serial constraints cleared: as on the S4 claim on feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206. S3 is onmain(7895671162). The S4 PR carriesRefs #22350, and this seat closes the card with S4's landing record.
- A package delete with neither key, refused today, is accepted. The ruling decides it, and S4's contract review at tier judges it on the diff.
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsLanded and closed: PR #22515 →
b389e4355c(#15206 stage S4) carries this card's ruling A (6070750378).domain:engine#2·session_01Bw3y2DWhT9RPnrmDsNqEVG· 2026-10-10T00:42Z.- What is on
origin/main:deletePackageanswers400 INVALID_REQUESTto a request carryingorganizationIdorallTenants(any value).- With neither key, the uninstall is environment-wide: every row bound to the package, legacy organization rows included, removed through the repository with history kept.
- The door's
requireUninstallOrganizationScopeand bothTENANT_SCOPE_REQUIREDrefusals are retired, along with their ledger rows. DeletePackageRequestandUninstallCleanupdrop the retired keys.
- Records: contract review 6090242635 (PASS; ① item 8 judges this ruling's width RIGHT); ACCEPT 6090274140 on feat(metadata-core,metadata-protocol,objectql,plugin-security): the
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206; the stage's landing record is on feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206. - Carried to C7 / feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211: two residue classes.
- A legacy organization row of a create-closed type would be refused
NOT_CREATABLEon uninstall. That refusal is loud. - A legacy organization
objectrow's table survives its uninstall.
- A legacy organization row of a create-closed type would be refused
- Closed as completed by the seat, per the ruling; the PR deliberately carries no closing keyword.
pm:dispatchedis removed in this act.
- What is on
Ruled: 6070750378 · letter A · 2026-10-08T23:03Z
Filing gate: ② a decision only the maintainer can make. This is question Q4 from #15206's stage 0 (ADR-0131 C5; the os-dev-report on #15206). Deleting a ruled guard is
Clause-②: yes(execution-duties.md), and the guard was ruled on #7780. Filed bydomain:engineseat 1 (seat post #6367) ·session_01EUBvqtauTDmHi2ZgY759p2. ⛔ Not graded or routed here; ⛔ not a claim.Who acts on it: the maintainer answers one letter; triage grades it; the
domain:engineseat carries the answer into #15206's stage S4 (the protocol refuses organization-scoped writes). Nothing before S4 waits for it.维护者速读
organizationId),或者明确说"所有组织"(allTenants: true),否则拒绝(TENANT_SCOPE_REQUIRED,400)。当时实测,不带组织的卸载会把每个组织(包括别人的组织)在这个包下的元数据行全删掉。sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206)落地后,元数据行不再属于任何组织,全部是环境级的。卸载本来就是整个环境的事,"指明哪个组织"已经没有可指的对象。dev 读代码发现:HTTP 卸载门从来不发allTenants,所以今天一个没有当前组织的运维,根本无法通过 HTTP 卸载包。TENANT_SCOPE_REQUIRED。谁能卸载,仍由现有的门禁权限决定(隔离部署下限运维)。回一个字母:A / B / C。一句话问题
包的元数据不再分组织以后,卸载时还要不要求"指明组织或明确说全部组织"?
Background (read on
main, from #15206's stage 0)metadata-protocol'sdeletePackagerefuses withTENANT_SCOPE_REQUIRED(400) nearprotocol.ts:24123–:24145unless the request namesorganizationIdorallTenants: true. The runtime door has its ownrequireUninstallOrganizationScope(nearruntime's packages domain:479). The semantic migration entry is17.package-uninstall-explicit-all-tenants.organizationIddeleted every organization's rows for that package, 5 of 5, including a foreign organization's.sys_metadatarow a package owns is environment-wide, so an uninstall is environment-wide by construction and an organization names nothing.allTenants, so an operator with no active organization cannot uninstall over HTTP at all (dev's reading).Governing text
17.package-uninstall-explicit-all-tenantsentry.选项 × 真实代价
organizationId/allTenants两个请求键和两处TENANT_SCOPE_REQUIRED;卸载即环境级,谁能卸载仍由门禁的运维权限决定allTenants: true,改成每次卸载都必须带的"确认"开关业务含义直译:
os-decision-facets
allTenants,没有当前组织的运维无法卸载;C5 之后组织不再指向任何行。Prior rulings read: package uninstall, allTenants, TENANT_SCOPE_REQUIRED → #7780 (ruled guard),
17.package-uninstall-explicit-all-tenants, #22007 B (re-meaning a key, not taken); ADR-0131 D6/D12, ADR-0049; thread: #15206 (stage 0).推荐
A:S4 撤掉这道闸。
allTenants"是读码,未经真实请求实测;仓库外是否有调用方传allTenants,测不到。裁后执行
sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 的 S4 PR 中删除两个请求键(packages/spec的请求 schema 跨车道声明)和两处TENANT_SCOPE_REQUIRED,加 ADR-0087 条目,changeset 写明,契约复审档复核。allTenants改为必填确认,另立 spec 车道卡记录键义变化。Dedupe: MCP
search_issues, repo-scoped, open and closed: 「deletePackage organizationId allTenants TENANT_SCOPE_REQUIRED uninstall organization scope retire」 → 15 results. The relevant hits:DELETE /packages/:idthrough the dispatcher removes the package from the live registry, then refuses withTENANT_SCOPE_REQUIRED: a 400 that leaves the uninstall half applied #20492 (closed): the dispatcher's half-applied uninstall that refusedTENANT_SCOPE_REQUIRED, a defect of the same guard.sys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206: this question's source.sys_metadata_activationtenant-less, a sibling precedent.None decides this.
Dedupe words:
uninstall organization scope guard retire·allTenants TENANT_SCOPE_REQUIRED C5·deletePackage environment-wideGenerated by Claude Code