Files

167 lines
5.4 KiB
SQL

-- Extended V1 domain tables. Secrets are referenced by encrypted_ref only;
-- user files live in staging/object adapters and never in static directories.
CREATE TABLE IF NOT EXISTS balance_units (
id TEXT PRIMARY KEY,
version INTEGER NOT NULL,
name TEXT NOT NULL,
short_code TEXT NOT NULL,
icon TEXT NOT NULL,
precision INTEGER NOT NULL DEFAULT 0,
currency_code TEXT NOT NULL,
conversion_rate NUMERIC(24, 8) NOT NULL,
rounding TEXT NOT NULL,
published_at TIMESTAMPTZ
);
CREATE TABLE IF NOT EXISTS balance_buckets (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id),
source TEXT NOT NULL,
remaining NUMERIC(24, 6) NOT NULL CHECK (remaining >= 0),
priority INTEGER NOT NULL DEFAULT 0,
expires_at TIMESTAMPTZ
);
CREATE TABLE IF NOT EXISTS membership_plans (
id TEXT PRIMARY KEY,
code TEXT NOT NULL UNIQUE,
version INTEGER NOT NULL DEFAULT 1,
snapshot JSONB NOT NULL,
published BOOLEAN NOT NULL DEFAULT false
);
CREATE TABLE IF NOT EXISTS user_plan_entitlements (
user_id UUID NOT NULL REFERENCES users(id),
plan_id TEXT NOT NULL REFERENCES membership_plans(id),
version INTEGER NOT NULL,
starts_at TIMESTAMPTZ NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
PRIMARY KEY (user_id, plan_id, version)
);
CREATE TABLE IF NOT EXISTS recharge_orders (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id),
provider TEXT NOT NULL,
status TEXT NOT NULL,
fiat_amount NUMERIC(24, 6) NOT NULL,
balance_amount NUMERIC(24, 6) NOT NULL,
unit_version INTEGER NOT NULL,
idempotency_key TEXT NOT NULL UNIQUE,
provider_order_id TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
paid_at TIMESTAMPTZ
);
CREATE TABLE IF NOT EXISTS payment_events (
id UUID PRIMARY KEY,
provider TEXT NOT NULL,
provider_event_id TEXT NOT NULL,
order_id UUID REFERENCES recharge_orders(id),
payload_digest TEXT NOT NULL,
status TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE(provider, provider_event_id)
);
CREATE TABLE IF NOT EXISTS generation_outputs (
id UUID PRIMARY KEY,
task_id UUID NOT NULL REFERENCES generation_tasks(id),
owner_id UUID NOT NULL REFERENCES users(id),
object_key TEXT NOT NULL,
mime_type TEXT NOT NULL,
status TEXT NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
revoked_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS upload_objects (
id UUID PRIMARY KEY,
owner_id UUID NOT NULL REFERENCES users(id),
object_key TEXT NOT NULL,
mime_type TEXT NOT NULL,
byte_size BIGINT NOT NULL,
checksum TEXT NOT NULL,
scan_status TEXT NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
deleted_at TIMESTAMPTZ
);
CREATE TABLE IF NOT EXISTS assets (
id UUID PRIMARY KEY,
owner_id UUID NOT NULL REFERENCES users(id),
task_id UUID REFERENCES generation_tasks(id),
object_id UUID REFERENCES upload_objects(id),
asset_type TEXT NOT NULL,
snapshot JSONB NOT NULL,
deleted_at TIMESTAMPTZ,
retention_expires_at TIMESTAMPTZ
);
CREATE TABLE IF NOT EXISTS email_sms_outbox (
id UUID PRIMARY KEY,
target_hash TEXT NOT NULL,
channel TEXT NOT NULL,
purpose TEXT NOT NULL,
payload JSONB NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
attempts INTEGER NOT NULL DEFAULT 0,
next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS webdav_configs (
user_id UUID PRIMARY KEY REFERENCES users(id),
encrypted_url_ref TEXT NOT NULL,
encrypted_username_ref TEXT,
encrypted_password_ref TEXT,
directory TEXT NOT NULL,
state TEXT NOT NULL,
last_synced_at TIMESTAMPTZ,
retention_days INTEGER NOT NULL DEFAULT 30
);
CREATE TABLE IF NOT EXISTS webdav_manifests (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id),
version BIGINT NOT NULL,
checksum TEXT NOT NULL,
manifest JSONB NOT NULL,
state TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE(user_id, version)
);
CREATE TABLE IF NOT EXISTS storage_policies (
id TEXT PRIMARY KEY,
version INTEGER NOT NULL,
snapshot JSONB NOT NULL,
published BOOLEAN NOT NULL DEFAULT false
);
CREATE TABLE IF NOT EXISTS admin_roles (
id TEXT PRIMARY KEY,
permissions JSONB NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT true
);
CREATE TABLE IF NOT EXISTS admin_user_roles (
admin_id UUID NOT NULL,
role_id TEXT NOT NULL REFERENCES admin_roles(id),
PRIMARY KEY (admin_id, role_id)
);
CREATE TABLE IF NOT EXISTS admin_approvals (
id UUID PRIMARY KEY,
requester_id UUID NOT NULL,
approver_id UUID,
action TEXT NOT NULL,
object_type TEXT NOT NULL,
object_id TEXT,
status TEXT NOT NULL DEFAULT 'pending',
before_value JSONB,
after_value JSONB,
expires_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
approved_at TIMESTAMPTZ
);
CREATE TABLE IF NOT EXISTS task_event_log (
task_id UUID NOT NULL REFERENCES generation_tasks(id),
sequence BIGINT NOT NULL,
event_id UUID NOT NULL UNIQUE,
event_type TEXT NOT NULL,
payload JSONB NOT NULL,
occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (task_id, sequence)
);
CREATE INDEX IF NOT EXISTS upload_objects_owner_idx ON upload_objects(owner_id, expires_at);
CREATE INDEX IF NOT EXISTS generation_outputs_owner_idx ON generation_outputs(owner_id, expires_at);
CREATE INDEX IF NOT EXISTS recharge_orders_user_created_idx ON recharge_orders(user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS task_event_log_task_sequence_idx ON task_event_log(task_id, sequence);