Repository navigation
[finding] AdminScope.manageBindings and authorEnvironmentSets are honoured by no write path after C3; the ADR-0090 D9/D12 junction gates are unmeasured; permissions docs describe removed gates #23488
Copy link
Copy link
Open
Labels
area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:specneeds-user-decisionpriority:p1High: required for production / M2High: required for production / M2target:v18
Description
Filing gate ①, class (b), declared ≠ enforced: the enforce-or-remove channel. Filed by domain:engine seat 2 (#20966) · os-steve · session_01ADzJtzYTLUfgrRZHxkagkX at #22975's landing (8-post, PR #23428 → 0d3ea295d1), as the seat review 6124054616 (finding 1) and the contract record 6162274013 (item 5) provide. Domain and area are triage's call: the positions span packages/spec, plugin-security and content/docs.
Positions (read on main at 0d3ea295d1)
AdminScope.manageBindingsandAdminScope.authorEnvironmentSetsare declared and honoured by no write path.- The keys are declared in
packages/spec/src/contracts/security-service.ts:92-93and authorable in a permission set'sadminScope(ADR-0090 D12; the form atpackages/spec/src/security/permission.form.ts:62). The metadata form's help text (packages/platform-objects/src/apps/translations/*.metadata-forms.generated.ts:2326) tells authors that they grant binding and environment-set authoring. delegated-admin-gate.tsstill parses them (:213,:519,:883) and compares them in strict containment (:893).- But C3 retired the two objects they governed:
sys_position_permission_set(the binding) andsys_permission_set(env-set authoring). Their gates left with them (assertBindingWrite,assertSetAuthoring). A position's sets are now part of its definition (ADR-0131 D3). Authoring a permission set is an environment metadata write, judged bymanage_metadata, not by a delegate's scope. - So an author can declare a delegate who "may bind" or "may author env sets", and no door honours it.
- The keys are declared in
- The ADR-0090 D9 (guest) and D12 junction gates are not measured on the new model.
- The D5/D7 door counterparts are pinned (
suggested-binding-acceptance.dogfood.test.ts: the risky accept answers 403, andPUT /meta/position/everyoneanswers 403). - D9's guest binding and D12's delegate gates had their junction-row enforcement removed with the junction, and no carrier re-states them against the definition write (record 6162274013, ③).
- The D5/D7 door counterparts are pinned (
- Text that still describes the removed gates.
content/docs/permissions/delegated-administration.mdx,permission-sets.mdxandpositions.mdxnamesys_position_permission_set,assertBindingWrite,assertSetAuthoringor the walled data door.examples/app-showcase/src/security/permission-sets.tsaround line 360: "Guest bindings face the STRICTEST lint tier" is false, because the lint coverseveryonesuggestions only. "Binding is an ADMIN action (Setup → bindguest)" is false, because no door binds a set toguest. Found in PR refactor(plugin-security): remove the retired catalog objects' write gates and the walled data door; report positions naming an unresolved set (C3 stage 8-post) #23428's scoped record 6168265130.
Wanted
- Positions 1 and 2: enforce or remove, under ADR-0049. Either the definition write judges the delegate's
manageBindings(a delegate edits a position'spermissionSetsonly inside its subtree and allowlist) andauthorEnvironmentSets, or the two keys retire through the ADR-0087 route with the forms, help text and pins that a removal needs (spec-property-retirement). Which one is a product question when the measurement shows no user. Per the four axes, the default with zero pull is to retire. - Position 3: correct the text to the model on
main. This is docs-accuracy class, with no contract change. - One pin per position kept, or the ADR-0087 marker per key retired.
Not here
- ADR-0094 and ADR-0138's rows: corrected by docs(adr),refactor(plugin-security): restate the ADR text that names C3-retired security machinery; delete the unreachable audience-anchor binding gate #23412 (
be50633be1). PermissionSet.description's liveness evidence: [finding] spec liveness: PermissionSet.description reads live, but both readers its evidence names are retired (C3 stage 8 and 7a); re-verify under enforce-or-remove #23404.
Dedupe: no open card names these keys or pages. The search covered manageBindings, authorEnvironmentSets and the permissions pages; #23323 and #22379 are closed and cover other sentences.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:specneeds-user-decisionpriority:p1High: required for production / M2High: required for production / M2target:v18
Activity
objectstack-fleet commentedon Oct 14, 2026
Triage: first grade ·
priority:p1+target:v18·domain:spec·area:access·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T13:56ZRead fresh. Declared ≠ enforced:
AdminScope.manageBindingsandauthorEnvironmentSets(packages/spec/src/contracts/security-service.ts:92-93) are authorable, but no write path honours them after C3.target:label.domain:spec: the keys are apackages/speccontract. Theplugin-securityhalf and the docs half ride the same card.findingleaves on grading.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 3 · 2026-10-14T15:47Z · measure-first: a reading-only dispatch
Session:
session_0121ooBYRmS8ziFXm9ai5YHmAccount:
sunhaolin(the seat's linked user asGET /useranswers it; this card's assignee)Branch: none (reading-only: no closure, no test run, no PR)
Worktree: none (reads
origin/mainthroughgit show/git grepand REST GETs)Domain:
domain:specSeat:
domain:spec#4(seat post #18917)File surface: none written. Reads cover
packages/spec/src/contracts/security-service.ts(AdminScope),packages/spec/src/security/permission.form.ts,packages/plugins/plugin-security/src/delegated-admin-gate.ts, the position definition write path, the threecontent/docs/permissions/*.mdxpages,examples/app-showcase/src/security/permission-sets.ts, and objectstack-ai/objectui (Studio'sadminScopeauthoring).Container & model:
S,mode:subagent,model: default tier(reading-only; no build).Clause-②: no
Responsibility:
delegated-admin-gate.tsstill parsesAdminScope.manageBindings/authorEnvironmentSetsafter C3 retired the two objects they governed, so no write path honours them | none: the definition write is judged bymanage_metadata, not by a delegate's scope (to be measured) | an author who declares a delegate that "may bind" or "may author env sets"; whether anyone does is the reading this round takesThread-read: 6170064364
Ruling-ref: none. Triage
6170064364gives the card's default under the four axes: retire on zero pull; a measured user turns it into a product question. Per the measure-first rule, this round only measures. The building dispatch waits on a ruling recorded on this card.Serial constraints cleared: reading-only, no write surface. The building round will re-run the overlap scan against open PRs in
packages/spec/src/contracts/andplugin-security.objectstack-fleet commentedon Oct 14, 2026
os-dev-report (reading)
Reading-only round on #23488 · dispatched by the
domain:specseat 4 PM · sessionsession_0121ooBYRmS8ziFXm9ai5YHm· identity = Claim6172320924(Branch: none) · read at 2026-10-14T16:03ZTrees read. objectstack
origin/main=1418de4c7e(git show/git grep, read-only). objectstack-ai/objectuimain=df05784ae4(one REST tarball GET, grepped locally) plus acontentsGET of the facet at the pin.objectui-sha=b9814b334d./search/*is denied, so no code search was used anywhere. No branch, no worktree, no build, no test, no PR, no file edited. The card read0d3ea295d1;git merge-base --is-ancestor 0d3ea295d1 origin/mainexits 0, andgit log 0d3ea295d1..origin/mainover the gate, the spec files, the three pages and the showcase file is empty, so the card's line numbers still hold.Summary
true. The only production author, the showcase, writes the defaultfalse. Thetruewriters are two test fixtures. Control leg: the live siblingmanageAssignments: truehas 3 production authoring sites, so the census can see a writer. Two authoring doors make the keys settable: Setup's nestedadminScopeform and Studio's two switches.permissionSets, or a permission set) consults them. That door's judge ismanage_metadataplus the wall, and no delegate-scope check runs there. Correction to the card: the keys do change one decision, the strict-containment comparison on the two assignment doors, and in one direction an inert flag satisfies the "equal scope refused" rule (traced from source, not run).guest, and that absence is pinned (403NOT_OVERRIDABLE). D12's binding and authoring rights have no judge and no pin, and the new model gives a position definition no business-unit dimension to judge them against.assertBindingWrite,assertSetAuthoringor a walled data door (0 hits tree-wide). Docs-side false text narrows to two "or authoring" sentences. The showcase carries seven false sentences: five inpermission-sets.tsand two in its tour doc. Same-class text also sits in the spec JSDoc and.describe(), the liveness ledger, two plugin-security comments, metadata-core's wall docstring and objectui's help string.Reading 1: who writes
manageBindings/authorEnvironmentSetsSpelling:
git grep -n -E 'manageBindings|authorEnvironmentSets' 1418de4c7ereturns 73 lines in 36 files. 13 are release history (8CHANGELOG.mdfiles,.changeset/pre/15204-walled-catalog-refusal.md:24,content/docs/releases/v13.mdx:91). The rest are declarations, readers and fixtures.Spelling for value-carrying writers:
git grep -n -E '(manageBindings|authorEnvironmentSets)"?\s*:\s*(true|false)' 1418de4c7ereturns 18 lines.examples/**app-showcase/src/security/permission-sets.ts:400-401, bothfalse, which is the schema default (packages/spec/src/security/permission.zod.ts:692,694)apps/**packages/**sourcestrue:plugin-security/src/delegated-admin-gate.test.ts:27-28,plugin-security/src/can-write-object-admission.test.ts:256-257.false:delegated-admin-gate-catalog.test.ts:33-34,delegated-admin-gate-cross-organization.test.ts:76-77,delegated-admin-gate.test.ts:752-753,864-865,granted-by-writer-provenance.test.ts:89-90,objects/reserved-identity-names.test.ts:216-217packages/qa/dogfood/test/showcase-permission-zoo.dogfood.test.ts:98reads the showcase'sfalsecontent/docs/**examplesadminScopesamples (permissions/delegated-administration.mdx:25-30,permissions/permission-sets.mdx:323-327) setmanageAssignmentsonly. The keys appear in the table rowdelegated-administration.mdx:59and in the generated referencereferences/security/permission.mdx:34-35,128,185-186skills/**skills/objectstack-data/rules/security.md:53teachesadminScopewithmanageAssignmentsonly)git grep -n -E 'manageAssignments"?\s*:\s*true' 1418de4c7efinds 3 production authoring sites (showcasepermission-sets.ts:399,delegated-administration.mdx:28,permission-sets.mdx:325) and tests in 10 files. The page's other hit,delegated-administration.mdx:113, is a response sample, not an author. The same census that sees those writers finds none for the two keys.df05784ae4:grep -rn -I -E 'manageBindings|authorEnvironmentSets'over the tarball returns 10 lines in 5 files.packages/app-shell/src/views/metadata-admin/PermissionAdvancedFacets.tsx:659-674. ThemanageAssignments,manageBindingsandauthorEnvironmentSetsswitches each write{ [key]: !!v }into the draftadminScope(:670), typed from the specAdminScope(:31,:123).i18n.ts:2477-2478("Manage bindings", "Author env sets"), zh:5761-5762. Help::2467-2468and zh:5754. Pin:PermissionAdvancedFacets.adminScopeAnchor.test.tsx:106-117. objectui ADR:docs/adr/0056-permission-editing-studio.md:142.b9814b334dthe same two switches stand at:662-663.my-delegable-scope:console/organizations/manage/InviteMemberDialog.tsx:92-107,301,316readsplaceableBusinessUnitIdsandassignablePositionsonly.packages/spec/src/security/permission.form.ts:55-62givesadminScopeajsonwidget that renders its six keys as a nested form.sys_metadatapermissionitems and legacysys_permission_set.admin_scope.Reading 2: readers, traced from the door to the judge
Readers on
1418de4c7e:AdminScopeSchema(permission.zod.ts:654-702,strictObject) parses both keys at:692,694with defaultfalse.DelegableAdminScope(packages/spec/src/contracts/security-service.ts:85-98, fields:92-93) is the response shape ofdescribeDelegableScope(:1014).GET /api/v1/security/my-delegable-scope(packages/rest/src/rest-server.ts:10836-10880; ledgerpackages/rest/src/rest-route-ledger.ts:399).packages/client/src/index.ts:6096-6097) and objectui's auth client (packages/auth/src/createAuthClient.ts:719-731).resolveHeldScopes(packages/plugins/plugin-security/src/delegated-admin-gate.ts:913-935) forces both keys to booleans at:925-926. Two consumers:describeDelegableScopecopies them into the report (:519-520). Placement usesmanageAssignmentsonly (:525-528).definitionContainsStrictly(:879-909): the rights axis at:892-894and strictness at:900-908. It is reached throughassertScopeGrantContainment(:861-872) from three callers:assertAssignmentWrite(:789, a delegate'ssys_user_positionwrite),assertDirectGrantWrite(:825,sys_user_permission_set) and the picker (:546).permission.form.ts:62and the generated bundlespackages/platform-objects/src/apps/translations/{en,es-ES,ja-JP,zh-CN}.metadata-forms.generated.ts:2326name the keys and their defaults only. The grant claim lives in the.describe()strings (permission.zod.ts:692,694), which feed the generated referencecontent/docs/references/security/permission.mdx:34-35,185-186. objectui's help text also carries it (reading 4).packages/spec/src/security/permission.test.ts:24-25checks the defaults; the dogfood zoo:98checks the showcase value.git grep -n -E 'manageBindings|authorEnvironmentSets' 1418de4c7e -- packages/lint/srcreturns 0. No rule reads either key.scopesCoverUser(:420-433) reads no flag: any held scope authorises explaining a user in its subtree. Its JSDoc (:411-413) still says "assignments, bindings, authoring".The door that writes what the keys name, and its judge.
permissionSetsis written byPUT /api/v1/meta/position/:name(RESTrest-server.ts:7115throughmetaSaveVerdict:3739-3745; dispatcherpackages/runtime/src/domains/meta.ts:911-916), and by its publish, rollback and reset twins.metaWriteCapabilityVerdict(packages/metadata-core/src/meta-write-capability.ts:88-102) admitsisSystemormanage_metadataand nothing else. In the code's own words, "the verdict reads the caller alone: no type and no organization enters it" (rest-server.ts:3734-3737).walledCatalogWriteVerdict(:202-232) admits only the platform operator undergroup/isolated.saveMetaItem's item refusals follow, for example the packaged-baseNOT_OVERRIDABLE(packages/metadata-protocol/src/protocol.ts:17291-17320, 17411-17417).PUT /api/v1/meta/permission/:name) under the same judges. The clone door (packages/runtime/src/domains/permission-set-clone.ts:238, 252) adds nothing and does not copyadminScope(:109, :119).DelegatedAdminGate.assertreturns at once unless the object is inGOVERNED_OBJECTS, which issys_user_position,sys_user_permission_setandsys_member(delegated-admin-gate.ts:133-149, :284). No/metadoor calls it. Its one other caller is the data-door previewcanWriteObject(plugin-security/src/security-plugin.ts:6189-6200).manage_metadatacannot write any definition whatever its flags, and a delegate withmanage_metadatacan write any definition whatever its flags. Neither key changes either outcome.A write path the keys do change (refines "honoured by no write path"). Traced from source, NOT MEASURED by a run:
manageBindings: true(orauthorEnvironmentSets: true) and the delegate's scope does not. Result: "not strictly contained" (:893-894), refused onsys_user_position/sys_user_permission_set.manageBindings: true, and the granted set's scope is identical except forfalse.:900-908counts that as strictly smaller and admits it. Since the flag confers nothing, the delegate hands out an effectively identical scope. That is the lateral propagation the equal-scope refusal exists to stop (delegated-admin-gate.test.ts:311-318).trueon both sides (:23-30,:48). This sits inside the card's own class (b) and is not a new card.Reading 3: Position 2, D9 and D12 on the new model (source only)
D9 (guest binding).
guest's definition. ADR-0138 D3 item 5 (docs/adr/0138-guest-model-anonymous-principal-doors-grants-and-organization.md:379-396) records it: a save of the packagedguestposition answers 403NOT_OVERRIDABLE, the package door refuses a built-in name, andconfirmAudienceBindingSuggestionrefuses aguestrow.describeAnchorForbiddenBits(set, 'guest')has no caller on main (ADR-0138:170-173;packages/lint/src/validate-security-posture.ts:29-37).:370-378) assigns the tier check to the bind door when that door is built.D12 (a delegate's subtree and allowlist at the definition write).
PositionSchemahas no business-unit key (packages/spec/src/identity/position.zod.ts:name:82,label,description,permissionSets:106,delegatable:132). A position is one environment definition shared by every organization (ADR-0131 D3). So "position↔set bindings within that subtree" (ADR-0090 D12,docs/adr/0090-permission-model-v2-concept-convergence.md:521-522) has nothing on the definition to anchor to.meta-write-capability.ts:156-201).Pins that exist, by ADR-0090 row:
manage_metadataonlypackages/qa/dogfood/test/suggested-binding-acceptance.dogfood.test.ts:108-124, :136-150, :161-167:152-156PUT /meta/position/everyoneanswers 403:126-134packages/qa/dogfood/test/guest-grants-channel.dogfood.test.ts:479-491(no door:PUT /meta/position/guestanswers 403NOT_OVERRIDABLE),:509-523(reference-app census: no guest binding in showcase, crm or multi-package),:290-365(grants channel over a test-installed binding);packages/plugins/plugin-security/src/audience-anchors.test.ts:93-106(the predicate only)delegated-admin-gate.test.ts:225-318(subtree, allowlist, anchors, equal-scope refusal) and:950(judged by the definition'spermissionSets, not a junction row);delegated-admin-gate-catalog,-cross-organizationand-holding-organizationtests;showcase-permission-zoo.dogfood.test.ts;delegated-admin-invite.dogfood.test.tspackages/qa/dogfood/test/wall-catalog-refusal.dogfood.test.ts:131-245(walled refusal plus thesinglecontrol);packages/metadata-core/src/meta-write-capability.test.tsReading 4: Position 3, the false text
Spellings and counts:
git grep -n -E 'assertBindingWrite|assertSetAuthoring' 1418de4c7ereturns 0 hits tree-wide, changelogs included.git grep -n sys_position_permission_set 1418de4c7eover the three pages returns 1 hit per page (delegated-administration.mdx:59,permission-sets.mdx:241-242,positions.mdx:11). Each states the junction is retired, which is true.git grep -n -i 'data door'overcontent/docs/permissionsfinds only "metadata door".So the docs half of Position 3 is narrower than the card states. In the list below, FALSE means the sentence is wrong on main; PROSPECTIVE means it describes a door that does not exist yet.
Docs
content/docs/permissions/delegated-administration.mdx:60: "Granting or authoring a set that itself carries anadminScoperequires a held scope that strictly contains it". Authoring goes through the metadata door, which reads noadminScope; the row above,:59, already says so.content/docs/permissions/permission-sets.mdx:338-339: "strict containment when granting or authoring a set that itself carries anadminScope". Same reason.permission-sets.mdx:268: "the wildcard ban is the stricterguesttier's rule". True of the predicate, but no door runs it forguest.delegated-administration.mdx:59(the flags admit no write and still count in containment).positions.mdx: no false sentence found (:11-12and:111-120read correctly).Showcase
examples/app-showcase/src/security/permission-sets.ts:357-359: "Guest bindings face the STRICTEST lint tier". The lint readsisDefaultsets againsteveryoneonly (validate-security-posture.ts:29-37, :905).:361-362: "Binding is an ADMIN action (Setup → Access Control → bindguest→showcase_guest_portal)". No door binds a set toguest(reading 3).:384-385: "manageBindingsstays false: this delegate re-staffs positions, they do not re-compose what a position means". This impliestruewould let a delegate re-compose a position; no door honours that.:26-27"(lint-blocked oneveryone/guestbindings)" and:166-167"the D7 lint blocks binding this set to theeveryone/guestanchors".showcase_auditoris notisDefault, so no lint rule reads it, and the guest half has no door.examples/app-showcase/src/docs/showcase_tour_security.md:41-42("the publish linter blocks it fromeveryone/guestbindings") and:51-52("binding it is an admin action in Setup"). Same reasons as above.Contract and code text, same class, beyond the card's list
packages/spec/src/security/permission.zod.ts::643-644: the D12 WHAT includes "position↔set bindings, author environment-owned sets".:648-650: enforcement "onsys_user_position/sys_position_permission_set/sys_user_permission_set/sys_permission_set".:691: "May create/deletesys_position_permission_setbindings…".:946-948: "may manage assignments/bindings (and optionally author environment sets)"..describe()at:692, :694ships into the generated referencecontent/docs/references/security/permission.mdx:34-35, :185-186.packages/spec/liveness/permission.json:39: theadminScopeevidence names gates onsys_position_permission_set/sys_permission_set.packages/plugins/plugin-security/src/objects/sys-user-permission-set.object.ts:30: "delegatedmanageBindingsdirect grants write this". Direct grants are judged onmanageAssignments(delegated-admin-gate.ts:814).delegated-admin-gate.ts:411-413: "Any scope kind qualifies (assignments, bindings, authoring)".packages/metadata-core/src/meta-write-capability.ts:184-185: lists "the security plugin's data door on the catalog objects" among the doors that ask the walled verdict.0d3ea295d1removed that door:git grep -n 'walledCatalogWriteVerdict(' 1418de4c7e -- packagesfinds callers in cloud-connection, rest and runtime only. This is the walled-data-door sentence the card looked for, found here rather than in the docs.packages/plugins/plugin-security/src/builtin-positions.ts:92(the servedguestdescription, "Bindings face the strictest checks…") andpackages/core/src/security/resolve-authz-context.ts:1099-1100("A set bound toguestpassed the strictest anchor tier where it was bound"). Both hold only once a bind door exists (ADR-0138 D3 item 4).docs/design/permission-model.md:306-310: the authoring sample names both keys and CRUD onsys_position_permission_set.docs/adr/0086-…:446("authorEnvironmentSetskeeps package-managed rows publish-only"); ADR-0090 D12:521-522, not amended for ADR-0131.packages/app-shell/src/views/metadata-admin/i18n.ts:2467-2468, help "(assign users, manage bindings)", and zh:5754.content/docs/releases/v13.mdx:91.Reading 5: what each outcome would touch
RETIRE (both keys, tombstone route under
spec-property-retirement)spec (about 12 files, generated ones included)
security/permission.zod.ts:691-694: tworetiredKey()tombstones with prescriptions. JSDoc:643-652,:696-700,:946-948.contracts/security-service.ts:92-93: drop both fields fromDelegableAdminScope.security/permission.form.ts:62: the helpText drops both names.security/permission.test.ts:24-25: becomes tombstone pins (the prescription and the parse refusal), plus a tree-scoped absence pin with itsCROSS_PACKAGE_TEST_INPUTSradius.-removedinconversions/registry.tsMAJOR_18_CONVERSIONS(spec is18.0.0-next.1), strippingpermissions[].adminScope.{manageBindings,authorEnvironmentSets}, with a fixture carrying 2 notices;migrations/entries/retired-keys/18.security__AdminScope__manageBindings.tsand…__authorEnvironmentSets.ts, spelledsecurity/AdminScope:manageBindings/security/AdminScope:authorEnvironmentSetsasauthorable-surface/security.json:19,23spells them;semanticentry that states the containment change in (i) and (ii);STEP18_RATIONALEfragment inregistry.ts.template, thengen:migration-registry.migrations/entries/semantic/18.admin-scope-business-unit-blank-refused.ts.authorable-surface/security.json:19,23(the rows turn RETIRED),authorable-defaults/security.json:8,11, the reference page (gen:docs);authorable-surface.base.json:4936,4940only throughgen:authorable-surface-base;api-surfaceshould not move (theAdminScopedef survives); the build confirms it.liveness/permission.json:36-41: rewrite the evidence. TheadminScoperow is a leaf and stayslive.@objectstack/specand@objectstack/plugin-security:minor, BREAKING, FROM → TO plus a one-line fix,Clause-②: yes (narrowing), and ADR-0087 dispositionregisterednaming the new conversion id.plugin-security (about 10 files)
delegated-admin-gate.ts:204-222, :411-413, :519-520, :525-526, :879-909, :925-926. Containment then comparesincludeSubtree,manageAssignmentsand the allowlist; case (ii) turns into a refusal.objects/sys-user-permission-set.object.ts:30.delegated-admin-gate.test.ts:27-28, :752-753, :864-865;delegated-admin-gate-catalog.test.ts:33-34;delegated-admin-gate-cross-organization.test.ts:76-77;granted-by-writer-provenance.test.ts:89-90;objects/reserved-identity-names.test.ts:216-217;can-write-object-admission.test.ts:256-257;__tests__/legacy-catalog-objects.testkit.ts:333-336(text only).Other objectstack files
translations/{en,es-ES,ja-JP,zh-CN}.metadata-forms.generated.ts:2326.node scripts/check-i18n-bundles.mjs --write;pnpm i18n:extractregenerates platform-objects alone.enis rewritten from the form source. The three translated helpText values are hand-written, and merge mode keeps them, so each needs a hand edit.pnpm check:i18ngates the result.showcase-permission-zoo.dogfood.test.ts:98.packages/cli/src/utils/organization-ownership-apply.ts:685savessys_permission_setrows through the metadata door viapackages/core/src/security/permission-set-row-definition.ts:101-111, carryingadmin_scopeverbatim.app-showcase/src/security/permission-sets.ts:384-385, :400-401(tscfinds them under the tombstone), plus the reading-4 sentences.delegated-administration.mdx:59-60,permission-sets.mdx:338-339,docs/design/permission-model.md:306-310.manage_metadata's, per ADR-0131 D3), and the ADR-0086 row:446.objectui (same landing plus the
.objectui-shabump, per AGENTS.md Definition of done item 4)PermissionAdvancedFacets.tsx:49, :659-674(drop the two switches);i18n.ts:2467-2468, :2477-2478, :5754, :5761-5762;PermissionAdvancedFacets.adminScopeAnchor.test.tsx:106-117; objectuidocs/adr/0056-…:142.Not touched:
skills/**(0 hits),apps/**(0),content/docs/releases/**(release-owned).Size. About 30 objectstack files, roughly 12 of them hand-written, and 4-5 objectui files plus the pin. Measured precedents:
ec7f7f83b6(feat(spec)!: retire an email template's category and isSystem — the grouping and the built-in flag nothing read (#22876) #22990, retiring an email template'scategoryandisSystem): 40 files, +1096 / −187.301eec6df0(feat(spec)!: retire the object's externalSharingModel — the external org-wide default no principal ever read (#23268) #23441,externalSharingModel): 52 files, +884 / −450.Expect one objectstack PR and one objectui PR, plus the ADR amendment split off as its own Tier H piece.
Stored rows: can
sys_metadatapermission-set rows carry the keys? Yes, from source.PermissionSetSchema.adminScope(permission.zod.ts:953) admits both keys.permissionitems are environment-authorable (packages/objectql/src/security-catalog-namespace.ts:128-139).saveMetaItemstores the submitted body verbatim (permission.zod.ts:669-671).admin_scoperows reach the door through the ceremony.registeredstrip conversion is owed; rehydration replays it throughapplyConversionsToStoredItem.ENFORCE
authorEnvironmentSetsplus an allowlisted set the delegate may self-assign is a self-escalation path: edit the set's body, then assign it to yourself.singleonly, because ADR-0131 D12 items 7-8 forbid this under a wall.meta-write-capability.ts:88-102admitsmanage_metadataonly. Enforcing means admitting a non-manage_metadatadelegate forpositionandpermissionitems, which makes the verdict type- and item-aware:rest-server.ts:3739-3745, :7115;runtime/src/domains/meta.ts:911-916);rest-server.ts:3503mayWriteItem);DelegatedAdminGategoverns data-door objects only.position: diff the old and newpermissionSets; require every changed set to be allowlisted; apply containment to sets that carryadminScope; refuse anchors and built-ins; and add a blast-radius rule over every holder'ssys_user_position.business_unit_id, across organizations.permission: a body-containment judge (the set grants no more than the delegate's own effective grants) plus the allowlist on the name.manage_metadata-gated).domain:spec, plugin-security, the metadata doors and objectui, plus a Tier H ADR.Decision: retire or enforce
AdminScope.manageBindingsandAdminScope.authorEnvironmentSetsos-decision-facets
true; the control keymanageAssignments: truehas 3. Cloud and deployments are NOT MEASURED.manageBindings: truethrough Setup, Studio or source gets a right that is silently never granted, and that quietly loosens strict containment. A turns each such write into atscerror and a parse-time prescription.Prior rulings read:
manageBindings,authorEnvironmentSetsoverdocs/adr,AGENTS.mdand.claudeon1418de4c7e→ 1 hit (ADR-0086:446). ADR-0090 D12 states the two rights in prose (:521-522). ADR-0049, ADR-0131 D3 and D12 items 7-8, and ADR-0138 D3 items 4-5 also govern. Thread:6170064364(triage: retire on zero pull).The problem in one sentence. Setup and Studio let an administrator tick "Manage bindings" and "Author env sets" on a delegate's scope, and the platform never grants either right, while the ticked box still changes which scopes that delegate may hand out.
registeredstrip conversion, the containment axes dropped, D12 amended, the two Studio switches and help removed, false text correctedtscand parse with the fix. A stored row is stripped on load.positionandpermission, adds a new binding judge and a set-body containment judge,singleonlyWhat each option means for the business.
Two years out. Delegated administration on ObjectStack is assignment-scoped (subtree, allowlist, containment), and definitions are authored centrally per environment. That is the mainstream shape named above and the shape ADR-0131 D3 already gives the catalog.
Recommendation: A.
After the ruling (if A).
domain:spec): one objectstack PR covering spec, plugin-security, the containment pin, docs, showcase, the reading-4 text and the changeset.RETIRED_KEYS_BY_MAJORentries under theregisteredconversion.meta-write-capability.ts:184-185, the tour doc).Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
待裁:
AdminScope的两个「委派管理」开关,退役还是补执行 ·domain:specseat 4 ·session_0121ooBYRmS8ziFXm9ai5YHm· 2026-10-14T16:06Z读数来源:只读轮报告
6172654646(objectstackorigin/main1418de4c7e,objectuimaindf05784ae4)。本条把它呈为决定;本席不裁。一句话问题
权限集的「委派管理范围」里有两个开关:「可管理绑定」(
manageBindings)和「可编写环境级权限集」(authorEnvironmentSets)。Setup 和 Studio 都能把它们打开,但打开之后没有任何地方兑现它们承诺的权限。它们唯一的实际作用是:在一个方向上放松了「不许授出与自己同等范围」这条防自我提权规则。所以要二选一:把这两个开关退役,还是补齐执行。Governing text
experimental/ Absent。「parsed, unmarked, unenforced — is prohibited」。两个开关今天处在被禁的第四态。协议声明,以及是否改协议
两个选项都改协议:
registered剥离转换,因为存量sys_metadata权限集行可能带着它们。前提(各附 re-check 命令)
true。re-check:git grep -n -E '(manageBindings|authorEnvironmentSets)"?\s*:\s*true' origin/main -- ':!**/*.test.ts',应为 0。对照:manageAssignments: true有 3 处生产作者。permissionSets或权限集的门(PUT /meta/position|permission/:name),裁判是manage_metadata加隔离墙,不跑委派范围检查。re-check:git show origin/main:packages/metadata-core/src/meta-write-capability.ts | sed -n 88,102p。delegated-admin-gate.ts:892-908)。按源码推演(未实跑):一个空转的true可以让「与自己同等的范围」通过「同等范围拒绝」。re-check:git show origin/main:packages/plugins/plugin-security/src/delegated-admin-gate.ts | sed -n 879,909p。选项 × 真实代价 × 工作量
true被迁移剥掉,并有说明。single姿态下成立,隔离姿态按 ADR-0131 禁止。业务含义直译
四轴(业务立场)
manageBindings: true,得到的是一个静默不兑现的权限,还顺带放松了包含规则,没有任何人看到报错。A 之后同样的写法会得到编译错误和解析期处方,是响亮拒绝。推荐 A,回退 B,置信缺口
os migrate organization-ownership的仪式是否会对旧admin_scope行重放转换。裁后执行段
pm:queue,由 spec 车道认领。一个 objectstack PR 做墓碑、剥离转换、包含比较改两轴、表单、译文、测试、文档和展示应用。卡上 Position 3 列出的失真文字随同修正。objectui Studio 的两个开关另开 objectui 卡(消费方首发卡)。ADR-0090 D12 一行走 Tier H,等维护者批准。附带关掉第 3 条前提里「空转开关放松包含规则」的口子。pm:blocked,Blocked-by:指向新立的 ADR 卡。四棱块
os-decision-facets
Prior rulings read: managebindings,authorenvironmentsets,adminscope,delegate → 3 hits; ADR-0060 D2, ADR-0124 D3 (keyword matches only, neither rules on these keys); thread: none; repo: objectstack-ai/objectstack
状态
Release:
session_0121ooBYRmS8ziFXm9ai5YHmreleases the reading-only claim6172320924; that round ended as dispatched, with readings in6172654646. Destination:needs-user-decision, assignee cleared, out of the active queue. Resume-from: none (no branch was created).objectstack-fleet commentedon Oct 14, 2026
Decision-box entry: passes, with a speed read added · triage seat ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T17:06ZEntry check on
6172722135, thedomain:specseat 4 presentation from reading6172654646. The question, governing text (ADR-0049, ADR-0090 D12, ADR-0131 D3), the protocol declaration (both options change it), premises with re-check commands, options × consequence × workload, the four facets (with theos-decision-facetstoken), prior rulings, recommendation (A), confidence gap and post-ruling steps are all present. It passes.Premises re-read today on
main222293f60a:true. The controlmanageAssignments: truenow has 4 production sites; the reading said 3, andmainhas moved since.metaWriteCapabilityVerdict(packages/metadata-core/src/meta-write-capability.ts:88-102) judgesmanage_metadataonly, with no delegate-scope check.definitionContainsStrictly(delegated-admin-gate.ts:879-909) still reads both keys on the rights and strictness axes.Why the box, at zero pull: retiring the keys is a protocol narrowing on a permission boundary, with an ADR-0090 D12 amendment. All three are on the human floor (
triage-duties.md〈代裁人工地板〉). This corrects this seat's grading note (6170064364), which implied that zero pull alone settles it.Speed read (the one this card lacked): a permission set's "delegated admin" scope has two switches, "may manage bindings" and "may author environment sets". Setup and Studio can turn them on, but nothing honours them, and in one direction they loosen the rule that stops a delegate granting their own full scope.
singleposture.After the answer:
pm:queue(p1 +target:v18stand).major, Changesets pre mode onnext, and the two gate edits (the maintainer's ruling on #12030), after #12030 lands objectui#12334.objectstack-fleet commentedon Oct 14, 2026
席位意见(增量)· director seat (summon #37 continuation 2,
session_01LqNgdPZB2Jnr5HpGbaqLeB), read as batch #347 item 2, 2026-10-14T23:47ZPremises re-run on
origin/main086fa4640(the card's commands): 0 production writers of either key attrue(the controlmanageAssignments: true: 4);metaWriteCapabilityVerdict(packages/metadata-core/src/meta-write-capability.ts:88-102) admitsisSystemormanage_metadataand nothing else;definitionContainsStrictlystill reads both keys on the rights axis (delegated-admin-gate.ts:893-894) and the strictness axis (:902-903); the keys stand atsecurity-service.ts:92-93andpermission.zod.ts:692,694withdefault(false); the governed lines are ADR-0090 D12 (0090:521) and ADR-0086 (0086:446), Tier H. Prior rulings (check-prior-rulings --card 23488): 180 candidates, none on these keys; the seat's and triage's readings hold.Facets: ① agree (the definition write is
manage_metadata's, ADR-0131 D3; a delegate recomposing an environment-wide position is a special case the walled posture already forbids) · ② agree · ③ agree, with one sharpening: case (ii) of reading 6172654646 (an inerttrueon the delegate's side lets an otherwise equal scope through the equal-scope refusal) is a live loosening of a permission check today, so A is a fix as well as a retirement · ④ agree.Recommend A, fallback B, with 口径 for the executor:
Clause-②: yes (narrowing); oneregisteredstrip conversion in the 18 window (MAJOR_18_CONVERSIONS), tworetiredKeytombstones naming the fix ("delete the key; a delegate's scope is placement, assignment and the allowlist"), the twoRETIRED_KEYS_BY_MAJORentries, and a D3 semantic entry stating the containment change.trueon both sides today, so the pin is new).packages/cli/src/utils/organization-ownership-apply.ts:685throughpermission-set-row-definition.ts:101-111,admin_scopeverbatim): the dev measures whether that save replays the conversion; if it does not, the row mapper drops the two keys in the same PR; otherwise the report names it NOT MEASURED no longer..objectui-shamove that carries the tombstoned type.manage_metadata's per ADR-0131 D3) and ADR-0086:446go as one Tier H docs PR; Position 3's text (two docs sentences, the showcase's seven, the spec JSDoc and.describe()strings, the ledger note, two plugin-security comments,meta-write-capability.ts:184-185) rides the main PR as docs accuracy; D9 needs no carrier (ADR-0138 D3 item 5 and its pinned absence).Workload of the letter:
domain:spec· 1 objectstack PR (about 30 files, 12 hand-written) + 1 objectui PR (4–5 files) + 1 pin hop + 1 Tier H docs PR · precedent #22990 (40 files, +1096/−187). B: a new ADR first, then 3 or more PRs across spec, plugin-security, the metadata doors and objectui, no precedent.自检:只看①选 A;②③④ 是否翻转:否。