create extension if not exists pgcrypto; create extension if not exists citext; create schema if not exists secd; create table if not exists secd.identity ( identity_id bigserial primary key , identity_public_id uuid , data text , created_at timestamptz not null , deleted_at timestamptz , unique(identity_public_id) ); create table if not exists secd.session ( session_id bigserial primary key , identity_id bigint not null references secd.identity(identity_id) , secret_hash bytea not null , created_at timestamptz not null , expired_at timestamptz , revoked_at timestamptz , unique(secret_hash) ); create table if not exists secd.oauth_provider ( oauth_provider_id serial primary key , name text not null , flow text not null , base_url text not null , response_type text not null , default_scope text , client_id text not null , client_secret text not null , redirect_url text not null , created_at timestamptz not null , deleted_at timestamptz , unique (name, flow) ); create table if not exists secd.oauth_validation ( oauth_validation_id bigserial primary key , oauth_validation_public_id uuid not null , oauth_provider_id integer not null references secd.oauth_provider(oauth_provider_id) , access_token text , raw_response text , created_at timestamptz not null , validated_at timestamptz , unique (oauth_validation_public_id) ); create table if not exists secd.identity_oauth_validation ( identity_oauth_validation_id bigserial primary key -- A validation does not require an identity to initiate , identity_id bigint references secd.identity(identity_id) , oauth_validation_id bigint not null references secd.oauth_validation(oauth_validation_id) , revoked_at timestamptz , deleted_at timestamptz , unique(identity_id, oauth_validation_id) ); create table if not exists secd.email ( email_id bigserial primary key , address text not null , unique(address) ); create table if not exists secd.email_validation ( email_validation_id bigserial primary key , email_validation_public_id uuid not null , email_id bigint not null references secd.email(email_id) , code text , is_oauth_derived boolean not null , created_at timestamptz not null , validated_at timestamptz , expired_at timestamptz , unique(email_validation_public_id) ); create table if not exists secd.identity_email_validation ( identity_email_validation_id bigserial primary key -- A validation does not require an identity to initiate , identity_id bigint references secd.identity(identity_id) , email_validation_id bigint not null references secd.email_validation(email_validation_id) , revoked_at timestamptz , deleted_at timestamptz , unique(identity_id, email_validation_id) );