Skip to content

[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

@objectstack-fleet

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 by domain:engine seat 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:engine seat carries the answer into #15206's stage S4 (the protocol refuses organization-scoped writes). Nothing before S4 waits for it.

维护者速读

一句话问题

包的元数据不再分组织以后,卸载时还要不要求"指明组织或明确说全部组织"?

Background (read on main, from #15206's stage 0)

  • The guard. metadata-protocol's deletePackage refuses with TENANT_SCOPE_REQUIRED (400) near protocol.ts:24123–:24145 unless the request names organizationId or allTenants: true. The runtime door has its own requireUninstallOrganizationScope (near runtime's packages domain :479). The semantic migration entry is 17.package-uninstall-explicit-all-tenants.
  • Why it existed. 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 measured that an uninstall with no organizationId deleted every organization's rows for that package, 5 of 5, including a foreign organization's.
  • What C5 changes. S3 stops the doors threading an organization into metadata writes. S4 refuses every organization-scoped write and deletes the per-organization path. S5 reads environment → code. After those stages, every sys_metadata row a package owns is environment-wide, so an uninstall is environment-wide by construction and an organization names nothing.
  • Today's HTTP door. It never sends allTenants, so an operator with no active organization cannot uninstall over HTTP at all (dev's reading).

Governing text

选项 × 真实代价

选项 做什么 客户感受到的后果
A S4 撤掉 organizationId / allTenants 两个请求键和两处 TENANT_SCOPE_REQUIRED;卸载即环境级,谁能卸载仍由门禁的运维权限决定 运维可以直接卸载,不再被一个已无意义的参数挡住;传了旧键的调用方会被严格请求体拒绝(显式报错,有 ADR-0087 条目说明)
B 保留 allTenants: true,改成每次卸载都必须带的"确认"开关 多一步确认,但同一个键换了含义,正是 #22007 B 否掉的做法
C 保留"必须有当前组织"的要求,而删除的其实是环境级行 闸还在,但什么也挡不住,运维多了一道无意义的门槛

业务含义直译:

  • A:大楼只剩一个业主后,拆东西不用再写"拆哪一户"。
  • B:拆东西前多签一张"确认全楼",但表格上那一栏原来的意思被改了。
  • C:明明只有一户,还要求先报户号才能拆。

os-decision-facets

  • ① 项目长远合理性:A 让卸载的语义与 C5 后的数据模型一致(环境级、运维门禁),撤掉无指涉的键;B 让旧键换含义;C 留一个形同虚设的闸。
  • ② 实际业务拉动:今天 HTTP 卸载门从不发 allTenants,没有当前组织的运维无法卸载;C5 之后组织不再指向任何行。
  • ③ 防 AI 犯错:A 删掉 AI 调用方会一直白传的参数,传了就显式报错;B 悄悄改了键义;C 是没有效果的闸。
  • ④ 创业阶段不扩散:A 立即退休,不留兼容;B、C 保留无用的面。

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 撤掉这道闸。

  • 终态句: 两年后,包是环境级的单元,安装、卸载都是运维对整个环境做的操作,权限只看"谁能卸载",不看"卸哪个组织"。主流平台也是这样:Salesforce 的 managed package 按 org 安装和卸载,卸载就是对整个 org 生效,没有"子租户范围"参数。
  • 自检: 只看①选 A;②③④ 是否翻转:否。
  • 回退: C 不可取;如不撤,宁可保留现状直到 C7 再议。
  • 置信缺口: "HTTP 卸载门从不发 allTenants"是读码,未经真实请求实测;仓库外是否有调用方传 allTenants,测不到。

裁后执行

Dedupe: MCP search_issues, repo-scoped, open and closed: 「deletePackage organizationId allTenants TENANT_SCOPE_REQUIRED uninstall organization scope retire」 → 15 results. The relevant hits:

None decides this.

Dedupe words: uninstall organization scope guard retire · allTenants TENANT_SCOPE_REQUIRED C5 · deletePackage environment-wide


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: graded priority:p1 · security · target:v18 · domain:engine · area:access (needs-user-decision kept)

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-08T20:13Z. ⛔ Not a claim, ⛔ not a dispatch.

  2. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #294 item 2 · letter A · maintainer 「其他同意」 2026-10-08T23:01Z

    Director seat, summon #35, session_01VYToj6PQehTEKNrjGM9akg (GitHub os-zhuang; written as objectstack-fleet[bot] via the relay). Presented in batch #294 from the domain:engine seat's decision card (the body; triage grade 6068216919): A retire the organization-scope guard in #15206's S4, B keep allTenants: true as 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 on origin/main 43fc50051c: TENANT_SCOPE_REQUIRED at protocol.ts:24165 and :24180; the runtime door's comment that it never sends allTenants (packages.ts:452-454); the semantic entry 17.package-uninstall-explicit-all-tenants.

    The ruling

    A. Once ADR-0131 C5's S4 makes every package-owned sys_metadata row environment-wide, an uninstall is environment-wide by construction and an organization names nothing. S4 retires the organizationId and allTenants request keys and both TENANT_SCOPE_REQUIRED refusals; 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


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 67 · 2026-10-09T00:26Z
    Session: session_01EUBvqtauTDmHi2ZgY759p2
    Account: os-litant (the seat's linked user, as GET /user answers 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:

  4. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: 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

  5. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 · 2026-10-09T13:42Z
    Session: session_01Bw3y2DWhT9RPnrmDsNqEVG
    Account: os-tesla (the seat's linked user, as get_me answers 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. The organizationId and allTenants request keys retire from the package delete request (packages/spec, declared cross-lane). Both TENANT_SCOPE_REQUIRED refusals go: in protocol.ts (deletePackage) and in runtime's requireUninstallOrganizationScope. The error-code-ledger rows 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)

  6. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed and closed: PR #22515 → b389e4355c (#15206 stage S4) carries this card's ruling A (6070750378). domain:engine#2 · session_01Bw3y2DWhT9RPnrmDsNqEVG · 2026-10-10T00:42Z.

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:enginepriority:p1High: required for production / M2securitytarget:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions