Phase 4: operational hardening and launch
What phase 4 delivered, with acceptance evidence, deviations and open items
Status: ✅ code and docs complete; the launch itself is a checklist of account-level actions only Esmee can do. Every automated gate is green.
What was built
- 30-day deletion job (SPEC decision 13):
expired_at(migration 0005) set by the webhook's expired-transition; daily scheduled sweep (ops-daily) wipes all content of tenants expired >30 days via the adapter layer, keeping the account skeleton and billing records (P4-1). Boundary-tested at 29/31 days, idempotent. - Monitoring & alerting (
monitor, hourly): failed job runs (24h), jobs stuck >2h, eligible tenants with sources but no ingest in 24h, LLM budget ≥80% (warn) / 100% (error); alerts by email toALERT_EMAILvia Resend./api/healthfor external uptime checks. Stripe-webhook health is monitored on Stripe's side (delivery dashboard + automatic retries against our idempotent handlers) — runbook documents the drill. - An operational runbook: deploy/migrate order, core-upgrade flow, price changes (data flip), comping, kill switch, incident drills (digests stopped, webhook outage, runaway spend), backup/restore, key rotation.
- A launch checklist: the complete go-live sequence — repos, hosted database + auth mail + backup drill, hosting, mail-domain authentication, Stripe live mode (Tax on, live Price with
tax_behavior: inclusive, webhook, portal), legal review, production smoke test, aftercare.
Acceptance vs SPEC §12 Phase 4
| Criterion | State |
|---|---|
| DNS + Resend domain verification | Checklist §4 (needs Esmee's DNS) |
| Monitoring & alerting | ✅ built + scheduled; gates green |
| Backups verified | Checklist §2 (restore drill on the Frankfurt project) |
| 30-day deletion job | ✅ built + boundary-tested |
| Runbook | ✅ |
| Launch checklist (Stripe live, real price) | ✅ written; execution is the go-live |
| "Production live at app.owlypost.com" | ⏳ = working through the launch checklist |
Definition of Done (SPEC §13) scorecard
- Stranger can sign up, pay (Stripe, iDEAL/card) and get access — proven end-to-end in sandbox
- Multiple tenants, zero leakage, proven by automated test (9/9, in CI)
- Paying customer receives a polished digest per category on schedule — pipeline + dispatcher + UI done; email delivery pending domain verification
- Payment stops → digests stop — tested
- LLM cost caps enforced (manual digests + monthly budget + kill switch) — boundary-tested
- One-sentence value over the bare core — live on /billing/start & terms ("runs for you: no Docker, no maintenance, first digest in minutes")
- Open source core runs unchanged as self-host — Phase 0 acceptance + Esmee's live instance
- One real paying customer runs stably — post-launch
- Logging/monitoring shows digests run and payments arrive — monitor + job_runs + Stripe dashboard (runbook)
Deviations
DECISIONS_LOG P4-1…P4-4.
Open items (all on the launch checklist)
Push owlypost-cloud to GitHub (private) + install Renovate · hosted database setup · hosting · mail domain · Stripe live · legal review · production smoke test. Plus carried over: runDigestNow deep-link, feedback un-rate (would need a core change — Esmee's call as maintainer), first-digest timing.
Addendum 2026-07-09 — untouched-core migration (P4-6)
After this report was written, the core-consumption architecture was migrated to
Esmee's final model: the open source repo stays byte-for-byte untouched (flat
single-user app, main = 1.0.0); the cloud pins it as the vendor/owlypost git
submodule and consumes it through the cloud-owned core-bridge/ package, with
per-tenant configuration injected via env per run (runWithTenantEnv) and metering
reworked to per-run v2. All gates re-proven after the migration (unit 25, db 10,
leakage 10/10, lint+gate, typecheck, build; submodule bump demo typechecks both
ways). Details and accepted trade-offs: DECISIONS_LOG P4-6.
The leakage count changed from 9 to 10 tests (a metering-isolation test was added).