Repository navigation
feat(spec)!: retire AdminScope.manageBindings and authorEnvironmentSets — delegation rights no door honoured (#23488) - #23601
Conversation
…#23488) Claude-Session: https://claude.ai/code/session_01LFqdRsuM5nkqoJdHd5ztVk Co-authored-by: Claude <noreply@anthropic.com>
…retired keys (#23488) Claude-Session: https://claude.ai/code/session_01LFqdRsuM5nkqoJdHd5ztVk Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LFqdRsuM5nkqoJdHd5ztVk Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LFqdRsuM5nkqoJdHd5ztVk Co-authored-by: Claude <noreply@anthropic.com>
…tire-adminscope-binding-keys
📓 Docs Drift CheckThis PR changes 5 package(s): 11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 150 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 4cc310b88f0b85ef8a88cce2753420b8e06a16e4 && git checkout 4cc310b88f0b85ef8a88cce2753420b8e06a16e4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 16abea88450be3c453a9e769445af341a956bd17 3854d1403f268d66b6ce39f7859e1fd52bbdccfe && git checkout -B drift-repro 16abea88450be3c453a9e769445af341a956bd17 && git merge --no-ff 3854d1403f268d66b6ce39f7859e1fd52bbdccfe
node scripts/docs-audit/affected-docs.mjs --json 16abea88450be3c453a9e769445af341a956bd17
|
席位核对 — ACCEPT ·
|
Contract reviewServed-tier: Inputs, and nothing else: card #23488 (its body and all ten comments; the ruling of record is 6181988435, letter A, items 1–5; the dev's report is 6184471100), PR #23601's body and its 38-file list, the net diff of this head against Gates, read off the head: all 45 runs concluded — 37 ① Derived judgmentsAccept-set changes the diff implies, each judged:
Public-surface and generated-surface changes, each judged:
Nothing in the diff was judged WRONG. ② Semver level
③ Boundary flagsThe report's
Implemented-by: VERDICT: PASS |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 38684646959 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Fixes #23488
Clause-②: yes
Executes ruling of record 6181988435 on #23488 (letter A, the maintainer's 「同意」):
AdminScope.manageBindingsandAdminScope.authorEnvironmentSetsretire inside the 18 major by thespec-property-retirementroute, the delegated-admin gate's strict-containment comparison stops reading them, and the text that described the removed gates is corrected. The changeset declaresClause-②: yes (narrowing), BREAKING, ADR-0087 dispositionregistered.The ADR half (ADR-0090 D12 status line, ADR-0086 line 446) is a separate Tier H docs PR on branch
claude/issue-23488-adr-delegation-rights-retired, as ruling item 5 requires. The objectui half (Studio's two switches, help strings, i18n keys, pin test) is objectstack-ai/objectui#12406, filed by the seat (ruling item 4); this PR does not touch objectui.What changes
1. The retirement kit (
@objectstack/spec).retiredKey()tombstones onAdminScopeSchema(security/permission.zod.ts). Each prescription says what the ruling binds: delete the key; a delegate's scope is placement, assignment and the allowlist. Both close with the houseos migrate meta --from 17sentence.DelegableAdminScope(contracts/security-service.ts) drops both fields.permission-admin-scope-binding-authoring-removedinMAJOR_18_CONVERSIONS(order 65,retiredFromLoadPath: true,retiredAfter: '17.7.0'). It strips both keys from everypermissions[].adminScope, whatever they hold, one notice per key, and the notice path names the set. Both keys carried.default(false), so a 17.x parse materialized them in every declared scope. The rehydration seams replay this entry over stored rows and built artifacts (theemail_template.isSystemprecedent;acceptRetiredDefaultResidueis not adopted).RETIRED_KEYS_BY_MAJOR[18]:security/AdminScope:manageBindings,security/AdminScope:authorEnvironmentSets.permission-admin-scope-binding-authoring-retired, which states the containment change, plus itsSTEP18_RATIONALEfragment (order 97).authorable-surface/security.json(two rows become RETIRED),authorable-defaults/security.json(two default rows go), the liveness note (liveness/permission.json, re-verified, stilllive), and the removal-version pin's JOIN row.2. The containment change (
@objectstack/plugin-security, ruling item 2).definitionContainsStrictlycomparesincludeSubtree,manageAssignmentsand the allowlist only.resolveHeldScopesanddescribeDelegableScopedrop both flags.truecan no longer hand out a scope otherwise equal to its own. It answers403 PERMISSION_DENIED.delegated-admin-gate.test.ts, under the describe[#23488] the retired binding/authoring flags count on no containment axis:code+status+ the message's first clause;trueno longer out-reaches the delegate.trueon both sides (EAST_SCOPE), so these pins are new, not flipped assertions. The six other plugin-security fixtures drop the keys.3. The legacy-row ceremony (
@objectstack/core, ruling item 3) — measured, and the mapper drops the keys.packages/metadata-protocolat43c50c843. It tookpermissionSetDefinitionFromRowover a 17.x-shaped row (admin_scopecarrying both keys asfalse) and passed the body toObjectStackProtocolImplementation.saveMetaItem. That is the dooros migrate organization-ownershipcomposes (packages/cli/src/commands/migrate/organization-ownership.ts:567-578).{"ok":false,"code":"INVALID_METADATA","status":422}atadminScope.manageBindings, with the tombstone's prescription.{"ok":true,"success":true}.conversions/stored.ts's header: "The write path must NOT use this:saveMetaItemrejects off-spec bodies with the current schema".permission-set-row-definition.tsdrops both keys from the parsedadmin_scope(RETIRED_ADMIN_SCOPE_KEYS).PermissionSetSchemaforfalse,trueand a non-boolean value. A CONTROL shows the same body with the key kept is refused at['adminScope','manageBindings'].packages/cli/src/utils/organization-ownership-apply.tsis read only, not edited (mechanism assumption 4 holds).4. Position 3 text (docs accuracy, no contract change).
content/docs/permissions/delegated-administration.mdx: the action-flag and strict-containment rows.content/docs/permissions/permission-sets.mdx: the strict-containment sentence.examples/app-showcase/src/security/permission-sets.ts(:26-27,:166-167,:357-362,:384-385, and the two keys deleted) and two inexamples/app-showcase/src/docs/showcase_tour_security.md.AdminScopeSchemaheader,assignablePermissionSets,PermissionSet.adminScope).delegated-admin-gate.tsscopesCoverUserand the placement comment, andobjects/sys-user-permission-set.object.ts.packages/metadata-core/src/meta-write-capability.ts:184-185: the security plugin's data door no longer asks the walled verdict. Measured:git grep -n 'walledCatalogWriteVerdict(' -- packagesfinds no caller underpackages/plugins.docs/design/permission-model.md(the delegated-admin bullets and the authoring sample).packages/platform-objects' fourmetadata-formsbundles:enwas regenerated withpnpm i18n:extract;helpTextvalues (zh-CN, ja-JP, es-ES) were edited by hand, since AGENTS.md allows translated-locale values to be hand-written;adminScopepath has no source-hash entry, so it is legacy-trusted.packages/qa/dogfood/test/showcase-permission-zoo.dogfood.test.tsnow asserts both keys are absent from the served definition.5. Tree-scoped absence pin.
packages/spec/src/security/admin-scope-binding-authoring-retirement.test.ts(registered invitest.repo-tests.json) pins:permissionwrite-door binding, anddefineStackwithSTACK_SCHEMA_INVALID/ 422;@ts-expect-error);@objectstack/specinscripts/cross-package-test-inputs.mjs.File surface vs the claim
These are outside the claim's list, each with the reason:
docs/design/permission-model.md: the reading (Reading 5) lists it, and it named both keys as authorable.examples/app-showcase/src/docs/showcase_tour_security.md: two of "the showcase's seven" (ruling item 5).packages/qa/dogfood/test/showcase-permission-zoo.dogfood.test.ts: it assertedmanageBindings === false.packages/plugins/plugin-security/src/*.test.tsfixtures.packages/spec/src/shared/retired-key-removal-version.pin.test.ts: its guard requires a JOIN row for every newest-stable retirement.packages/spec/vitest.repo-tests.json.authorable-*and reference files.Mechanism assumption 3 does not hold: no generator wrote under
skills/**, so this PR touches no governed surface.Verification
Pre-merge head
0221b165f. Each command ran throughscripts/pm/os-verify-lock.sh, with the exit code captured before any pipe:pnpm --filter @objectstack/spec test: 677 files passed, 1 skipped; 20729 tests passed.pnpm --filter @objectstack/spec test:repo: 62 files, 1051 tests passed.pnpm --filter @objectstack/spec typecheck: exit 0. That includescheck:test-typecheck, so the two@ts-expect-errorlines are compiled and used.pnpm --filter @objectstack/plugin-security typecheck: exit 0.pnpm --filter @objectstack/core test: exit 0.pnpm --filter @objectstack/platform-objects test: exit 0.delegated-admin-gate*.test.ts,granted-by-writer-provenance,reserved-identity-names,can-write-object-admission): 206 passed.pnpm --filter @objectstack/spec check:generated: one stale artifact (content/docs/references/**), regenerated withgen:docs. Every other gate was green.Reverse verification, at
0221b165f, both restored and proved by blob hash and an emptygit diff HEAD:delegated-admin-gate.tsat the branch pointfa6a6085cwas written over the file. Of the four selected cases, 2 failed (case (ii) and case (i) reversed) and 2 passed (the CONTROL and the existing equal-scope refusal). That is the expected direction.scripts/ablation-replace.mjsremoved thewithoutRetiredAdminScopeKeys(...)call (anchor 1 → 0, blob03f32ba6f610→01d09ba3e389). The mapper pin failed (1 failed, 12 passed), and the file was restored to the HEAD blob.objectui at the pin (
b9814b334d), measured by reproduction, not by a full objectui build.PermissionAdvancedFacets.tsx's typing against this branch's built@objectstack/specdist. The copy covered theAdminScopeimport,Partialalias,setScopeDetail, the three switches'scope[key]and the{ [key]: !!v } as Partialwrite, plusDelegableAdminScope. It used objectui's compiler options (strict,moduleResolution: bundler) and TypeScript 6.0.3, and exited 0.{ businessUnit: 'x', manageBindings: false }typed asAdminScopefailsTS2322(the retired mark), andDelegableAdminScope['manageBindings']failsTS2339. So the reproduction reads the new types.Merged head
3854d1403(origin/mainmerged throughscripts/pm/os-regen-merge.sh): the closure rebuild, the derived gate families, the consumer typechecks and the dogfood zoo file were in progress when this PR opened. Their readings go into theos-dev-reportcomment on #23488, and CI's check-runs on this PR are authoritative.Acceptance notes
packages/plugins/plugin-security/src/__tests__/legacy-catalog-objects.testkit.ts:333-336. It describes the retiredsys_permission_set.admin_scopecolumn as it was, both keys included. That is accurate for a model of a retired object; carrier: none.packages/plugins/plugin-security/src/builtin-positions.ts:92,packages/core/src/security/resolve-authz-context.ts:1099-1100, andcontent/docs/permissions/permission-sets.mdx"the wildcard ban is the stricterguesttier's rule". Carrier: none.content/docs/releases/v13.mdx:91and theCHANGELOG.mdentries.Generated by Claude Code