# Oncall product contract

- **OC-001 — Event identity and alerts.** Persist accepted events separately from alerts and human incidents. Repeated source event IDs return the original receipt; changed bytes with the same identity conflict. A deduplication key groups active alerts only within its source/service/environment; recovery affects the matching alert and never resolves an incident.
- **OC-002 — Routing replay.** Retain routing policy version and explanation at admission. Replay is read-only, returns ordered decisions, and produces no alert, incident or external effect. Unmatched signals remain visible and unowned; suppression reasons remain inspectable.
- **OC-003 — Roles and authority.** Incident changes require an active authorized session. Viewer reads; responder coordinates; admin manages services/policies/members/import. Ingest credentials grant no read or human authority. Bearer and signed intake return only `duplicate`, stored event `id`, source `eventId`, `service`, `observedAt` and `acceptedAt` (201 accepted; 200 deduplicated). Routing decisions, snapshots and alert identities stay behind session-protected read/export doors. Revocation takes effect on the next request. Every mutation enforces current authority server-side.
- **OC-004 — Incident state transitions.** Incident state transitions are explicit. Acknowledgement assigns responsibility. Resolution requires recovery evidence and a summary, independently of alert recovery. Optimistic revision checks reject stale edits. All accepted changes append an attributed timeline transactionally with state.
- **OC-005 — Copied runbooks.** Runbooks are copied into the incident at declaration; future service edits never silently rewrite incident instructions. Follow-ups carry owner, due date, open/completed state and completion evidence. Resolved incidents retain open work and editable review.
- **OC-006 — No outbound incident effects.** No paging provider notification, AI call, production action or Lamp publication occurs in release 1. Configured remote mail sends sign-in links only. Handoffs are minimum summaries with stable identity and visibility; exported draft is explicitly unreviewed. Source links grant no access. External acceptance/delivery/acknowledgement are distinct later records.
- **OC-007 — Native archive.** Native archive preserves services, policies, incident/alert/event/timeline identity and attribution, runbook and follow-up history. Validate schema and references before atomic restore. Invalid restore preserves existing data. Do not export authentication secrets/sessions. Released migrations remain immutable; verify prior-data transitions.
- **OC-008 — User-authored records kept.** No automatic deletion of user-authored incident records. Owner export/restore is supported. Ingress accepts bounded structured fields, no arbitrary raw body storage; request bytes max 64 KiB. No arbitrary remote fetching or runbook execution. Display user content as text, never HTML.
- **OC-009 — Accessible interface.** Keyboard-complete responsive UI, labelled fields, focus-visible controls, status announcements, readable failure states and contrast. A failed write is visible and never shown as saved. UI unavailable must not be described as pager coverage failure because stage 1 supplies no pager.
- **OC-010 — Health and honest commands.** Health checks storage and identifies the deployed version, operating commands describe actual local and hosted effects, and acceptance records distinguish local evidence from remote/provider/pilot outcomes. Capacity promises require measured evidence.

## Admission and authority refinements after independent review

