CTO plan · 2026-05-10 · planning only

Pocket Coach Dev/Test Segregation

Implementation-ready developer plan to protect the current TestFlight beta while creating an isolated Supabase/EAS/PostHog dev lane. No code, database, secrets, deploys, OAuth consoles, or production systems were changed while preparing this page.

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

AreaBeta/Prod laneDev/Test lane
PurposeStable beta for testersSafe-to-break implementation/testing
Mobile appPocketCoachPocketCoach Dev
Bundle/packagecom.jackdinneen.pocketcoachcom.jackdinneen.pocketcoach.dev
URL schemepocketcoach://pocketcoachdev://
EAS profileproductiondevelopment / preview
SupabaseCurrent production projectSeparate dev project, same region
PostHogProduction projectSeparate PocketCoach Dev project
StravaWebhook owned by prodOAuth/manual sync only; no dev webhook
Google/OutlookExisting prod callbacksAdd dev callbacks alongside prod
DataReal beta usersJack/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

EpicTicketAcceptance criteriaApproval
ACreate prod baseline/release logBuild/version, project refs/labels, latest commit, OAuth state; no secrets.Required
BCreate/verify dev Supabase + replay migrationsSame region, all migrations apply, RLS verified, prod untouched.Required
BSet dev secrets + deploy functionsRequired env vars present, lane randoms unique, dev logs clean.Required
CConfigure EAS dev env + build appDev app installs side-by-side, targets dev Supabase/PostHog.Required
CReview EAS Updates separationNo dev OTA can target prod update channel; decision documented.Required for changes
DAdd Google/Outlook dev redirectsDev URIs added, prod URIs unchanged, screenshots captured.Required
DVerify Strava callback/webhook ownershipCallback domain supabase.co; prod webhook remains owner.Required for edits
ERun full dev smoke checklistAuth, AI, tool writes, OAuth, analytics, cross-talk checks pass.Required
FCreate release/rollback templatesRisk, 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_tokens only.
  • 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

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

LaneSkill/modelResponsibilities
CTO/orchestratorpocket-coach-cto, strongest modelArchitecture, gates, release risk, final recommendation.
Supabase/backendpocket-coach-cto, strong coding modelMigrations, RLS, Edge Functions, secrets checklist, logs.
Mobile/EASpocket-coach-cto, strong coding modelExpo config, EAS env/build, app identity, deep links, OTA risk.
OAuth/integrationspocket-coach-cto, strong coding modelStrava/Google/Outlook callback URIs, app scheme verification, token storage.
QA/releasepocket-coach-cto, efficient model with escalationSmoke checklist, evidence, cross-talk checks, release notes.
Security/privacypocket-coach-cto, strong modelSecrets, RLS, tokens, analytics/session replay, GDPR boundaries.

Open questions

  1. Has Jack already created the dev Supabase project? If yes, what is the non-secret <dev-ref>?
  2. Should dev use shared AI provider keys initially, or separate keys for cost attribution?
  3. Is a dev PostHog project already available?
  4. Will Jack test dev with his own Strava account or a separate test athlete account?
  5. Should daily-summarise cron run in dev, or stay disabled/manual-only?
  6. Should dev MCP be deferred entirely, or is external Claude testing against dev needed soon?
  7. Should EAS Updates be disabled for dev or made env-aware now?
  8. What beta release cadence does Jack want: weekly, ad hoc, or only after feature bundles?
  9. Who can approve production actions if Jack is unavailable? Default: Jack only.
  10. Should a synthetic seed script be implemented now or after first smoke test?

Evidence inspected

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.