-- Token runtime schema baseline (PostgreSQL 15) -- Purpose: persistent storage for platform token lifecycle and audit timeline. -- Updated: 2026-03-30 BEGIN; CREATE TABLE IF NOT EXISTS auth_platform_tokens ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, token_id VARCHAR(64) NOT NULL UNIQUE, token_fingerprint CHAR(64) NOT NULL, hash_algo VARCHAR(32) NOT NULL DEFAULT 'SHA-256', tenant_id BIGINT, project_id BIGINT, subject_id VARCHAR(128) NOT NULL, role_code VARCHAR(32) NOT NULL CHECK (role_code IN ('owner', 'viewer', 'admin')), scope_json JSONB NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'revoked', 'expired')), issued_at TIMESTAMPTZ NOT NULL, expires_at TIMESTAMPTZ NOT NULL, revoked_at TIMESTAMPTZ, revoked_reason VARCHAR(256), issue_request_id VARCHAR(128) NOT NULL, issue_idempotency_key VARCHAR(128), last_seen_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX IF NOT EXISTS uq_auth_platform_tokens_fingerprint ON auth_platform_tokens (token_fingerprint); CREATE INDEX IF NOT EXISTS idx_auth_platform_tokens_subject_status ON auth_platform_tokens (subject_id, status); CREATE INDEX IF NOT EXISTS idx_auth_platform_tokens_expires_at ON auth_platform_tokens (expires_at); CREATE INDEX IF NOT EXISTS idx_auth_platform_tokens_tenant_project ON auth_platform_tokens (tenant_id, project_id); CREATE TABLE IF NOT EXISTS auth_token_audit_events ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, event_id VARCHAR(64) NOT NULL UNIQUE, event_name VARCHAR(128) NOT NULL, request_id VARCHAR(128) NOT NULL, token_id VARCHAR(64), subject_id VARCHAR(128), route VARCHAR(256) NOT NULL, result_code VARCHAR(64) NOT NULL, client_ip INET, tenant_id BIGINT, project_id BIGINT, operator_id VARCHAR(128), created_at TIMESTAMPTZ NOT NULL, metadata JSONB ); CREATE INDEX IF NOT EXISTS idx_auth_token_audit_events_token_time ON auth_token_audit_events (token_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_auth_token_audit_events_request_id ON auth_token_audit_events (request_id); CREATE INDEX IF NOT EXISTS idx_auth_token_audit_events_subject_time ON auth_token_audit_events (subject_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_auth_token_audit_events_event_name ON auth_token_audit_events (event_name); COMMIT;