Repository navigation
[finding] The record page draws ManagedByBadge (「身份」 for better-auth objects) outside the page tree, so a host page cannot leave it out #12194
Description
Activity
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsTriage: first grade,
bug·priority:p3·domain:ui·area:records, intopm:queue. Option (a): the badge renders where authoring is offered; no new keyTriage seat (seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-12T07:59Z. ⛔ Not a claim, ⛔ not a dispatch.- Why p3: an end user sees an implementation word (「身份」) on a page a host authored. The maintainer accepted removing it from the cloud workspace page (objectstack-ai/cloud#2773). It is cosmetic.
- Direction, option (a):
ManagedByBadgeis an authoring aid. It renders only for a caller who can author the object, in Studio or with the metadata-authoring capability.- ⛔ Option (b), a declared switch, is not taken. A new spec key for one badge is a new surface, and the renderer can answer the question from the caller's capability.
- Pins: an end user on a record page sees no badge. An authoring caller still sees it.
Clause-②: no.
- addedarea:recordsBusiness objects, records, the views that show data, usable forms, searchBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatand removed
on Oct 12, 2026 objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (as triage
6120170778directs, option (a):ManagedByBadgeis an authoring aid and renders only for a caller who can author the object; ⛔ no new spec key)
Session:session_01G5TSaEwbEQsKMjhzTB4rEd
Account:os-warren
Branch:claude/issue-12194-managed-by-badge-authoring
Worktree:objectui-issue-12194
Domain:domain:ui
Seat:domain:ui#2
File surface, on objectuimain9646e2e:- The badge:
packages/app-shell/src/components/ManagedByBadge.tsx. - Its three render sites, measured with
git grep:packages/app-shell/src/views/RecordDetailView.tsx:3200(the card's site; the card's:2874has drifted),packages/app-shell/src/views/ObjectView.tsx:3883andpackages/app-shell/src/views/RecordFormPage.tsx:346. The authoring gate lands where one rule covers every site, or per site, as the dev measures. - The capability:
useCanAuthorMetadata(packages/app-shell/src/hooks/useCanAuthorMetadata.ts), read, ⛔ not changed. - Co-located tests, and
.changeset/12194-managed-by-badge-authoring.md(@object-ui/app-shellpatch). - ⛔ No new prop, spec key or i18n key.
- (Stop on breach; explain in the report.)
Container & model:M,mode:subagent,model: default tier — dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate"
Clause-②: no
Responsibility:objectui's record page (@object-ui/app-shell RecordDetailView), which draws ManagedByBadge for every caller, outside the page tree, so a host page cannot leave it out | the badge is an authoring aid, and useCanAuthorMetadata already answers who can author | every end user opening a record of a better-auth-managed object, e.g. sys_organization on the cloud workspace page (managedBy better-auth, measured by the cloud seat on an in-process control-plane boot)
Thread-read: 6120170778
Serial constraints cleared: read at 2026-10-12T08:59Z on objectuimain9646e2e: - The four files: the last changes on
maintoRecordDetailView.tsx(a7d4920) andManagedByBadge.tsx(8732846) have landed. No open PR touches any of the four (7 open PRs read). - Seat 1's in-flight cards objectui#12205 (
plugin-form) and console: inline-editing a date-only field in record highlights saves the day before east of UTC — it sends local midnight as a UTC instant (the Edit form sends the plain date) #12206 (plugin-detail) sharearea:recordsbut no file. Epic objectui#7611's territory does not include these files.
Generated by Claude Code
- The badge:
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 12194, "status": "done", "branch": "claude/issue-12194-managed-by-badge-authoring", "pr": "https://github.com/objectstack-ai/objectui/pull/12227", "session": "session_01G5TSaEwbEQsKMjhzTB4rEd", "premise_still_valid": true, "summary": "ManagedByBadge now reads useCanAuthorMetadata() (the server's manage_metadata answer) and renders nothing for a caller who cannot author metadata, per triage option (a). The check sits inside the badge, so the record page (the card's site, which draws the badge in its own chrome above the page tree), the ObjectView list header and the RecordFormPage header follow one rule. No prop, export, spec key or i18n key changed; ManagedByBadge is not exported from @object-ui/app-shell. Premise verified on main 9646e2e (the card's line address has drifted; cited here by content). Measured: (1) the framework's /api/v1/auth/me/permissions always sends a systemPermissions array on its success path (objectstack plugin-hono-server current-user-endpoints.ts at 6a40a09ed), so an end user on a deployment that serves it does NOT see the badge; the check fails open only when the answer omits systemPermissions (security plugin not wired, the endpoint's catch branch) or no permission provider is mounted. The fail-open rule is unchanged and pinned. (2) app-shell has no per-object authoring check; every authoring entry point reads the global capability. (3) All three sites are authoring aids. On the form, the end user's explanation for read-only fields is plugin-form's ClosedAffordanceNotice (objectui#11000), which never reads the badge.", "tests": "New (real view + real MePermissionsProvider via initialPermissions): RecordDetailView.managedByBadgeAuthoring-12194 (5 cases: end user none / author better-auth / CONTROL no managedBy none for both / CONTROL platform none / unreported systemPermissions fails open), ObjectView.managedByBadgeAuthoring-12194 and RecordFormPage.managedByBadgeAuthoring-12194 (3 each: end user none / author sees it / CONTROL no managedBy for both). Run at 4c026221 under the lock: 'Test Files 3 passed (3) / Tests 11 passed (11)'. Reach set, narrowed and declared: every app-shell and console test file importing a badge-drawing view or the shell (git grep, plugin-view's own ObjectView excluded), 166 files, all green: batches at 28ef0f23 '35 passed (35) / 301 passed', '33 passed (33) / 280 passed', '35 passed (35) / 320 passed', '32 passed (32) / 234 passed'; batch at 4c026221 '31 passed (31) / 312 passed'. The only change from 28ef0f23 to 4c026221 is a typing cleanup in one new test file. Full app-shell suite left to CI. Ablation (no file kept): objectstack scripts/ablation-replace.mjs replaced 'if (!canAuthor) return null;' with a marker; on disk anchor x1 to x0, marker x0 to x1, blob 8d5e4835a52d to 1ce4cbfec118, grep -c in-run 1 and 0. Tests import from src relatively, so no build or dist preflight was needed. Predicted in the file headers: only the end-user cases RED. Observed: 'Tests 3 failed | 8 passed (11)', the 3 failures exactly the three end-user cases. Restore proven: blob == HEAD 8d5e4835a52d, git diff HEAD empty, git status clean.", "mcp_calls": "0", "api_writes": "2 relay dispatches (each a POST /repos/objectstack-ai/objectstack/dispatches from this session, executed by fleet-write.yml as objectstack-fleet[bot]): (1) pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12227/assignees [os-warren]; read-back 7146 bytes sent, 7146 stored, identical; (2) comment = POST /repos/objectstack-ai/objectui/issues/12194/comments (this os-dev-report). git push x4 (not REST). No label writes.", "open_questions": [], "out_of_scope_findings": [], "gates": [ "pnpm --filter @object-ui/app-shell type-check → exit 0 at 4c026221, after pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build → exit 0 (29-package upstream closure); tsc -p tsconfig.test.json --listFilesOnly lists all three new test files. The first attempt without the closure built exited 2 on TS2307 for workspace imports: a missing prerequisite, not a measurement", "pnpm --filter @object-ui/app-shell lint (eslint .) → exit 0 at 4c026221", "vitest (new files) → exit 0, 'Tests 11 passed (11)' at 4c026221", "vitest (166-file reach set) → exit 0 in all 5 batches (shas above)", "pnpm check:control-bytes → exit 0 'check-control-bytes: OK (scanned 8459 tracked text file(s); skipped 85 binary).'", "pnpm check:new-line-citations → exit 0 'VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0'", "node scripts/check-changeset-no-major.mjs → exit 0 'No changeset declares a `major` bump.'", "node scripts/check-changeset-presence.mjs → exit 0; check-changeset-fixed / check-changeset-overwrite / check:changeset-claims → exit 0", "check:vi-mock-specifiers / check:vi-mock-inherit / check:vi-mock-override-shape / check:test-path-roots / check:pending-changeset-literals / check-type-check-coverage / check-lint-coverage / check:unreferenced-sources → exit 0 each, at 4c026221", "node scripts/check-governed-queue-guard.mjs --test (8 paths) → exit 0 'NOT GOVERNED'", "NOT MEASURED: check:eager-closure, reason: needs apps/console/dist (exit 2 'No eager-closure report'); the new import hooks/useCanAuthorMetadata is already imported by AppHeader and HomePage. Left to CI", "CI on PR head 4c026221 at report time: in_progress (one read: 42 check runs, 19 success, 3 skipped, 20 in progress, 0 failed)" ], "line_budget": "n/a", "deviations": [ "Commit trailers are the model-free pair (Claude-Session + Co-authored-by: Claude), per the role file and objectui AGENTS.md. The harness reminder asked for a model-named trailer and a different PR footer; the PR body ends with the session-URL footer from the role file.", "Test run narrowed and declared: the new files plus the 166-file reach set. The full app-shell suite is left to CI.", "objectui has no ablation-replace script, so the ablation used objectstack's scripts/ablation-replace.mjs against the objectui worktree.", "The shared lock timed out three times (exit 99, held by sibling issue-12190 running its full app-shell suite). I resumed with the same slot; the results above were taken under the lock.", "Comment-only edits at the three view files' badge sites (inside the claim's surface). The RecordFormPage comment said forms disable inputs for every non-platform bucket. That is not true for config and system-data, so it now names ClosedAffordanceNotice.", "Worktree and node_modules removed after the PR opened; the branch head is 4c026221 on origin." ], "files_changed": [ ".changeset/12194-managed-by-badge-authoring.md (new, @object-ui/app-shell patch)", "packages/app-shell/src/components/ManagedByBadge.tsx", "packages/app-shell/src/views/RecordDetailView.tsx (badge-site comment)", "packages/app-shell/src/views/ObjectView.tsx (badge-site comment)", "packages/app-shell/src/views/RecordFormPage.tsx (badge-site comment)", "packages/app-shell/src/views/RecordDetailView.managedByBadgeAuthoring-12194.test.tsx (new)", "packages/app-shell/src/views/ObjectView.managedByBadgeAuthoring-12194.test.tsx (new)", "packages/app-shell/src/views/RecordFormPage.managedByBadgeAuthoring-12194.test.tsx (new)" ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsACCEPT: PR objectui#12227 (head
4c02622) ·domain:uiseat 2 ·session_01G5TSaEwbEQsKMjhzTB4rEd· 2026-10-12T10:41ZReviewed against GitHub and the diff, not the report. Claim
6121045537; report6122354019.- Shape: draft on
main. The first line isFixes #12194, and no other closing keyword is in the body.Clause-②: no. 8 files, all inside the claim's surface:ManagedByBadge.tsx, comment-only edits at the badge sites of the three views, three new co-located tests, and the changeset. - Contract review: none owed. The diff touches no published surface.
ManagedByBadgeis not re-exported from@object-ui/app-shell's entry, and no prop, export, spec key or language-pack key changes. It touches no governed path (check-governed-merges --pr: NOT governed, 583 lines), and the claim saysClause-②: no. - Direction: this is triage
6120170778's option (a). The gate sits inside the badge, so the record page, the list header and the form page follow one rule. Both hooks run before any early return. - Changeset (
@object-ui/app-shellpatch), checked sentence by sentence against the diff:- the three sites;
- the affordances, the empty-state guidance and the form notice are unchanged;
- the fail-open rule of
useCanAuthorMetadatais unchanged (its file is not in the diff).
- Evidence: CI on
4c02622reads 40 success and 3 skipped (the coverage jobs and dependabot);LintandType Checkaresuccess. The dev's ablation turned exactly the three end-user cases red. - Deviation accepted: the local test run was narrowed to a declared 166-file reach set, and CI then ran the full suite green.
- Landing: ready, then auto-merge, through the merge queue.
Generated by Claude Code
- Shape: draft on
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsLanded ·
domain:uiseat 2 ·session_01G5TSaEwbEQsKMjhzTB4rEd· 2026-10-12T11:09ZPR objectui#12227 merged through the merge queue as
f38a428onmain. Verified by content onorigin/main, not by sha:ManagedByBadge.tsxreadsuseCanAuthorMetadataand returns nothing for a caller who cannot author.RecordDetailView.managedByBadgeAuthoring-12194.test.tsxis present.- Control: objectui#12225's
app-switcher-all-appsis still onmain.
The card was closed by the PR's
Fixesline, andpm:dispatchedis removed in this same act. No follow-up is owed on this card.
Generated by Claude Code
Filed by the
repo:cloud#1seat (sessionsession_01WVbr5J6u8BHh8EyFtcWciH), from the objectstack-ai/cloud#2773 dev report (cloud PR objectstack-ai/cloud#2786). ⛔ Not graded: grading is triage's. ⛔ Not a claim.The claim
The maintainer accepted, for the cloud console's workspace page (
sys_organization), "no 「身份」 badge" (objectstack-ai/cloud#2772 item 1 → objectstack-ai/cloud#2773, acceptance 2). Cloud now ships its ownsys_organizationrecord page (PR objectstack-ai/cloud#2786), but the badge is not part of any page.Evidence (objectui at cloud's pin
d758f2f2)packages/app-shell/src/views/RecordDetailView.tsx:2874rendersManagedByBadgeforobjectDef.managedBy, outside the page tree. The badge ispackages/app-shell/src/components/ManagedByBadge.tsx, with i18nmanagedByBadge.betterAuth.short= 「身份」.sys_organization.managedBy=better-auth, measured on an in-process control-plane boot.Why it matters
An end user on a workspace page sees an implementation word, 「身份」 (the auth library manages this object), with no meaning to them. The badge is useful in Studio and for admins. It is noise on an end-user record page that a host has deliberately authored.
Options (not chosen here)
Delivery note: cloud's objectui-alone pin bumps stop at
82bb1d5842until cloud's framework pin moves to v18 (pin-pair rule, objectstack-ai/cloud#27096116951023).Dedupe: searched objectui for
ManagedByBadge, the betterAuth badge and the 身份 badge on record pages. The only hit, objectui#11866, is a different badge (role).Generated by Claude Code