diff --git a/CHANGELOG.md b/CHANGELOG.md index d6c4265..f6e3f51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Kern-Tabellen-Migration fuer `profiles`, `tenants` und `memberships` angelegt. - `golang-migrate`-Setup mit Baseline-Migration und Make-Targets fuer Up/Down/Version angelegt. - Gemeinsames Go-Modul `platform/` mit ENV-Konfiguration und strukturiertem JSON-Logging angelegt. - Forgejo-Actions-CI mit Go/Frontend-Verifikation und Gitleaks-Secret-Scan angelegt. diff --git a/TODO.md b/TODO.md index 5d2fb9c..48f1b8c 100644 --- a/TODO.md +++ b/TODO.md @@ -34,6 +34,11 @@ Arbeitsliste auf Basis von `proxmox-console-entwicklungsplan.md`. Die Entwurfsda - [x] `make migrate`, `make migrate-down` und `make migrate-version` verdrahtet - [x] Migrationen laufen lokal per `migrate`-Binary oder Docker-Image `migrate/migrate:v4.18.3` - [x] DB-URL wird aus `.env`, `deploy/supabase/.env` oder `MIGRATE_DATABASE_URL` abgeleitet +- [x] E2-T02: Kern-Tabellen: profiles, tenants, memberships + - [x] Migration fuer `profiles`, `tenants`, `memberships` angelegt + - [x] `profiles.id` referenziert `auth.users.id` + - [x] Rollen-Enum `membership_role` mit `owner`, `admin`, `member`, `viewer` angelegt + - [x] FKs, Unique-/Primary-Keys und Indizes gesetzt ## MVP-Backlog @@ -73,3 +78,4 @@ Arbeitsliste auf Basis von `proxmox-console-entwicklungsplan.md`. Die Entwurfsda - 2026-06-10: Gitleaks-Secret-Scan lokal mit `zricethezav/gitleaks:v8.28.0` erfolgreich; keine Leaks gefunden. - 2026-06-10: Gemeinsamer Go-Config-/Logging-Layer angelegt; Tests fuer Config-Defaults und Validierung ergaenzt. - 2026-06-10: `golang-migrate`-Setup mit Baseline-Migration angelegt; lokaler Up/Down-Lauf gegen Supabase verifiziert. +- 2026-06-10: Kern-Tabellen-Migration `0002_core_identity` angelegt und lokal gegen Supabase verifiziert. diff --git a/migrations/0002_core_identity.down.sql b/migrations/0002_core_identity.down.sql new file mode 100644 index 0000000..c43d7e1 --- /dev/null +++ b/migrations/0002_core_identity.down.sql @@ -0,0 +1,7 @@ +DROP INDEX IF EXISTS public.memberships_profile_id_idx; +DROP INDEX IF EXISTS public.memberships_tenant_id_idx; +DROP TABLE IF EXISTS public.memberships; +DROP INDEX IF EXISTS public.tenants_slug_key; +DROP TABLE IF EXISTS public.tenants; +DROP TABLE IF EXISTS public.profiles; +DROP TYPE IF EXISTS public.membership_role; diff --git a/migrations/0002_core_identity.up.sql b/migrations/0002_core_identity.up.sql new file mode 100644 index 0000000..e2d408a --- /dev/null +++ b/migrations/0002_core_identity.up.sql @@ -0,0 +1,31 @@ +CREATE TYPE public.membership_role AS ENUM ('owner', 'admin', 'member', 'viewer'); + +CREATE TABLE public.profiles ( + id uuid PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, + email text NOT NULL, + display_name text, + created_at timestamptz NOT NULL DEFAULT now() +); + +CREATE TABLE public.tenants ( + id uuid PRIMARY KEY DEFAULT gen_random_uuid(), + name text NOT NULL, + slug text NOT NULL, + status text NOT NULL DEFAULT 'active', + created_at timestamptz NOT NULL DEFAULT now(), + CONSTRAINT tenants_slug_format_check CHECK (slug ~ '^[a-z0-9]([a-z0-9-]*[a-z0-9])?$'), + CONSTRAINT tenants_status_check CHECK (status IN ('active', 'suspended')) +); + +CREATE UNIQUE INDEX tenants_slug_key ON public.tenants (slug); + +CREATE TABLE public.memberships ( + profile_id uuid NOT NULL REFERENCES public.profiles(id) ON DELETE CASCADE, + tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, + role public.membership_role NOT NULL DEFAULT 'member', + created_at timestamptz NOT NULL DEFAULT now(), + PRIMARY KEY (profile_id, tenant_id) +); + +CREATE INDEX memberships_tenant_id_idx ON public.memberships (tenant_id); +CREATE INDEX memberships_profile_id_idx ON public.memberships (profile_id);