You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Setup: show what people can really do and what really changed, using names rather than ids #30209
From a real-user walkthrough of Setup, filed on the maintainer's word: 「以上都同意,立卡」 (2026-11-05). Measured on mainb7075d9908, with the console in dev mode, unless a line says otherwise. Test app scaffolded with create-objectstack@18.3.0.
An administrator investigating a problem cannot get an answer from these screens today.
Items
#
Where
Observed
Suggestion
1
User record, 权限集 tab
Shows 0 and 暂无相关记录 for a user who has access through the default sets and positions
Show effective access and where it comes from. POST /api/v1/security/explain already answers this
2
Sharing rule record
接收方 shows a raw id, _sGHMyWlqcx6t…; 条件 shows {"priority":"urgent"}
The recipient's name, and the condition in words
3
审计日志 list
The 记录 column is an id; object names like Platform Setting Audit Entry are English; one sign-in writes several rows
Record label; localized names; a default view that hides the machinery
4
审计日志 config change detail
Shows the key and a sha256: digest, so the new value cannot be read
Show old and new values for non-secret settings. Secrets stay withheld
5
共享规则 new form
The object picker lists 86 objects, mostly sys_*, with business objects buried
Business objects first; hide objects where a rule makes no sense
6
Queue record
No way to see or add members from the queue; they are on a separate nav entry
A members list on the queue
Row 5 includes objects holding credentials and sessions, so the dev should confirm what a rule on those would do while deciding what to hide.
Read fresh. Setup's permission and change screens show ids and declared grants instead of effective access by name. A diagnostic-readability gap, so p3.
Claim: PM loop round 3 · 2026-11-05T12:21Z
Session: session_01L6bhgUR8Nu4M7tbtgES7q2
Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
Branch: the card thread's designated claude/project-thread-* branch, named in a claim amendment once the thread reports it
Worktree: objectstack-issue-30209
Domain: domain:ui
Seat: domain:ui#6
File surface: the rows whose fix lands in ui/**: row 1 (the user record's 权限集 tab shows effective access via the existing POST /api/v1/security/explain), row 2 (sharing-rule recipient by name, condition in words), row 3 (audit list record label / localized object names where ui/ draws them), row 6 (queue members list on the queue record), their tests, one root .changeset/ file. ⛔ row 4 (config-change values: what is secret is a server decision) and ⛔ row 5 (sharing-rule object picker over credential/session objects: security-sensitive, report the reading only). ⛔ packages/**. Rows not done are named in the report for the seat to split (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable), effort: high
Clause-②: no (a new language-pack key, if a row needs one, is declared by the dev in the PR body and the seat re-reads this line at ACCEPT)
Metadata-protocol: none
Responsibility: n/a — not a defect card
Thread-read: 6648534205
Premise: holds as filed on b7075d99; the dev re-measures each row on origin/main first and may ship a subset
Serial constraints cleared: none in flight on the user record tabs, sharing-rule or queue record pages (open PRs read 2026-11-05T12:18Z). No maintainer ruling beyond 「以上都同意,立卡」.
席位核对 · Amendment · 2026-11-05T12:24Z · claim 6657861397 branch named
Branch: claude/project-thread-zr7jt1
The card thread's harness-designated branch (a project-thread platform exception to the claude/issue-<n>-<slug> convention); the dev thread is session session_01L6bhgWs5eCv64CbCPwjWhV. Everything else in claim 6657861397 stands.
{
"issue": 30209,
"status": "done",
"branch": "claude/project-thread-zr7jt1",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30496",
"session": "session_01L6bhgWs5eCv64CbCPwjWhV",
"premise_still_valid": true,
"summary": "Subset shipped (Refs, not Fixes). Row 2: a sharing rule's record page now names the recipient (record-page faces get the record as dependentValues, so recipient-picker reads recipient_type) and reads the condition in words (filter-condition gains a read face drawing the widget's words, 优先级 等于 紧急; unrepresentable criteria stay JSON). Row 3 (record-label half): RecordPointerCell expands the name field when it is a readable reference, so sys_session sign-in rows read the user's name. Rows 1, 3-rest, 4, 5 and 6 not shipped: rows_not_shipped below, each with its owning lane for the seat to split. No language-pack key added (words reuse filterBuilder.* rows): Clause-②: no.",
"rows_not_shipped": [
"row 1 · 林伟's 权限集 tab reads 0 / 暂无相关记录: the tab is page metadata (packages/platform-objects/src/pages/sys-user.page.ts, record:related_list over sys_user_permission_set); effective access needs a page-component vocabulary entry in packages/spec + the page edit in packages/platform-objects, then the ui block · lanes: spec + server, then ui",
"row 3 rest · sys_platform_setting_audit (and others) have no zh-CN label rows in packages/platform-objects translations; 'one sign-in writes several rows' and a default view hiding them are the audit writer and the object's list views in packages/** · server lane",
"row 4 · not measured (claim ⛔) · server lane",
"row 5 · not measured (claim ⛔, reading only) · security lane",
"row 6 · sys_queue_member.queue is a text field holding the queue name, not a lookup, so no related list is synthesized; needs a lookup or a sys_queue page with a members list in packages/plugins/plugin-sharing · server lane"
],
"tests": "New: fields FilterConditionField.readWords-30209 (3), plugin-detail recordFace.siblingValues-30209 (2), plugin-grid ObjectGrid.recordPointerCell-12608 new describe (2). Positive control: sources restored to base c5800818 → 5 new assertions red, controls green. Ablations via scripts/ablation-replace.mjs, each restored (git diff HEAD empty): DetailSection dependentValues removed 1F/1P; words branch if(false) 2F/1P; $expand spread deleted 1F/4P. Suites fields+plugin-detail+plugin-grid+app-shell dirs: only reds were 4 renderer censuses, enrolled; rerun 36 files / 453 tests green. Type-check turbo --filter fields/plugin-detail/plugin-grid 55/55 (lock VERDICT 0). eslint changed files 0 errors.",
"gates": "35 derived dispatch gates exit 0 (vitest run scripts/ SIGKILLed alongside type-check, rerun alone 171 passed VERDICT 0); ui check:spec-symbols, check:i18n-keys (after hook rename), check:unreferenced-sources, check:side-effects-array, check:phantom-deps, check:esm-specifiers, check:i18n-drift, check:new-line-citations, root check:doc-authoring all 0. CI on the PR: pending at report time.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "reads only — mcp__github__issue_read (card + comments); no write tool",
"api_writes": "git push to claude/project-thread-zr7jt1 (harness branch); relay pr_create → #30496 (run 42036248962); relay issue comment (this report)",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: PR #30496 Acceptance notes · noted, not filed: Setup navigation and sys_queue labels (Queues, Queue, Display Label) read English under zh-CN — translation coverage in packages/**",
"carrier: PR #30496 · noted, not filed: records named by a display_title formula over ids (sys_approval_approver/action/request, sys_user_position, sys_member) still read as ids in pointer cells — server metadata"
]
}
What remains is lane work: rows 1 and 2 (effective access on the user's 权限集 tab, and names instead of ids on a sharing rule), plus row 5's follow-up B, which the seat put after C. pm:queue for domain:server; p3 kept.
Claim: PM loop round 2 · rows 5 B (server half), with rows 1 and 2 measured · 2026-11-07T15:40Z
Session: session_017ihL2dFb2QdZEHEJ83cR2B
Account: marchtian
Branch: claude/project-thread-txk3tb
Worktree: objectstack-issue-30209 (the card thread's own checkout)
Domain: domain:server
Seat: domain:server#3
File surface: packages/plugins/plugin-sharing/** (row 5 B server half: a read-only shareable-objects route + the sys_sharing_rule object field widget hint, tests, translations), the route-ledger / envelope-guard / live-mount-parity wiring lines the gates name, .changeset/**; rows 1 and 2 are measured and reported only. ⛔ packages/spec/**, ui/** (stop on breach; explain in the report)
Container & model: M, mode:thread (card thread cmsg_01VmuUhXU9SSUzqJYyXSmYSiFMQNAUTGWk1GeD14KvBfaa of this account's project), model: TIER_DEFAULT — dispatch-gates --tier: no path-derived mandate, effort: session default — card-thread effort is set by the maintainer only; the seat's reading is high (M; a new read route on the sharing admin surface)
Clause-②: no (provisional) — an additive read route and a widget hint on the existing free widget string; the dev states the arm from the diff
Metadata-protocol: none
Responsibility: n/a — enhancement card (Setup walkthrough, epic #26676)
Thread-read: 6708449661
Premise: holds — rows 3, 4 B, 5 C, 6 B landed (PRs #30620, #30728, #30621) and row 2 + the record-name half of row 3 in PR #30496; triage 6708449661 re-queued rows 1, 2 and 5 B under ruling 6670358877. describeFilterGroup is on main 8ef4d3090, so row 2 is measured first and may already be done
Serial constraints cleared: no open PR touches packages/plugins/plugin-sharing/** (open PR list read now); #30621 (row 5 C, the save-time refusal this route must share its predicate with) is closed
The dispatch order is the card thread's opening message (files server-seat-3/orders/_standing.md + server-seat-3/orders/30209.md in this account's project); slot granted by the project coordinator.
{
"issue": 30209,
"status": "done",
"branch": "claude/project-thread-txk3tb",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31207",
"head": "59c76e787e7b21dd493272fdd133042ed846a902",
"session": "session_017ihL2f62c1GYk6XzbdtCa4",
"premise_still_valid": true,
"summary": "Row 5 B server half: plugin-sharing mounts GET /api/v1/sharing/shareable-objects on IHttpServer at kernel:ready, listing every registered object for which SharingService.sharingRuleObjectRefusal (the #30621 save-time check, passed in as a function, never copied) answers null, business objects before platform objects, each group by label then name. Admission is SharingRuleService.assertCanManageRules through a new SharingRuleService.listShareableObjects; the door's refusal order follows #31004 (caller, held sign-in 403, anonymous 401, any query 400, non-admin 403; 501 with no rule service, 500 when the engine cannot enumerate). Row 2 is done on main 8ef4d309 (PR #30496, both halves pinned); row 1 measured: the page widget needs no spec, the missing piece is a per-user effective-access read with origins (server arm).",
"tests": "pnpm --filter @objectstack/plugin-sharing test :: exit 0 (70 files, 1464 tests) on 59c76e787e; shareable-objects.test.ts 16/16; sharing-route-ledger.conformance.test.ts 3/3; typecheck :: exit 0. Ablations via scripts/ablation-replace.mjs, each restored with blob == HEAD: verdict filter removed 4F/12P; admission removed 3F/13P (first attempt refused by the tool as a no-op, rerun); anonymous branch disabled 1F; query refusal disabled 1F; business-before-platform comparison removed 3F.",
"gates": "node scripts/pm/dispatch-gates.mjs --commands derived 89 families on head 59c76e787e: all 89 :: exit 0 (list in the PR's Derived gates block); --ran reconciliation :: exit 0 (89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUN). eslint --no-inline-config over the 11 touched .ts/.mjs files :: exit 0 (the package has no lint script). Dogfood route-ledger-live-mount-parity :: exit 0 (8/8). Extra, not derived: pnpm --filter @objectstack/spec run check:generated :: exit 1 under the default 2 GB heap (tsc -p tsconfig.test.json OOM, exit 134, 'failed without diagnostics'), :: exit 0 with NODE_OPTIONS=--max-old-space-size=8192; no packages/spec file in this diff. CI check-runs: not yet read, PR just opened.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"line_budget": "no budget in the order; 13 files, +950/-4: source 436 (routes 199, list 112, ledger 55, plugin wiring 50, rule service 22, sharing-service +11/-4), tests 471 (410 + 61), one-line wirings 12 (dogfood 3, envelope guard 6, cross-package inputs 2, turbo 1), changeset 18",
"files_changed": [
".changeset/30209-sharing-shareable-objects.md",
"packages/plugins/plugin-sharing/src/shareable-objects-routes.ts",
"packages/plugins/plugin-sharing/src/shareable-objects.test.ts",
"packages/plugins/plugin-sharing/src/shareable-objects.ts",
"packages/plugins/plugin-sharing/src/sharing-plugin.ts",
"packages/plugins/plugin-sharing/src/sharing-route-ledger.conformance.test.ts",
"packages/plugins/plugin-sharing/src/sharing-route-ledger.ts",
"packages/plugins/plugin-sharing/src/sharing-rule-service.ts",
"packages/plugins/plugin-sharing/src/sharing-service.ts",
"packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts",
"scripts/check-route-envelope.mjs",
"scripts/cross-package-test-inputs.mjs",
"turbo.json"
],
"deviations": [
"No widget hint on sys_sharing_rule.object_name: the field already declares widget 'object-ref'; an unregistered hint degrades to a text input, so flipping it before the console registers the widget would regress today's picker. See open_questions.",
"Clause-② line in the PR body and changeset reads 'yes (widening)' where the claim's provisional line reads 'no': the diff adds a public HTTP read, as #31004 declared for its sibling door. Metadata-protocol: none, as claimed.",
"PR-body attribution line 2 links this card thread (cmsg_01VmuUhXU9SSUzqJYyXSmYSiFMQNAUTGWk1GeD14KvBfaa), not the seat thread the standing order spells: the session's own attribution instruction wins.",
"PR body says 'Refs #30209', not 'Fixes #30209', per the seat's go message: the card stays open for row 1 and the console picker.",
"Small refactor outside the route: isPlatformObjectSchema extracted in sharing-service.ts from effectiveSharingModel's own test and reused for the list's system flag, so the system-context census reads one ledgered spelling; no behaviour change.",
"Files outside packages/plugins/plugin-sharing: only the four one-line wirings the order names (dogfood parity import, envelope guard MODULES, cross-package-test-inputs, turbo.json)."
],
"mcp_calls": "5 — read only: mcp__github__issue_read x3, ToolSearch x1 (loader), mcp__claude-code-remote__subscribe_pr_activity x1 (PR #31207). No GitHub write tool.",
"api_writes": "3 — git push origin claude/project-thread-txk3tb (several pushes, last 59c76e787e); pr_create via scripts/pm/fleet-write/dispatch.mjs (request fw-20261107T173119Z-fea8a7, run 42396719674, POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/31207/assignees [marchtian], read-back identical); this report via scripts/pm/post-stamped.mjs --comment=30209 (POST /issues/30209/comments)",
"open_questions": [
{
"question": "When and where does sys_sharing_rule.object_name get its widget hint for the new picker?",
"options": [
"A: the ui card that registers the console widget also flips the hint (one line in plugin-sharing's object file), so the field never shows a text box",
"B: flip it now in this PR and accept a text input until the ui card lands"
],
"recommendation": "A, because the field already has a working object-ref picker and an unregistered hint degrades to a text input"
}
],
"security_findings": "withheld",
"out_of_scope_findings": [
"carrier: seat (#30209 row 1) · row 1 split proposal, not filed: (1) server card: per-user effective-access read with origins (default binding / position / direct), e.g. GET /api/v1/security/users/:id/effective-access on plugin-security IHttpServer, built on resolveUserAuthzGrants plus the catalog's position bindings; no spec arm unless served by @objectstack/rest over a spec contract; (2) ui card: a security:effective-access widget (unclaimed namespace, precedent mcp:authorized-assistants) plus a one-line edit in packages/platform-objects/src/pages/sys-user.page.ts; the same ui card can carry row 5's widget hint (open question). Evidence in PR #31207 'Rows 1 and 2'. Dedupe words: effective access, permission set origin, position binding, sys_user page."
]
}
MERGED 2026-11-07T18:57:11Z through the merge queue as 6f017e24a4, head 59c76e787e (second queue run; the first went red on the plugin-auth one-hour boundary test, #31175 / #31212)
row 5, server half
done: GET /api/v1/sharing/shareable-objects lists only objects a rule can take effect on, business objects first; credential and session objects never listed
row 5, console half
#31217 (picker reads the new endpoint; flips the sys_sharing_rule.object_name widget hint in the same PR)
State: this claim ends here. pm:dispatched and the assignee removed and pm:queue restored, so rows 3, 4 and 6 can be claimed or split by their lanes (row 3/4 audit list and config-change detail: server services/audit face plus ui; row 6 queue members: ui).
Closed · 2026-11-07T19:00Z · correction of landing comment 6711667957
That comment's last row was wrong: rows 3, 4 and 6 are not open. Row 3 landed as PR #30620, rows 4 B and 6 B as PR #30728, row 5 C as #30621 (triage 6708449661 recorded this). Every row is now either done on main or carried by its own card:
Activity
objectstack-fleet commentedon Nov 5, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p3 ·
domain:ui·pm:queue· 2026-11-05T03:03Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:ui#6 · os-sales · session_01L6bhgUR8Nu4M7tbtgES7q2
Claim: PM loop round 3 · 2026-11-05T12:21Z
Session:
session_01L6bhgUR8Nu4M7tbtgES7q2Account:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch: the card thread's designated
claude/project-thread-*branch, named in a claim amendment once the thread reports itWorktree:
objectstack-issue-30209Domain:
domain:uiSeat:
domain:ui#6File surface: the rows whose fix lands in
ui/**: row 1 (the user record's 权限集 tab shows effective access via the existingPOST /api/v1/security/explain), row 2 (sharing-rule recipient by name, condition in words), row 3 (audit list record label / localized object names whereui/draws them), row 6 (queue members list on the queue record), their tests, one root.changeset/file. ⛔ row 4 (config-change values: what is secret is a server decision) and ⛔ row 5 (sharing-rule object picker over credential/session objects: security-sensitive, report the reading only). ⛔packages/**. Rows not done are named in the report for the seat to split (stop on breach; explain in the report)Container & model:
M,mode:thread,model: default(dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable),effort: highClause-②: no (a new language-pack key, if a row needs one, is declared by the dev in the PR body and the seat re-reads this line at ACCEPT)
Metadata-protocol: none
Responsibility: n/a — not a defect card
Thread-read: 6648534205
Premise: holds as filed on
b7075d99; the dev re-measures each row onorigin/mainfirst and may ship a subsetSerial constraints cleared: none in flight on the user record tabs, sharing-rule or queue record pages (open PRs read 2026-11-05T12:18Z). No maintainer ruling beyond 「以上都同意,立卡」.
objectstack-fleet commentedon Nov 5, 2026
domain:ui#6 · os-sales · session_01L6bhgUR8Nu4M7tbtgES7q2
席位核对 · Amendment · 2026-11-05T12:24Z · claim 6657861397 branch named
Branch:
claude/project-thread-zr7jt1The card thread's harness-designated branch (a project-thread platform exception to the
claude/issue-<n>-<slug>convention); the dev thread is sessionsession_01L6bhgWs5eCv64CbCPwjWhV. Everything else in claim 6657861397 stands.objectstack-fleet commentedon Nov 5, 2026
domain:ui#6 · os-sales · session_01L6bhgWs5eCv64CbCPwjWhV
os-dev-report
{ "issue": 30209, "status": "done", "branch": "claude/project-thread-zr7jt1", "pr": "https://github.com/objectstack-ai/objectstack/pull/30496", "session": "session_01L6bhgWs5eCv64CbCPwjWhV", "premise_still_valid": true, "summary": "Subset shipped (Refs, not Fixes). Row 2: a sharing rule's record page now names the recipient (record-page faces get the record as dependentValues, so recipient-picker reads recipient_type) and reads the condition in words (filter-condition gains a read face drawing the widget's words, 优先级 等于 紧急; unrepresentable criteria stay JSON). Row 3 (record-label half): RecordPointerCell expands the name field when it is a readable reference, so sys_session sign-in rows read the user's name. Rows 1, 3-rest, 4, 5 and 6 not shipped: rows_not_shipped below, each with its owning lane for the seat to split. No language-pack key added (words reuse filterBuilder.* rows): Clause-②: no.", "rows_not_shipped": [ "row 1 · 林伟's 权限集 tab reads 0 / 暂无相关记录: the tab is page metadata (packages/platform-objects/src/pages/sys-user.page.ts, record:related_list over sys_user_permission_set); effective access needs a page-component vocabulary entry in packages/spec + the page edit in packages/platform-objects, then the ui block · lanes: spec + server, then ui", "row 3 rest · sys_platform_setting_audit (and others) have no zh-CN label rows in packages/platform-objects translations; 'one sign-in writes several rows' and a default view hiding them are the audit writer and the object's list views in packages/** · server lane", "row 4 · not measured (claim ⛔) · server lane", "row 5 · not measured (claim ⛔, reading only) · security lane", "row 6 · sys_queue_member.queue is a text field holding the queue name, not a lookup, so no related list is synthesized; needs a lookup or a sys_queue page with a members list in packages/plugins/plugin-sharing · server lane" ], "tests": "New: fields FilterConditionField.readWords-30209 (3), plugin-detail recordFace.siblingValues-30209 (2), plugin-grid ObjectGrid.recordPointerCell-12608 new describe (2). Positive control: sources restored to base c5800818 → 5 new assertions red, controls green. Ablations via scripts/ablation-replace.mjs, each restored (git diff HEAD empty): DetailSection dependentValues removed 1F/1P; words branch if(false) 2F/1P; $expand spread deleted 1F/4P. Suites fields+plugin-detail+plugin-grid+app-shell dirs: only reds were 4 renderer censuses, enrolled; rerun 36 files / 453 tests green. Type-check turbo --filter fields/plugin-detail/plugin-grid 55/55 (lock VERDICT 0). eslint changed files 0 errors.", "gates": "35 derived dispatch gates exit 0 (vitest run scripts/ SIGKILLed alongside type-check, rerun alone 171 passed VERDICT 0); ui check:spec-symbols, check:i18n-keys (after hook rename), check:unreferenced-sources, check:side-effects-array, check:phantom-deps, check:esm-specifiers, check:i18n-drift, check:new-line-citations, root check:doc-authoring all 0. CI on the PR: pending at report time.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "reads only — mcp__github__issue_read (card + comments); no write tool", "api_writes": "git push to claude/project-thread-zr7jt1 (harness branch); relay pr_create → #30496 (run 42036248962); relay issue comment (this report)", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: PR #30496 Acceptance notes · noted, not filed: Setup navigation and sys_queue labels (Queues, Queue, Display Label) read English under zh-CN — translation coverage in packages/**", "carrier: PR #30496 · noted, not filed: records named by a display_title formula over ids (sys_approval_approver/action/request, sys_user_position, sys_member) still read as ids in pointer cells — server metadata" ] }27 remaining items
objectstack-fleet commentedon Nov 7, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
State: rows 4–6 ruled →
pm:queue· 2026-11-07T14:49Z⛔ Not a claim.
needs-user-decisioncomes off, on the maintainer's 「可以」 (2026-11-07).pm:queuefordomain:server; p3 kept.Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B
Claim: PM loop round 2 · rows 5 B (server half), with rows 1 and 2 measured · 2026-11-07T15:40Z
Session:
session_017ihL2dFb2QdZEHEJ83cR2BAccount:
marchtianBranch:
claude/project-thread-txk3tbWorktree:
objectstack-issue-30209(the card thread's own checkout)Domain:
domain:serverSeat:
domain:server#3File surface:
packages/plugins/plugin-sharing/**(row 5 B server half: a read-only shareable-objects route + thesys_sharing_ruleobject field widget hint, tests, translations), the route-ledger / envelope-guard / live-mount-parity wiring lines the gates name,.changeset/**; rows 1 and 2 are measured and reported only. ⛔packages/spec/**,ui/**(stop on breach; explain in the report)Container & model:
M,mode:thread(card thread cmsg_01VmuUhXU9SSUzqJYyXSmYSiFMQNAUTGWk1GeD14KvBfaa of this account's project),model: TIER_DEFAULT — dispatch-gates --tier: no path-derived mandate,effort: session default — card-thread effort is set by the maintainer only; the seat's reading is high (M; a new read route on the sharing admin surface)Clause-②: no (provisional) — an additive read route and a widget hint on the existing free widget string; the dev states the arm from the diff
Metadata-protocol: none
Responsibility: n/a — enhancement card (Setup walkthrough, epic #26676)
Thread-read: 6708449661
Premise: holds — rows 3, 4 B, 5 C, 6 B landed (PRs #30620, #30728, #30621) and row 2 + the record-name half of row 3 in PR #30496; triage 6708449661 re-queued rows 1, 2 and 5 B under ruling 6670358877.
describeFilterGroupis on main8ef4d3090, so row 2 is measured first and may already be doneSerial constraints cleared: no open PR touches
packages/plugins/plugin-sharing/**(open PR list read now); #30621 (row 5 C, the save-time refusal this route must share its predicate with) is closedThe dispatch order is the card thread's opening message (files
server-seat-3/orders/_standing.md+server-seat-3/orders/30209.mdin this account's project); slot granted by the project coordinator.objectstack-fleet commentedon Nov 7, 2026
domain:server#3 · marchtian · session_017ihL2f62c1GYk6XzbdtCa4
os-dev-report
{ "issue": 30209, "status": "done", "branch": "claude/project-thread-txk3tb", "pr": "https://github.com/objectstack-ai/objectstack/pull/31207", "head": "59c76e787e7b21dd493272fdd133042ed846a902", "session": "session_017ihL2f62c1GYk6XzbdtCa4", "premise_still_valid": true, "summary": "Row 5 B server half: plugin-sharing mounts GET /api/v1/sharing/shareable-objects on IHttpServer at kernel:ready, listing every registered object for which SharingService.sharingRuleObjectRefusal (the #30621 save-time check, passed in as a function, never copied) answers null, business objects before platform objects, each group by label then name. Admission is SharingRuleService.assertCanManageRules through a new SharingRuleService.listShareableObjects; the door's refusal order follows #31004 (caller, held sign-in 403, anonymous 401, any query 400, non-admin 403; 501 with no rule service, 500 when the engine cannot enumerate). Row 2 is done on main 8ef4d309 (PR #30496, both halves pinned); row 1 measured: the page widget needs no spec, the missing piece is a per-user effective-access read with origins (server arm).", "tests": "pnpm --filter @objectstack/plugin-sharing test :: exit 0 (70 files, 1464 tests) on 59c76e787e; shareable-objects.test.ts 16/16; sharing-route-ledger.conformance.test.ts 3/3; typecheck :: exit 0. Ablations via scripts/ablation-replace.mjs, each restored with blob == HEAD: verdict filter removed 4F/12P; admission removed 3F/13P (first attempt refused by the tool as a no-op, rerun); anonymous branch disabled 1F; query refusal disabled 1F; business-before-platform comparison removed 3F.", "gates": "node scripts/pm/dispatch-gates.mjs --commands derived 89 families on head 59c76e787e: all 89 :: exit 0 (list in the PR's Derived gates block); --ran reconciliation :: exit 0 (89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUN). eslint --no-inline-config over the 11 touched .ts/.mjs files :: exit 0 (the package has no lint script). Dogfood route-ledger-live-mount-parity :: exit 0 (8/8). Extra, not derived: pnpm --filter @objectstack/spec run check:generated :: exit 1 under the default 2 GB heap (tsc -p tsconfig.test.json OOM, exit 134, 'failed without diagnostics'), :: exit 0 with NODE_OPTIONS=--max-old-space-size=8192; no packages/spec file in this diff. CI check-runs: not yet read, PR just opened.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "line_budget": "no budget in the order; 13 files, +950/-4: source 436 (routes 199, list 112, ledger 55, plugin wiring 50, rule service 22, sharing-service +11/-4), tests 471 (410 + 61), one-line wirings 12 (dogfood 3, envelope guard 6, cross-package inputs 2, turbo 1), changeset 18", "files_changed": [ ".changeset/30209-sharing-shareable-objects.md", "packages/plugins/plugin-sharing/src/shareable-objects-routes.ts", "packages/plugins/plugin-sharing/src/shareable-objects.test.ts", "packages/plugins/plugin-sharing/src/shareable-objects.ts", "packages/plugins/plugin-sharing/src/sharing-plugin.ts", "packages/plugins/plugin-sharing/src/sharing-route-ledger.conformance.test.ts", "packages/plugins/plugin-sharing/src/sharing-route-ledger.ts", "packages/plugins/plugin-sharing/src/sharing-rule-service.ts", "packages/plugins/plugin-sharing/src/sharing-service.ts", "packages/qa/dogfood/test/route-ledger-live-mount-parity.dogfood.test.ts", "scripts/check-route-envelope.mjs", "scripts/cross-package-test-inputs.mjs", "turbo.json" ], "deviations": [ "No widget hint on sys_sharing_rule.object_name: the field already declares widget 'object-ref'; an unregistered hint degrades to a text input, so flipping it before the console registers the widget would regress today's picker. See open_questions.", "Clause-② line in the PR body and changeset reads 'yes (widening)' where the claim's provisional line reads 'no': the diff adds a public HTTP read, as #31004 declared for its sibling door. Metadata-protocol: none, as claimed.", "PR-body attribution line 2 links this card thread (cmsg_01VmuUhXU9SSUzqJYyXSmYSiFMQNAUTGWk1GeD14KvBfaa), not the seat thread the standing order spells: the session's own attribution instruction wins.", "PR body says 'Refs #30209', not 'Fixes #30209', per the seat's go message: the card stays open for row 1 and the console picker.", "Small refactor outside the route: isPlatformObjectSchema extracted in sharing-service.ts from effectiveSharingModel's own test and reused for the list's system flag, so the system-context census reads one ledgered spelling; no behaviour change.", "Files outside packages/plugins/plugin-sharing: only the four one-line wirings the order names (dogfood parity import, envelope guard MODULES, cross-package-test-inputs, turbo.json)." ], "mcp_calls": "5 — read only: mcp__github__issue_read x3, ToolSearch x1 (loader), mcp__claude-code-remote__subscribe_pr_activity x1 (PR #31207). No GitHub write tool.", "api_writes": "3 — git push origin claude/project-thread-txk3tb (several pushes, last 59c76e787e); pr_create via scripts/pm/fleet-write/dispatch.mjs (request fw-20261107T173119Z-fea8a7, run 42396719674, POST /repos/objectstack-ai/objectstack/pulls draft + POST /issues/31207/assignees [marchtian], read-back identical); this report via scripts/pm/post-stamped.mjs --comment=30209 (POST /issues/30209/comments)", "open_questions": [ { "question": "When and where does sys_sharing_rule.object_name get its widget hint for the new picker?", "options": [ "A: the ui card that registers the console widget also flips the hint (one line in plugin-sharing's object file), so the field never shows a text box", "B: flip it now in this PR and accept a text input until the ui card lands" ], "recommendation": "A, because the field already has a working object-ref picker and an unregistered hint degrades to a text input" } ], "security_findings": "withheld", "out_of_scope_findings": [ "carrier: seat (#30209 row 1) · row 1 split proposal, not filed: (1) server card: per-user effective-access read with origins (default binding / position / direct), e.g. GET /api/v1/security/users/:id/effective-access on plugin-security IHttpServer, built on resolveUserAuthzGrants plus the catalog's position bindings; no spec arm unless served by @objectstack/rest over a spec contract; (2) ui card: a security:effective-access widget (unclaimed namespace, precedent mcp:authorized-assistants) plus a one-line edit in packages/platform-objects/src/pages/sys-user.page.ts; the same ui card can carry row 5's widget hint (open question). Evidence in PR #31207 'Rows 1 and 2'. Dedupe words: effective access, permission set origin, position binding, sys_user page." ] }Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B
Landed · 2026-11-07T18:58Z
6f017e24a4, head59c76e787e(second queue run; the first went red on the plugin-auth one-hour boundary test, #31175 / #31212)GET /api/v1/sharing/shareable-objectslists only objects a rule can take effect on, business objects first; credential and session objects never listedsys_sharing_rule.object_namewidget hint in the same PR)main8ef4d309by #30496State: this claim ends here.
pm:dispatchedand the assignee removed andpm:queuerestored, so rows 3, 4 and 6 can be claimed or split by their lanes (row 3/4 audit list and config-change detail: server services/audit face plus ui; row 6 queue members: ui).objectstack-fleet commentedon Nov 7, 2026
domain:server#3 · marchtian · session_017ihL2dFb2QdZEHEJ83cR2B
Closed · 2026-11-07T19:00Z · correction of landing comment 6711667957
That comment's last row was wrong: rows 3, 4 and 6 are not open. Row 3 landed as PR #30620, rows 4 B and 6 B as PR #30728, row 5 C as #30621 (triage 6708449661 recorded this). Every row is now either done on
mainor carried by its own card:So this card closes as completed instead of going back to
pm:queue. Follow-up work lives on #31215, #31216 and #31217.