- Drop @supabase/supabase-js entirely; add drizzle-orm + postgres (porsager) driver - New packages/db: schema (pgSchema ordinarthur_os), client factory, migrate runner, drizzle-kit config - SQL migrations: 0000_init (pgcrypto + schema), 0001_jobs (jobs + job_search_criteria, no RLS) - Rewrite apps/api db module with DI symbols DB/DB_HANDLE + @InjectDb() decorator - Rewrite jobs.service.ts with Drizzle queries (upsert via onConflictDoUpdate, arrayOverlaps for stack filter) - Replace SUPABASE_* env vars with DATABASE_URL in env config + .env.example - Add docker-compose.yml (Postgres 16-alpine, dev only) - Add deploy/k8s/postgres.yaml (StatefulSet + PVC), migrate.job.yaml, updated secrets.template.yaml - Update all docs (README, PLAN, ARCHITECTURE, CLAUDE.md, AGENTS.md, packages/db/README.md) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ordinarthur-os/db
Schéma Postgres + migrations versionnées pour ordinarthur-os, via Drizzle ORM.
La base tourne dans le cluster k3s d'Arthur (cf. deploy/k8s/postgres.yaml). Plus de Supabase — l'API NestJS parle directement à Postgres.
Arbo
src/schema/— définitions Drizzle (TypeScript). Une table = un fichier, réexporté depuisschema/index.ts.src/client.ts— factorycreateDb(connectionString)utilisée par l'API.src/migrate.ts— runner des migrations (consommeDATABASE_URL).drizzle.config.ts— config drizzle-kit.migrations/— SQL versionné (0000_init.sql,0001_jobs.sql, …) +meta/_journal.jsonexploité par le runner.
Commandes
Depuis la racine du monorepo :
# 0. Lancer le Postgres de dev (cf. docker-compose.yml à la racine).
docker compose up -d
# 1. Générer un diff SQL à partir du schéma TS (nouvelle migration).
pnpm --filter @ordinarthur-os/db generate
# 2. Appliquer les migrations pendantes sur la base pointée par DATABASE_URL.
# Le .env de apps/api suffit : le script lit process.env.DATABASE_URL.
pnpm --filter @ordinarthur-os/db migrate
# 3. Ouvrir Drizzle Studio (inspection UI).
pnpm --filter @ordinarthur-os/db studio
Convention migrations
0000_init.sql— extensionpgcrypto+ création du schémaordinarthur_os. Idempotent (à ne PAS régénérer via drizzle-kit).0001_jobs.sql— tablesjobs+job_search_criteria(Phase 1).0002_todos.sql—todos+client_mutations(Phase 2).0003_projects.sql—projects,project_steps,project_ideas(Phase 3).0004_agenda.sql—calendar_events,google_oauth_tokens(Phase 4).0005_ai.sql—ai_actions(Phase 5).0006_health.sql—daily_checkins(Phase 7).
Plus de RLS
Contrairement au setup Supabase initial, la DB n'est pas exposée publiquement : le seul consommateur est l'API NestJS, protégée par bearer token. On ne déploie donc aucune policy RLS — c'est du pur isolement réseau (service ClusterIP interne) + contrôle d'accès Postgres classique.