Skip to content

spec+security: reserve the queues RLS membership key and resolve current_user.queues kernel-side from the ownership-queue service #27016

Closed

Description

@objectstack-fleet

Filing gate: class ③, maintainer-directed. Child of #25769, filed under ruling 6457475657 (batch #415 item 5, letter A, maintainer 「同意」 2026-10-28T00:36Z), which says "the next spec seat files the child". Filed by domain:spec seat 1 (#6017, session session_01WGufzfhobWEgUUrjz4rrbh). ⛔ Not a claim.

What the ruling decides

queues joins RESERVED_RLS_MEMBERSHIP_KEYS. plugin-security resolves it from the ownership-queue service into current_user.queues the same way it resolves positions, so there is one kernel-side producer. An app IRlsMembershipResolver that supplies queues is screened out and fails closed. Option B (plugin-sharing's own resolver) and option C (an ADR-0142 amendment that drops the key) were not chosen.

Measured on origin/main 7eb613c3

  • packages/spec/src/contracts/rls-membership-resolver.ts:89: RESERVED_RLS_MEMBERSHIP_KEYS = id, organization_id, positions, org_user_ids, accessible_org_ids, email. queues is not reserved.
  • The ownership-queue runtime landed with feat!: ownership queues and assignment rules (ADR-0142 phase 2) #26337 (packages/objectql/src/ownership-queue.test.ts, assignment-rules.ts). No RLS policy reads current_user.queues yet, because the D3 access path goes through the sharing owner match.

What lands (one PR, size S)

  • spec: queues added to RESERVED_RLS_MEMBERSHIP_KEYS, with its doc comment and the published-list pins that count the keys.
  • plugin-security: populate current_user.queues (the ids of the queues the user is a member of, directly or through a position or team, as the ownership-queue membership defines) next to positions. The value comes from one producer, and the screen drops an app resolver's queues.
  • Tests: the kernel value appears for a member and is empty for a non-member, and an app resolver that returns queues is screened out with the existing fail-closed outcome.

Clause-②: yes (widening). A reserved key is added to a published list. The ruling declares this arm; no accept set an author writes narrows.
Metadata-protocol: none

Out of scope (the rest of the ADR-0142 execution plan on #25769): the HotCRM stopgap deletion, the Console queue picker and Claim affordance, and the authoring guide. The skills docs are #26475.

Dedupe: #25769's comments and open issues mentioning "RESERVED_RLS_MEMBERSHIP_KEYS queues" or "current_user.queues". None found.

Activity

  1. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-28T01:33Z
    Session: session_01WGufzfhobWEgUUrjz4rrbh
    Account: os-support-ai
    Branch: claude/project-thread-1d234m (card thread session_01WGufzhD6Fqfyavauv2KoGA. The platform assigns the thread's branch and the thread can push only that one, so the branch is written as measured instead of claude/issue-27016-<slug>.)
    Worktree: objectstack-issue-27016
    Domain: domain:spec
    Seat: domain:spec#1
    File surface:

  2. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment · domain:spec seat 1 (#6017) · session session_01WGufzfhobWEgUUrjz4rrbh · 2026-10-28T01:35Z

    This amends claim 6458269562, which declared "yes (widening)". The ruling left the arm to the lane, and the dev measured a narrowing. RESERVED_RLS_MEMBERSHIP_KEYS is also read by MembershipKeyNameSchema (packages/spec/src/security/rls.zod.ts:780, the key-name refine on ObjectSchema.membershipKeys). Reserving queues therefore refuses an authored membershipKeys: { queues: … } at parse. The in-repo census on 7eb613c3 found zero such declarations.

    Clause-②: no (narrowing). An authored membership key named queues is refused; the kernel resolves that name.
    Metadata-protocol: narrowed

    The changeset carries a BREAKING banner and the ADR-0087 marker not-required (no-migration-prescription). The new key name is the author's choice, so there is no mechanical rewrite, and the changeset gives a **The remedy.** line instead. The file surface is unchanged.

  3. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 27016,
      "status": "done",
      "branch": "claude/project-thread-1d234m",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27044",
      "session": "session_01WGufzhD6Fqfyavauv2KoGA",
      "premise_still_valid": true,
      "summary": "Head 8660c53ef, off origin/main 7eb613c3 (premise reproduced there: RESERVED_RLS_MEMBERSHIP_KEYS lacked queues; plugin-security had no current_user.queues producer). Ruling 6457475657 (A) applied: queues joins RESERVED_RLS_MEMBERSHIP_KEYS with its doc comment. plugin-security resolves current_user.queues from ownership-queue queuesOf (same specsReachUser/access answer as the claim gate's isMember), new kernel-queue-membership.ts: once per request, only when a policy about to compile reads the key, stored under a module-private symbol keyed to the principal and organization (context.queues never read; a copied context for another user/org does not carry it). RLSCompiler.userContextOf sets queues beside positions. Existing screens (resolver screen, compiler merge) drop an app's queues by name and fail closed. Declaration per seat 1's ruling: Clause-② no (narrowing), Metadata-protocol narrowed (MembershipKeyNameSchema reads the list, so membershipKeys.queues is refused), ADR-0087 not-required (no-migration-prescription), **The remedy.** line; census 0 declarations/resolvers. Changeset minor for spec, plugin-security, lint, skills. Pins moved: plugin-security CELLS, lint KERNEL_KEY_RUNTIME_TYPE and three os explain texts plus the engine-judge copy; the unknown-variable fix line reworded (Read a kernel key) to stay at or under 200. skills/objectstack-data/rules/security.md reserved-name line gains queues, paid by a deletion in the same file. Reference docs regenerated (gen:docs, 4 files). PR body: /mnt/project-files/issue-27016/pr-body.md.",
      "tests": "Under the lock on 7f4c13eb/8660c53ef: spec 738 files / 22131 passed (1 todo); plugin-sharing 57 / 1279; lint 170 / 7510; plugin-security 234 / 5065 passed, 45 skipped; typecheck of the four packages exit 0. New: kernel-queue-membership.test.ts 12 cases (member, other org, non-member deny = no-service bytes, isMember agreement, once per request and lazy, no user / throwing service fail closed, app resolver queues screened with WARN, no-service gap, forged context field, copied context); queues cell in rls-reserved-membership-keys.test.ts; plugin-sharing queuesOf-agrees-with-isMember pin (non-vacuous). Ablation: compiler line queues: undefined gives 5 failed; queues removed from built spec list gives 4 failed; both restored.",
      "gates": "dispatch-gates --commands on 38a151a1: 115 commands; 111 exit 0; check-skills-token-ratchet red (+3) then exit 0 after the paying deletion; check:skill-examples, check:dual-build-cjs-loads, check:i18n exit 3 then 0 after the dogfood closure build. check:generated: references stale, regenerated. CI on the PR: not yet read at report time.",
      "dogfood_battery": "8660c53ef · os-verify-lock VERDICT command-exit 1 · Test Files 1 failed / 344 passed / 3 skipped (348) · Tests 2 failed / 2788 passed / 20 skipped (2810) · both failures packaged-action-disabled-dispatch-live.dogfood.test.ts (acceptance[0], [5]/[2]), reproduce alone (2 failed / 6 passed); not this diff: the test reads the first showcase_task unsorted and that row was already done before the action; no stack reads current_user.queues",
      "mcp_calls": "5: issue_read x4 (27016 get, get_comments; 26954 get_comments), 0 writes",
      "api_writes": "3 via the relay: pr_create (#27044, 10714 bytes read back identical, assignee os-support-ai), pr_request_reviewers, and this os-dev-report comment",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: b · reach: dogfood suite only · packaged-action-disabled-dispatch-live.dogfood.test.ts picks GET /data/showcase_task?$top=1 with no sort and asserts its done is false after the refused action; on this box the first row was already done, so acceptance[0] and [5]/[2] fail even when the file runs alone · dedupe: packaged-action-disabled-dispatch-live first task done · carrier: seat 1 to file or route",
        "boundary: current_user.queues inside a field permission `when` resolves only if a row policy on the same request staged it first (compileRowPredicate does not stage); unresolved fails closed (the entry locks), same as resolver keys today · carrier: none"
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:spec seat 1 (#6017) · session session_01WGufzfhobWEgUUrjz4rrbh · 2026-10-28T05:37Z

    PR #27044 merged at e3470ed9 through the queue, under os-zhuang's Tier H approval. The merge commit is an ancestor of origin/main. On all 23 paths the PR touched, the merge tree matches the accepted head e3749743 byte for byte.

    queues is now a reserved RLS membership key. plugin-security resolves current_user.queues kernel-side from the ownership-queue service (queuesOf, the same answer the claim gate's isMember reads). It is resolved once per request and bound to the user and organization, and it fails closed when the service is absent or errors. An app IRlsMembershipResolver that answers queues is screened out, and an authored membershipKeys.queues is refused at parse. ADR-0142 D3 is amended to ruling 6457475657 (letter A).

    @objectstack/spec, plugin-security, lint and skills are minor, with a BREAKING banner and ADR-0087 not-required (no-migration-prescription). Clause-②: no (narrowing) and Metadata-protocol: narrowed. The card closed through Fixes #27016, and this seat removes pm:dispatched. The triage seat's delta review raised two ADR-only should-fixes (the Status-line Amended marker and the Execution plan item 1 annotation). They follow in PR #27096 (Part of #27016, skip-changeset, Tier H).

  5. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Follow-up landed · domain:spec seat 1 (#6017) · session session_01WGufzfhobWEgUUrjz4rrbh · 2026-10-28T06:34Z

    PR #27096 merged at a305b94e under os-zhuang's Tier H approval. ADR-0142 Status line now carries the Amended marker for ruling 6457475657, and Execution plan item 1 is annotated as superseded by the amended D3. Nothing is left on #27016.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions