# CLAUDE.md — Phase 15: Polish and Extension

## Scope of This File

This file instructs you (Claude Code) to implement **Phase 15 only** of the Seedbox Command Center.

There are no further phases after this one. After Phase 15, the system is complete per `PROJECT.md`'s success criteria.

## Authoritative Specification

`PROJECT.md` §9 (Phase 15 description), §8.10 (Panic Button and Emergency Controls), §10.1 (Backup and Recovery), and §13 (Success Criteria) are authoritative. Read all. Also read:
- `PROGRESS.md` for the cumulative state across Phases 0–14.
- `DECISIONS.md` for the binding decisions.

## Phase 15 Mission

Polish, finishing touches, and the few capabilities deliberately deferred. Loading and error and empty states throughout. iOS-specific polish (safe area, install prompt, theme color, splash screens). Onboarding flow for first-time setup. A settings interface that touches every operator-configurable subsystem. Data export. Backup automation with age encryption and off-host upload. Generic webhook receivers. Audit log enhancements. Emergency mode.

After Phase 15, the operator finds themselves opening the Command Center first when something is happening with their seedbox, instead of opening five different service tabs (PROJECT.md §13).

## Deliverables Checklist

Phase 15 is complete when every item below is true.

### Onboarding
- [ ] First-visit onboarding flow on a fresh install:
    1. Show a welcome screen explaining the threat model and the Tailscale assumption.
    2. WebAuthn registration (re-uses Phase 2 register-start/finish).
    3. Recovery codes display with explicit "I've saved these" confirmation.
    4. Add first tracker (re-uses Phase 1 form).
    5. Add first torrent client (re-uses Phase 3 form).
    6. Optional: enable push notifications (re-uses Phase 6 flow).
    7. Mark onboarding complete; subsequent visits go to the dashboard.

### Settings Interface
- [ ] `/settings` route with sub-pages for every operator-tunable subsystem:
    - Profile (registered devices, recovery codes regeneration).
    - Trackers (CRUD).
    - Torrent Clients (CRUD).
    - Automation Tools (CRUD).
    - Notification Rules (read-only with link to edit via YAML; YAML editor with validation).
    - Health Budgets (same).
    - Filter Variants / Bandits (same).
    - Tracker Rule Corpus (same).
    - LLM (model selection, system prompt template editing, redaction toggle defaults).
    - Backup (manual trigger, schedule, off-host destination config).
    - Observability (Prometheus endpoint, OTLP endpoint, log level).
    - Emergency.
- [ ] All YAML editors validate against the same typed schemas the loaders use; surface errors inline before save.

### Empty / Loading / Error States
- [ ] Every list view: empty state with onboarding hint, loading skeleton, error state with retry.
- [ ] Every form: validation errors inline, save-in-progress, success toast, conflict resolution.
- [ ] WebSocket disconnect: badge in the header, automatic reconnect with backoff, manual reconnect button.
- [ ] Stale data indicators: any view backed by a scraper that has failed within the configured threshold shows a "data stale (last update Nm ago)" banner.

### iOS-Specific Polish
- [ ] PWA splash screens for the iPhone family screen sizes (PROJECT.md §5.3 noted notch / Dynamic Island handling; the manifest now includes correct `display: "standalone"` + viewport-fit + safe-area CSS env() usage).
- [ ] Apple touch icons in all required sizes (real raster icons, not Phase 0's placeholder SVGs).
- [ ] Pull-to-refresh on list views.
- [ ] Haptic feedback via the Vibration API on key interactions (operator opt-in).

### Data Export
- [ ] `GET /api/system/exports?format=csv|json&table=...` endpoint that streams an export of a chosen table (operator-specified subset; sensitive columns redacted).
- [ ] Bulk export: a "Download my data" button in Settings → Profile that produces a zip with audit log, decisions, snapshots, conversations, and the operator's YAML configs. Backed by an asynchronous job (the bulk export can be slow).

### Backup Automation
- [ ] Backup scheduler (`internal/backup`):
    - Daily local backup of SQLite (online with `VACUUM INTO`); retain 30 days.
    - Weekly off-host backup, age-encrypted to the operator's identity, uploaded to S3-compatible storage (Cloudflare R2 and Backblaze B2 supported; configurable endpoint).
    - Restore documentation in `DEPLOYMENT.md` covering both paths.
- [ ] `POST /api/system/backup` — manual trigger.
- [ ] Backup credentials in `secrets`. Never in YAML.

### Generic Webhook Receivers
- [ ] Phase 4's `/webhook/generic/:endpoint_id` is finished: the endpoint accepts any HMAC-signed JSON payload and publishes it onto a custom event bus topic. Operators wire custom scripts, third-party integrations, or monitoring tools into the system without modifying the binary.

### Audit Log Enhancements
- [ ] `/audit` route with a rich filterable view (actor, action, target, time range, free-text search).
- [ ] Audit log retention policy (configurable, default 365 days). A nightly job prunes older entries with a summary row.
- [ ] Audit export (uses the bulk export above).

### Emergency Mode (PROJECT.md §8.10)
- [ ] `POST /api/emergency/activate` and `POST /api/emergency/deactivate` and `GET /api/emergency/state`.
- [ ] Activation effects:
    - Pause all torrents on all clients (via Phase 3 adapter).
    - Disable all autobrr filters (via Phase 5 client; record original state for recovery).
    - Disable all tqm runs (mark `automation_tools.enabled = false`; tqm cron sees this on next poll).
    - Silence notifications for a configurable window (default 2h).
    - Write a prominent audit entry with the snapshot of pre-emergency state.
- [ ] Deactivation: restores prior state from the snapshot. Operator can override per item ("don't restore filter X").
- [ ] Dashboard "panic button": a tap with confirmation; emergency mode badge appears on every page until deactivated.

### Tests
- [ ] End-to-end onboarding test against an in-memory fixture: complete flow boots the system from blank state.
- [ ] Backup → restore round-trip test: encrypted backup decrypts, restored database matches original.
- [ ] Emergency activate → deactivate restores prior state exactly.
- [ ] Audit log pruning preserves the summary semantics.

### Documentation
- [ ] `PROGRESS.md` written with the final cumulative summary across all phases.
- [ ] `DECISIONS.md` updated with the Phase 15 additions.
- [ ] `OPERATOR.md` — a single living document for the operator that consolidates `DEPLOYMENT.md`, `TESTING.md`, `OBSERVABILITY.md`, and the per-feature notes scattered across phases.
- [ ] `CONTRIBUTING.md` — how external operators can contribute tracker rule corpus entries, notification trigger types, or LLM tools (the community contribution path PROJECT.md §8.8 mentioned).

## Phase 15 Database Scope

No new tables for emergency or backup. Phase 15 uses:
- `audit_log` (existing) for emergency state transitions, backups, exports.
- A new optional `emergency_state` row stored in a small key-value table is acceptable if the snapshot is large enough to warrant it; document the choice in `DECISIONS.md`. A simple "emergency mode is a JSON blob in the secrets table keyed `emergency:current_snapshot`" approach is also fine.

## Repository Layout

```
internal/
  backup/
    scheduler.go
    local.go                 # sqlite VACUUM INTO
    offsite.go               # age-encrypt + S3 upload
    *_test.go
  emergency/
    state.go
    activate.go
    deactivate.go
    *_test.go
  audit/
    pruner.go
    search.go
    *_test.go
  export/
    streamer.go
    bulk.go
    *_test.go
docs/
  OPERATOR.md
  CONTRIBUTING.md
```

Files added across packages:
- `internal/server/routes_settings.go`
- `internal/server/routes_export.go`
- `internal/server/routes_backup.go`
- `internal/server/routes_emergency.go`
- `internal/server/routes_audit.go`

Frontend additions:
- `web/src/pages/Onboarding.tsx`
- `web/src/pages/Settings/*.tsx` (one per sub-page above)
- `web/src/pages/Audit.tsx`
- `web/src/pages/Emergency.tsx`
- Polish across every existing page: empty states, loading skeletons, error states, pull-to-refresh, stale-data banners, splash screens, iOS-specific safe-area handling.

## Working Rules

**Polish work is the long tail.** Phase 15 is the longest phase by hours in `PROJECT.md §9`; budget accordingly. Resist the urge to add new features — every "while we're at it" is a Phase 16.

**Emergency mode is restorable.** Activation snapshots pre-state precisely so deactivation can restore. Test the restore path on every change to the activation logic.

**Backup encryption never leaks.** Use the operator's age identity (Phase 0). The encrypted blob is opaque to the storage provider. The age recipient string never appears in logs.

**Onboarding is the first thing a new operator sees.** It's the only chance to convey the threat model, the recovery code importance, and the basic mental model.

**Audit log is durable.** Pruning is configurable; the default is conservative (365 days). A summary row replaces pruned entries so the historical narrative isn't lost.

## What "Phase 15 Complete" Looks Like

After Phase 15 ships, the operator can:

1. Wipe the database, restart, and walk through the onboarding flow on a fresh phone. End up at a populated dashboard with one tracker, one client, and notifications enabled — all in under five minutes.
2. Pull-to-refresh on the dashboard. See the loading indicator briefly; data updates.
3. Configure off-host backup to Cloudflare R2 in Settings → Backup. Watch the weekly job run, the encrypted blob arrive in R2. Practice restore from the blob on a scratch host.
4. During an unexpected event (mass tracker outage, suspected client compromise), tap the panic button. All torrents pause; all autobrr filters disable; notifications silence for two hours. Sleep. Wake up. Tap "Restore". Prior state returns.
5. Wire a custom shell script that emits a webhook on disk warnings. Receive the event on the bus; configure a notification rule that uses it.
6. Export the operator's last year of activity via Settings → Data Export. Receive an encrypted zip.
7. Discover a friend with a similar setup. Share `config/trackers/` entries via a private git repo; the friend imports them.
8. Read the `OPERATOR.md` document. Find every operational concern in one place.

The strongest success signal, from `PROJECT.md §13`: the operator opens the Command Center first when something is happening with their seedbox, instead of opening five different service tabs. Phase 15 makes that habit possible.

## Begin

This phase has the most scope of any. Sequence: onboarding (it's the marketing surface), then emergency mode (it's the most consequential single feature), then backup (it's the operational guarantee), then audit and export, then polish across every screen. Documentation last but mandatory. After Phase 15, write a final `PROGRESS.md` entry summarizing the full project arc. Stop.
