Skip to content

docs(adr-0044): the revise pause must be service-owned — record why the generic wait reverses (#3823) - #3892

Merged
os-zhuang merged 2 commits into
mainfrom
claude/run-resume-auth-gate-w67lvk
Jul 28, 2026
Merged

docs(adr-0044): the revise pause must be service-owned — record why the generic wait reverses (#3823)#3892
os-zhuang merged 2 commits into
mainfrom
claude/run-resume-auth-gate-w67lvk

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Design decision-of-record for #3823, before any code moves — so the fix lands against a settled design rather than inventing one in the PR. Docs-only.

Why an amendment, not a patch

ADR-0044 D3 routes the revise edge into an ordinary author-placed wait, chosen to reuse the durable pause already shipped for timers/signals. That was sound under the information ADR-0044 had: resume(runId) then had no authorization model, so which node the run is parked on carried no security weight.

#3801 changed that — a node's descriptor now declares resumeAuthority, and an approval pause is refused to anyone but its owning service. New information reversing an earlier trade-off, not a defect in the original call. The consequence, demonstrated in #3823 with a repro on the real engine:

  1. a raw resume(runId) of the revise-window run walks the resubmit back-edge with no submitter check and no resubmit audit row (empty body suffices); and
  2. when a colliding pending request exists — the case resubmit refuses with DUPLICATE_REQUEST specifically to keep the run alive — the raw resume bypasses that guard, the approval node's re-entry fails after the suspension is consumed, and the run is permanently destroyed.

What the amendment records

  • The revise edge targets a dedicated service-owned pause (a node type carrying resumeAuthority: 'service', or the approval node re-suspending in a revise mode). Still visible on the canvas and in run logs; no longer raw-resumable, so the existing automation: the generic run-resume route needs an authorization gate keyed on the suspended node #3801 gate covers it with no new machinery.
  • This answers ADR-0044's own objection to the alternative — "hides a state machine inside one node, invisible to the canvas" — which was against re-suspending inside the approval node, not against a dedicated node. The real axis was reuse-vs-a-new-type, not visibility-vs-enforcement.
  • Publish-time graph-lint rejects a revise edge wired into a bare wait — the previously-recommended shape becomes un-authorable. Decisive for a metadata-driven platform: an AI author following the original D3 sketch would generate the vulnerable graph verbatim, since nothing in the metadata expressed that the wait sat in a privileged position. Making the wrong shape unrepresentable is the only fix that survives AI authoring.
  • Deferred, not built (ADR-0049 posture): a fail-closed resumeAuthority default (every future pausing node is currently fail-open) and a per-suspension owner claim (the Step Functions task-token shape) — with the caveat that such a claim must not be inherited by a downstream screen, or it breaks screen flows.

A mainstream-engine survey (Salesforce / ServiceNow / Camunda / Temporal / Step Functions — none exposes a generic node-type-agnostic resume to untrusted callers) is included as the rationale for why the generic resume door is the outlier and how the platform would generalise if a third case appears.

Inline supersede-notes at D3 and the rejected-alternative bullet point to the amendment; the Status line flags it.

No changeset (docs-only, no npm-consumer change). check:doc-authoring clean.


Generated by Claude Code

…he generic `wait` reverses (#3823)

ADR-0044 D3 routes the `revise` edge into an ordinary author-placed `wait`,
chosen for reuse of the already-shipped durable pause. #3801 later made
`resume` authorization-bearing (a node's descriptor declares `resumeAuthority`,
and an `approval` pause is refused to anyone but its owning service). That
reframes the D3 trade-off: a generic node in a service-owned position is exactly
what a type-keyed gate cannot see.

Demonstrated in #3823 (repro on the real engine): a raw resume of the
revise-window run walks the resubmit back-edge with no submitter check and no
`resubmit` audit row, and — when a colliding pending request exists — bypasses
the `DUPLICATE_REQUEST` guard that keeps the run alive, permanently destroying
it.

Records the decision of record before any code moves:
- the `revise` edge targets a DEDICATED service-owned pause (still visible on
  the canvas, no longer raw-resumable) — which answers the original "hides a
  state machine" objection: that was against re-suspending inside the approval
  node, not against a dedicated node type. The real axis was reuse-vs-a-new-type.
- publish-time graph-lint rejects a `revise` edge wired into a bare `wait`, so
  the vulnerable shape is un-authorable — the only fix that survives AI authoring.
- fail-closed descriptor default and a per-suspension owner claim are recorded
  as directions, deliberately not built (ADR-0049 posture).

Inline supersede-notes at D3 and the rejected-alternative bullet point to the
amendment. No code change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gvN32u1EiuvY9uQEMJiMR
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 28, 2026 2:51pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation size/m labels Jul 28, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review July 28, 2026 16:03
@os-zhuang
os-zhuang merged commit b1614d6 into main Jul 28, 2026
14 checks passed
@os-zhuang
os-zhuang deleted the claude/run-resume-auth-gate-w67lvk branch July 28, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants