# Business continuity and disaster recovery policy

**Version:** 1.0
**Effective date:** 2026-04-17

## 1. Objectives

| Metric | Target | Measured by |
|---|---|---|
| RTO - core services (login, view proposal, approve) | 4 hours | Post-incident measurement |
| RTO - non-core (analytics, branding tools, team admin) | 24 hours | Post-incident measurement |
| RPO - customer data (Airtable) | 24 hours | Backup cadence |
| RPO - blobs (files, images) | 24 hours | Provider versioning |

## 2. Backup architecture

- **Airtable:** nightly export to S3-compatible storage via a Netlify Scheduled Function. Retention 30 days. Restore tested quarterly.
- **Netlify Blobs:** provider-native versioning with 30-day retention
- **Source code:** GitHub is authoritative; mirrored to a separate protected branch in a secondary org
- **Secrets:** stored in Netlify env vars; copies held in a password manager (founder)

## 3. Failure modes and response

| Failure | Impact | Response |
|---|---|---|
| Netlify outage (regional) | Platform unavailable | Status page post; no action - Netlify owns recovery |
| Netlify outage (global, >4h) | Platform unavailable | Fallback static page pointing at email/support; post-incident migrate to contingency host if needed |
| Airtable outage | Reads/writes fail | Queue writes client-side (future work); else status page + hold |
| Airtable data corruption | Customer data inconsistent | Restore from last nightly backup; customers compensated per SLA |
| Stripe outage | Checkout disabled | Banner notifying buyers to retry; retain the proposal for 72h extension |
| Mux outage | Videos fail to play | Show fallback image; continue serving proposal text |
| Resend outage | Transactional emails queued | Secondary provider on standby (Postmark configured as cold failover) |
| Credential compromise | Multiple | Rotate all keys; see incident response policy |
| Founder unavailable (hit by a bus scenario) | Decision bottleneck | Documented runbook in password manager; designated second-party access path for legal/support; insurance in place |

## 4. Testing

- **Backup restore test:** quarterly. Restore last Airtable export to a sandbox base and verify record counts, schema, and row-level spot checks. Log result in `docs/security/exercises/`.
- **Failover test:** annually. Spin up the static fallback site and verify DNS cutover readiness.
- **Tabletop exercise:** quarterly, per incident response policy.

## 5. Customer communication during incidents

- Status page: `status.myframeboard.app`
- In-app banner for SEV-1/2
- Email notification for any incident affecting more than 10% of customers
- Postmortem published publicly within 10 working days of SEV-1 resolution
