Skip to content

Setup → Positions list shows no holder count and no bound permission sets, and only the name cell opens the row — so the list cannot answer "who is a sales manager?" (hotcrm#2194 T2-U05, the platform half) #25333

Closed

Description

@objectstack-fleet

维护者速读

  • 事由: 岗位列表看不到持有人数和绑定的权限集,只有名称单元格能点开,回答不了「谁是销售经理」。
  • 要做: 列表显示持有人数和绑定的权限集,整行可点。HotCRM 补岗位描述的那一半另立卡,等本卡。
  • 完成标准: 列表一眼看出每个岗位有几个人、授予哪些权限集。

Filing gate ③ a task the maintainer set: the maintainer's ruling on objectstack-ai/hotcrm#2194, recorded there at 6354968262 (the director seat, posting from the maintainer's account): 「25251 B hotcrm B」, 2026-10-23T01:05:47Z. That is letter B for all three rounds, exactly as the seat recommended, and it adopts T2-U05 (the platform half). Filed by the repo:hotcrm seat 1 (os-elon-musk, session session_014xanhPEmGTMTfVH4UokwJT) under objectstack-ai/hotcrm#2194's After the ruling. ⛔ Not a claim.

Grade: triage's. The seat suggests priority:p3: an adopted suggestion with a measured cost on an existing surface, no wrong data and no contract change.

Reader (who acts): objectstack triage routes and grades it. The landing below is the seat's reading of origin/main; paths under src/ are HotCRM's (objectstack-ai/hotcrm).

Governing text

Why (measured)

Landing

Done when

Size: S.

Dedupe

Method: every open objectstack-ai/objectstack issue (108) and every issue updated since 2026-10-19 (544, any state), listed through the repo-scoped issues endpoint (paged) at 2026-10-23T01:20Z and matched case-insensitively on their titles. Words: position. 5 open hits: #24757 (pairs, above), #25251 (a security gate on assignment rows), #25249, #12224 and #9559 (other subjects); none is this list. New for the list columns.


Generated by Claude Code

