-- API Key Management Migration -- Version: 001 -- Date: 2026-03-21 -- Description: Add API key management tables for secure API access -- API Keys Table CREATE TABLE IF NOT EXISTS api_keys ( id SERIAL PRIMARY KEY, key_id VARCHAR(48) UNIQUE NOT NULL, key_hash VARCHAR(64) NOT NULL, key_prefix VARCHAR(8) NOT NULL, name VARCHAR(128) NOT NULL, key_type VARCHAR(20) NOT NULL DEFAULT 'user', user_id BIGINT, service_name VARCHAR(64), permissions JSONB DEFAULT '["read", "write"]', expires_at TIMESTAMP, last_used_at TIMESTAMP, last_used_ip VARCHAR(45), usage_count BIGINT DEFAULT 0, status VARCHAR(20) NOT NULL DEFAULT 'active', rotation_required BOOLEAN DEFAULT FALSE, rotation_reason TEXT, grace_period_end TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Indexes for api_keys CREATE INDEX IF NOT EXISTS idx_api_keys_key_id ON api_keys(key_id); CREATE INDEX IF NOT EXISTS idx_api_keys_hash ON api_keys(key_hash); CREATE INDEX IF NOT EXISTS idx_api_keys_type ON api_keys(key_type); CREATE INDEX IF NOT EXISTS idx_api_keys_status ON api_keys(status); CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id); -- API Key Audit Log Table CREATE TABLE IF NOT EXISTS api_key_audit_log ( id SERIAL PRIMARY KEY, key_id VARCHAR(32) NOT NULL, action VARCHAR(50) NOT NULL, actor VARCHAR(128), ip_address VARCHAR(45), user_agent TEXT, request_path TEXT, response_code INT, anomaly_type VARCHAR(30), details JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Indexes for audit log CREATE INDEX IF NOT EXISTS idx_audit_key_id ON api_key_audit_log(key_id); CREATE INDEX IF NOT EXISTS idx_audit_action ON api_key_audit_log(action); CREATE INDEX IF NOT EXISTS idx_audit_created_at ON api_key_audit_log(created_at); CREATE INDEX IF NOT EXISTS idx_audit_ip ON api_key_audit_log(ip_address); -- API Key Anomalies Table CREATE TABLE IF NOT EXISTS api_key_anomalies ( id SERIAL PRIMARY KEY, key_id VARCHAR(32) NOT NULL, anomaly_type VARCHAR(30) NOT NULL, severity VARCHAR(10) NOT NULL, ip_address VARCHAR(45), request_count INT, error_count INT, error_rate DOUBLE PRECISION, unique_ips INT, details JSONB, resolved BOOLEAN DEFAULT FALSE, resolved_at TIMESTAMP, resolved_by VARCHAR(128), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Indexes for anomalies CREATE INDEX IF NOT EXISTS idx_anomalies_key_id ON api_key_anomalies(key_id); CREATE INDEX IF NOT EXISTS idx_anomalies_resolved ON api_key_anomalies(resolved); CREATE INDEX IF NOT EXISTS idx_anomalies_severity ON api_key_anomalies(severity); CREATE INDEX IF NOT EXISTS idx_anomalies_created_at ON api_key_anomalies(created_at); -- API Key Types Reference -- System (msys_): Internal system use, 365 days TTL, 72h grace -- User (muser_): User authentication, 90 days TTL, 24h grace -- Service (msvc_): Service-to-service, 180 days TTL, 48h grace -- Integration (mint_): Third-party integrations, 30 days TTL, 24h grace -- Emergency (memg_): Emergency access, 1 day TTL, 0h grace (immediate) -- Anomaly Types Reference -- high_request_rate: Requests exceed threshold per minute -- high_error_rate: Error rate exceeds threshold -- multiple_ips: Unusual number of unique IPs -- unusual_time: Activity at unusual hours -- brute_force: Potential brute force attack -- data_exfiltration: Unusual data access patterns