CREATE TABLE IF NOT EXISTS gateway_security_event_receipts ( issuer text NOT NULL, jti uuid NOT NULL, audience text NOT NULL, event_type text NOT NULL, transaction_id text, tenant_id text, subject_hash text, event_timestamp timestamptz, received_at timestamptz NOT NULL DEFAULT now(), processed_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (issuer, jti) ); CREATE INDEX IF NOT EXISTS idx_gateway_security_event_receipts_received ON gateway_security_event_receipts(received_at DESC); CREATE TABLE IF NOT EXISTS gateway_oidc_revocation_watermarks ( issuer text NOT NULL, tenant_id text NOT NULL, subject text NOT NULL, revoked_at timestamptz NOT NULL, source_jti uuid NOT NULL, updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (issuer, tenant_id, subject) ); CREATE INDEX IF NOT EXISTS idx_gateway_oidc_revocation_watermarks_lookup ON gateway_oidc_revocation_watermarks(issuer, tenant_id, subject, revoked_at); CREATE TABLE IF NOT EXISTS gateway_security_event_stream_state ( issuer text NOT NULL, audience text NOT NULL, stream_id uuid NOT NULL, stream_status text NOT NULL DEFAULT 'unknown', mode text NOT NULL DEFAULT 'bootstrap', last_verification_at timestamptz, bootstrap_until timestamptz, consecutive_verifications integer NOT NULL DEFAULT 0, pending_state_hash bytea, pending_state_created_at timestamptz, fallback_since timestamptz, last_error_category text, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (issuer, audience), UNIQUE (stream_id), CONSTRAINT gateway_security_event_stream_state_mode CHECK (mode IN ('bootstrap','push_healthy','introspection_fallback')), CONSTRAINT gateway_security_event_stream_state_status CHECK (stream_status IN ('unknown','enabled','paused','disabled')), CONSTRAINT gateway_security_event_stream_state_pending_hash CHECK (pending_state_hash IS NULL OR octet_length(pending_state_hash) = 32) ); CREATE TABLE IF NOT EXISTS gateway_security_event_verification_challenges ( issuer text NOT NULL, audience text NOT NULL, state_hash bytea NOT NULL, created_at timestamptz NOT NULL, expires_at timestamptz NOT NULL, PRIMARY KEY (issuer, audience, state_hash), FOREIGN KEY (issuer, audience) REFERENCES gateway_security_event_stream_state(issuer, audience) ON DELETE CASCADE, CONSTRAINT gateway_security_event_verification_challenge_hash CHECK (octet_length(state_hash) = 32) ); CREATE INDEX IF NOT EXISTS idx_gateway_security_event_challenges_expiry ON gateway_security_event_verification_challenges(expires_at);