First comprehensive infrastructure audit covering all services, deployments, monitoring, and security.
Period: 2026-03-29 to 2026-04-01
11 areas verified across the entire stack:
| # | Area | Components |
|---|
| 1 | Supabase | STG + PRD projects, RLS, auth, migrations |
| 2 | Railway | API deploys, health checks, env vars, logging |
| 3 | Sentry | API + iOS error monitoring, console integration |
| 4 | TelemetryDeck | iOS analytics, 18 signals, SDK verification |
| 5 | Console | Auth (4 layers), monitoring dashboard, admin API |
| 6 | Docs | Starlight deploy, password gate, custom domain |
| 7 | Vercel | 3 apps (console, landing, docs), SSL, security headers |
| 8 | iOS | Fastlane, TestFlight, Match signing, Apple secret rotation |
| 9 | GitHub | Branch protection, secrets, 6 CI/CD workflows |
| 10 | Logging | Pino structured logging, log levels per environment |
| 11 | Hardening | Security improvements, design fixes, cleanup |
All 11 areas verified and passing.
- 20 tables with RLS enabled, 52 policies
- Admin users created for console (STG + PRD)
- Apple OAuth active, secret expires 2026-09-20 (172 days)
- Email provider enabled for console auth
- All 17 migrations applied to both environments
- Health checks responding (STG + PRD)
- API key enforcement active (403 without
X-API-Key)
NODE_ENV=production confirmed
- HEALTH_SECRET matches
railway.toml path
- Restart policy: on_failure, max 3 retries
- Structured JSON logging (pino-pretty only in dev)
- LOG_LEVEL: STG=
info, PRD=warn
- API:
@sentry/node v10.45, PII scrubbing, 100% error capture
- iOS:
sentry-cocoa v8+, crash + ANR detection, non-DEBUG only
- Console: personal token with
project:read + event:read scopes
- dSYM upload: Xcode build phase +
SENTRY_AUTH_TOKEN in Doppler
- 3 tokens correctly configured (ingest DSN, CLI upload, console API)
- SDK v2.11.0 initialized and sending signals
- 18 signals all wired up (conversion, monetization, engagement, errors, navigation)
- Test mode active in DEBUG builds, filtered in dashboard
- Free tier: 100K signals/month
- Unused API project identified for deletion
- 4-layer auth: Supabase email/pwd +
is_console_admin + email allowlist + bearer token
- Admin users:
console-admin-stg@impulseai.app (STG), console-admin@impulseai.app (PRD)
- Quick Links section (12 external service links)
- Anthropic balance tracking (manual entry + burn rate chart)
- Settings migrated from DB to Doppler env vars
- Security headers: nosniff, DENY frame, noindex, XSS protection, HSTS
- Console (
console.impulseai.app): live, SSL valid (Let’s Encrypt)
- Landing (
impulseai.app): live, SSL valid (GoDaddy)
- Docs (
docs.impulseai.app): live, SSL valid, password gate active
- Fastlane doctor: Xcode 26.3, Gradle OK
- TestFlight deploys working via
fastlane ios beta
- Match certificates valid (private
im-certificates repo)
- Apple auth secret: 172 days remaining
- Environment auto-detection: Simulator=DEV, USB=STG, TestFlight=STG, AppStore=PRD
- 2 branches:
main + production (no stale branches)
- CI Gate required on main, force push blocked
DOPPLER_TOKEN_STG + DOPPLER_TOKEN_PRD in repository secrets
- 6 workflows: ci, deploy-production, db-deploy, ios-release, apple-secret-check, rotate-apple-secret
- Apple secret check: runs weekly (Mondays), last run successful
- Pino structured JSON in production
pino-pretty gated by !isDev (never in production)
- No
console.log in production code (only JSDoc comments + 1 sentry startup log)
- iOS: AppLogger with WARN+ in release, INFO+ in debug
| Change | Impact |
|---|
Console email allowlist (CONSOLE_ALLOWED_EMAILS) | Defense-in-depth for admin login |
/admin/* exempt from API key middleware | Console uses bearer token, not mobile API key |
| Settings endpoints removed | No writable config via API (moved to Doppler) |
| Login placeholder removed | No email hints in login UI |
| Sentry token upgraded | Personal token with correct scopes (was org token with org:ci only) |
| Change | Impact |
|---|
| Cross-env health check removed | Each console checks its own API via localhost |
CONSOLE_API_PRODUCTION_URL etc. deleted | No cross-environment dependencies in Doppler |
maybeSingle() for empty tables | Prevents PostgREST 406 on empty anthropic_balance_entries |
| Server Action for balance entry | Avoids CORS issues (server-side fetch) |
| DELETE Content-Type fix | Empty body DELETE no longer rejected by Fastify |
| Feature | Description |
|---|
| Quick Links | 12 external service links on Monitoring page |
| Anthropic Balance Log | Manual entry form + history table + burn rate chart (recharts) |
| Console auth docs | Full architecture documented in Starlight docs |
New variables added:
| Variable | Config | Purpose |
|---|
CONSOLE_ALLOWED_EMAILS | stg, prd | Email allowlist for console login |
CONSOLE_SENTRY_API_TOKEN | stg, prd | Personal token for Sentry issue reads |
CONSOLE_SENTRY_ORG | stg, prd | digiteers-as |
CONSOLE_SENTRY_PROJECT | stg, prd | im-api |
SENTRY_AUTH_TOKEN | prd | dSYM upload for CI builds |
Variables removed:
| Variable | Reason |
|---|
CONSOLE_API_PRODUCTION_URL | Cross-env dependency removed |
CONSOLE_API_PRODUCTION_HEALTH_SECRET | Uses localhost + existing HEALTH_SECRET |
CONSOLE_API_STAGING_URL | Cross-env dependency removed |
CONSOLE_API_STAGING_HEALTH_SECRET | Cross-env dependency removed |
| Client | Client Auth | User Auth | Scope |
|---|
| iOS/Android | X-API-Key header | Supabase JWT | Own data (RLS) |
| Console | Bearer CONSOLE_ADMIN_TOKEN | Supabase session cookie | All data (admin) |
| Webhooks | Platform signature | None | Write (events) |
| Health check | Secret URL path | None | Status only |
| Token | Name | Type | Scopes | Used By |
|---|
SENTRY_DSN | N/A | Ingest URL | N/A | API error capture |
SENTRY_AUTH_TOKEN | im-ios-dsym-upload | Org | org:ci | dSYM upload (Xcode + CI) |
CONSOLE_SENTRY_API_TOKEN | im-console-monitoring | Personal | project:read, event:read | Console error dashboard |
| Item | Type | Notes |
|---|
| Sentry KMP migration | Spec ready | docs/specs/sentry-kmp-migration.md |
| Workflow failure notifications | Nice-to-have | GitHub notification settings |
TelemetryDeck: onboarding.skipped + trial.expired | Wired up | Verification with real user flow pending |