Skip to content

platform-admin re-anchor L1 (spec seat): export the kernel platform-admin capability declaration — one list, imported by plugin-security (Choice 6A) #11965

Description

@os-support-ai

Leg L1 of the accepted #11663 platform-admin re-anchor design. Provenance: design document = #11663 comment 5394453215 (§4 Choice 6, §6 row L1); maintainer acceptance = #11663 comment 5404675670 (2026-08-25, verbatim 「接受你的建议,继续」, bundle 1A/2B/3A/4A/5A/6A/7A). Filed by PM session session_01KWRU3s15AJz7PGW7a7wdCh.

Surface: packages/spec — ⛔ spec seat only (sole owner of this package).

Content: @objectstack/spec exports the platform-admin capability declaration (the capability set today carried by the org-less admin_full_access row); plugin-security's admin_full_access declaration imports that same list, so exactly one copy exists. Behaviour-neutral; lands alone (migration sequence step 2). Measured precedent in the design: core already imports ADMIN_FULL_ACCESS from @objectstack/spec.

Acceptance criterion: git grep -n ADMIN_FULL_ACCESS packages/spec/src packages/plugins/plugin-security/src shows the capability list declared once (spec) and imported — not duplicated — by plugin-security, and no behaviour change lands with it.

Notes: the design expects no authorable-surface movement (no new authorable key) — the spec seat must confirm that on the tree rather than take the design's word. Premise-first: re-verify the cited files/lines on current origin/main before implementing; the design was measured at cad8b42f00.

Downstream: the core derivation leg (L2) declares Blocked-by: on this card.

