RTO / RPO targets
- RTO (Recovery Time Objective): ambient system fully operational within 24 hours of getting a replacement Mac. Phase 1 (brain-only) within 4 hours.
- RPO (Recovery Point Objective): ≤ 90 days of data loss worst case (quarterly backup cadence). For practical purposes: most recent quarterly + Drive sync = ~few days RPO since most operator data syncs to Drive in near-real-time.
What survives a Mac loss
| Survives | Where |
|---|---|
| ✅ Full SkyRun folder | iCloud Drive (live sync) + local quarterly backup zips + iCloud Drive backup zips |
| ✅ Memory dir | quarterly backup zip (added 2026-05-02 PM enterprise sweep) |
| ✅ Cloudflare resources (Pages + KV state) | Cloudflare account (independent of Mac) |
| ✅ HubSpot data | HS account (independent of Mac) |
| ✅ Gmail history | Google Workspace account |
| ✅ Anthropic API state | Anthropic account |
| ⚠️ Keychain | iCloud Keychain (when enabled) — verify ON |
| ⚠️ Active scheduled-task registrations | Lost — must re-register on new Mac |
| ⚠️ launchd agents | Lost — must reinstall plists |
| ⚠️ Active chrome_bridge sessions | Lost — must re-auth + re-flip JS toggle |
| ❌ /tmp state | Gone (intentional — ephemeral) |
| ❌ Local logs | Gone (operationally OK; quarterly backup includes Logs dir if needed) |
Pre-disaster prep (do these NOW if not already)
- [ ] FileVault ON — encrypts all data at rest. Currently OFF (P0 operator action).
- [ ] iCloud Keychain ON — secrets sync across devices. Settings → Apple ID → iCloud → Keychain.
- [ ] iCloud Advanced Data Protection ON — E2E for iCloud (recommended).
- [ ] Touch the iCloud backup flag (one-time):
bash
touch "/Users/josephbowens/Library/Application Support/SkyRun/.icloud_backup_enabled"
This enables the iCloud-mirror step in quarterly_backup.sh.
- [ ] Verify Time Machine ON — system-level backup.
tmutil statusreports running. - [ ] Run a quarterly backup manually + verify zip is valid:
bash
bash ~/Library/Application\ Support/SkyRun/quarterly_backup.sh
ls -la ~/Library/Application\ Support/SkyRun_Backups/
unzip -t ~/Library/Application\ Support/SkyRun_Backups/SkyRun_<latest>.zip > /dev/null && echo "✓ zip integrity ok"
- [ ] Document recovery key for FileVault — when enabled, save the recovery key to a password manager + a physical safe.
- [ ] Print this doc — paper copy in case Mac is the only place you read it.
Recovery procedure (after Mac loss/destruction)
Phase A — immediate containment (within 1 hour of loss detection)
Per reference_incident_runbook.md Scenario 3:
1. iCloud Find My — mark as lost; remote-wipe if FileVault OFF
2. Revoke Cloudflare tokens
3. Sign out of HubSpot everywhere
4. Revoke Workspace device + change password
5. Rotate Anthropic API key
Phase B — replacement Mac setup (Day 1)
#### B.1 — macOS install + initial config (~1 hour)
1. Install macOS on the replacement (clean or migrate from Time Machine).
2. Sign into Apple ID. Wait for iCloud Drive to sync. Wait for iCloud Keychain to sync.
3. Sign into Google Workspace (Joseph.Bowens@SkyRun.com). Re-auth Gmail/Calendar/Drive.
4. Install Claude Code + Microsoft Office (Word, Excel, PowerPoint).
5. Install Python 3.9+ (likely included with Xcode CLI tools).
6. Install Google Drive for desktop + sign in. Wait for ~/Desktop/SkyRun/ to sync.
#### B.2 — restore SkyRun runtime (~30 min)
If iCloud sync of ~/Desktop/SkyRun/ worked:
- ✅ Operator-tree is restored automatically
- Move on to runtime restore
Restore runtime tree from backup zip:
bash
LATEST_BACKUP=$(ls -t ~/Library/Application\ Support/SkyRun_Backups/SkyRun_*.zip 2>/dev/null | head -1)
If no local backup exists, get from iCloud:
[ -z "$LATEST_BACKUP" ] && LATEST_BACKUP=$(ls -t ~/Library/Mobile\ Documents/com~apple~CloudDocs/SkyRun_Backups/SkyRun_*.zip | head -1)
mkdir -p /tmp/skyrun_restore && cd /tmp/skyrun_restore
unzip "$LATEST_BACKUP"
3-source restore (post-2026-05-02 backups have this layout)
mkdir -p ~/Library/Application\ Support
cp -R runtime_SkyRun ~/Library/Application\ Support/SkyRun
Memory dir restore
mkdir -p ~/.claude/projects
cp -R memory_SkyRun ~/.claude/projects/-Users-$(whoami)-Desktop-SkyRun/memory
Verify quick
ls ~/Library/Application\ Support/SkyRun/{chrome_bridge.py,system_hygiene.sh,quarterly_backup.sh,gate_proof_runner.sh,secrets.py,schema_guards.py,recompute_health_summary.py,fleet_status_push.py,build_pwa.py,deploy_pwa.sh,notify.sh,pwa_auto_rebuild.sh}
#### B.3 — re-add Keychain secrets (~10 min)
If iCloud Keychain synced, secrets should already be there. Verify:
bash
python3 ~/Library/Application\ Support/SkyRun/secrets.py list
If anything is ✗:
- Get a fresh CF API token from CF dashboard. Run
python3 secrets.py set cloudflare_api_token <new-token> - Get the ntfy topic from
secrets_manifest.txtin the backup zip + runpython3 secrets.py set ntfy_topic <topic>
#### B.4 — fix permissions + locks (~5 min)
The backup zip preserves perms via ditto, but verify:
bash
bash ~/Library/Application\ Support/SkyRun/gate_proof_runner.sh
All 57 gates should pass; if any fail, address per their messages.
#### B.5 — install launchd agents (~5 min)
bash
LD="$HOME/Library/LaunchAgents"
mkdir -p "$LD"
system-hygiene
cat > "$LD/com.skyrun.system-hygiene.plist" <<'PLIST'
[plist content from quarterly backup OR from package install.sh]
PLIST
launchctl load "$LD/com.skyrun.system-hygiene.plist"
Same for quarterly-backup
(If you don't remember the exact plist content, regenerate by running the package's installer/install.sh from ~/Desktop/adam-bd-bootstrap/ against a SkyRun-tenant config — it produces correct plists.)
#### B.6 — re-register scheduled tasks (~30 min)
For each skill in ~/.claude/scheduled-tasks/, register via mcp__scheduled-tasks__create_scheduled_task. Expected list:
- live-ea, nightly-consolidation, transcript-scan, gmail-deep-scan, daily-data-quality-check
- daily-beenverified-enrichment, grand-county-property-scout
- commitment-tracker, qb-quarterback, gate-proof-runner
- close-to-onboarding-handoff, deal-postmortem-capture, referral-watchdog
- postcard-ledger, smartlead-bounce-handler, stalled-deal-watchdog
Cron expressions per reference_scheduled_tasks.md. Verify registered:
bash
Via Claude Code: mcp__scheduled-tasks__list_scheduled_tasks
#### B.7 — re-auth browser sessions (~15 min)
Open Chrome:
- HubSpot — log in, leave the tab open
- Gmail — log in, leave open
- Track — log in
- KeyData — log in
- BeenVerified — log in
- SmartLead — log in
Flip the Chrome JS toggle ON: View → Developer → Allow JavaScript from Apple Events.
System Settings → Privacy & Security → Automation → Terminal/iTerm/Claude → Google Chrome ON.
#### B.8 — verify end-to-end (~15 min)
bash
1. chrome_bridge probe
python3 ~/Library/Application\ Support/SkyRun/chrome_bridge.py list
2. Full gate-proof run
bash ~/Library/Application\ Support/SkyRun/gate_proof_runner.sh
Expect: 57 PASSED, 0 FAILED.
3. Recompute health
python3 ~/Library/Application\ Support/SkyRun/recompute_health_summary.py
4. Manual fire of nightly-consolidation
(via Claude Code: mcp__scheduled-tasks__update_scheduled_task fireAt=now+30s)
5. Verify PWA deploys cleanly
python3 ~/Library/Application\ Support/SkyRun/build_pwa.py
bash ~/Library/Application\ Support/SkyRun/deploy_pwa.sh
Post-recovery validation (Day 2)
- [ ] Morning brief generated overnight (open
~/Desktop/SkyRun/morning_brief.md) - [ ] PWA loads on iPhone with fresh state
- [ ] live-ea fires every 20 min during business hours
- [ ] Approval queue is populated
- [ ] No RED flags in fleet observability (if enabled) or system-hygiene heartbeats
Tabletop exercise — practice this annually
Recommend Joseph runs through Phase B (steps B.1–B.8) on a secondary Mac at least once a year, just to confirm the procedure works without surprises. Estimated time: 4 hours including all browser auths. Document any deviations from this runbook in a follow-up update.
Cross-references
reference_quarterly_backup.md— backup mechanicsreference_security_posture.md— overall architecturereference_incident_runbook.md— sub-proceduresreference_vendor_security_posture.md— what credentials to revoke per vendor