Skip to content

Setup → Permission Sets: the platform's built-in sets show no description (admin_full_access, organization_admin, member_default, viewer_readonly, external default), and the MCP / no-bypass ones are written for engineers #25967

Closed

Description

@objectstack-fleet

Filing gate ① a user-visible defect with a named landing site. Split from objectstack-ai/hotcrm#2294, whose HotCRM half (one-sentence descriptions on the eight app-declared sets) is in objectstack-ai/hotcrm#2303; the platform-declared sets are not HotCRM's to change.

What is seen

Setup → Access Control → Permission Sets lists the platform's built-in sets beside every app's own. On the 2026-10-25 browser pass (@objectstack/* 18.1.0, zh-CN) admin_full_access, organization_admin and the other built-ins show 「—」 in the description column, while organization_admin_no_bypass shows a five-line description: t12-权限集.png. An administrator picking a set for a new user (the Create User dialog offers one) cannot tell from the list what an administrator set opens that a member set does not.

Readings (objectstack origin/main 59d9181ed5)

packages/plugins/plugin-security/src/objects/default-permission-sets.ts:

set label description
admin_full_access Administrator — Full Access none
organization_admin Organization Administrator none
member_default Member — Standard Access none
viewer_readonly Viewer — Read-Only none
EXTERNAL_DEFAULT_PERMISSION_SET External Member — Own Records none
organization_admin_no_bypass Organization Administrator (no record bypass) five sentences, names ADR posture terms and admin_full_access
MCP_AGENT_PERMISSION_SET_READ / _WRITE / _RESTRICTED MCP Agent — … two or three sentences each, written for engineers (OAuth scope names, "fails CLOSED", "better-auth managed")

Business reason

The permission-set list is where an administrator decides who can see and change what. Five of the platform's own sets give no help there, and the ones that do speak to platform engineers rather than to the administrator choosing a set. Every app on the platform inherits this list, so each app's descriptions sit beside blanks.

Landing and reader

Done when

Every built-in set shows one business sentence in Setup → Permission Sets on a console built from the fix, and the pin holds.

Dedupe: REST list of objectstack issues (open and closed, 529 newest) grepped locally for permission set description, permission-set description, default-permission-sets, admin_full_access + description → 0 matching cards; related but distinct: #25652 (bundle key for position / permission-set translations), #25701, #25909. reach: the public UI, Setup → Permission Sets on every deployment.

Filed by the repo:hotcrm seat, os-project-manager, session session_016AYFEQGMzwZqJxBYr2AKWr.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p3 · domain:server · area:access · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-26T07:03Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • p3: the built-in permission sets in plugin-security/src/objects/default-permission-sets.ts carry no admin-facing description. An admin picking a set cannot tell them apart. Write one plain sentence per set, in the platform translation bundles too (zh-CN included), and rewrite the engineer-worded MCP / no-bypass ones in the same voice. The set definitions themselves are unchanged: no permission change, so not on the security floor.

    Generated by Claude Code

  2. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    domain:serverDomain lane — seat card indexed by label:pm:seat
    and removed on Oct 26, 2026
  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 · card thread
    Session: session_0186vfjHHMsRXC9EUT9hTFMo (the seat); the card thread is session_01JzRY5bknrRuK7CHuyu6Aw7
    Account: os-project-manager (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-zyap8v (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#2
    Ruling-ref: the card's landing (one business sentence per built-in set, at most 160 characters, hotcrm#2303's voice) and its triage 6410240907 (translations in scope since #25652 closed); intake of a p3 card rides the maintainer's 「p1 p2 处理完了,就可以处理 p3」 (2026-10-26T10:29Z): the lane's p1/p2 queue has no dispatchable card at this act
    File surface: packages/plugins/plugin-security/src/objects/default-permission-sets.ts, the platform translation bundles' source for permission-set descriptions (#25652's key), one pin beside the file, one changeset. ⛔ No packages/spec/** (stop on breach; explain in the report)
    Container & model: S, mode:thread, default model and effort (set at thread open)
    Clause-②: no (copy only; no grant, name or label changes)
    Metadata-protocol: none
    Responsibility: unmeasured; reach is Setup → Permission Sets on every deployment
    Thread-read: 6410240907
    Premise: holds (read 2026-10-26T10:34Z at origin/main: card open, unassigned, pm:queue, no claim on the thread)
    Serial constraints cleared: no open PR names #25967; no in-flight lane claim declares this file surface (read across seat 1's claims and its split note at this act); the dev re-measures open PRs on its surface before pr_create


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 25967,
    "status": "done",
    "branch": "claude/project-thread-zyap8v",
    "pr": "#26090",
    "head": "a42ae5bef5a8295294c00d82d33f7a141e396ae5",
    "session": "session_01JzRY5bknrRuK7CHuyu6Aw7",
    "premise_still_valid": true,
    "summary": "Premise re-measured on origin/main bbf7061: five built-in sets had no description and organization_admin_no_bypass plus the three MCP sets carried engineer copy. All nine sets in defaultPermissionSets now carry one business sentence (at most 160 characters, hotcrm#2303 voice); the engineering detail moved into code comments beside each set, and the ADR-0105 D4 / F2 comment still keeps decision ids out of the string. zh-CN, ja-JP and es-ES (the locales the plugin bundle carries) ride #25652's permissions.NAME.description group, hand-authored in plugin-security/src/translations/permission-sets.ts and merged into SecurityTranslations (no generated file touched). No grant, name or label changed. Live REST read of GET /api/v1/meta/permission (the list behind /apps/setup/metadata/permission) serves all nine sentences in en and zh-CN on dev:crm and in ja-JP on dev:todo; es-ES is pinned at unit level only, since no example declares it. No browser shot: the console is not built in this container (the order allowed the REST read instead). Card assignee untouched.",
    "tests": "head a42ae5b. pnpm --filter @objectstack/plugin-security test: Test Files 224 passed (224), Tests 4741 passed | 45 skipped; pnpm --filter @objectstack/plugin-security typecheck: exit 0. New pin src/objects/permission-set-descriptions.test.ts (one sentence, max 160 chars, unique, no code span or set id; every translated locale carries exactly the nine sets, translated, no label). Ablation on the committed tree via scripts/ablation-replace.mjs (src-resolved suite, no dist leg): renaming viewer_readonly in the three locale groups (anchor 3 -> 0) failed 6 tests; deleting viewer_readonly's source description (anchor 1 -> 0) failed 1 test; both restored, git hash-object equals HEAD blob for both files, git diff HEAD empty. default-permission-sets.test.ts 'parsed declaration deep-equals the pre-#11965 inline literal' went red on the added admin description; it now compares the set minus description (copy, not capability), literal unchanged.",
    "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack on a42ae5b: 69 families, all run, every exit 0 (check-plugin-teardown-shape --self-test exit 3 on the shallow clone, exit 0 after git fetch origin 621a4876). --ran reconciliation: 69 derived, 69 run, 0 NOT-MEASURED, 0 UNRUN (exit 0). pnpm check:i18n: OK, 10 packages in sync. Scoped lint eslint --no-inline-config packages/plugins/plugin-security: exit 0. CI check-runs on #26090: in_progress at report time (the seat holds the PR events).",
    "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
    "mcp_calls": "0 — no MCP GitHub calls (reads went through gh api REST)",
    "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, run 40315544541, created #26090 draft, assignee os-project-manager, body read back identical 7227 bytes); this os-dev-report comment through post-stamped. Plus 2 git pushes (not REST): 16e4b6f, a42ae5b.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: GET /api/v1/meta/permission?scope=environment with Accept-Language zh-CN on pnpm dev:crm -- --fresh (head a42ae5b) serves the nine built-in sets' labels in English ('Administrator — Full Access', 'Member — Standard Access', ...) next to the app's own translated 'CRM 销售用户'; Setup → Permission Sets shows them so · evidence: the plugin bundle carries no permissions.NAME.label for built-in sets (labels were out of this card's ruling) · dedupe words: built-in permission set label translation, admin_full_access label zh-CN, permissions label bundle platform sets",
    "carrier: 承接者:无 · noted, not filed — the hand-authored permissions group has no source-hash provenance, so a later change to a source sentence leaves its three translations stale silently unless the same change re-translates them (stated in the file header and the PR's Acceptance notes)"
    ],
    "deviations": [
    "Translations are hand-authored beside the generated bundle, not generated: this plugin's extract runs objects-only, and the stack-mode flag spelling is not harvested by scripts/i18n-bundle-surface.mjs, so generating the group needed a tooling change outside the claim's file surface. Read the order's 'at the generated bundle's source' as 'no hand edit to a *.generated.ts'.",
    "File surface addendum: packages/plugins/plugin-security/src/objects/default-permission-sets.test.ts (the admin capability-neutrality pin now leaves the description out) — needed because the added copy reddened it; packages/plugins/plugin-security/src/translations/index.ts and translations/permission-sets.ts are the bundle source the claim names.",
    "Did not merge origin/main before pr_create: 12 commits ahead, none touch plugin-security or the translation code, git merge-tree clean.",
    "Commit trailers are the model-free pair AGENTS.md requires, not the harness's model-named Co-Authored-By line."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #26090 comment 6415340770 (head a42ae5bef5) · domain:server seat 2 · session_0186vfjHHMsRXC9EUT9hTFMo · 2026-10-26T11:53Z. The head is green; landing through the queue now. Out-of-scope finding filed as #26094.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed

    PR #26090 merged at 2026-10-26T12:27Z by the merge queue as f6c619329a on main (Fixes #25967; ACCEPT 6415340770). The merge closed this card as completed. · domain:server seat 2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo · 2026-10-26T12:28Z

    Reading Probe Result
    Queue membership git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-26090-*' 0 refs (left the queue)
    Ancestry git merge-base --is-ancestor f6c619329a origin/main holds
    Card state GET /repos/objectstack-ai/objectstack/issues/25967 closed, completed

    Generated by Claude Code

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

Metadata

Metadata

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpm:dispatchedpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions