-- P1 core schema (see .ai/domain/erd.md) CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE TABLE IF NOT EXISTS schema_migrations ( version text PRIMARY KEY, applied_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS users ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), status varchar(32) NOT NULL DEFAULT 'active', created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL ); CREATE TABLE IF NOT EXISTS device_identities ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), device_key varchar(128) NOT NULL UNIQUE, user_id uuid NULL REFERENCES users(id), created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL ); CREATE INDEX IF NOT EXISTS idx_device_identities_user_id ON device_identities(user_id); CREATE TABLE IF NOT EXISTS profiles ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id), relation varchar(16) NOT NULL CHECK (relation IN ('self', 'other')), display_name varchar(64) NOT NULL DEFAULT '', birth_date date NOT NULL, birth_time time NULL, birth_place varchar(128) NULL, gender varchar(32) NULL, relation_type varchar(32) NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL ); CREATE INDEX IF NOT EXISTS idx_profiles_user_id ON profiles(user_id); CREATE TABLE IF NOT EXISTS growth_reports ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id), profile_id uuid NOT NULL REFERENCES profiles(id), type varchar(32) NOT NULL, summary jsonb NOT NULL DEFAULT '{}', detail jsonb NOT NULL DEFAULT '{}', created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL ); CREATE INDEX IF NOT EXISTS idx_growth_reports_user_id ON growth_reports(user_id); CREATE INDEX IF NOT EXISTS idx_growth_reports_profile_id ON growth_reports(profile_id); CREATE TABLE IF NOT EXISTS memberships ( user_id uuid PRIMARY KEY REFERENCES users(id), plan varchar(32) NOT NULL DEFAULT 'month', status varchar(32) NOT NULL DEFAULT 'expired', expires_at timestamptz NULL, ask_quota_left int NOT NULL DEFAULT 0, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL ); CREATE TABLE IF NOT EXISTS orders ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id), kind varchar(32) NOT NULL, plan varchar(32) NULL, report_id uuid NULL REFERENCES growth_reports(id), amount_cents int NOT NULL DEFAULT 0, status varchar(32) NOT NULL DEFAULT 'created', created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL ); CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id); CREATE TABLE IF NOT EXISTS payments ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), order_id uuid NOT NULL REFERENCES orders(id), channel varchar(32) NOT NULL DEFAULT 'mock', status varchar(32) NOT NULL DEFAULT 'created', raw jsonb NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL ); CREATE INDEX IF NOT EXISTS idx_payments_order_id ON payments(order_id); CREATE TABLE IF NOT EXISTS deep_accesses ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES users(id), report_id uuid NOT NULL REFERENCES growth_reports(id), order_id uuid NOT NULL REFERENCES orders(id), created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), deleted_at timestamptz NULL, UNIQUE (user_id, report_id) ); CREATE INDEX IF NOT EXISTS idx_deep_accesses_report_id ON deep_accesses(report_id);