-- Migration 0047: Enhanced Audit Logging for Authentication Events
-- AEG-AUTH-001: Comprehensive audit trail for security compliance
-- Created: 2026-08-18
-- Status: READY FOR DEPLOYMENT

BEGIN;

-- 1. CREATE ENHANCED AUDIT LOG TABLE
CREATE TABLE IF NOT EXISTS public.auth_audit_log (
  audit_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

  -- Event Classification
  event_type VARCHAR(50) NOT NULL
    CHECK (event_type IN ('LOGIN', 'LOGOUT', 'MFA_SETUP', 'MFA_VERIFY', 'TOKEN_REFRESH', 'PERMISSION_DENIED', 'INVALID_TOKEN')),

  -- User Information
  identity_id UUID REFERENCES public.identity(identity_id) ON DELETE SET NULL,
  username VARCHAR(255),
  role VARCHAR(100),

  -- Request Context (for forensics)
  ip_address INET,
  user_agent TEXT,
  endpoint VARCHAR(255),
  http_method VARCHAR(10),

  -- Result Status
  status VARCHAR(20) NOT NULL
    CHECK (status IN ('SUCCESS', 'FAILURE', 'BLOCKED')),

  -- Error Details
  error_code VARCHAR(50),
  error_message TEXT,

  -- Security Details
  token_claims JSONB,  -- For token analysis
  authentication_method VARCHAR(50),  -- JWT, Header, MFA, etc.

  -- Lifecycle (immutable append-only)
  occurred_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
  correlation_id UUID NOT NULL DEFAULT gen_random_uuid(),

  -- Indexing
  INDEX_created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- 2. INDEXES FOR PERFORMANCE & FORENSICS
CREATE INDEX idx_auth_audit_identity ON public.auth_audit_log(identity_id);
CREATE INDEX idx_auth_audit_occurred_at ON public.auth_audit_log(occurred_at DESC);
CREATE INDEX idx_auth_audit_event_type ON public.auth_audit_log(event_type);
CREATE INDEX idx_auth_audit_correlation ON public.auth_audit_log(correlation_id);
CREATE INDEX idx_auth_audit_ip_address ON public.auth_audit_log(ip_address);
CREATE INDEX idx_auth_audit_status ON public.auth_audit_log(status);
CREATE INDEX idx_auth_audit_username ON public.auth_audit_log(username);

-- 3. MONTHLY PARTITIONING (for large deployments)
-- CREATE TABLE auth_audit_log_2026_08 PARTITION OF public.auth_audit_log
--   FOR VALUES FROM ('2026-08-01') TO ('2026-09-01');

-- 4. IMMUTABILITY TRIGGER
CREATE OR REPLACE FUNCTION prevent_audit_log_modification()
RETURNS TRIGGER AS $$
BEGIN
  IF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN
    RAISE EXCEPTION 'Audit logs are immutable. Operation % not allowed.', TG_OP;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER auth_audit_log_immutable
  BEFORE UPDATE OR DELETE ON public.auth_audit_log
  FOR EACH ROW
  EXECUTE FUNCTION prevent_audit_log_modification();

-- 5. VIEW FOR COMPLIANCE REPORTING
CREATE OR REPLACE VIEW public.v_auth_audit_summary AS
SELECT
  DATE_TRUNC('hour', occurred_at) AS hour,
  event_type,
  status,
  COUNT(*) AS count,
  COUNT(DISTINCT identity_id) AS unique_users,
  COUNT(DISTINCT ip_address) AS unique_ips
FROM public.auth_audit_log
WHERE occurred_at > NOW() - INTERVAL '30 days'
GROUP BY DATE_TRUNC('hour', occurred_at), event_type, status
ORDER BY hour DESC, event_type;

-- 6. VIEW FOR FAILURE ANALYSIS
CREATE OR REPLACE VIEW public.v_auth_failures AS
SELECT
  identity_id,
  username,
  ip_address,
  event_type,
  error_code,
  error_message,
  occurred_at,
  COUNT(*) OVER (
    PARTITION BY ip_address, DATE_TRUNC('minute', occurred_at)
    ORDER BY occurred_at
  ) AS attempts_per_minute
FROM public.auth_audit_log
WHERE status IN ('FAILURE', 'BLOCKED')
  AND occurred_at > NOW() - INTERVAL '24 hours'
ORDER BY occurred_at DESC;

COMMIT;