The public intake request keys, authentication modes, field limits, service-ID lookup and a curl example are documented in [Incidents and alerts](docs/incidents.md#send-an-alert-event).

Identity is source + eventId; conflicts compare the normalized allowlisted signal fields (canonical timestamps and trimmed strings), rather than irrelevant JSON whitespace/order or discarded fields. Receipts, admission order, decision snapshot and alert mutation commit atomically. Each signed/bearer source is explicitly scoped to service identities; the service binds its environment. Lifecycle generation is required: trigger and recovery must carry the same generation. Recovery before trigger creates a recovered tombstone; later trigger for that generation records evidence without reopening. Reopening needs a new generation. A delayed recovery can only close its own generation, never a new alert.

Stage 1 routes coordination ownership, with no timed escalation or paging. Replay returns historical decision/ownership/policy/evaluation snapshot beside the proposed current decision in submitted order; it does not claim schedule replay. All active members see all workspace incident data. Admin/responder/viewer permissions differ from incident commander attribution. Any active responder/admin can attest recovery and follow-up evidence; attestation is a human claim, not automatic measurement verification. Archive and restore require current admin authority; handoffs remain internal. Restore replaces application state while preserving the current administrator identity; credentials remain installation-local, other sessions are revoked, clients reload state. Historical and inactive identities are retained.

## Scheduling and held history

- **OC-011 — Calendar-day rotations.** Named-zone calendar-day rotations retain fixed primary/backup member slots. Hand-offs use the wall minute plus integer civil days, not fixed elapsed seconds. Repeated minutes explicitly choose earlier, later or reject; nonexistent/rejected boundaries produce visible gaps. Override intervals include their start and exclude their end; overlap in the same role is rejected. Inactive/viewer/missing members do not shift slots. A duplicated primary/backup assignment leaves backup unavailable.
- **OC-012 — Paging off.** Paging is OFF. Every delivery attempt refuses with an explanation that an independent standby and real-phone drill are required. No paging provider sends, synthetic sends, cron delivery, SMS, voice or push are performed. Existing pager is authoritative. Escalation policies are inspectable configuration data, not active timers.
- **OC-013 — Held history stays historical.** Held synthetic job/receipt/callback identities remain historical data. Restore pauses pending jobs. Historical acknowledgement and explicit cancellation retain attribution; resume and new timer starts refuse while paging is OFF. An acknowledgement never proves recovery.
- **OC-014 — Side-effect-free previews.** Schedule preview, now/next and replay are side-effect-free; actual historical delivery claims remain labelled synthetic. Nothing in this release certifies production delivery.
- **OC-015 — Strict module archives.** Strict module archive validation and atomic replacement remain supported. Imported pending historical jobs pause. Scope and local capacity limits remain explicit.

## Consistent recovery checkpoint target

- **OC-016 — Recovery checkpoint.** A paired recovery checkpoint captures coordination and scheduling records with both revisions in one consistent storage snapshot, excludes authentication, and validates its envelope and intrinsic record integrity. Explicit current-admin restore replaces both datasets atomically, pauses imported pending jobs, preserves the current-password mapping rule and revokes prior authority exactly as coordination restore does. Missing references in retained paused/finished history remain evidence, never dispatch authority; missing references for pending jobs are invalid. Invalid input, capacity failures, storage failure or losing concurrent writes preserve the previous complete state and cannot revoke a winning restore's new session. Verify the actual emitted Worker/D1 and private local CLI workflow before claiming this target implemented.

## Retained reviewed handoffs

- **OC-017 — Reviewed handoffs.** Persist explicitly authored, unsent handoff copy with an explicit intended audience, immutable incident/service snapshots and canonical content hashes. Preparation and review actions have stable identities that conflict on changed content. Only current active responders/admins prepare, review or withdraw; viewers inspect permitted internal records and admins restore. A review binds exact copy and source versions, becomes ineligible on source drift or a recovery hold, and never grants sending, publication, recovery verification or independent-review authority. Withdrawal is terminal and preserves attributed append-only history. Keep OC-006 and historical unreviewed envelopes unchanged. Use separate additive handoff storage/archive bounded to 64 records, 128 history entries per record, 128 KiB per record and 1 MiB aggregate. Explicit checkpoint version 2 includes handoffs; version 1 remains supported. Restore retains historical identities and holds active approvals atomically alongside existing recovery and credential/session safeguards. Invalid input, capacity/storage failure or losing concurrent writes preserve the complete prior state. HANDOFF-STAGE.md defines retained snapshots, eligibility and permissions; transfer proof exercises the protected HTTP review and restore flow. No provider send, remote fetch or Lamp publication is authorized.

## Activated installation and move-in

- **OC-018 — Maintained root commands.** Maintained root seed commands use the pinned Base installer, owner identity, dev identity and theme. Ordinary email-link sign-in is kept and tested independently of dev identity. Setup creates no example incident or service. Release 1 supports hosted coordination beside the existing pager without an independent standby; portable SQL batch bindings are required. `rer deploy` verifies deployment identity, claims the configured owner automatically and retires the setup token. Hosted email-link sign-in requires a configured remote mail provider. Removal with the same Cloudflare credentials deletes only recorded deployment resources and verifies that they are gone. On local and hosted apps, the configured owner uses native email links, while admin-created team members use installation-local workspace names and passwords at `/signin/local`; no invitations are sent. Local dev identity never grants hosted access, and anonymous first-admin bootstrap at `/api/setup` remains loopback-only.
- **OC-019 — Additive upgrade.** The additive upgrade removes the one-row coordination store after migrating every entity and original array order to relational tables. Released migrations stay unchanged. Held passwords and identities are preserved. New Base identity cannot silently claim held coordination data.
- **OC-020 — Now/next and calendar feed.** Now/next explains current coverage and each role's next effective hand-off. The private ICS feed uses the same resolved UTC boundaries including overrides/gaps and exports primary/backup separately. It requires a current session; default window is seven days, explicit windows are bounded to 31 elapsed days. Calendar downloads carry no public bearer access. Alert intake records immutable events with scoped source credentials; intake never starts paging.
- **OC-021 — Move-in preview.** Opsgenie then PagerDuty file move-in uses Base import-kit D1. Preview writes zero rows. A current administrator must review the exact source fingerprint before applying. Users are matched by normalized email and grant no login rights; schedules and policy data stay paused. Original bytes, unmapped fields, rejected objects, journal and provenance are retained. Every unmappable rotation/rule is named; no partial rotation approximation is allowed. Missing detail exports reject. No account/API calls or routing credentials are activated.
- **OC-022 — Resume and undo.** Journaled imports support bounded resume after restart and explicit undo. SQL checks current actor/session/admin authority inside publication and reversal. Changed source identities conflict; duplicate unchanged sources are idempotent. Undo removes only unchanged attributed native objects; edits are preserved with an explicit conflict. Invalid input or failed publication leaves prior committed state unchanged; partial progress remains visible and resumable.
- Shapes recorded under OC-021 (13 Oct 2026, no requirement reworded): each documented Opsgenie `data` response and each documented PagerDuty list or single-detail response, saved unchanged, one per bundle key or an array of them; PagerDuty layers that ended before the one open-ended layer began, kept as named history; a PagerDuty whole-day layer in a zone with offset changes when the supplied `final_schedule` is equivalent across an offset change. [MOVE-IN.md](MOVE-IN.md) lists the fields and pages read.

## Release scope — owner direction, 16 October 2026

Release 1 is hosted incident coordination alongside the team's existing pager. Paging stays OFF, the existing pager stays authoritative, and coordination does not require an independent standby. Hosting does not synchronize the pager's configuration, deliver pages, announce role moves externally or prove delivery. Teams keep their existing pager routes and responder notification settings in place.

Release 2 paging and its independent standby are not built. Its requirements include dual alert intake, configuration pull, independent store/secrets/identity and external role-move announcements; durable absolute deadlines and term-scoped sent markers; one-use acknowledgement at both sites; two channels on two providers per responder; carrier registration; and real-phone and provider-failure drills. Measured takeover-to-page time belongs in this contract only after those drills. None is inferred from coordination deployment or local proof.
