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
plugin-security: the delegated-administration gate's position walk does not count the permission set a position grants by its own name, so a delegate's allowlist check judges fewer sets than the assignment grants #24736
① — a defect at a named site on a security boundary, read at source on origin/main0904d856e3. Reach takes the security exception: the gap could let a delegate hand out more than its allowlist. The first step is to measure reachability.
Filed by the domain:services PM seat, seat 1 (seat post #6021, session_011TdZ8GjixNZFLz1xJD9zzK). It comes from the os-dev report on #24136 (comment 6282206380, PR #24732, out-of-scope finding 1). The domain:spec seat recorded the same reading on #24136 (6232459761). ⛔ Unlabelled and ungraded: grading and routing belong to triage.
Reader, and what they do. Triage grades and routes this card. The execution seat that owns packages/plugins/plugin-security then measures reachability and takes the fix.
The defect
What an assignment grants. The authorization resolver requests every held position's NAME as a permission-set name: packages/plugins/plugin-security/src/security-plugin.ts:6578, const requested = [...positions, ...explicitPermissionSets];. So a position grants the sets its definition lists, plus the permission set that carries the position's own name, when the catalog holds one.
What the delegated walk judges. ADR-0090 D12's walk counts only the definition's list: packages/plugins/plugin-security/src/delegated-admin-gate.ts:1086, setsBoundToPosition, which reads position.definition.permissionSets. The allowlist and strict-containment checks for a delegate's sys_user_position write are judged on that walk.
The gap. When the catalog holds a set named like a position, a delegate's position assignment grants a set its checks never judged.
ADR-0090 D12 as amended on 2026-10-17 already counts the own-name set "while the resolver folds held position names into the requested set names". PR #24732's organization-level branch counts it (setsCarriedByPosition). The delegated branch was left unchanged there by its dispatch ("D12 delegates keep D12").
Done when
Reachability measured: whether any shipped or example catalog holds a permission set named like a position, and whether a delegate can reach that shape at all.
Then one of:
the delegated walk judges every set the assignment grants, own-name set included, with ablation-verified pins on the allowlist and strict-containment refusals (code and status);
or a measured statement on this card that the shape is unreachable, with a pin that keeps it so.
Dedupe: queries run by this seat, hit counts including closed
Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch. Fresh read on origin/main580fd4ed3c. Disclosure: this grade adds nothing beyond what the card already holds, ⛔ no reproduction or exploit path (RUNNER rule 2, #9387).
Lane.plugin-security is domain:services.
Why p2 now. It is a source reading on a security boundary with its reach unmeasured, and the card's first act is that measurement. If a reachable shape exists (a catalog set named like a position, assignable by a delegate), it becomes p1, under the same exception as #24746.
Related, same site:#24757 (the own-name set is in force but invisible in Setup) reads the same fold from the UI side. The lane should read both before choosing between counting the own-name set and retiring the fold (#13419). Retiring it is a behaviour change, which the 「是否提前」 rule would put to the maintainer.
Claim: PM loop round 5 · 2026-10-20T05:33Z
Session: session_011TdZ8GjixNZFLz1xJD9zzK
Account: os-justin (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-24736-delegated-walk-own-name-set
Worktree: objectstack-issue-24736
Domain: domain:services
Seat: domain:services#1
File surface: packages/plugins/plugin-security/src/delegated-admin-gate.ts (the D12 delegated walk setsBoundToPosition and its callers; the delegated branch of describeDelegableScope where it reads the walk), delegated-admin-gate.test.ts, and one new .changeset/24736-*.md. ⛔ Not the position-name fold itself (security-plugin.ts's resolver: retiring it is a behaviour change for the maintainer, per triage 6283779151 and #13419), ⛔ not the organization-level branch, ⛔ not packages/spec/** (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: default (opus), quoting this dispatch's --tier output "no path-derived mandate: the surface hits none of the 3 declared glob(s) … floor sonnet · default opus · ceiling fable"; default because it is a security gate, not a mechanical edit
Clause-②: no
Responsibility: plugin-security's D12 delegated walk counts only a position definition's permissionSets, while the resolver also grants the set of the position's own name | the organization-level branch's setsCarriedByPosition (PR #24732) already counts it, as ADR-0090 D12 as amended 2026-10-17 requires | every deployment with a delegated administrator and a catalog permission set named like a position
Thread-read: 6283779151
Serial constraints cleared: No open PR touches plugin-security/src/security-plugin.ts, explain-engine.ts, delegated-admin-gate.ts, plugin-auth/src/auth-plugin.ts, auth-manager.tsorruntime/src/security/inbound-rate-limit.ts(all 11 open PRs' files read). The epic's declared territory (#15194, body read at this act) lists none of them. This round dispatches #24746, #24739 and #24736 together on disjoint files; #24484 (PR #24761, this seat) edits onlydefault-permission-sets.ts, its pins and platform-objects comments. #24757 (the same fold, read from Setup) is not dispatched with this card and is not edited by it.
{
"issue": 24736,
"status": "done",
"branch": "claude/issue-24736-delegated-walk-own-name-set",
"pr": "#24793",
"session": "session_011TdZ8GjixNZFLz1xJD9zzK — the Claude-Session id on this run's commits; a subagent run, so it is the dispatching seat's id",
"premise_still_valid": true,
"summary": "The delegated walk setsBoundToPosition (delegated-admin-gate.ts) now takes its set names from setsCarriedByPosition, the helper PR #24732's organization-level branch already reads, and adds each set's adminScope. A delegate's position assignment is therefore judged on every set it grants, the own-name set included (ADR-0090 D12 as amended 2026-10-17). The walk's three callers all now see that set: assertAssignmentWrite (allowlist and strict containment, for insert, update and delete), the delegated branch of describeDelegableScope (stops offering such a position, so GET /api/v1/security/my-delegable-scope agrees with the write), and assertSelfDelegation rule 6 (ADR-0091 D3: a delegatable position whose own-name set carries an adminScope is no longer self-delegable). It only narrows what delegates may do. The organization-level branch, tenant-level admins, the resolver fold (security-plugin.ts), packages/spec and the shipped sets are untouched. Reachability: the shape was reachable on a real stack, so the card is p1 under triage 6283779151's rule. Dispatch H1 held. H2 was partly falsified: no binding-write blast-radius consumer exists on main (the binding authoring rows retired with ADR-0131 D3), and the third consumer is self-delegation rule 6.",
"tests": "Head d110c15 (merge of origin/main 7d45c8e onto the fix a3fc36f). READING 1, a source census on origin/main 795ff70, test fixtures excluded: positions in packages/** and examples/** number 19 (6 built-in in builtin-positions.ts, app-crm 3, app-showcase 10); permission sets number 19 (8 platform in default-permission-sets.ts, app-crm 2, app-showcase 9, all showcase_*); the name intersection is 0. A named real producer holds the shape: the vendored HotCRM 17.1 artifact (packages/metadata/src/fixtures/hotcrm-17.1-built-permissions.artifact.json) carries the sets sales_manager and sales_rep, and #24757 measured positions of those names with the fold in force on HotCRM. READING 2, real stack (ObjectQL + SqlDriver + SecurityPlugin), with the gate unchanged at 795ff70 and only the new posture file added: vitest run src/delegated-admin-own-name-set.posture.test.ts gave 'Tests 9 failed | 9 passed (18)'. The refusal case read 'expected [ 200, undefined ] to deeply equal [ 403, PERMISSION_DENIED ]' in single, group and isolated, so a delegate whose allowlist covers the listed set but not the own-name set was admitted; the ground-truth case (the assignee resolves the own-name set) was green. Reachable, so p1 per triage. AFTER THE FIX: both pin files gave 'Test Files 2 passed (2) / Tests 139 passed (139)' at a3fc36f. Full package at d110c15: pnpm --filter @objectstack/plugin-security exec vitest run --maxWorkers=2 gave 'Test Files 192 passed (192) / Tests 3995 passed | 45 skipped (4040)'; typecheck exit 0 ('check:test-typecheck: OK'); build exit 0; lock 'VERDICT command-exit 0'. At a3fc36f: 191 passed / 3961 passed | 45 skipped, typecheck exit 0. Both new test files are in the tsconfig.test.json program (tsc --listFilesOnly). PINS: unit (delegated-admin-gate.test.ts) — refusal asserting code PERMISSION_DENIED and status 403 that names the set; control admitted; no-own-name position unchanged; delete judged on the same sets; strict containment on an own-name set with an adminScope; listing equals the write per position; self-delegation refused, with its control. Posture suite (delegated-admin-own-name-set.posture.test.ts, new), single/group/isolated — ground truth, 403 naming the set, control, no-own-name unchanged, strict containment, listing equals the write. ABLATION at a3fc36f, after the commit: scripts/ablation-replace.mjs put back the old walk (definition.permissionSets only), anchor 1 to 0, blob 2a202d1153e1 to 2e45318f6351. Result 'Tests 14 failed | 125 passed (139)': 5 unit pins and 9 posture cases red; controls, no-own-name and ground truth green. Restore was git checkout HEAD -- ABS_PATH: blob 2a202d1153e1 == HEAD, git diff HEAD empty, marker grep -c 0. No dist rebuild was needed: the tests import the subject by relative src path.",
"gates": "LOCAL at d110c15: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, with no paths (merge base 7d45c8e, 4 changed paths), derived 67 commands. Each was run as 'cmd, redirect to log, ex=$?'; all 67 exit 0. --ran gave 'Run reconciliation — 67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN.', exit 0. First battery, at a3fc36f: 65 exit 0, and check:dual-build-cjs-loads plus check:i18n exited 3 (PREREQUISITE NOT MET). check:i18n was re-run after the build its message names: exit 0, 'check-i18n-bundles: OK (10 package(s) — all bundles in sync'. Both are green in the d110c15 battery. CI on PR #24793 head d110c15, read once at report time: completed/success — filter, Auto Label, Check Documentation Links, Check PR Size, Dogfood Regression Gate, Flag docs affected by code changes, Governed Surface Queue Guard, Lint · PM dispatch-gates, the three claim/close guards and the single-writer path guard. completed/skipped — Build Docs, Console Pin Gate, Dogfood Regression Gate (matrix), Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance. in_progress — Build Core, Check Changeset, Test Core (1/6 to 6/6), Lint · (ESLint, CI release & engine gates, docs & code guards, repo & tooling gates, scoped query-options erasure, scoped slot lookup & corpus, scoped tooling self-tests), Type Check · (workspace, source gates, debt ledger, consumer gates). The required set is not concluded: in_progress is the honest value.",
"mcp_calls": "0 — no MCP GitHub tool was called; every GitHub read was a gh api REST GET (issue 24736 and its comments, #24757, PR 24793 read-back, check-runs)",
"api_writes": "2 relay strokes (fleet-write repository_dispatch, as objectstack-fleet[bot]): (1) pr_create — POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/24793/assignees [os-justin]; read-back 7703 bytes sent = 7703 stored, identical; no labels sent. (2) comment — POST /repos//issues/24736/comments (this report). Not REST: 3 git pushes (the empty branch probe, a3fc36f, d110c15).",
"deviations": [
"File surface: the claim named delegated-admin-gate.ts, delegated-admin-gate.test.ts and one changeset. One new test file was added, packages/plugins/plugin-security/src/delegated-admin-own-name-set.posture.test.ts, for the real-stack pin the dispatch preferred. No other claim holds it.",
"Postures: the dispatch said 'both tenancy postures'. The package's posture suite covers three (single, group, isolated), and all three are covered.",
"origin/main was merged before the PR opened (7d45c8e, from #24761, touches plugin-security's shipped sets; AGENTS.md section 10). The closure was rebuilt, and the full package test, typecheck, build and the 67-gate battery were re-run on the merged head.",
"The harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. Commits carry AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude); the PR body carries the session-URL footer.",
"Self-delegation rule 6 (ADR-0091 D3) is narrowed too. It is the walk's third caller, the one the dispatch listed at about :1010. It is pinned with a control.",
"test:repo was not run locally: the diff touches no repo-project test, so it is left to CI (Test Core). check-platform-checklist was not run: no export is renamed or deleted.",
"A temporary scratch test file measured the out-of-scope finding below. It was deleted before any gate ran and was never committed."
],
"files_changed": [
".changeset/24736-delegated-walk-own-name-set.md",
"packages/plugins/plugin-security/src/delegated-admin-gate.ts",
"packages/plugins/plugin-security/src/delegated-admin-gate.test.ts",
"packages/plugins/plugin-security/src/delegated-admin-own-name-set.posture.test.ts"
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: real-stack measurement of the service method that GET /api/v1/security/my-delegable-scope returns verbatim (packages/rest/src/security-routes.ts:385, res.json(await svc.describeDelegableScope(context))). On ObjectQL + SqlDriver + SecurityPlugin in single, group and isolated, a delegate holding a placing adminScope gets assignablePositions containing platform_admin, org_owner, org_admin and org_member. The write refuses each with 400 VALIDATION_FAILED: 'position' cannot spell a framework-reserved built-in identity name. The HTTP hop itself was not exercised · evidence: the delegated branch of describeDelegableScope (delegated-admin-gate.ts, the loop over placing scopes) has no isReservedIdentityName skip; the organization-level branch has one. The picker therefore offers positions the write refuses (user-visible, misleading picker) · landing: packages/plugins/plugin-security/src/delegated-admin-gate.ts describeDelegableScope, delegated branch · not fixed in place: a different defect class from this card's · dedupe words: describeDelegableScope identity names · my-delegable-scope platform_admin · assignablePositions reserved identity · delegable scope built-in positions"
]
}
State change in this stroke: pm:dispatched off and the assignee cleared (the card closed completed on the merge). #24737, which now also carries the delegated branch's identity-name listing (6285203700), is released from its serial wait in the same round.
Activity
objectstack-fleet commentedon Oct 20, 2026
Triage: p2 ·
bug·security· lanedomain:services·area:access·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-20T05:01ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch. Fresh read on
origin/main580fd4ed3c. Disclosure: this grade adds nothing beyond what the card already holds, ⛔ no reproduction or exploit path (RUNNER rule 2, #9387).Lane.
plugin-securityisdomain:services.Why p2 now. It is a source reading on a security boundary with its reach unmeasured, and the card's first act is that measurement. If a reachable shape exists (a catalog set named like a position, assignable by a delegate), it becomes p1, under the same exception as #24746.
Related, same site: #24757 (the own-name set is in force but invisible in Setup) reads the same fold from the UI side. The lane should read both before choosing between counting the own-name set and retiring the fold (#13419). Retiring it is a behaviour change, which the 「是否提前」 rule would put to the maintainer.
Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 5 · 2026-10-20T05:33Z
Session:
session_011TdZ8GjixNZFLz1xJD9zzKAccount:
os-justin(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24736-delegated-walk-own-name-setWorktree:
objectstack-issue-24736Domain:
domain:servicesSeat:
domain:services#1File surface:
packages/plugins/plugin-security/src/delegated-admin-gate.ts(the D12 delegated walksetsBoundToPositionand its callers; the delegated branch ofdescribeDelegableScopewhere it reads the walk),delegated-admin-gate.test.ts, and one new.changeset/24736-*.md. ⛔ Not the position-name fold itself (security-plugin.ts's resolver: retiring it is a behaviour change for the maintainer, per triage 6283779151 and #13419), ⛔ not the organization-level branch, ⛔ notpackages/spec/**(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: default (opus), quoting this dispatch's --tier output "no path-derived mandate: the surface hits none of the 3 declared glob(s) … floor sonnet · default opus · ceiling fable"; default because it is a security gate, not a mechanical editClause-②: no
Responsibility:
plugin-security's D12 delegated walk counts only a position definition's permissionSets, while the resolver also grants the set of the position's own name | the organization-level branch's setsCarriedByPosition (PR #24732) already counts it, as ADR-0090 D12 as amended 2026-10-17 requires | every deployment with a delegated administrator and a catalog permission set named like a positionThread-read: 6283779151
Serial constraints cleared:
No open PR touchesplugin-security/src/security-plugin.ts,explain-engine.ts,delegated-admin-gate.ts,plugin-auth/src/auth-plugin.ts,auth-manager.tsorruntime/src/security/inbound-rate-limit.ts(all 11 open PRs' files read). The epic's declared territory (#15194, body read at this act) lists none of them. This round dispatches #24746, #24739 and #24736 together on disjoint files; #24484 (PR #24761, this seat) edits onlydefault-permission-sets.ts, its pins andplatform-objectscomments. #24757 (the same fold, read from Setup) is not dispatched with this card and is not edited by it.Readings taken on
origin/main795ff708d8.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{
"issue": 24736,
"status": "done",
"branch": "claude/issue-24736-delegated-walk-own-name-set",
"pr": "#24793",
"session": "session_011TdZ8GjixNZFLz1xJD9zzK — the Claude-Session id on this run's commits; a subagent run, so it is the dispatching seat's id",
"premise_still_valid": true,
"summary": "The delegated walk setsBoundToPosition (delegated-admin-gate.ts) now takes its set names from setsCarriedByPosition, the helper PR #24732's organization-level branch already reads, and adds each set's adminScope. A delegate's position assignment is therefore judged on every set it grants, the own-name set included (ADR-0090 D12 as amended 2026-10-17). The walk's three callers all now see that set: assertAssignmentWrite (allowlist and strict containment, for insert, update and delete), the delegated branch of describeDelegableScope (stops offering such a position, so GET /api/v1/security/my-delegable-scope agrees with the write), and assertSelfDelegation rule 6 (ADR-0091 D3: a delegatable position whose own-name set carries an adminScope is no longer self-delegable). It only narrows what delegates may do. The organization-level branch, tenant-level admins, the resolver fold (security-plugin.ts), packages/spec and the shipped sets are untouched. Reachability: the shape was reachable on a real stack, so the card is p1 under triage 6283779151's rule. Dispatch H1 held. H2 was partly falsified: no binding-write blast-radius consumer exists on main (the binding authoring rows retired with ADR-0131 D3), and the third consumer is self-delegation rule 6.",
"tests": "Head d110c15 (merge of origin/main 7d45c8e onto the fix a3fc36f). READING 1, a source census on origin/main 795ff70, test fixtures excluded: positions in packages/** and examples/** number 19 (6 built-in in builtin-positions.ts, app-crm 3, app-showcase 10); permission sets number 19 (8 platform in default-permission-sets.ts, app-crm 2, app-showcase 9, all showcase_*); the name intersection is 0. A named real producer holds the shape: the vendored HotCRM 17.1 artifact (packages/metadata/src/fixtures/hotcrm-17.1-built-permissions.artifact.json) carries the sets sales_manager and sales_rep, and #24757 measured positions of those names with the fold in force on HotCRM. READING 2, real stack (ObjectQL + SqlDriver + SecurityPlugin), with the gate unchanged at 795ff70 and only the new posture file added: vitest run src/delegated-admin-own-name-set.posture.test.ts gave 'Tests 9 failed | 9 passed (18)'. The refusal case read 'expected [ 200, undefined ] to deeply equal [ 403, PERMISSION_DENIED ]' in single, group and isolated, so a delegate whose allowlist covers the listed set but not the own-name set was admitted; the ground-truth case (the assignee resolves the own-name set) was green. Reachable, so p1 per triage. AFTER THE FIX: both pin files gave 'Test Files 2 passed (2) / Tests 139 passed (139)' at a3fc36f. Full package at d110c15: pnpm --filter @objectstack/plugin-security exec vitest run --maxWorkers=2 gave 'Test Files 192 passed (192) / Tests 3995 passed | 45 skipped (4040)'; typecheck exit 0 ('check:test-typecheck: OK'); build exit 0; lock 'VERDICT command-exit 0'. At a3fc36f: 191 passed / 3961 passed | 45 skipped, typecheck exit 0. Both new test files are in the tsconfig.test.json program (tsc --listFilesOnly). PINS: unit (delegated-admin-gate.test.ts) — refusal asserting code PERMISSION_DENIED and status 403 that names the set; control admitted; no-own-name position unchanged; delete judged on the same sets; strict containment on an own-name set with an adminScope; listing equals the write per position; self-delegation refused, with its control. Posture suite (delegated-admin-own-name-set.posture.test.ts, new), single/group/isolated — ground truth, 403 naming the set, control, no-own-name unchanged, strict containment, listing equals the write. ABLATION at a3fc36f, after the commit: scripts/ablation-replace.mjs put back the old walk (definition.permissionSets only), anchor 1 to 0, blob 2a202d1153e1 to 2e45318f6351. Result 'Tests 14 failed | 125 passed (139)': 5 unit pins and 9 posture cases red; controls, no-own-name and ground truth green. Restore was git checkout HEAD -- ABS_PATH: blob 2a202d1153e1 == HEAD, git diff HEAD empty, marker grep -c 0. No dist rebuild was needed: the tests import the subject by relative src path.",
"gates": "LOCAL at d110c15: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, with no paths (merge base 7d45c8e, 4 changed paths), derived 67 commands. Each was run as 'cmd, redirect to log, ex=$?'; all 67 exit 0. --ran gave 'Run reconciliation — 67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN.', exit 0. First battery, at a3fc36f: 65 exit 0, and check:dual-build-cjs-loads plus check:i18n exited 3 (PREREQUISITE NOT MET). check:i18n was re-run after the build its message names: exit 0, 'check-i18n-bundles: OK (10 package(s) — all bundles in sync'. Both are green in the d110c15 battery. CI on PR #24793 head d110c15, read once at report time: completed/success — filter, Auto Label, Check Documentation Links, Check PR Size, Dogfood Regression Gate, Flag docs affected by code changes, Governed Surface Queue Guard, Lint · PM dispatch-gates, the three claim/close guards and the single-writer path guard. completed/skipped — Build Docs, Console Pin Gate, Dogfood Regression Gate (matrix), Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance. in_progress — Build Core, Check Changeset, Test Core (1/6 to 6/6), Lint · (ESLint, CI release & engine gates, docs & code guards, repo & tooling gates, scoped query-options erasure, scoped slot lookup & corpus, scoped tooling self-tests), Type Check · (workspace, source gates, debt ledger, consumer gates). The required set is not concluded: in_progress is the honest value.",
"mcp_calls": "0 — no MCP GitHub tool was called; every GitHub read was a gh api REST GET (issue 24736 and its comments, #24757, PR 24793 read-back, check-runs)",
"api_writes": "2 relay strokes (fleet-write repository_dispatch, as objectstack-fleet[bot]): (1) pr_create — POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/24793/assignees [os-justin]; read-back 7703 bytes sent = 7703 stored, identical; no labels sent. (2) comment — POST /repos//issues/24736/comments (this report). Not REST: 3 git pushes (the empty branch probe, a3fc36f, d110c15).",
"deviations": [
"File surface: the claim named delegated-admin-gate.ts, delegated-admin-gate.test.ts and one changeset. One new test file was added, packages/plugins/plugin-security/src/delegated-admin-own-name-set.posture.test.ts, for the real-stack pin the dispatch preferred. No other claim holds it.",
"Postures: the dispatch said 'both tenancy postures'. The package's posture suite covers three (single, group, isolated), and all three are covered.",
"origin/main was merged before the PR opened (7d45c8e, from #24761, touches plugin-security's shipped sets; AGENTS.md section 10). The closure was rebuilt, and the full package test, typecheck, build and the 67-gate battery were re-run on the merged head.",
"The harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. Commits carry AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude); the PR body carries the session-URL footer.",
"Self-delegation rule 6 (ADR-0091 D3) is narrowed too. It is the walk's third caller, the one the dispatch listed at about :1010. It is pinned with a control.",
"test:repo was not run locally: the diff touches no repo-project test, so it is left to CI (Test Core). check-platform-checklist was not run: no export is renamed or deleted.",
"A temporary scratch test file measured the out-of-scope finding below. It was deleted before any gate ran and was never committed."
],
"files_changed": [
".changeset/24736-delegated-walk-own-name-set.md",
"packages/plugins/plugin-security/src/delegated-admin-gate.ts",
"packages/plugins/plugin-security/src/delegated-admin-gate.test.ts",
"packages/plugins/plugin-security/src/delegated-admin-own-name-set.posture.test.ts"
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: real-stack measurement of the service method that GET /api/v1/security/my-delegable-scope returns verbatim (packages/rest/src/security-routes.ts:385, res.json(await svc.describeDelegableScope(context))). On ObjectQL + SqlDriver + SecurityPlugin in single, group and isolated, a delegate holding a placing adminScope gets assignablePositions containing platform_admin, org_owner, org_admin and org_member. The write refuses each with 400 VALIDATION_FAILED: 'position' cannot spell a framework-reserved built-in identity name. The HTTP hop itself was not exercised · evidence: the delegated branch of describeDelegableScope (delegated-admin-gate.ts, the loop over placing scopes) has no isReservedIdentityName skip; the organization-level branch has one. The picker therefore offers positions the write refuses (user-visible, misleading picker) · landing: packages/plugins/plugin-security/src/delegated-admin-gate.ts describeDelegableScope, delegated branch · not fixed in place: a different defect class from this card's · dedupe words: describeDelegableScope identity names · my-delegable-scope platform_admin · assignablePositions reserved identity · delegable scope built-in positions"
]
}
objectstack-fleet commentedon Oct 20, 2026
ACCEPT → PR #24793 comment 6285547392 ·
domain:servicesseat 1 ·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-20T07:16Z. Landing goes through the merge queue.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Landed ·
domain:servicesseat 1 ·session_011TdZ8GjixNZFLz1xJD9zzK· 2026-10-20T07:55Zadded_to_merge_queue2026-10-20T07:18Z →merged2026-10-20T07:55Zorigin/mainby content21301a3406(one parent,307ce4c4b4)..changeset/24736-delegated-walk-own-name-set.mdand the posture pindelegated-admin-own-name-set.posture.test.tsare present.setsBoundToPositionreadssetsCarriedByPositionState change in this stroke:
pm:dispatchedoff and the assignee cleared (the card closedcompletedon the merge). #24737, which now also carries the delegated branch's identity-name listing (6285203700), is released from its serial wait in the same round.Generated by Claude Code