Activity

  1. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    domain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land
    enhancementNew feature or request
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 23, 2026
  2. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01K9LFkQaGHiensHNgGGgKvD (a card thread scheduled by the project's coordinator, which follows .claude/agents/os-dev.md as its role file; the seat session is session_014Hse9cj2i4o5UAVrd21NKr)
    Account: os-tesla
    Branch: claude/project-thread-kuevbz (the thread's designated branch: a card thread can push only that branch, a measured platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-25333
    Domain: domain:engine
    Seat: domain:engine#1 (seat post #6367)
    File surface: objectstack: the position catalog's reader (packages/metadata* / platform-objects, located by the dev) + pins; objectstack-ai/objectui: the Positions list columns and row click, as that repo's own draft PR on the same branch name (stop on breach; explain in the report)
    Container & model: S (non-mechanical, so M treatment), mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: yes
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: none
    Serial constraints cleared: #24757 (pm:on-hold): read first, so the bound-sets column shows what is in force. Seat 2's #25278 / #25295: no shared region.

    Clause-② reading: undecided at claim: added read-only catalog fields would widen a public read shape; the dev measures it on the built declaration closure and the report settles it. Dispatch order: /mnt/project-files/engine-seat1/dispatch-25333.md (+ common.md). Ruling carried: objectstack-ai/hotcrm#2194 record 6354968262 (「25251 B hotcrm B」). Claimed 2026-10-23T03:47Z.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25333,
      "status": "done",
      "branch": "claude/project-thread-kuevbz",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25369",
      "pr_objectui": "https://github.com/objectstack-ai/objectui/pull/13351",
      "head": {
        "objectstack": "0ca1af8c",
        "objectui": "957ef47"
      },
      "session": "session_01K9LFkQaGHiensHNgGGgKvD",
      "premise_still_valid": true,
      "summary": "The server computes both columns, not the console. GET /meta/position?include=grants adds _holderCount and _grantedPermissionSets [{name, via}] through the shared list chain (createMetaListAnswer, both transports). The values come from two readers lifted out of resolveUserAuthzGrants (readPositionGrantsInForce for the §6a rule, countPositionHolders for the §3/§4 holding rule), which the resolver itself now calls, plus plugin-security's describePositionGrants, which runs the evaluator's resolvePermissionSets plus dropDeactivatedFoldedSets. via:'name' is the position-name fold's same-named set, the #24757 set, shown and not hidden because the fold's retirement is on hold. The holder count is null (never 0) with no org, for platform_admin/guest, after a truncated read, or for a caller without read on sys_user_position. objectui#13351 renders the two columns with the by-name set marked, and makes the whole row open the item on every Setup metadata list.",
      "clause_2": "yes (widening): two read-only served keys on GET /meta/position?include=grants (opt-in; the plain list is unchanged); ISecurityService gains optional describePositionGrants",
      "metadata_protocol": "none",
      "tests": "New pins agree with enforcement, not with the reader's own output. position-catalog-readers.test.ts (4): user by user, the holder count equals resolveUserAuthzGrants' positions; a position's sets in force equal what the resolver grants a holder of it alone. describe-position-grants.test.ts (4): the same-named set via:'name' with three controls (declared under its own name, fold set switched off, guest), agreement with resolvePermissionSetsForContext, and the count gated on the read. meta-list-projection-parity.test.ts: the ?include=grants probe on RestServer and the dispatcher (785/785). Package suites: plugin-security 213 files / 4446 tests passed; rest 316 files / 6327 tests passed; core security 51 files / 1083 tests passed. Ablations via scripts/ablation-replace.mjs, restored to the HEAD blob: no fold, 2 red; no canReadObject gate, 1 red. objectui: 8 new tests, and three ablations (no control guard, no row handler, no include) each turned exactly its test red; metadata-admin, app-shell __tests__ and data-objectstack suites green.",
      "gates": "objectstack local: dispatch-gates --commands derived 97 families, all run under os-verify-lock, exit codes captured before any pipe; --ran reconciliation: 97 derived, 97 run, 0 NOT-MEASURED, 0 UNRUN. Three first readings were not measurements and were re-run green: check-plugin-teardown-shape --self-test exit 3 (shallow clone, pinned fixture fetched), check:i18n and check:dual-build-cjs-loads exit 3 (no dist; full pnpm build then green). check:where-matcher exit 1 was a real finding: the new test double read a $-combinator as a field. Fixed in 0ca1af8c (the double refuses combinators), then green. objectui local: type-check app-shell + data-objectstack, eslint on touched files, check:i18n-keys/-drift/-dead-keys, check:new-line-citations, check:vi-mock-specifiers, check:test-path-roots, changeset presence, all exit 0. CI check-runs on both PRs were still pending when this report was posted; the seat's ACCEPT reads them.",
      "line_budget": "objectstack: 12 files, +783/-26 (src +408, tests +375). objectui: 10 files, +461/-4 (src +194, tests +267).",
      "deviations": [
        "Landing is outside the expected packages/metadata* / platform-objects: the readers the resolver enforces with live in @objectstack/core (security/resolve-authz-context.ts), the decoration on the shared list chain in @objectstack/rest, the contract in @objectstack/spec, and the service in plugin-security. Putting the computation in the catalog package would have been a second copy of the rule.",
        "Decorating opt-in on the existing list chain (?include=grants) instead of adding a new route keeps the route ledger, discovery and the SDK surface unchanged. The objectui list requests it via a new MetadataClient.list include option.",
        "The objectui whole-row click applies to every Setup metadata list, not only Positions (one handler in ResourceListPage). Row controls, modified clicks, text selection and portal clicks are excluded and pinned.",
        "No review request was sent to os-tesla: it would be a write beyond the budget. Both PRs carry assignee os-tesla."
      ],
      "files_changed": [
        "objectstack: .changeset/25333-position-list-holders-and-grants.md",
        "objectstack: packages/core/src/security/resolve-authz-context.ts",
        "objectstack: packages/core/src/security/index.ts",
        "objectstack: packages/core/src/security/position-catalog-readers.test.ts",
        "objectstack: packages/spec/src/contracts/security-service.ts",
        "objectstack: packages/spec/api-surface/contracts.json",
        "objectstack: packages/spec/export-origins/contracts.json",
        "objectstack: packages/plugins/plugin-security/src/security-plugin.ts",
        "objectstack: packages/plugins/plugin-security/src/describe-position-grants.test.ts",
        "objectstack: packages/plugins/plugin-security/src/registered-security-service-members.pin.test.ts",
        "objectstack: packages/rest/src/meta-item-read-gate.ts",
        "objectstack: packages/runtime/src/domains/meta-list-projection-parity.test.ts",
        "objectui: .changeset/25333-position-list-holders-and-grants.md",
        "objectui: content/docs/guide/console.md",
        "objectui: packages/app-shell/src/services/builtinComponents.tsx",
        "objectui: packages/app-shell/src/views/metadata-admin/PositionGrantCells.tsx",
        "objectui: packages/app-shell/src/views/metadata-admin/ResourceListPage.tsx",
        "objectui: packages/app-shell/src/views/metadata-admin/ResourceListPage.positionGrants-25333.test.tsx",
        "objectui: packages/app-shell/src/views/metadata-admin/i18n.ts",
        "objectui: packages/app-shell/src/views/metadata-admin/registry.ts",
        "objectui: packages/data-objectstack/src/metadata-client.ts",
        "objectui: packages/data-objectstack/src/metadata-client.listInclude-25333.test.ts"
      ],
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0 MCP GitHub calls (2 subscribe_pr_activity calls on the session's own remote tool, no GitHub write)",
      "api_writes": "3 relay writes: pr_create objectstack-ai/objectstack#25369 (run 39900036030), pr_create objectstack-ai/objectui#13351 (run 39902644510), and this os-dev-report comment on #25333. Plus git pushes to claude/project-thread-kuevbz in both repos.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #25369 comment 6358165319 and objectstack-ai/objectui#13351 comment 6358172887 (both ready + auto-merge set 2026-10-23T05:33Z).


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they landenhancementNew feature or requestpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions