Remove Supabase
The database moved to a container of our own; the platform is gone. This takes out what was left of it — and, where the leftovers were load bearing, moves rather than deletes. Moved, not deleted: supabase/migrations/ -> db/migrations/ the schema's source of truth supabase/build-org.ts -> scripts/build-org.ts lib/supabase/types.ts -> lib/types.ts 52 import sites repointed The bookkeeping needed care. It lived in `supabase_migrations.schema_migrations`, and simply renaming the schema would have left the runner facing an empty table: it would have called all 67 migrations pending and replayed them against a database that is long since current. So the runner now creates `migrationen.schema_migrations` and, once, copies the old rows across — guarded so a second run does nothing and a fresh database skips it entirely. Only then does migration 20260907100000 drop the old schema. Deleted: the CLI config, the seed, the historical schema/function dumps (nothing read them), scripts/umzug-von-supabase.sh (the move is done), and both Supabase packages plus the CLI. Nothing in the application imported them — the build now succeeds with no environment variables at all, which is the proof. Integration tests: six of them signed in through Supabase Auth and asserted against the anon key and the service role. That model is gone, so the tests were not portable — they are deleted. session-context and employee-status-filter already ran on pg and are untouched; om-reporting is ported to a direct connection because it guards a real risk (the reporting line rule exists twice, once in SQL and once in TypeScript). CI: the integration job started a Supabase stack. It now runs a postgres service, applies deploy/db-init and every migration to an empty database — that was the valuable part, and it still holds — then checks that a second run is a no-op, which is what proves the bookkeeping works. Docs: security-review.md audited a service-role key, a cookie adapter and auth.users, none of which exist. Restating findings about removed components would suggest today's system had been reviewed; it has not. It now records what was removed and says a fresh review is due. data-model.md was already marked obsolete and described the pre-OM schema; azure-migration.md was a plan for a route not taken. Both deleted. Verified: npm ci, typecheck, lint, 445 tests, build — all clean without the packages. Integration tests skip cleanly with no database. Migration SQL and the runner are reviewed but NOT executed: no Docker here, and the old instance no longer resolves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,12 +15,10 @@ eine `profiles`-Zeile braucht (siehe [docs/entra-sso.md](docs/entra-sso.md)).
|
||||
- **Containerisiert:** die Next.js-App (`Dockerfile`) **und die Datenbank**
|
||||
(Dienst `db`, `postgres:17-alpine`). Beide zusammen in
|
||||
`docker-compose.yml`; die Daten liegen im benannten Volume `db-daten`.
|
||||
- **Nicht mehr Supabase.** Die Anwendung sprach ohnehin unmittelbar mit
|
||||
PostgreSQL — Supabase war nur der Betreiber. Was die Plattform beisteuerte,
|
||||
bringt jetzt `deploy/db-init/` mit: die Anwendungsrolle ohne BYPASSRLS, die
|
||||
zwei benutzten Erweiterungen und eine Attrappe des `auth`-Schemas, die nur
|
||||
die alten Migrationen von Juni brauchen. Der Umzug steht in
|
||||
[Abschnitt 3a](#3a-umzug-von-supabase).
|
||||
- **Die Datenbank gehört zum Projekt.** Was eine gehostete Plattform sonst
|
||||
beisteuert, bringt `deploy/db-init/` mit: die Anwendungsrolle ohne
|
||||
BYPASSRLS, die zwei benutzten Erweiterungen und eine Attrappe des
|
||||
`auth`-Schemas, die nur die Migrationen von Juni 2026 brauchen.
|
||||
- Läuft die Datenbank woanders (Azure Flexible Server, RDS, eigenes Blech),
|
||||
genügt es, `DATABASE_URL` dorthin zeigen zu lassen und den `db`-Dienst nicht
|
||||
zu starten. Die Anwendung merkt keinen Unterschied.
|
||||
@@ -152,41 +150,6 @@ docker compose up -d --build
|
||||
`migrate` steht im Profil `tools` und läuft bei `docker compose up` nicht mit.
|
||||
Auf dem Host wird dafür weder Node noch psql gebraucht — nur Docker.
|
||||
|
||||
## 3a. Umzug von Supabase
|
||||
|
||||
Einmalig, wenn der Bestand noch bei Supabase liegt:
|
||||
|
||||
```bash
|
||||
SUPABASE_DB_URL='postgresql://postgres:<passwort>@<projekt>.supabase.com:5432/postgres' \
|
||||
./scripts/umzug-von-supabase.sh
|
||||
```
|
||||
|
||||
Was das Skript tut und warum:
|
||||
|
||||
1. **Schema aus den Migrationen**, nicht aus einem Abzug. Nachgewiesen ist,
|
||||
dass alle Migrationen auf einer leeren Datenbank durchlaufen und dabei
|
||||
Spalte für Spalte, Index für Index, Policy für Policy dasselbe ergeben wie
|
||||
die gewachsene Produktion. Der Weg hat zwei Vorteile: die Buchführung
|
||||
stimmt danach von selbst, und Supabase-eigene Rechte und Eigentümer kommen
|
||||
gar nicht erst mit.
|
||||
2. **Nur die Daten** werden abgezogen (`pg_dump --data-only
|
||||
--disable-triggers`). Ohne `--disable-triggers` stolpert jede
|
||||
Fremdschlüsselprüfung über die Ladereihenfolge. RLS steht nicht im Weg —
|
||||
keine der 19 Tabellen hat `FORCE ROW LEVEL SECURITY`, der Eigentümer
|
||||
schreibt also durch.
|
||||
3. Am Ende werden die Zeilenzahlen ausgegeben. **Mit denen bei Supabase
|
||||
vergleichen**, bevor irgendetwas abgeschaltet wird.
|
||||
|
||||
Der Abzug bleibt als Datei liegen. Erst löschen, wenn die Anwendung gegen die
|
||||
neue Datenbank nachweislich läuft.
|
||||
|
||||
Danach in `.env`:
|
||||
|
||||
```
|
||||
DATABASE_URL=postgresql://alpenwerk_app:<APP_DB_PASSWORD>@db:5432/alpenwerk
|
||||
DATABASE_SSL=false
|
||||
```
|
||||
|
||||
### Was am `auth`-Schema übrigbleibt
|
||||
|
||||
`deploy/db-init/01-auth-attrappe.sql` legt ein leeres `auth`-Schema an. Es wird
|
||||
@@ -283,8 +246,8 @@ und löscht sie danach wieder.
|
||||
|
||||
| Secret | Anmerkung |
|
||||
|---|---|
|
||||
| `DATABASE_URL` | Transaktions-Pooler (Supabase: 6543) — den benutzt die Anwendung |
|
||||
| `SUPABASE_DB_URL` | **Direkter** Zugang (Supabase: 5432) — nur für die Migrationen |
|
||||
| `DATABASE_URL` | Verbindung der Anwendungsrolle — die benutzt die Anwendung |
|
||||
| `MIGRATE_DATABASE_URL` | Zugang als Verwalter — nur für die Migrationen |
|
||||
| `AUTH_SECRET` | |
|
||||
| `AUTH_URL` | z. B. `https://hr.elycon.solutions` |
|
||||
| `AUTH_MICROSOFT_ENTRA_ID_ID` | |
|
||||
@@ -332,9 +295,9 @@ node --env-file=.env scripts/migrate.mjs --dry-run # was stünde an
|
||||
node --env-file=.env scripts/migrate.mjs # anwenden
|
||||
```
|
||||
|
||||
Buch geführt wird in `supabase_migrations.schema_migrations`, derselben Tabelle
|
||||
in derselben Form, die die Supabase-CLI benutzt — `supabase db push` von der
|
||||
Arbeitsstation bleibt damit möglich und überspringt, was hier schon lief.
|
||||
Buch geführt wird in `migrationen.schema_migrations`: eine Zeile je
|
||||
angewendeter Datei, mit ihrem Text. Der Läufer wendet nur an, was dort
|
||||
fehlt.
|
||||
|
||||
> **Einmalig, im August 2026 bereits erledigt:** Die Migrationen wurden bis
|
||||
> dahin von Hand eingespielt, die Buchführungstabelle existierte gar nicht. Ein
|
||||
@@ -409,9 +372,6 @@ Single-Instance-Compose-Konfiguration ist das nicht nötig.
|
||||
- **Cron läuft nicht:** `docker compose logs cron` – prüft, ob
|
||||
`/etc/crontabs/root` korrekt geschrieben wurde und ob `CRON_SECRET` in
|
||||
`.env` gesetzt ist (leer/fehlend führt serverseitig zu `401`).
|
||||
- **`max clients reached in session mode`:** der Verbindungsstring zeigt auf
|
||||
den Sitzungs-Modus des Poolers. Auf den Transaktions-Modus wechseln (bei
|
||||
Supabase Port 6543).
|
||||
- **Healthcheck rot:** `docker compose logs app` – meist `DATABASE_URL`
|
||||
fehlend oder nicht erreichbar. Der Pool baut die Verbindung erst beim
|
||||
ersten Zugriff auf, der Fehler steht deshalb im Log der Anfrage, nicht im
|
||||
|
||||
Reference in New Issue
Block a user