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
test: prove pause, orphan recovery and provisioning against a live project
Three claims the README makes that had never run against real Hookdeck.
All three now do, and the live suite is 23/23.
Pause on shutdown. A clean stop pauses the connection (`paused_at` set),
an event arriving while paused is held at HOLD rather than failed, and
restarting releases it — delivered SUCCESSFUL with the UNPAUSE trigger.
This is the zero-loss-restart claim, end to end. Driven through the
Gateway's own shutdown rather than the tool, because `hookdeck_pause`
from a CLI process correctly refuses: it cannot record the state it would
need to.
Boot recovery re-queuing an orphan. The earlier run never exercised it —
"no row was left running (dispatch completed first)" — because wake
dispatch finishes faster than a crash can interrupt it. The precondition
is therefore planted: a running row owned by a dead instance, for a real
event id. Everything after it is real, and that is the part worth
testing — reconciliation finds it, calls POST /events/{id}/retry against
a real event, Hookdeck redelivers, and the ledger reaches runCount 2.
Provisioning. The quickstart's first action, never run live until now.
The plugin creates its own connection from config, with a retry rule
covering every status it emits (400, 401, 404, 408, 409, 429, 500-599)
and path_forwarding_disabled pinned true.
Two harness faults found and fixed, one of which mattered: the teardown
swept only the harness's own `openclaw-e2e-` prefix, but the plugin names
what it provisions `openclaw-<routeId>`, so the first provisioning run
left a destination behind in the project. Deleted, and the sweep now
covers both. The other was asserting the connection name matched the
source name, which it never does.
Docs now state plainly what is and is not proven live. Still not covered:
taskflow and agent dispatch, route filters, http transport, the CLI
version gate, and provider verification at the source — that last needs a
provider secret, which is dashboard-only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/durability.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -56,3 +56,11 @@ What it cannot do is recover anything Hookdeck has already aged out — 3 days o
56
56
## Malformed bodies never reach the plugin
57
57
58
58
Verified end to end: Hookdeck rejects an unparseable JSON body **at the edge**, answering the sender `400` with `rejection_cause: UNPARSABLE_JSON` and creating no event. The plugin's own `malformed_json` handling is therefore defence in depth rather than a path real traffic takes — it covers a body that survives the edge and fails here, such as one that is valid JSON but not valid UTF-8.
59
+
60
+
## What has been proven against a live project
61
+
62
+
`npm run test:e2e` runs 23 scenarios against a real Hookdeck project — a real source, a tunnel supervised by the plugin itself, real events and real retries — creating everything under a scoped name and deleting it afterwards.
63
+
64
+
Covered: signature verification of a real delivery; the ledger row that follows it; a manual retry admitted rather than suppressed; a malformed body rejected at Hookdeck's edge; an event stranded by an outage, replayed on reconnect, and confirmed recovered by the batch's own counts; a clean shutdown pausing the connection, an event held at `HOLD`, and its release on restart; boot recovery finding work a dead process left `running` and asking Hookdeck to redeliver it; the plugin provisioning its own connection with a retry rule covering every status it emits; and `hookdeck_doctor` reading the project match and the verification state from real data.
65
+
66
+
Not covered live, and honest about it: `taskflow` and `agent` dispatch, route filters, `http` transport, the CLI version gate, and provider signature verification at the source — that last one needs a real provider secret, which is dashboard-only.
0 commit comments