SOMA docs
Reference

Audit & fixes

Everything we fixed during the audit run on 2026-04-19.

Audit stages

StageResult
pnpm install✅ 12 workspaces
pnpm format:check (prettier)✅ all files
pnpm typecheck✅ 10/10 workspaces, ~5s warm
pnpm lint (ESLint flat configs)✅ 9/9 workspaces after install + 7 code fixes
pnpm test (vitest)✅ core 33 · ui 11 · tools suite · web 11 · bot 4 · db 1 skipped (needs live Postgres)
pnpm build (web only post-migration)✅ on Vercel, ~3min
E2E (Playwright, landing only)✅ 1 passed, 6 skipped (auth-gated, expected on prod without DEV_USER_ID)

Code-level fixes during audit

  1. Mastra memory eagerly connected to Postgres at module load, crashing next build with ECONNREFUSED. Gated behind SOMA_MASTRA_MEMORY=1 opt-in; SOMA's knowledge graph covers semantic recall without Mastra's built-in Memory.
  2. NODE_ENV=development in Doppler local broke next build — Next's /_error prerender fell back to Pages Router rendering, which imports <Html> from next/document. Removed NODE_ENV from Doppler so Next manages it itself.
  3. Sentry statically imported from 9 server files pulled the SDK's pages-router instrumentation into App Router chunks. Introduced apps/web/src/lib/sentry.ts lazy wrapper. All call sites migrated. Bumped @sentry/nextjs 8.55 → 9.47.
  4. Pino thread-stream crashed inside Next runtime (Turbopack rewrites absolute paths, worker can't resolve). Gated transport on !process.env.NEXT_RUNTIME → sync stdout inside serverless.
  5. Mastra tool names with . rejected by Anthropic (pattern ^[a-zA-Z0-9_-]{1,128}$). Renamed all memory.capturememory_capture, etc. Both internal id and the allTools object keys (which Mastra forwards as LLM tool names).
  6. DB setup script order bug — applied Drizzle migrations before extensions, but migrations reference vector type. Reordered: extensions first, then migrations, then RLS policies.
  7. Supabase direct DB hostname is IPv6-only on Pro without IPv4 add-on. Switched DATABASE_URL to Session pooler (aws-0-eu-west-1.pooler.supabase.com:5432).
  8. require-in-the-middle / import-in-the-middle not resolvable through pnpm hoisting. Added as direct deps of apps/web.

ESLint infrastructure (fixed during audit)

  • Installed eslint, @eslint/js, typescript-eslint, @next/eslint-plugin-next, eslint-plugin-react, eslint-plugin-react-hooks, globals at repo root.
  • Created 9 per-package eslint.config.mjs re-exporting from @soma/config/eslint/{base,next,node}.
  • Fixed 7 lint issues found on first pass (unused imports, floating promises, unnecessary as assertions).
  • pnpm lint now returns green 9/9 workspaces.

Open TODOs

  • RLS integration tests are still placeholder (expect(true).toBe(true) with skipIf). Wire a Docker Postgres into CI or run pnpm db:setup before vitest.
  • Gmail Pub/Sub subscription needs to be created in Google Cloud Console → Pub/Sub → subscribe topic to push https://soma-ai.cc/api/webhooks/gmail?token=<GMAIL_PUBSUB_TOKEN>, then users.watch on Gmail API per user. Without this, Gmail ingestion sits idle — the webhook handler and Inngest function exist but nobody's firing events yet.
  • Google OAuth consent screen verification (for public launch). Currently in Testing mode → only added Test users can sign in. Gmail scopes are "restricted" → security assessment required before public launch.
  • Supabase dev config — if needed later for staging. Currently only prod is used.