Activity

  1. self-assigned this
    on Aug 26, 2026
  2. os-zhuang commented on Aug 26, 2026

    @os-zhuang
    Contributor

    Claim: PM loop round R8, wave 4 — leg L1 of the accepted #11663 platform-admin re-anchor (maintainer 2026-08-25, verbatim 「接受你的建议,继续」, bundle 1A/2B/3A/4A/5A/6A/7A; design doc = #11663 comment 5394453215 §4 Choice 6 / §6 row L1)
    Session: session_012xGvxcwPRTJfA7RfjXEYA4
    Branch: claude/issue-11965-platform-admin-capability-export
    Worktree: objectstack-issue-11965
    Domain: domain:spec
    File surface: packages/spec/src/** (the platform-admin capability-list export, placed per the design's precedent that core already imports ADMIN_FULL_ACCESS from @objectstack/spec) + packages/plugins/plugin-security/src/** (the admin_full_access declaration switches to importing that list — single-copy, behaviour-neutral) + tests + one changeset. Stop on breach.
    Container & model: M, mode:subagent, model: claude-fable-5 — clause-② per triage ("spec public surface"); path limb also fires (packages/spec/src/**)
    Clause-②: yes
    Serial constraints cleared: in-flight #11504 (contracts/automation-service.ts + error-code-ledger) — disjoint files, same package: both PRs regenerate nothing shared beyond build artifacts handled at landing; dev merges current main before PR. PR #12610 (scripts) and parked PR #12606 (data/object.zod.ts) — disjoint. Services-lane in-flight #12515 touches plugin-security (suggested-audience-bindings predicates area) — the claim there declares a different file surface; this card's plugin-security diff is confined to the admin_full_access capability declaration — if the dev finds the two surfaces actually intersect at file level, stop and report. H17 — no intersection. Downstream L2 stays Blocked-by: this card.


    Generated by Claude Code

  3. os-zhuang commented on Aug 26, 2026

    @os-zhuang
    Contributor

    Dev claim (posted late — implementation already in flight when the PM probe arrived; acknowledging the ordering breach rather than hiding it): I run as mode:subagent inside PM session session_012xGvxcwPRTJfA7RfjXEYA4 (R8 wave 4), dispatched for exactly this issue.

    Branch: claude/issue-11965-platform-admin-capability-export (pushed empty as the write-route probe at task start; implementation commits pushed at 0bc6a4803).

    File surface actually touched (within the claim of PM comment 5429883374): packages/spec/src/identity/eval-user.zod.ts, packages/spec/src/index.ts, packages/spec/src/identity/platform-admin-capabilities.test.ts (new), packages/spec/api-surface/{root,identity}.json + packages/spec/export-origins/{root,identity}.json (regenerated baselines), packages/plugins/plugin-security/src/objects/default-permission-sets.ts, packages/plugins/plugin-security/src/objects/default-permission-sets.test.ts, one changeset. No intersection with #12515's suggested-audience-bindings predicate surface.


    Generated by Claude Code


    Generated by Claude Code

  4. os-zhuang commented on Aug 26, 2026

    @os-zhuang
    Contributor

    os-dev-report

    {
      "issue": 11965,
      "status": "done",
      "branch": "claude/issue-11965-platform-admin-capability-export",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/12612",
      "premise_still_valid": true,
      "summary": "Choice 6A / leg L1 implemented as designed. @objectstack/spec exports ADMIN_FULL_ACCESS_CAPABILITIES (the objects wildcard + systemPermissions previously inlined in plugin-security) beside ADMIN_FULL_ACCESS in identity/eval-user.zod.ts, root-exported from the same index.ts block core already imports the name constant from; plugin-security's admin_full_access declaration now spreads the imported list, so exactly one copy exists. The #3544/#8681 export-axis rulings moved verbatim with the declaration. Premises re-verified on origin/main at 7c0d0c395: the inline declaration was at default-permission-sets.ts:119-166 as measured; core's import at resolve-authz-context.ts:31; authorable-surface CONFIRMED unmoved (check green, 1255 defaults unchanged, no baseline diff). api-surface and export-origins baselines regenerated (2 exports added, 0 breaking). Acceptance grep shows the list declared once (spec eval-user.zod.ts:83) and imported (plugin-security default-permission-sets.ts:6,132); remaining plugin-security ADMIN_FULL_ACCESS hits are a test-local fixture in vama-write-path-convergence.test.ts, not a duplicate. No file intersection with #12515 (suggested-audience-bindings untouched). Process note, self-reported: my own claim comment was posted late (comment 5430605677), after implementation had started — ordering breach against the dispatch, no duplication resulted.",
      "tests": "All verification at merged head 0bc6a4803 (= PR head; origin/main merged immediately before PR). Behaviour-neutrality pinned: new test parses the exact pre-move inline literal and asserts deep-equality with the current declaration ('admin_full_access imports the kernel capability declaration unchanged'), 4/4 new spec tests (platform-admin-capabilities.test.ts: two-field shape, strict-parse composition, #8681 no-export pin, systemPermissions all resolve in PLATFORM_CAPABILITY_NAMES). vitest: spec 4/4, plugin-security targeted (default-permission-sets, bootstrap-platform-admin, bootstrap-seed-round-trips, bootstrap-declared-permissions) 76/76 ('Test Files 4 passed, Tests 76 passed'). Typecheck green both packages; spec's check:test-typecheck line: 'OK — test layer compiles'; NOT-MEASURED note: plugin-security tsc excludes **/*.test.ts, its edited test file is measured by vitest execution only. Gates derived via dispatch-gates.mjs (no paths passed; stderr provenance line confirmed objectstack-ai/objectstack at 7c0d0c395), full derived list run green pre-merge, union re-run on 0bc6a4803: check:authorable-surface '1255 default(s) unchanged' + '1596 schemas', check:api-surface 'public API surface + factory signatures unchanged' (after gen), check:export-origins '5181 exports across 17 entry points resolve exactly as recorded', engine-double-contract '689 pinned', where-matcher, i18n 'all bundles in sync', i18n-stale-fill 'no new stale fills', query-options-erasure, type-check-coverage, type-check-debt '31 ledger entries re-measured, none above its recorded number', nul-bytes 'no raw ASCII control bytes'. All verdicts read from gate-printed lines with exit codes captured before any pipe. check-governed-queue-guard is CI-context-only (reads the workflow event payload): NOT MEASURED locally, runs on the PR. No ablation performed (refactor with value-equality pin; no new gate to falsify).",
      "mcp_calls": "3 — add_issue_comment (late claim), create_pull_request, add_issue_comment (this report)",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  5. os-zhuang commented on Aug 26, 2026

    @os-zhuang
    Contributor

    ACCEPT — reviewer of record: spec seat R8, session_012xGvxcwPRTJfA7RfjXEYA4. PR: #12612 (draft, head 0bc6a4803, 10 files).

    Checked against the PR itself: ADMIN_FULL_ACCESS_CAPABILITIES declared once in spec/src/identity/eval-user.zod.ts beside ADMIN_FULL_ACCESS (the constant core already imports — the design's precedent honoured), typed Pick<PermissionSet, 'objects' | 'systemPermissions'> so name/label stay with the declaring package (pinned by the exact-keys test); plugin-security's declaration now spreads the import — acceptance grep satisfied (declared once, imported, remaining hits are a test-local fixture, no duplicate). The #3544/#8681 export-axis ruling comments travel VERBATIM with the declaration and are re-pinned at the new home (allowExport absent + parse-level assertion). Behaviour-neutrality is pinned the strong way: the pre-#11965 inline literal parsed and deep-equalled against the live declaration. Design's fork condition did NOT fire: authorable-surface unmoved (gate line "1255 default(s) unchanged"); api-surface/{identity,root}.json + export-origins regenerated with exactly the 2 new export rows, 0 breaking — the expected mechanical trace of a new export, not the authorable fork. No file intersection with services-lane #12515 (suggested-audience-bindings untouched). Changeset patch × 2 with the single-copy rationale.

    Accepted deviation, recorded: the dev's own claim comment (5430605677) was posted AFTER implementation started — an ordering breach against the dispatch, self-reported, with no duplication resulting (the PM claim + branch held the card). This is the #12220 finding class (subagent claim identity), already with the skills lane — no new card owed.

    Clause-② enqueue gate: path limb (packages/spec/src/**) + declaration limb both fire; dispatch tier claude-fable-5 = CONTRACT_REVIEW_TIER — satisfied. Landing path: ready → merge queue once every check on 0bc6a4803 is green; this seat watches to MERGED, then downstream L2 unlocks.


    Generated by Claude Code

  6. removed their assignment
    on Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions