← back to Costa Rica
costa-rica: add docs/GO-LIVE.md operator runbook — TK-10346
b0232a1e50d5835362911347556c9e018660cda7 · 2026-08-08 08:34:10 -0700 · Steve
Consolidates the go-live path for a Kamatera operator: the real-world credential steps only
Steve can do (Tilopay CR-KYC, Meta/Plaid keys, ASC submit), secret routing, webhook registration,
the applied DB migrations + runner usage, the SURGICAL no-delete deploy (canonical /deploy is a
--delete landmine vs prod-only images), the live-only preflight, money-math invariant, and the
optional public-directory publish decision.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit b0232a1e50d5835362911347556c9e018660cda7
Author: Steve <steve@designerwallcoverings.com>
Date: Sat Aug 8 08:34:10 2026 -0700
costa-rica: add docs/GO-LIVE.md operator runbook — TK-10346
Consolidates the go-live path for a Kamatera operator: the real-world credential steps only
Steve can do (Tilopay CR-KYC, Meta/Plaid keys, ASC submit), secret routing, webhook registration,
the applied DB migrations + runner usage, the SURGICAL no-delete deploy (canonical /deploy is a
--delete landmine vs prod-only images), the live-only preflight, money-math invariant, and the
optional public-directory publish decision.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
docs/GO-LIVE.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/docs/GO-LIVE.md b/docs/GO-LIVE.md
new file mode 100644
index 0000000..abc5eee
--- /dev/null
+++ b/docs/GO-LIVE.md
@@ -0,0 +1,65 @@
+# Costa Rica Marketplace — GO-LIVE runbook
+
+Repo: `~/Projects/costa-rica` (backend) · prod: Kamatera `root@45.61.58.125`, pm2 `costa-rica` :9791, `costarica.agentabrams.com`.
+Status as of 2026-08-08: **backend LIVE on prod in SANDBOX mode**; DB migrations applied; hardened code deployed; iOS build #13 on TestFlight. Suite: `DATABASE_URL=postgresql:///costa_rica_directory?host=/tmp npm test` → 113/113.
+
+Everything runs sandbox-safe with NO creds. Each integration flips live the moment its keys are set. The boot guard (`lib/preflight.js`) **refuses to start in production** if any integration is live but missing its webhook secret / verify token — so a half-configured go-live fails loud instead of silently dropping bookings.
+
+---
+
+## 0. What only YOU (Steve) can do — real-world credential steps
+These are NOT permission gates; they need your own logins/identity and cannot be automated:
+1. **Tilopay merchant account** — requires a CR bank IBAN + Ministerio de Hacienda tax registration + notarial shareholding cert (or a non-CR processor). No API keys exist until this is done.
+2. **Meta WhatsApp (WABA)** — Meta Business + WhatsApp number + permanent system-user token + pre-approved templates.
+3. **Plaid production** — create prod keys in the Plaid dashboard.
+4. **App Store Submit-for-Review** — your Apple ID login in the ASC console (build/desc/screenshots already staged).
+
+## 1. Set secrets (when you have them)
+Paste each key; route via the `secrets` skill → `~/Projects/costa-rica/.env` on prod. Never commit `.env` (deploys exclude it).
+```
+# payments (pick one provider via PAYMENT_PROVIDER=tilopay|onvo)
+TILOPAY_API_USER= TILOPAY_API_PASSWORD= TILOPAY_API_KEY= TILOPAY_WEBHOOK_SECRET=
+# whatsapp
+WHATSAPP_TOKEN= WHATSAPP_PHONE_ID= WHATSAPP_APP_SECRET= WHATSAPP_VERIFY_TOKEN=<random, NOT the default>
+# plaid
+PLAID_CLIENT_ID= PLAID_SECRET= PLAID_ENV=production
+```
+The boot guard will REFUSE to start if a provider is live but its `*_WEBHOOK_SECRET` (or `WHATSAPP_VERIFY_TOKEN`) is unset — set them together.
+
+## 2. Register webhooks with the providers
+- Meta WhatsApp: `https://costarica.agentabrams.com/webhooks/whatsapp` (GET verify uses `WHATSAPP_VERIFY_TOKEN`).
+- Tilopay/ONVO: point the processor's webhook at `https://costarica.agentabrams.com/webhooks/tilopay` (or `/onvo`).
+
+## 3. DB migrations (already applied on prod 2026-08-08)
+Ordered, idempotent, ledgered runner:
+```
+cd /root/Projects/costa-rica
+export DATABASE_URL="$(grep -E '^DATABASE_URL=' .env | cut -d= -f2-)"
+bash scripts/apply-migrations.sh --status # READ-ONLY: applied vs pending
+bash scripts/apply-migrations.sh # apply pending (idempotent; existing objects no-op)
+psql "$DATABASE_URL" -c "SELECT conname FROM pg_constraint WHERE conname IN ('bookings_no_overlap_stay','bookings_no_overlap_slot');" # 0 rows => STOP
+```
+NEVER `--baseline` on prod (marks pending files applied WITHOUT running → would skip the double-book/integrity guards); the runner refuses it unless `FORCE=1`. For partial adoption use `--baseline-through <file>`.
+
+## 4. Deploy code to prod — SURGICAL only (do NOT use canonical /deploy)
+`deploy.sh` uses `rsync --delete` and prod holds prod-only data (`data/img/places/*.jpg` live images, OSM cache) missing locally → `/deploy` would erase them. Until local↔prod converge, ship code with a no-delete rsync (lib/routes WITHOUT trailing slashes so they stay directories):
+```
+cd ~/Projects/costa-rica
+rsync -az server.js package.json package-lock.json lib routes root@45.61.58.125:/root/Projects/costa-rica/
+ssh root@45.61.58.125 'pm2 reload costa-rica --update-env'
+curl -s https://costarica.agentabrams.com/api/app/health # expect ok:true
+```
+
+## 5. Live-only preflight (verify against the REAL provider before opening bookings — do NOT guess)
+1. **Webhook signature encoding** — adapters compare hex; if the provider signs base64, set `Buffer.from(sig,'base64')` explicitly once the real delivery is observable.
+2. **Live createCharge error path** — guard `res.ok` + explicit `failed` mapping before extracting `providerRef` (a bad live response can write `providerRef=undefined,status=processing` → stuck booking).
+3. **Verify with a $1 real charge + refund** before opening bookings.
+
+## 6. Verify money math
+`total = platform_fee + host_payout` (10% platform fee; `fees` is display-only). Enforced by DB CHECK `bookings_total_reconciles` + `test/money.test.js`.
+
+## 7. App Store
+ASC app 6799240433; build #13 on TestFlight. Remaining: attach build + `store/listing.md` desc + 5 screenshots + export-compliance in the ASC console, then Submit for Review (your Apple login).
+
+## 8. Optional — public web directory
+The web directory pages are basic-auth gated (`admin`/`DW2024!`); the app API (`/api/app`) + `/webhooks` are already public. Dropping the web gate exposes ~34k listings publicly — a customer-facing publish of scraped third-party business data; decide deliberately before removing `BASIC_AUTH_*`.
← 86510e3 costa-rica: /yoloforever cycle 2 ledger — TK-10346
·
back to Costa Rica
·
Add public /privacy + /support pages before basic-auth gate 471a896 →