feat: integrate platform backend and application interfaces
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
-- Plan purchases use a separate payment-event table because the recharge
|
||||
-- payment_events.order_id foreign key intentionally points at recharge_orders.
|
||||
ALTER TABLE IF EXISTS plan_purchases ADD COLUMN IF NOT EXISTS provider TEXT NOT NULL DEFAULT 'adapter';
|
||||
ALTER TABLE IF EXISTS plan_purchases ADD COLUMN IF NOT EXISTS plan_snapshot JSONB;
|
||||
ALTER TABLE IF EXISTS plan_purchases ADD COLUMN IF NOT EXISTS credit_bucket_id UUID;
|
||||
ALTER TABLE IF EXISTS plan_purchases ADD COLUMN IF NOT EXISTS entitlement_id UUID;
|
||||
ALTER TABLE IF EXISTS recharge_orders ADD COLUMN IF NOT EXISTS credit_bucket_id UUID;
|
||||
ALTER TABLE IF EXISTS user_plan_entitlements ADD COLUMN IF NOT EXISTS snapshot JSONB;
|
||||
CREATE TABLE IF NOT EXISTS plan_payment_events (
|
||||
id UUID PRIMARY KEY,
|
||||
provider TEXT NOT NULL,
|
||||
external_event_id TEXT NOT NULL,
|
||||
purchase_id UUID NOT NULL REFERENCES plan_purchases(id),
|
||||
payload_digest TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
applied_at TIMESTAMPTZ,
|
||||
UNIQUE(provider, external_event_id)
|
||||
);
|
||||
|
||||
-- Runtime records that are part of the server's durable state but are not
|
||||
-- user-facing business aggregates. They keep authentication challenges,
|
||||
-- provider configuration and staging metadata relationally addressable while
|
||||
-- preserving encrypted payloads and ownership boundaries.
|
||||
ALTER TABLE IF EXISTS verification_codes ADD COLUMN IF NOT EXISTS record_key TEXT;
|
||||
ALTER TABLE IF EXISTS verification_codes ADD COLUMN IF NOT EXISTS record_kind TEXT NOT NULL DEFAULT 'verification';
|
||||
ALTER TABLE IF EXISTS verification_codes ADD COLUMN IF NOT EXISTS ip TEXT;
|
||||
ALTER TABLE IF EXISTS verification_codes ADD COLUMN IF NOT EXISTS device_id TEXT;
|
||||
ALTER TABLE IF EXISTS verification_codes ADD COLUMN IF NOT EXISTS max_attempts INTEGER NOT NULL DEFAULT 5;
|
||||
CREATE INDEX IF NOT EXISTS verification_codes_record_key_idx ON verification_codes(record_kind, record_key);
|
||||
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS mfa_secret_encrypted TEXT;
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS mfa_recovery_code_hashes JSONB;
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS mfa_last_totp_counter BIGINT;
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS mfa_required BOOLEAN NOT NULL DEFAULT false;
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS mfa_enabled BOOLEAN NOT NULL DEFAULT false;
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS roles JSONB NOT NULL DEFAULT '[]'::jsonb;
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS failed_login_count INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE IF EXISTS users ADD COLUMN IF NOT EXISTS locked_until BIGINT;
|
||||
|
||||
ALTER TABLE IF EXISTS sessions ADD COLUMN IF NOT EXISTS replaced_by TEXT;
|
||||
ALTER TABLE IF EXISTS sessions ADD COLUMN IF NOT EXISTS roles JSONB;
|
||||
ALTER TABLE IF EXISTS sessions ADD COLUMN IF NOT EXISTS scopes JSONB;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS captcha_challenges (
|
||||
id TEXT PRIMARY KEY,
|
||||
action TEXT NOT NULL,
|
||||
answer_hash TEXT NOT NULL,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
attempts INTEGER NOT NULL DEFAULT 0,
|
||||
max_attempts INTEGER NOT NULL DEFAULT 5,
|
||||
consumed_at TIMESTAMPTZ,
|
||||
ip TEXT NOT NULL,
|
||||
device_id TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS mfa_challenges (
|
||||
id TEXT PRIMARY KEY,
|
||||
subject_id TEXT NOT NULL,
|
||||
scope TEXT NOT NULL,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
attempts INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS session_families (
|
||||
family_id TEXT PRIMARY KEY,
|
||||
subject_id TEXT NOT NULL,
|
||||
scope TEXT NOT NULL,
|
||||
revoked_at TIMESTAMPTZ
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS admin_accounts (
|
||||
id TEXT PRIMARY KEY,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
mfa_secret_encrypted TEXT,
|
||||
mfa_required BOOLEAN NOT NULL DEFAULT true,
|
||||
recovery_code_hashes JSONB NOT NULL DEFAULT '[]'::jsonb,
|
||||
mfa_last_totp_counter BIGINT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS runtime_records (
|
||||
record_type TEXT NOT NULL,
|
||||
record_key TEXT NOT NULL,
|
||||
payload JSONB NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (record_type, record_key)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS message_providers (
|
||||
id TEXT PRIMARY KEY,
|
||||
snapshot JSONB NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS message_templates (
|
||||
id TEXT PRIMARY KEY,
|
||||
snapshot JSONB NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS payment_providers (
|
||||
id TEXT PRIMARY KEY,
|
||||
snapshot JSONB NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS webdav_files (
|
||||
user_id TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL,
|
||||
data TEXT NOT NULL DEFAULT '',
|
||||
checksum TEXT NOT NULL,
|
||||
etag TEXT NOT NULL,
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
updated_at TIMESTAMPTZ NOT NULL,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
PRIMARY KEY (user_id, path)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS webdav_sync_jobs (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
operation TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
data TEXT,
|
||||
mime_type TEXT,
|
||||
if_match TEXT,
|
||||
attempts INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL,
|
||||
next_attempt_at TIMESTAMPTZ NOT NULL,
|
||||
lease_expires_at TIMESTAMPTZ,
|
||||
last_error TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS stored_objects (
|
||||
id TEXT PRIMARY KEY,
|
||||
owner_id TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL,
|
||||
data TEXT,
|
||||
staging_key TEXT,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
task_id TEXT,
|
||||
revoked BOOLEAN NOT NULL DEFAULT false
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS webdav_files_user_idx ON webdav_files(user_id, updated_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS webdav_sync_jobs_user_idx ON webdav_sync_jobs(user_id, status, next_attempt_at);
|
||||
CREATE INDEX IF NOT EXISTS stored_objects_owner_idx ON stored_objects(owner_id, expires_at);
|
||||
|
||||
ALTER TABLE IF EXISTS webdav_configs ADD COLUMN IF NOT EXISTS manifest_retention_expires_at TIMESTAMPTZ;
|
||||
ALTER TABLE IF EXISTS webdav_configs ADD COLUMN IF NOT EXISTS manifest_extension_days INTEGER NOT NULL DEFAULT 0;
|
||||
Reference in New Issue
Block a user