Files
shared-memory/apps/web/drizzle/0003_groups.sql
T

64 lines
2.9 KiB
SQL
Raw Normal View History

-- Groups + per-user group memberships, plus the `memory_access` enum.
--
-- This migration is the substrate for the upcoming group-scoped sharing
-- feature (project_shares). It owns:
--
-- * memory_access enum — reserved for project_shares to reference.
-- * groups table — one row per distinct group seen in any user's
-- OIDC `groups` claim, keyed by (oidc_iss, name)
-- so different IdPs can both have a group called
-- e.g. "platform" without colliding.
-- * user_groups table — current group memberships for each user. Synced
-- on every sign-in: rows are inserted/deleted to
-- mirror the freshly-issued claim, so IdP
-- membership changes propagate at next login.
--
-- We deliberately do NOT add project_shares here — that's Agent B's 0004.
-- Defining the enum in 0003 lets 0004 reference it without sequencing
-- gymnastics.
-- =============================================================================
-- Enums
-- =============================================================================
CREATE TYPE "memory_access" AS ENUM ('ro', 'rw');
-- =============================================================================
-- groups
-- =============================================================================
CREATE TABLE "groups" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
-- OIDC issuer this group's identity comes from. Pairs with `name` to
-- form the natural key — same group name in two IdPs are distinct rows.
"oidc_iss" text NOT NULL,
-- The group name as it appears in the OIDC `groups` claim.
"name" text NOT NULL,
-- Optional human-friendly label. Most IdPs only emit names so this is
-- typically NULL; reserved for future enrichment.
"display_name" text,
"created_at" timestamptz NOT NULL DEFAULT now(),
"updated_at" timestamptz NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX "groups_iss_name_uq" ON "groups" ("oidc_iss", "name");
CREATE TRIGGER groups_set_updated_at BEFORE UPDATE ON "groups"
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
-- =============================================================================
-- user_groups
-- =============================================================================
CREATE TABLE "user_groups" (
"user_id" uuid NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
"group_id" uuid NOT NULL REFERENCES "groups"("id") ON DELETE CASCADE,
-- When this membership was last observed in a sign-in claim. The auth
-- callback rewrites this on every login (insert ... on conflict do
-- update) so it's effectively "last sign-in seen this membership".
"synced_at" timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY ("user_id", "group_id")
);
CREATE INDEX "user_groups_user_idx" ON "user_groups" ("user_id");