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 needSeamward gives youWhere
Something to tell supportAn impact summary built from the incident's evidenceIncident overview, CLI
The affected recordsA list with each record's recovery statusCLI export
Which of your accountsCounts per account, as hashes you resolve locallyIncident overview, CLI
The missed events processedA recovery plan and a local runner that calls your re-sendCLI
Proof it workedRecords moving from missing to recovered as outcomes are observedIncident 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.txt

account-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 recordMeaning
observationIdSeamward's identifier for the source observation
occurredAtWhen the source event happened
eventType, operationWhat it was, as labels
statusmissing while the expected outcome is absent, recovered once it is observed
sourceEventIdHashKeyed hash of the provider's event identifier
idempotencyKeyHash, businessObjectIdHash, accountRefHashKeyed 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.mjs

Code 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 --json

The 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 resolve for 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