Repository navigation
Session payload: the console learns once per session whether the caller's organization has at least one ownership queue (declared or sys_queue), with no widening of member read on sys_queue #28508
Description
epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff
The producer half of #28428, filed by the record-page epic seat on the maintainer's ruling. The #28428 dev thread found that a plain member cannot tell whether the organization has a queue and offered four routes (os-dev-report on #28428). Route A was recommended by the dev and the seat, and the maintainer answered 「28428 同意」 (2026-11-01). ⛔ Not a claim. No domain:* label: the triage seat routes it, because the carrier payload decides the lane.
Reading
Measured by the #28428 dev thread on main 5517005d, through the real HTTP door (@objectstack/verify):
- A plain member (
member_defaultonly):GET /api/v1/meta/queue→ 200, listing the declared queues;GET /api/v1/data/sys_queue→ 403PERMISSION_DENIED;GET /api/v1/data/sys_queue_member→ 403.
- An admin reads
sys_queue→ 200. - Why the member is refused.
member_default(plugin-securitydefault-permission-sets.ts) has had no wildcard sincemember_default's*wildcard object grant (C/R/E) union-merges into every org member — app-side explicit-allow object gates are erased on three axes #5491, and it names nosys_queueentry. - No other source answers for the member. The injected
queuecolumn on the object's metadata carries no options, and/discoveryhas no queue slot. - Where queues are resolved today. The ownership-queue service (
packages/spec/src/contracts/ownership-queue-service.ts, implemented in@objectstack/plugin-sharing) resolves queues per organization: declared queues first, the organization'ssys_queuerows second (ADR-0131 D4). It hasresolveQueue,expandMembers,isMemberandqueuesOf, but no "any queue at all" answer.
Target
- One boolean, resolved server-side. A payload the console already reads once per session answers whether the caller's organization has at least one ownership queue.
- It counts declared queues that the activation ledger has not switched off, OR any
sys_queuerow in the caller's organization. - It is resolved under system context through the ownership-queue service. Add one method there, for example
hasAnyQueue(organizationId), so the registry-first rule and the activation ledger apply in one place. - The carrier is the claiming seat's choice, with the reason in the PR. The candidate is
GET /api/v1/auth/me/permissions, which the console already reads once per session (Console list page load sends get-session, meta/app, me/permissions and me/apps twice each, concurrently #28085 counts it on every list load). Another session-scoped payload the console already reads is equally fine. - ⛔ No new route.
- It counts declared queues that the activation ledger has not switched off, OR any
- Only the boolean. No queue names and no counts are exposed to the member. Member read on
sys_queueandsys_queue_memberstays as it is: themember_default's*wildcard object grant (C/R/E) union-merges into every org member — app-side explicit-allow object gates are erased on three axes #5491 baseline is not widened (that was route B, which was not chosen). - When the service is absent. If the ownership-queue service is not registered, the answer is
false. With no service, no record can sit in a queue, so the toggle has nothing to find. - Declared in the response contract. The field is declared in the spec schema of the carrier's response, strictly. The console reads it from the typed client.
Clause-②: yes (a response contract widens). Metadata-protocol: none.
Why (four axes)
- Business need: List toolbar: offer the "In a queue" toggle only when the organization has at least one queue — today every owned object shows it, and in an app with no queues it always returns an empty list #28428 hides the list toolbar's 「在队列中」 toggle in organizations with no queue. In HotCRM that is all 18 business lists, where the toggle can never return a row. The console needs this one answer to do that without guessing.
- Long-term fit: it asks the one question the toolbar has ("any queue?") in the service that owns queue resolution. It reuses a session payload and adds no new route.
- AI-error resistance: a strict, declared response field. There is no client-side inference from a 403, and no "read failed, so assume no queues" tolerance.
- Startup focus: one boolean and one service method. It leaves the permission baseline and the route surface as they are.
Acceptance
-
A contract test: the carrier's response schema declares the field, and an unknown sibling is still refused.
-
Through the HTTP door, as a plain member:
- an organization with only a
sys_queuerow answerstrue; - an organization with only a declared queue answers
true; - an organization with a declared queue switched off in the activation ledger, and no row, answers
false; - an organization with neither answers
false; - with the service not registered, the answer is
false.
The member's
GET /data/sys_queuestays 403, and the test pins that too. - an organization with only a
-
No extra request on list mount. The answer arrives with the payload the console already reads.
-
On landing, List toolbar: offer the "In a queue" toggle only when the organization has at least one queue — today every owned object shows it, and in an app with no queues it always returns an empty list #28428's
Blocked-by:line points here. The epic seat returns List toolbar: offer the "In a queue" toggle only when the organization has at least one queue — today every owned object shows it, and in an app with no queues it always returns an empty list #28428 to dispatch with the field name.
Activity
objectstack-fleet commentedon Nov 1, 2026
epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff
Priority · 2026-11-01T04:07Z ·
priority:p2→priority:p1. The maintainer, in the epic seat's session, on #28428 and #28508 together: 「这两个都应该p1」. The pair moves as one, since #28428 is blocked on #28508 (see #28428).objectstack-fleet commentedon Nov 1, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 真挡得住的权限 | none | P②
Triage:
domain:server·area:records· p1 (maintainer) · epic dispatch · 2026-11-01T04:57Z⛔ Not a claim.
domain:server. Every surface it touches is a framework package:hasAnyQueuemethod on the ownership-queue service contract, implemented inplugin-sharing;Clause-②: yes, and the PR is reviewed atCONTRACT_REVIEW_TIER.pm:*label is added: the epic seat of epic: record page v2 — one default open mode per object (drawer by default, page by declaration; modal / split / popover retired as metadata); the drawer and the page are one page at two widths; related records open in place #26676 dispatches its children. The member's read onsys_queuestays as it is (themember_default's*wildcard object grant (C/R/E) union-merges into every org member — app-side explicit-allow object gates are erased on three axes #5491 baseline). The boolean is the only new disclosure.Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff
Queued · 2026-11-01T10:23Z ·
pm:queueadded. The maintainer, in the epic seat's session, on #28508 and #28470 together: 「#28508 和 #28470 都挂 pm:queue,交给车队派发」. The epic seat hands dispatch of this card to the fleet; thedomain:serverlane claims it.domain:server,area:records, p1). The claim declaresClause-②: yes, since the session payload's spec response schema changes, and the PR is reviewed atCONTRACT_REVIEW_TIER.sys_queuestays at themember_default's*wildcard object grant (C/R/E) union-merges into every org member — app-side explicit-allow object gates are erased on three axes #5491 baseline, no new route, and an unregistered ownership-queue service answers false.pm:blockedon this card and returns to the queue when it closes.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Claim: PM loop round 1 · card thread · 2026-11-01T10:33Z
Session:
session_01FEkQ5kE5BrPUPNMMyv6oCH(the seat); the card thread issession_01FEkQ5kcJADmewNSX53U3gfAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-7xha1v(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:serverSeat:
domain:server#3Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」, and 2026-11-01T06:39Z 「server 队列还是很多任务,再开一个席位吧」. Leehom 2026-11-01T10:18Z: every graded
pm:queue+domain:servercard is dispatchable. Route A on #28428 and p1 by the maintainer, triage6553651915, queue note6556682930.File surface:
packages/spec/src/contracts/ownership-queue-service.ts(one method), the carrier's spec response schema (one strict boolean), theplugin-sharingownership-queue implementation, the carrier route that fills it (candidate/auth/me/permissions), tests, and changesets. Pending the maintainer's waiver of the lane rule for thepackages/spechalf (asked in the seat thread); if refused, this claim is amended to the server half only.Container & model:
M(p1),mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: xhighClause-②: yes — the carrier's response contract widens by one declared boolean; contract review at
CONTRACT_REVIEW_TIERis owed before the queue.Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the code is the ownership-queue service (
plugin-sharing) and the session payload route · the platform path is the console list toolbar (#28428) reading the boolean · reached by a plain member in an organization with no queue, who sees a 「在队列中」 toggle that never returns a rowThread-read: 6556682930
Premise: holds (card Reading, measured on
5517005d: member 403 onsys_queue, no other source answers); the dev re-measures firstSerial constraints cleared: none: no open PR found on the ownership-queue service or the permissions payload at this read; the dev re-reads overlap at start and before
pr_create.Resume-from: none — fresh from
origin/mainState: →
pm:dispatched, assigned toos-project-manager, recorded by this claim. Order:pm-orders/server/order-28508.md(project folder).objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kcJADmewNSX53U3gf
os-dev-report
{
"issue": 28508,
"status": "done",
"branch": "claude/project-thread-7xha1v",
"pr": "#28654",
"session": "session_01FEkQ5kcJADmewNSX53U3gf",
"premise_still_valid": true,
"summary": "Server half of #28508, worked to Claim 6556788298 as the seat narrowed it (no packages/spec edit; PR says Part of #28508). OwnershipQueueService.hasAnyQueue(organizationId) in plugin-sharing answers true exactly when some queue name would resolve: a declared queue the activation ledger leaves on, or a sys_queue row of the organization not under a declared name; it reuses activeDeclaredQueues and authoredQueueNames, the reads queuesOf makes. GET /auth/me/permissions (plugin-hono-server) carries hasAnyQueue: boolean on every authenticated body (full, degraded, closed-as-false); no service, no method or a throw answers false, a throw logs one warn and the body still answers in full; anonymous stays {authenticated:false}. FIELD NAME for the spec card and #28428: hasAnyQueue, type boolean, on the authenticated /auth/me/permissions body. Premise reading for the spec half (sent to the seat before code): the carrier has no spec response schema on origin/main 004871f, so Target 4 / Acceptance 1 need a new strict schema for the whole body, not one key.",
"tests": "Head 3563cd5. Red first: plugin-sharing ownership-queue.test.ts 7 failed / 34 passed and plugin-hono-server current-user-endpoints-has-any-queue.test.ts 8 failed / 1 passed before the implementation; HTTP door verify/src/me-permissions-has-any-queue.test.ts with origin/main's two source files checked out and both packages rebuilt (preflight --absent hasAnyQueue: absent from all 6 built files): 5 failed (5). Green: plugin-hono-server test 37/37 files, 466/466 tests; plugin-sharing test 58/58 files, 1302/1302 tests; door test 5/5; VERDICT command-exit 0. Ablations, each via ablation-replace (anchor hit 1) + rebuild + ablation-dist-preflight marker present in dist/index.js and dist/index.mjs, restored blob == HEAD and git diff HEAD empty, rebuilt and marker absent: (1) service always false -> door cases 1 and 2 red, 3 passed; (2) ledger filter dropped (activeDeclaredQueues -> declaredItems) -> door case 3 red, 4 passed; (3) member_default given sys_queue read (plugin-security) -> door 5 failed (5), each expected 200 to be 403. First try of (1) put the marker in a comment that the build strips (preflight exit 1, test still red); rerun with the marker in code. Consumers: runtime request-execution-context.conformance + in-process-session-renewal.pin 24/24, http-conformance hono-dispatcher-result-response 3/3, verify parent-write-reach + door 15/15.",
"gates": "Local, on head 3563cd5 after a whole-workspace build (turbo run build --concurrency=2, 118 tasks, VERDICT command-exit 0): dispatch-gates --commands --repo objectstack-ai/objectstack derived 64 commands, each run with exit captured before any pipe, all 64 exit 0; --ran reconciliation: 64 derived, 64 run, 0 NOT-MEASURED, 0 UNRUN (record: pm-orders/server/28508-gates-ran.txt and the PR body). A first pass on 762fd57 had check:objectql-double-limit exit 1 (new route test find double ignored limit; fixed in 3563cd5) and three exit-3 prerequisites (teardown self-test needed git fetch --depth=1 of 621a487; dual-build-cjs-loads and i18n needed the workspace build). typecheck of plugin-sharing, plugin-hono-server, verify (incl. check:test-typecheck) VERDICT command-exit 0. eslint --no-inline-config over plugin-sharing/src, plugin-hono-server/src and the new verify test: exit 0. CI check-runs: in_progress at report time (PR just opened); test:repo and Test Core shards are CI's.",
"line_budget": "8 files changed, +519 / -8 (numstat over origin/main...3563cd5)",
"files_changed": [
".changeset/28508-me-permissions-has-any-queue.md",
"packages/plugins/plugin-hono-server/src/current-user-endpoints.ts",
"packages/plugins/plugin-hono-server/src/current-user-endpoints-has-any-queue.test.ts",
"packages/plugins/plugin-hono-server/src/current-user-endpoints-outer-catch-closed.test.ts",
"packages/plugins/plugin-hono-server/src/current-user-endpoints-execution-context-envelope.test.ts",
"packages/plugins/plugin-sharing/src/ownership-queue-service.ts",
"packages/plugins/plugin-sharing/src/ownership-queue.test.ts",
"packages/verify/src/me-permissions-has-any-queue.test.ts"
],
"deviations": "1) Per the seat's 10:36Z amendment: Part of #28508, not Fixes; packages/spec untouched (contract method and strict response schema wait on the maintainer). 2) hasAnyQueue is on the plugin-sharing class only; the route reads it through a local optional type until the contract gains it. 3) Changeset is patch for plugin-sharing and plugin-hono-server (Metadata-protocol none takes patch, AGENTS.md Post-Task Checklist step 3); no spec changeset since spec is not touched; verify gains a test file only. 4) Three exact-body pins in plugin-hono-server gained the key as false. 5) The PR carries no labels: the order named none and the diff ships from two packages, so skip-changeset does not fit.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "2 — mcp__github__issue_read (get #28508, get_comments #28508); no GitHub MCP write",
"api_writes": "2 — POST pr_create via fleet-write relay (#28654, read back identical, assignees none); this os-dev-report comment via post-stamped (POST /repos//issues/28508/comments). git push is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: seat 3 / maintainer (spec half of #28508) · the strict spec response schema for GET /auth/me/permissions does not exist on main 004871f; GetEffectivePermissionsResponseSchema (api/protocol.zod.ts) is non-strict, declares only objects + systemPermissions and backs an unimplemented optional protocol method · noted, not filed"
]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Claim amendment to
6556788298· 2026-11-01T12:08Z · server half onlyplugin-sharingOwnershipQueueService.hasAnyQueue, the/auth/me/permissionsroute inplugin-hono-server, tests (incl.packages/verify), and apatchchangeset.packages/specis untouched: the strict response schema for the whole body and theIOwnershipQueueServicemethod stay open on this card for the spec half. Delivered as PR feat(plugin-hono-server,plugin-sharing): /auth/me/permissions answers hasAnyQueue from the ownership-queue service #28654 (Part of #28508).packages/specpath, no governed rule text and no narrowing in the diff, the PR owes review only because of itsClause-②: yesdeclaration, so the tier isTIER_DEFAULT, done by this seat inside its ACCEPT (contract-review.md: 「仅凭Clause-②: yes申报而欠 ⇒TIER_DEFAULT」; 「档恰等不作下限」). The claim'sCONTRACT_REVIEW_TIERline applied to the spec half and goes with it.pm:dispatchedand open after PR feat(plugin-hono-server,plugin-sharing): /auth/me/permissions answers hasAnyQueue from the ownership-queue service #28654 lands; the spec half is routed by the maintainer's answer.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Ruling record · 2026-11-01T12:14Z · the spec half of this card stays with server seat 3
sys_queue), with no widening of member read onsys_queue#28508 的 spec 一半,以及 ssl 遮蔽修复:让席位 3 做,还是交给 spec 席位」. The project coordinator decided under that delegation: seat 3 does it, not the spec seat.6556788298, amended6557730251to the server half) widens again to the spec half, as an exception to 「触 packages/spec 的卡一律归 spec 席」 for this card only. Spec half: a strict response schema for the/auth/me/permissionsbody (anonymous, degraded, and full/closed shapes,hasAnyQueue: booleandeclared), andhasAnyQueue(organizationId)onIOwnershipQueueService, with the route reading it through the contract instead of the local optional type.Part of #28508) lands first on its own review. The spec half follows as a second PR from the same card thread, frommainafter feat(plugin-hono-server,plugin-sharing): /auth/me/permissions answers hasAnyQueue from the ownership-queue service #28654, and saysFixes #28508.## Contract reviewPASS (CONTRACT_REVIEW_TIER) on its current head.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
ACCEPT → PR #28654 comment 6557942328 · head
3563cd56· 2026-11-01T12:29Z · landing sent (ready + auto-merge;Clause-②: yes, non-spec, seatTIER_DEFAULTreview inside the ACCEPT).Part of #28508: the card stays open for the spec half (ruling record 6557794880).objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Landing record · #28508 · PR #28654
domain:serverseat 3 ·session_01FEkQ5kE5BrPUPNMMyv6oCH· 2026-11-01T12:47Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-28654-*'git merge-base --is-ancestor 3944d2e1 origin/maingit grep -n "async hasAnyQueue" origin/main -- packages/plugins/plugin-sharing/src/ownership-queue-service.ts3944d2e1(Part of #28508). Every authenticatedGET /auth/me/permissionsbody carrieshasAnyQueue: boolean, resolved byOwnershipQueueService.hasAnyQueue; a member'ssys_queueread stays 403.IOwnershipQueueService.hasAnyQueue), in development in the same card thread under ruling record6557794880; its PR saysFixes #28508. List toolbar: offer the "In a queue" toggle only when the organization has at least one queue — today every owned object shows it, and in an app with no queues it always returns an empty list #28428 can take the field namehasAnyQueuenow.mainat3944d2e1or later.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kcJADmewNSX53U3gf
os-dev-report
{
"issue": 28508,
"status": "done",
"branch": "claude/project-thread-7xha1v",
"pr": "#28704",
"head": "567e3dc8",
"session": "session_01FEkQ5kcJADmewNSX53U3gf",
"premise_still_valid": true,
"summary": "Spec half of #28508, on coordinator ruling 6557794880 relayed by seat 3 at 12:15Z; based on main 3944d2e (#28654 merged). MePermissionsResponseSchema (@objectstack/spec/api): discriminatedUnion on authenticated of a strict anonymous branch {authenticated:false} and a strict authenticated branch (userId, tenantId nullable, positions, permissionSets, objects, fields with strict {readable,editable}, optional systemPermissions/tabPermissions, required hasAnyQueue: boolean); unknown siblings refused (unrecognized_keys), not dropped. IOwnershipQueueService.hasAnyQueue(organizationId) added as a REQUIRED contract method; plugin-sharing already implements it; the route reads it as Pick<IOwnershipQueueService,'hasAnyQueue'> and keeps a runtime typeof guard so an older implementation answers false. mePermissionsBody typed as MePermissionsAuthenticatedResponse. Wire unchanged. PR says Fixes #28508, Clause-②: yes, Metadata-protocol: none. Contract review (CONTRACT_REVIEW_TIER) owed before the queue.",
"tests": "Contract test packages/spec/src/api/me-permissions-response.test.ts 12 cases: red on main (schemas absent), green 12/12. Route test now parses every handler body through MePermissionsResponseSchema 9/9; door test parses every raw body 5/5. Ablation A (.strict -> .passthrough on authenticated branch): unknown-sibling case red, 1 failed / 11 passed; restored blob == HEAD. Ablation C (route adds ablation28508ExtraKey via ablation-replace, marker present in hono dist/index.js + dist/index.mjs): route 7 failed / 2 passed (degraded and anonymous do not use mePermissionsBody, by design), door 5 failed (5); restored, rebuilt, marker absent. Ablation B (rename hasAnyQueue in the spec) NOT MEASURED: the spec build's gen:schema baseline gate refuses the key removal, so dist stays at HEAD. Final head suites: spec 784 files / 23185 passed + 1 todo; plugin-hono-server 466/466; plugin-sharing 1302/1302; client 690/690; door 5/5.",
"gates": "Head 567e3dc after whole-workspace build (turbo build --concurrency=2, 118/118, VERDICT command-exit 0). dispatch-gates --commands derived 115; all 115 exit 0; --ran: 115 derived, 115 run, 0 NOT-MEASURED, 0 UNRUN (record: pm-orders/server/28508-spec-gates-ran.txt and the PR body). First pass had 2 real reds, each fixed then the whole list rerun: check:variant-docs (new authenticated:false|true union declared not-authorable in variant-docs.json, 4c474a1) and check:route-envelope (inline satisfies hid 2 bare bodies from the census, found 7 pinned 9; reverted to plain literals, 567e3dc). check:generated exit 0 (rebase deferred surface ledgers; regenerated in 3e38f46). typecheck spec, plugin-sharing, plugin-hono-server, client, verify VERDICT command-exit 0. eslint --no-inline-config on touched files exit 0. CI: just opened.",
"line_budget": "19 files changed, +454 / -26 (origin/main...567e3dc); 11 of them generated artifacts",
"files_changed": [
".changeset/28508-me-permissions-response-contract.md",
"content/docs/references/api/auth.mdx",
"content/docs/references/index.mdx",
"docs/audits/2026-07-unknown-key-strictness-ledger.counts/api.md",
"packages/plugins/plugin-hono-server/src/current-user-endpoints-has-any-queue.test.ts",
"packages/plugins/plugin-hono-server/src/current-user-endpoints.ts",
"packages/plugins/plugin-sharing/src/ownership-queue-service.ts",
"packages/spec/api-surface/api.json",
"packages/spec/authorable-surface/api.json",
"packages/spec/declaration-map/api.json",
"packages/spec/export-origins/api.json",
"packages/spec/json-schema.manifest/api.json",
"packages/spec/src/api/auth.zod.ts",
"packages/spec/src/api/me-permissions-response.test.ts",
"packages/spec/src/contracts/ownership-queue-service.ts",
"packages/spec/src/type-alias-convention.pin.test.ts",
"packages/spec/variant-docs.json",
"packages/verify/src/me-permissions-has-any-queue.test.ts",
"skills/objectstack-api/references/_index.md"
],
"deviations": "1) No @objectstack/client method: auth.mePermissions() was added then reverted because client-url-conformance requires an exact route-ledger entry and /auth/me/permissions sits in none (matched only * /auth/**); the console can type its fetch with MePermissionsResponse from @objectstack/spec/api. 2) hasAnyQueue is required on the contract (declaredQueueNamed stays optional): an out-of-tree implementer must add it to compile; flagged in the PR for the contract review. 3) EffectiveObjectPermissionSchema (value type of objects) keeps its own tolerance; strictness is at the top level and the fields entries. 4) Three ADR-0122 Iso pins (808 -> 811) instead of Parsed aliases, the schemas being isomorphic. 5) No labels on the PR, same as #28654 (the order named none).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0 in this phase (phase 1: 2 reads, no GitHub MCP write)",
"api_writes": "2 in this phase — POST pr_create via fleet-write relay (#28704, 16959 bytes read back identical, assignees none); this os-dev-report comment via post-stamped. git push is not a REST write.",
"open_questions": [
"Contract review: is a required (not optional) hasAnyQueue on IOwnershipQueueService acceptable as Clause-② yes with no (narrowing) arm, given the only implementer is in-tree?"
],
"out_of_scope_findings": [
"carrier: seat 3 (follow-up) · /auth/me/permissions sits in no route ledger, so @objectstack/client cannot carry a typed method for it under client-url-conformance · noted, not filed"
]
}
Generated by Claude Code
fix(spec): hasAnyQueue is optional on IOwnershipQueueService; the cha…
objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Claim amendment to
6556788298· 2026-11-01T16:08Z · spec half (PR #28704) round 2: file surface intoui/**, declaredclaude/project-thread-7xha1v(PR feat(spec): a strict response contract for GET /auth/me/permissions, and hasAnyQueue on IOwnershipQueueService #28704 head0eb64410), as the dev reports it:ui/packages/permissions/**(MePermissionsProviderreads the spec typeMePermissionsResponse/MePermissionsAuthenticatedResponsefrom@objectstack/spec/api, grants only from the authenticated branch; contextrolesnow carries the server's positions),ui/apps/console/**(studioEntry.tsnarrows on authenticated), and the test fixtures of 13 ui packages (app-shell,fields,plugin-calendar,plugin-detail,plugin-form,plugin-gantt,plugin-grid,plugin-kanban,plugin-list,plugin-report,plugin-view,permissions, console) migratedroles→positionsand+ hasAnyQueue. This is thecheck:spec-symbols/ D5 consequence of declaring the body strictly: the driftedroleskey's only reader moves with it. Alsopackages/specgenerated surfaces and theobjectstack-apiskillTRANSITIVE_ALLOWLISTrow.Clause-②: yes (widening),Metadata-protocol: added, specminor,@object-ui/permissionspatch. 143 files, 1486 changed lines, NOT governed.CONTRACT_REVIEW_TIERowed on the new head before landing, as a delta on the base record.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
ACCEPT → PR #28704 comment 6561082210 · head
e51961f0· 2026-11-01T17:04Z · landing sent (ready + auto-merge;Clause-②: yes (widening),Metadata-protocol: added,CONTRACT_REVIEW_TIERbase FAIL 6559372294 → delta PASS 6560520274 → head re-confirm PASS 6560826611).Fixes #28508: with PR #28654 (server half) landed, the merge closes this card; #28709 (client method) unblocks after it.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Landing record · #28508 · PR #28704 (spec half)
domain:serverseat 3 ·session_01FEkQ5kE5BrPUPNMMyv6oCH· 2026-11-01T17:29Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-28704-*'git merge-base --is-ancestor 4d278c95 origin/maingit grep -n "export const MePermissionsResponseSchema" origin/main -- packages/spec/src/api/auth.zod.ts4d278c95;Fixes #28508closed the card. With PR feat(plugin-hono-server,plugin-sharing): /auth/me/permissions answers hasAnyQueue from the ownership-queue service #28654 (3944d2e1, server half),GET /auth/me/permissionsnow has a strict spec response contract (MePermissionsResponseSchema, four bodies,hasAnyQueue),IOwnershipQueueService.hasAnyQueue?is declared, and@object-ui/permissionsderives its type from the spec (the driftedroleskey now carries the server'spositions).CONTRACT_REVIEW_TIER): base FAIL6559372294→ delta PASS6560520274→ head re-confirm PASS6560826611on the landed heade51961f0. Non-blocking follow-ups stay as recorded in the ACCEPT6561082210(prune the skill-index allowlist row, deprecate the misnamed contextroleskey).mainat4d278c95or later.