Recovery
Finding a failure is half the job. The other half is cleaning up: which records were affected, which of your customers they belong to, getting the missed events processed, and telling the people who ask. Seamward gives you the lists and the summary. Your team does the re-sending, in your own environment.
| You need | Seamward gives you | Where |
|---|---|---|
| Something to tell support | An impact summary built from the incident's evidence | Incident overview, CLI |
| The affected records | A list with each record's recovery status | CLI export |
| Which of your accounts | Counts per account, as hashes you resolve locally | Incident overview, CLI |
| The missed events processed | A recovery plan and a local runner that calls your re-send | CLI |
| Proof it worked | Records moving from missing to recovered as outcomes are observed | Incident overview, CLI |
What Seamward holds, and what it does not
Seamward never received your identifiers. The collector hashes each one in your process with your hash key, so what Seamward can list is hashes: of the source event, of the record, of the account. Every document on this page contains hashes, times and labels only.
Turning a hash back into a record or an account name is done on your machine, by hashing your own identifiers with the same key and comparing. The CLI does this for you and sends nothing: the key is read from the SEAMWARD_HASH_KEY environment variable and the files stay local.
Seamward also re-sends nothing and calls none of your systems. It is observe-only before an incident and after one.
The impact summary
Every incident's Overview has an Impact and recovery card. Its summary is written for people who do not read evidence:
Code example
Applications webhook: expected records were not created after events that were accepted. First seen on 4 October 2026 at 03:10 UTC, last seen on 4 October 2026 at 09:15 UTC. 412 records are affected across 14 of your accounts. 409 have been recovered and 3 are still missing. A fix is deployed and recovery is being verified.It is built from a template, so every figure in it is a count or a date from the incident's evidence. No model writes or rewrites it. Copy summary puts it on your clipboard, and anyone who can read incidents can read it.
seamward incidents impact returns the same summary with the facts it was built from.
Affected accounts
To see which of your customers an incident affects, report an account reference from the collector: your own identifier for the customer or account a record belongs to. See the collector reference. It is sent only as a keyed hash.
The card then shows how many of your accounts are affected and, for the 50 most affected, how many records each has and how many are still missing. Accounts appear as hashes. To put names to them:
Code example
seamward incidents export inc_example --connection int_example --workspace acme --out records.jsonexport SEAMWARD_HASH_KEY="<the hash key your collector uses>"seamward hashes resolve --file records.json --ids account-ids.txtaccount-ids.txt is your own list of account identifiers, one per line. The output counts affected and still-missing records per identifier and says how many account hashes matched none of them.
Without an account reference the card says none is reported, and counts are per record only.
The affected records
seamward incidents export writes one seamward.affected-records/1 file:
| Field per record | Meaning |
|---|---|
observationId | Seamward's identifier for the source observation |
occurredAt | When the source event happened |
eventType, operation | What it was, as labels |
status | missing while the expected outcome is absent, recovered once it is observed |
sourceEventIdHash | Keyed hash of the provider's event identifier |
idempotencyKeyHash, businessObjectIdHash, accountRefHash | Keyed hashes, or null when not reported |
totals gives affected, missing, recovered and distinct accounts for the whole incident. Add --status missing to export only what is still missing. An incident about duplicated records, or records that left their declared state order, lists its records as affected and later cleared instead: nothing is missing, so it has no recovery plan, and the export is for finding which records to correct. Incidents that compare totals (counts, amounts and lateness) name no records.
A connected MCP client reads the same summary and list with the get_incident_impact and list_affected_records tools. Each export is recorded in the audit trail.
The list exists for incidents raised by an expected-outcome rule, where each record is a source event. Incidents from the windowed rules (duplicates, counts, amounts, order, lateness) have totals and a summary, and no per-record list.
Request the missed events again
After the fix is deployed, the events that were lost still need processing. seamward recovery plan writes what is still missing, oldest first. seamward recovery run walks that plan and calls a function you supply for each event it can name:
Code example
seamward recovery plan inc_example --connection int_example --workspace acme --out plan.jsonseamward recovery run --plan plan.json --ids source-event-ids.txt --hook ./resend.mjs --dry-runseamward recovery run --plan plan.json --ids source-event-ids.txt --hook ./resend.mjsCode example
// resend.mjs: ask your provider or webhook gateway to deliver one event againexport default async function resend({ sourceEventId }) { await gateway.replay(sourceEventId);}source-event-ids.txt is your own list of the provider's event identifiers for the period, one per line; extra identifiers are ignored. The runner reports how many were requested, any request that failed, and any plan entry none of your identifiers matched.
Your handler must be idempotent
Requesting an event again is safe only if your handler ignores one it has
already processed. Every plan says so in requiresIdempotentHandler. Put a
no-duplicates reconciliation rule on the
connection and a re-drive that creates a record twice raises its own incident.
Where your provider cannot deliver an event again, the plan is still the list of what to repair by hand.
Watching it recover
A record counts as recovered when its expected outcome is observed: the same check that raised the incident. As re-sent events are handled, the card moves from 0 of 412 recovered towards 412 of 412, and the summary changes with it. Export again at any time for the records still missing. The incident itself follows the usual resolution and verification rules.
The progress of one plan
Every plan Seamward hands out is kept under a planId, which recovery plan prints and writes into the plan file. The same set of missing events is the same plan, however often you read it, and an incident keeps its 20 most recent plans.
Code example
seamward recovery status inc_example --connection int_example --workspace acme --jsonseamward recovery status inc_example --connection int_example --workspace acme --plan rplan_example --jsonThe first command lists the incident's plans, newest first, with how many of each plan's events have recovered. The second lists one plan item by item: recovered once the event's expected outcome was observed, pending until then, and unknown if the evidence the item pointed at is no longer held. So after a re-drive of 412 events you can read "409 recovered, 3 pending" for that plan and see which three.
Seamward does not record that an event was requested: it never sees your re-drive. An item's status is what reconciliation observed, so a plan cannot disagree with its incident.
For support and success teams
- Open the incident and use Copy summary. It states what stopped, since when, how many records and accounts, and whether it is fixed.
- The figures are counts from evidence. "Still missing" means the expected record has not been seen yet, not that it is lost.
- Account names are not in Seamward. Ask engineering to run
seamward hashes resolvefor the list of affected customers.
Boundaries
- Seamward does not re-send. Re-drive runs in your environment, through your hook.
- Seamward does not know names. It holds hashes; your key and identifiers never leave your machine.
- The summary is a template. It never states a figure that is not in the evidence, and a test proves it.
- A plan lists up to 1,000 events. Run it, then fetch the next.
- No recovery tables are kept. Recovery status is the reconciliation result itself, read when you ask.
Next steps
- CLI reference: the commands in full.
- Reconciliation rules: what "expected outcome" means.
- Measure the affected scope: a worked example.
