-- 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),
    issue_request_hash CHAR(64),
    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 UNIQUE INDEX IF NOT EXISTS uq_auth_platform_tokens_issue_idempotency_key
    ON auth_platform_tokens (issue_idempotency_key)
    WHERE issue_idempotency_key IS NOT NULL;
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;
