Skip to content

Campaign-final checkpoint

campaign-final is a non-sending migration CLI command and a disabled-by-default chart operation. It closes an approved campaign only after reconciling the mounted Auth0 export against current PM Investigators and the Identity ledger, running the existing import verifier, and checking that all eligible deliveries are settled. Unmatched, duplicate or missing mappings fail closed; this version accepts no mapping exceptions. Unknown sends anywhere in the ledger, in-flight claims, missing canary approval and incomplete campaign evidence prevent completion.

Reconciliation compares imported security provenance as well as row mappings: email, identity classification, blocking/deactivation, provider email, mapping origin, last login, and every source identity's provider/subject/email/verification assertion. A same-count export with changed provenance is not interchangeable with the imported export. Reader observation timestamps are excluded because reading the unchanged export again necessarily changes that timestamp. The comparison uses immutable ledger provenance, not mutable local password or email confirmation state that a successful campaign redemption may legitimately change. Every ledger row must also match its live Identity user's exact identity ID, Auth0 source ID and Investigator ID; a merely non-null live mapping is not enough. Live authorization groups must equal the normalized current Investigator roles, and Google/merged accounts must retain the expected imported Google subject. Temporary lockouts leave unfinished recipients in the remaining cohort: only provenance-confirmed blocked/deactivated accounts or reconciled terminal dispositions can remove that delivery obligation.

The control Secret needs a final-evidence key, bound through SYRF__CampaignFinalEvidence__File. The document is private operator input, never a GitOps value or command-line argument. Its JSON schema requires every field:

Field Required value
schemaVersion 1
runHandle Exact secret-mounted handle of the active campaign
controlGeneration Current durable generation; update after resume
templateVersion Current reviewed campaign template generation
exportSha256 Lowercase SHA-256 of the exact mounted export bytes
forcedResetGuidanceReady true after reviewing forced-reset guidance and synthetic redemption evidence
optionalMfaPasskeyReenrolmentPlanReady true after reviewing native optional MFA/passkey re-enrolment instructions
rollbackEvidenceReady true after reviewing the retained rollback evidence for this campaign

Unknown JSON properties, absent fields and invalid input fail closed. The three booleans are operator attestations: the command does not pretend to independently prove mailbox receipt, a browser redemption, or a backup restore. Keep their review records with the campaign evidence, and bind them to the same export, run, control generation and template. They do not waive reconciliation or authorize activation. The later readiness percentages and S13 cutover gates still apply.

The Job mounts Identity and PM connection inputs, the export, run handle and final evidence. It has no SES credentials or DataProtection material. Its output sink is writable ephemeral storage; retain the aggregate JSON report and Job completion record before a subsequent GitOps sync prunes that Job. The report includes a schema version, export digest, control/template generations, aggregate imported, eligible, remaining, sent, retired and pending-unknown counts, and the outcome. It excludes handles, addresses, identities, credentials and wall-clock timestamps. Repeating against unchanged state produces the same report and sends no mail. If report writing fails after the durable transition, rerun the same checkpoint to recover the report; do not restart delivery.

S12 now has both catalogue paths: import-rerun invokes import --require-no-writes with a declared zero-write invariant, and campaign-final invokes the checkpoint described here. Before importing, the rerun requires a readable declaration with rerun-writes=0; an absent, malformed, or nonzero declaration is rejected without database writes. This is an executed idempotence assertion, not a read-only preview or a transaction that prevents changes: a validly declared rerun still executes the importer. If it creates users/ledger rows or repairs lockout eligibility/reservations, it exits nonzero and reports the aggregate changes. It does not roll those repairs back. Investigate the failed idempotency evidence and repeat against the corrected, unchanged inventory. Unacknowledged write concern (w=0) is rejected before importing: an unknown repair result cannot establish zero writes. The sequence remains import → verify → import-rerun, followed by canary → approval → bounded batches → stop/status → resume → remaining batches → campaign-final → idempotent-rerun. Each operation is a separate reviewed GitOps commit/sync with retained evidence. Imports and campaign writes must be quiescent during the final checkpoint; no final report grants permission to mutate the reconciled inventory.

Automated coverage includes real-Mongo partial/resumed campaigns, stale generation refusal, in-flight and unknown-send refusal, source-to-PM mapping drift, production mounted-input execution, privacy-safe deterministic reports, repeated completion without sends/writes, and Helm argv/declaration/input isolation assertions. Live synthetic rehearsal and production campaign execution remain separate evidence gates; repository tests are not records of those operations.