Skip to content

feat(approvals): recall endpoint + business-readable inbox contract#1728

Merged
os-zhuang merged 1 commit into
mainfrom
feat-approvals-recall-inbox-contract
Jun 11, 2026
Merged

feat(approvals): recall endpoint + business-readable inbox contract#1728
os-zhuang merged 1 commit into
mainfrom
feat-approvals-recall-inbox-contract

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

E2E review of the showcase Approvals Inbox surfaced four service-level gaps. This PR fixes the backend half; the Console UI revamp that consumes it lands in objectui.

  • Recall was a dead button. The contract declares recalled/recall, the Console renders a Recall button, but neither the service nor REST implemented it — every click 404'd. Adds ApprovalService.recall() (submitter-only, audited recall action, status-field mirror, resumes the owning flow run down the reject branch with output.decision='recall' — the engine has no run-cancel primitive, and leaving the run suspended forever would leak it) plus POST /approvals/requests/:id/recall with the same error mapping as approve/reject.
  • submitted_at never existed. The inbox showed in every time cell and its newest-first sort compared empty strings. Rows now expose submitted_at as an alias of created_at.
  • Rows were machine-speak. flow:manager_review, opaque record ids, raw user ids. The engine now seeds $flowName / $flowLabel variables (mirroring $runId), the approval node snapshots authored flow/node labels onto node_config_json (no schema migration), and rows surface process_label / step_label with a prettified fallback for legacy rows.
  • No display enrichment. listRequests/getRequest now resolve record_title (schema displayNameField, falling back to the payload snapshot when the record is gone) and submitter_name (sys_user by id or email), batched one query per distinct object.

Test plan

  • plugin-approvals: 43 tests (11 new: recall permissions/state/resume/mirror, submitted_at alias, label snapshot + fallback, enrichment incl. payload fallback and email submitter) ✅
  • service-automation: 180 tests ✅
  • E2E against the showcase app: recall via REST returns 200 → status recalled, audit trail submit → recall, suspended run resumed; new budget-approval requests carry process_label: "Project Budget Approval" / step_label: "Manager Review"; legacy rows enrich with record titles and submitter names ✅

🤖 Generated with Claude Code

The Console approvals inbox surfaced four service-level gaps (found via
e2e review of the showcase app):

- Recall was advertised in the contract (status 'recalled', action
  'recall') and rendered in the Console UI, but never implemented — the
  button always died with HTTP 404. Implement ApprovalService.recall()
  (submitter-only, audits a 'recall' action, mirrors the status field,
  resumes the owning flow run down the reject branch with
  output.decision='recall' since the engine has no run-cancel
  primitive) and register POST /approvals/requests/:id/recall.

- Rows never carried submitted_at; the inbox showed "—" for every
  request and its newest-first sort compared empty strings. Expose
  submitted_at as an alias of created_at on the row mapper.

- Requests displayed machine names (flow:manager_review, opaque record
  ids, raw user ids). Seed $flowName/$flowLabel into engine variables,
  snapshot authored flow/node labels onto node_config_json (no schema
  migration), and surface process_label/step_label with a prettified
  fallback for legacy rows. Enrich listRequests/getRequest with
  record_title (schema displayNameField, payload-snapshot fallback) and
  submitter_name (sys_user by id or email), batched per object.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Building Building Preview, Comment Jun 11, 2026 1:32pm

Request Review

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant