CTO gate
PASS WITH WARNINGS for implementation readiness. Production remains blocked until Jack approves exact actions/commands.
Architecture recommendation
Use two lanes now: frozen Beta/Prod and safe-to-break Dev/Test. Defer a third staging project until beta scale or revenue justifies it.
Core risk
Accidental production targeting. Every Supabase command must include --project-ref <dev-ref|prod-ref>; never rely on linked CLI state.
Contents
Non-negotiable boundaries
No app-side coaching intelligence
The app assembles context, streams AI responses, executes tool calls, and displays/stores returned data. It must not calculate readiness, training quality, calorie/macros advice, performance trends, or plan changes.
No secrets in docs/chat/repo
Use Supabase secrets, EAS env, local .env, or 1Password. Docs may contain variable names and placeholders only.
No prod action without approval
Production migrations, function deploys, builds/submits, OAuth edits, secrets, webhooks, data exports/imports, and releases require Jack's explicit approval.
No beta data in dev by default
Dev uses synthetic/manual test accounts. Any prod-data clone/anonymisation needs a separate GDPR/security approval.
Target lane architecture
| Area | Beta/Prod lane | Dev/Test lane |
|---|---|---|
| Purpose | Stable beta for testers | Safe-to-break implementation/testing |
| Mobile app | PocketCoach | PocketCoach Dev |
| Bundle/package | com.jackdinneen.pocketcoach | com.jackdinneen.pocketcoach.dev |
| URL scheme | pocketcoach:// | pocketcoachdev:// |
| EAS profile | production | development / preview |
| Supabase | Current production project | Separate dev project, same region |
| PostHog | Production project | Separate PocketCoach Dev project |
| Strava | Webhook owned by prod | OAuth/manual sync only; no dev webhook |
| Google/Outlook | Existing prod callbacks | Add dev callbacks alongside prod |
| Data | Real beta users | Jack/test accounts + synthetic fixtures |
Current support already present
Env-aware Expo config
app.config.ts switches name, icon, scheme, bundle/package IDs, and EAS project ID from APP_ENV.
EAS split
eas.json uses APP_ENV=dev for development/preview and APP_ENV=prod for production.
Supabase client
lib/supabase.ts uses EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY.
OAuth scheme routing
oauth_state.app_scheme stores pocketcoach vs pocketcoachdev; Strava initiate/callback shows the pattern.
Implementation phases
Phase 0 — Freeze and baseline prod/beta
Create a release log, record non-secret identifiers, capture OAuth current state, and enforce “no prod changes until dev smoke passes.” Acceptance: baseline log exists, no secrets, Jack confirms freeze.
Phase 1 — Provision/verify dev Supabase
Create pocketcoach-dev in the same region as prod, configure Auth site/redirect URLs, replay all migrations, verify RLS, and confirm dev has no prod users/tokens/health data.
supabase db push --project-ref <dev-ref> supabase migration list --project-ref <dev-ref>
Phase 2 — Dev secrets and Edge Functions
Set dev secrets with lane-specific randoms for webhook/cron/MCP/calendar secrets; shared AI/OAuth client credentials are acceptable initially if monitored. Deploy all functions to dev only.
supabase secrets set --project-ref <dev-ref> \ GEMINI_API_KEY=<from-approved-store> \ ANTHROPIC_API_KEY=<from-approved-store> \ STRAVA_REDIRECT_URI=https://<dev-ref>.supabase.co/functions/v1/strava-oauth-callback \ GOOGLE_REDIRECT_URI=https://<dev-ref>.supabase.co/functions/v1/google-oauth-callback \ OUTLOOK_REDIRECT_URI=https://<dev-ref>.supabase.co/functions/v1/outlook-oauth-callback \ STRAVA_WEBHOOK_VERIFY_TOKEN=<new-random> \ DAILY_SUMMARISE_SECRET=<new-random> supabase functions deploy --no-verify-jwt --project-ref <dev-ref>
Phase 3 — EAS, app identity, env vars
Create/verify dev EAS project, store development env vars, verify production envs, build/install PocketCoach Dev, and confirm side-by-side install with TestFlight.
eas env:create --environment development --name EXPO_PUBLIC_SUPABASE_URL --value https://<dev-ref>.supabase.co eas env:create --environment development --name EXPO_PUBLIC_SUPABASE_ANON_KEY --value <dev-anon> eas env:create --environment development --name EXPO_PUBLIC_POSTHOG_KEY --value <dev-posthog-write-key> eas env:create --environment development --name EAS_PROJECT_ID_DEV --value <dev-eas-id> pnpm build:dev:ios
Phase 4 — OAuth/integration segregation
Add dev Google and Outlook callback URIs without removing prod. Confirm Strava callback domain is supabase.co. Keep Strava webhook prod-owned; dev uses manual pull. Keep external MCP prod-only unless separately scoped.
Phase 5 — Dev seed/test data
Use one Jack/test account and synthetic fixtures for onboarding, sessions, nutrition, check-ins, activities, and memories. No prod beta users, OAuth tokens, health data, or voice transcripts in dev.
Phase 6 — CI/testing gates
Run typecheck, lint, tests, dev migrations/functions, smoke tests, privacy/RLS checks, and coaching-boundary review before any prod promotion.
npm run typecheck npm run lint npm test
Phase 7 — Branch and release workflow
Use short-lived branches off main, never push directly to main, deploy to dev first, smoke test, draft release notes/rollback, then request explicit prod approval.
Developer tickets
| Epic | Ticket | Acceptance criteria | Approval |
|---|---|---|---|
| A | Create prod baseline/release log | Build/version, project refs/labels, latest commit, OAuth state; no secrets. | Required |
| B | Create/verify dev Supabase + replay migrations | Same region, all migrations apply, RLS verified, prod untouched. | Required |
| B | Set dev secrets + deploy functions | Required env vars present, lane randoms unique, dev logs clean. | Required |
| C | Configure EAS dev env + build app | Dev app installs side-by-side, targets dev Supabase/PostHog. | Required |
| C | Review EAS Updates separation | No dev OTA can target prod update channel; decision documented. | Required for changes |
| D | Add Google/Outlook dev redirects | Dev URIs added, prod URIs unchanged, screenshots captured. | Required |
| D | Verify Strava callback/webhook ownership | Callback domain supabase.co; prod webhook remains owner. | Required for edits |
| E | Run full dev smoke checklist | Auth, AI, tool writes, OAuth, analytics, cross-talk checks pass. | Required |
| F | Create release/rollback templates | Risk, commands, evidence, rollback, approval checkbox. | Docs-only |
QA and release gates
Isolation
- Dev name/icon/bundle/scheme differ from prod.
- Dev app public Supabase URL is dev.
- PostHog events route to correct lane.
- Prod TestFlight remains on prod DB.
Auth/OAuth
- Dev login and magic link work.
- Strava/Google/Outlook return to
pocketcoachdev://. - Tokens write to dev
provider_tokensonly. - Prod webhook still works.
AI/tool loop
- Coach tab streams in dev.
- Tool call writes to dev DB.
- Memory/tool handlers work.
- No app-side coaching logic added.
Privacy/security
- No secrets in diff/docs/logs.
- RLS enabled.
- Functions authenticate internally.
- PostHog excludes sensitive content.
Release gate
- Local tests pass.
- Dev migration/function/build smoke passed.
- Cross-talk test passed.
- Release note drafted.
- Rollback path documented.
- Exact prod commands/actions reviewed.
- Jack approves prod action.
- Post-release smoke completed.
- Release log updated.
Rollback plan
Mobile/TestFlight
Stop distribution of broken build, direct testers to prior build if available, reproduce and verify fix in dev before resubmitting.
Edge Functions
Redeploy previous known-good commit/function bundle to prod with explicit --project-ref <prod-ref>. If shared modules changed, redeploy affected functions together.
Database
Prefer forward-fix migrations. Risky migrations need backup/export checkpoint, dev replay proof, reviewed SQL, and exact prod command approval.
OAuth/secrets
Capture console state before edits. Restore prod settings if auth breaks. Rotate incorrect/compromised secrets without recording values in docs.
Agent/subagent team structure
| Lane | Skill/model | Responsibilities |
|---|---|---|
| CTO/orchestrator | pocket-coach-cto, strongest model | Architecture, gates, release risk, final recommendation. |
| Supabase/backend | pocket-coach-cto, strong coding model | Migrations, RLS, Edge Functions, secrets checklist, logs. |
| Mobile/EAS | pocket-coach-cto, strong coding model | Expo config, EAS env/build, app identity, deep links, OTA risk. |
| OAuth/integrations | pocket-coach-cto, strong coding model | Strava/Google/Outlook callback URIs, app scheme verification, token storage. |
| QA/release | pocket-coach-cto, efficient model with escalation | Smoke checklist, evidence, cross-talk checks, release notes. |
| Security/privacy | pocket-coach-cto, strong model | Secrets, RLS, tokens, analytics/session replay, GDPR boundaries. |
Open questions
- Has Jack already created the dev Supabase project? If yes, what is the non-secret
<dev-ref>? - Should dev use shared AI provider keys initially, or separate keys for cost attribution?
- Is a dev PostHog project already available?
- Will Jack test dev with his own Strava account or a separate test athlete account?
- Should
daily-summarisecron run in dev, or stay disabled/manual-only? - Should dev MCP be deferred entirely, or is external Claude testing against dev needed soon?
- Should EAS Updates be disabled for dev or made env-aware now?
- What beta release cadence does Jack want: weekly, ad hoc, or only after feature bundles?
- Who can approve production actions if Jack is unavailable? Default: Jack only.
- Should a synthetic seed script be implemented now or after first smoke test?
Evidence inspected
Jack_OS/RESEARCH/Pocket_Coach_Dev_Test_Segregation_Plan_2026-05-10.mdJack_OS/review_cache/Ai-Coach-Bridge/README.md,AGENTS.md,CLAUDE.mdJack_OS/review_cache/Ai-Coach-Bridge/DOCS/DECISIONS.md,DOCS/PRD-AI-COACH-BRIDGE.md,DOCS/SETUP-CHECKLIST.mdapp.config.ts,eas.json,package.json,.env.examplelib/supabase.ts,lib/analytics.tssupabase/migrations/20260507000001_oauth_state_app_scheme.sqlsupabase/functions/strava-oauth-initiate/index.ts,supabase/functions/strava-oauth-callback/index.tsmcp-proxy/api/proxy.ts,vercel-mcp-proxy/api/index.js- Repo cache status:
main...origin/main; latest visible commit186b28e; 62 migrations visible.
Bottom line
Pocket Coach does not need heavy enterprise process yet. It needs a hard, visible boundary: prod is frozen and stable; dev is isolated and safe to break; promotion is explicit and reversible.