SPRINT-7 T2-3 Report — D-live Secret Rotation (Twilio / Stripe / SendGrid / Anthropic)¶
Date: 2026-08-30
Status: T2-3 PARTIAL PASS (Ryan accepted). T-2 CLOSED. Rotations completed where provider API allows; follow-ups tracked on pre-teardown checklist. STOP — await Ryan on T-3+.
Playbook: R940_MIGRATION_PLAYBOOK.md §5c (no live SMS/payments during rotation verification)
Executive summary¶
| Workstream | Result |
|---|---|
| Twilio auth token (GG 29160801) | Rotated via Secondary+Promote; BWS + Railway updated |
| Stripe webhook secret (GG 29615730) | Rotated; endpoint recreated at unchanged URL; BWS + Railway updated |
| Stripe secret key (GG 29615733) | Not rotated — no API roll for sk_live_; needs Dashboard roll |
| SendGrid API key (GG 29615727) | Verified dead (401); needs new key from SendGrid Dashboard |
| Anthropic API key (GG 29615732) | Not rotated — needs new key from Anthropic Console (format-only check per §5c) |
| Webhook URLs | Unchanged (Twilio/Stripe still point at last1.app; T-5 cutover only) |
| R940 redeploy | Edge + monolith force-recreate; reachability smoke PASS (no live sends) |
| SMS crons (R940) | Still inactive (sms-checkin-cron, org-sms-cron); proof-events cron active |
Scripts: t2-3-rotate-secrets.py, t2-3-redeploy.sh
Rotation log: /tmp/last1app-gate-b/t2-3-rotation-20260830T190017Z.json
1. Secret rotation matrix¶
| Secret | GG | BWS key | Rotated? | Method | Verification (no live sends) |
|---|---|---|---|---|---|
| Twilio auth token | 29160801 | LAST1APP_APP_PROD_TWILIO_AUTH_TOKEN |
Yes | Twilio AuthTokens Secondary → Promote API | GET /2010-04-01/Accounts/{sid}.json → status=active |
| Stripe webhook secret | 29615730 | LAST1APP_APP_PROD_STRIPE_WEBHOOK_SECRET |
Yes | Delete old endpoint we_1TLT4c… (+ probe we_1UADvO…); create new at same URL |
New endpoint we_1UADxsJBZ5q5XOPp47kRDgMi; whsec_* stored in BWS |
| Stripe secret key | 29615733 | LAST1APP_APP_PROD_STRIPE_SECRET_KEY |
No | Dashboard roll only (7-day dual-key grace) | Existing key still valid (GET /v1/balance → 200 at rotation time) |
| SendGrid API key | 29615727 | LAST1APP_APP_PROD_SENDGRID_API_KEY |
No | Key already invalid in prod | GET /v3/scopes → 401 (dead before rotation) |
| Anthropic API key | 29615732 | LAST1APP_APP_PROD_ANTHROPIC_API_KEY |
No | Console new key required | Prefix check only (sk-ant-…); no inference call per §5c |
Stripe webhook URL (unchanged — critical)¶
| Field | Value |
|---|---|
| URL | https://last1.app/api/stripe/webhook |
| New endpoint ID | we_1UADxsJBZ5q5XOPp47kRDgMi |
| BWS (new) | LAST1APP_APP_PROD_STRIPE_WEBHOOK_ENDPOINT_ID |
Not done (by design): No change to Twilio or Stripe webhook URLs toward api.last1.app. URL cutover belongs at T-5 when the public sovereign endpoint is live.
2. BWS + Railway push¶
Project: last1-radiocheck (8a22f77d-8c33-4293-9262-b480015e84d2)
Railway service: ee89d9f1-547e-45cb-9c16-8427be6d8e60 (live prod monolith)
| Runtime var | Updated in BWS + Railway |
|---|---|
TWILIO_AUTH_TOKEN |
Yes (new token) |
STRIPE_WEBHOOK_SECRET |
Yes (new whsec_*) |
STRIPE_SECRET_KEY |
No (unchanged; GG still open) |
SENDGRID_API_KEY |
No (dead value unchanged) |
ANTHROPIC_API_KEY |
No (unchanged) |
Railway prod now uses the new Twilio token and new Stripe webhook signing secret. Live Stripe events to last1.app should verify with the new whsec after Railway redeploy picks up env (Railway GraphQL upsert at rotation time).
3. R940 redeploy (force-recreate)¶
| Target | VM | Action | Result |
|---|---|---|---|
| Edge Functions | 120 last1app-db @ 192.168.1.103 |
t2-1-deploy-edge.sh + fresh secrets env |
supabase-edge-functions Up (healthy) |
| Monolith | 121 last1app-app @ 192.168.1.104 |
Re-render .env from BWS → deploy-last1app-app.sh (--force-recreate) |
last1app-app Up on :5000 |
Idempotency fix: t2-1-deploy-edge.sh now strips prior injected env keys before re-insert (prevents duplicate CHECK_IN_PROOF_SECRET on repeat deploys).
Post-redeploy smoke (reachability only — §5c)¶
| Check | HTTP | Notes |
|---|---|---|
GET http://192.168.1.104:5000/ |
200 | Monolith SPA |
GET …/functions/v1/last1-id-callback |
200 | Edge reachable |
POST …/functions/v1/stripe-webhook (no sig) |
400 | Expected (handler live, rejects unsigned) |
POST …/functions/v1/sms-webhook (no sig) |
(400-class) | No outbound SMS fired |
No live SMS, payment, or inference calls were made for rotation verification.
4. Registry v2 (parallel track — not T2-3)¶
Ryan accepted: pre-existing Railway prod bug, not migration regression. Fix registryService.ts (certification_status → certification_state) in last1.app repo, normal deploy to both Railway and R940, before T-5. Not an R940-only hotfix.
- Findings: SPRINT7_REGISTRY_500_FINDINGS.md
- Tracked: Muster
last1app-registry-v2-certification-status-bug
5. Ryan follow-ups (before T-6 teardown — see pre-teardown checklist)¶
Checklist: SPRINT7_PRE_TEARDOWN_CHECKLIST.md
- Stripe SK (GG 29615733): Dashboard roll →
STRIPE_NEW_SECRET_KEY=…+ rotate script + redeploy. Old key still live until done. - SendGrid (GG 29615727): No rotation — key already dead (401). Close GG as invalid credential; SendGrid→Resend migration handles removal later.
- Anthropic (GG 29615732): New Console key issued; revoke old leaked key (revocation closes exposure, not supersession alone). Push new key:
ANTHROPIC_NEW_API_KEY=…+ rotate script + redeploy. 2026-08-30: BWS still holds pre-rotation material → API probe 401; new key not yet in BWS.
6. Hosted unchanged (except rotated secrets on Railway)¶
- Railway
last1.appstill serves production traffic. - Hosted Supabase
tcthzakppndkykatoefxSMS crons still active until T-5 teardown. - R940 SMS crons remain inactive (duplicate-scheduler guard).
STOP¶
T2-3 complete for this session. T-2 gate sequence (T2-0 → T2-3) is ready for Ryan review.
Do not proceed to T-3/T-4/T-5 until Ryan approves.
Next after approval: T-3+ per migration playbook; complete pending secret rotations when Ryan supplies Dashboard keys; registry code fix in parallel before T-5.