Found during the live dogfood verification of #2572 (PR #2604 / #2615) on the showcase stack (framework/examples/app-showcase, Project "Website Relaunch", showcase_budget_approval flow).
Symptom
When a record is approval-locked, DetailView's approval-lock band ("Locked for approval" + the recall affordance) never renders on this backend — even though the lock is real: the server rejects writes with RECORD_LOCKED, and the inline-edit session correctly locks (pencils hidden, enter() no-op, save bar locked).
Cause
The band keys off the record's own field ONLY:
packages/plugin-detail/src/DetailView.tsx → const approvalStatus = data?.approval_status; const isLocked = approvalStatus === 'pending' || approvalStatus === 'in_approval';
But the framework does not materialize an approval_status field on the record — verified live: the record payload after the flow opened the approval carries no such key, while GET /api/v1/approvals/requests?object=…&recordId=… returns the request with status: "pending". The lock signal exists only in the approvals API.
RecordDetailView (app-shell) already handles this for the inline-edit path since #2615's base PR: its approvalLocked is approval_status ∈ {pending, in_approval} OR !!approvals.pendingRequest (useRecordApprovals). With the field-only signal, the lock would never have engaged on this backend at all — the dual signal is what made #2572 item 2 work.
Suggested direction
Either (pick one, don't do both):
- Renderer: thread the host's
approvalLocked (or the pending request) into DetailView so the band renders from the same signal the session lock uses — e.g. a locked/lockedReason prop supplied by RecordDetailView, keeping DetailView itself DataSource-agnostic; or
- Contract-first (framework): decide that the platform SHOULD materialize
approval_status on locked records (spec-level decision), in which case this is a framework issue and the renderer stays as-is.
Given AGENTS.md #0.1 (fix the producer, not the renderer), option 2 deserves a deliberate look first; option 1 is still renderer-correct because the approvals API is an official signal, not a lenient fallback.
Impact
Cosmetic-but-confusing: users on request-tracked backends see editing silently disabled with no explanation banner (the save-bar lockedHint tooltip only shows if a session was already open). Low priority — the lock behavior itself is correct.
Found during the live dogfood verification of #2572 (PR #2604 / #2615) on the showcase stack (
framework/examples/app-showcase, Project "Website Relaunch",showcase_budget_approvalflow).Symptom
When a record is approval-locked,
DetailView's approval-lock band ("Locked for approval" + the recall affordance) never renders on this backend — even though the lock is real: the server rejects writes withRECORD_LOCKED, and the inline-edit session correctly locks (pencils hidden,enter()no-op, save barlocked).Cause
The band keys off the record's own field ONLY:
packages/plugin-detail/src/DetailView.tsx→const approvalStatus = data?.approval_status; const isLocked = approvalStatus === 'pending' || approvalStatus === 'in_approval';But the framework does not materialize an
approval_statusfield on the record — verified live: the record payload after the flow opened the approval carries no such key, whileGET /api/v1/approvals/requests?object=…&recordId=…returns the request withstatus: "pending". The lock signal exists only in the approvals API.RecordDetailView(app-shell) already handles this for the inline-edit path since #2615's base PR: itsapprovalLockedisapproval_status ∈ {pending, in_approval} OR !!approvals.pendingRequest(useRecordApprovals). With the field-only signal, the lock would never have engaged on this backend at all — the dual signal is what made #2572 item 2 work.Suggested direction
Either (pick one, don't do both):
approvalLocked(or the pending request) intoDetailViewso the band renders from the same signal the session lock uses — e.g. alocked/lockedReasonprop supplied byRecordDetailView, keepingDetailViewitself DataSource-agnostic; orapproval_statuson locked records (spec-level decision), in which case this is a framework issue and the renderer stays as-is.Given AGENTS.md #0.1 (fix the producer, not the renderer), option 2 deserves a deliberate look first; option 1 is still renderer-correct because the approvals API is an official signal, not a lenient fallback.
Impact
Cosmetic-but-confusing: users on request-tracked backends see editing silently disabled with no explanation banner (the save-bar
lockedHinttooltip only shows if a session was already open). Low priority — the lock behavior itself is correct.