-- Migration: 004_v2_secure_session_core.sql
-- Purpose: v2 Secure Session Core (Task 1) - per-agent keys + tenancy-ready schema.
--          Adds the tenants table + a fixed default tenant, the connect_agent_keys
--          table, a nullable tenant_id on every scoped table (backfilled to the
--          default tenant), and the new session/support-code state columns.
--
-- Idempotent: CREATE TABLE IF NOT EXISTS / ADD COLUMN IF NOT EXISTS / ON CONFLICT.
-- Applied on server startup by sqlx::migrate!(); never pre-applied via psql.
-- See .claude/standards/gururmm/sqlx-migrations.md.

-- pgcrypto provides gen_random_uuid(); enabled in 001 but re-asserted for safety.
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- ============================================================================
-- Tenants (tenancy-ready; isolation NOT enforced until Phase 4)
-- ============================================================================

CREATE TABLE IF NOT EXISTS tenants (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Seed exactly one default tenant with a FIXED, hard-coded UUID. This constant
-- is the Phase-4 multi-tenancy switch point (mirrored by
-- db::tenancy::DEFAULT_TENANT_ID). Idempotent via ON CONFLICT.
INSERT INTO tenants (id, name)
VALUES ('00000000-0000-0000-0000-000000000001', 'Default Tenant')
ON CONFLICT (id) DO NOTHING;

-- ============================================================================
-- Per-agent keys (connect_agent_keys) - replaces the shared AGENT_API_KEY
-- ============================================================================
-- Stores ONLY the key hash. Hashing + cak_ issuance is Task 2; this table
-- persists an already-hashed value. revoked_at set marks a key inactive.

CREATE TABLE IF NOT EXISTS connect_agent_keys (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    machine_id UUID NOT NULL REFERENCES connect_machines(id) ON DELETE CASCADE,
    key_hash TEXT NOT NULL UNIQUE,
    tenant_id UUID,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    last_used_at TIMESTAMPTZ,
    revoked_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_connect_agent_keys_machine ON connect_agent_keys(machine_id);
CREATE INDEX IF NOT EXISTS idx_connect_agent_keys_key_hash ON connect_agent_keys(key_hash);

-- Backfill the agent-keys tenant_id to the default tenant (table is empty on a
-- fresh DB; this is a no-op there but keeps the migration self-consistent).
UPDATE connect_agent_keys
SET tenant_id = '00000000-0000-0000-0000-000000000001'
WHERE tenant_id IS NULL;

-- ============================================================================
-- tenant_id on all scoped tables (nullable; backfilled to the default tenant)
-- ============================================================================

ALTER TABLE connect_machines ADD COLUMN IF NOT EXISTS tenant_id UUID;
ALTER TABLE connect_sessions ADD COLUMN IF NOT EXISTS tenant_id UUID;
ALTER TABLE connect_support_codes ADD COLUMN IF NOT EXISTS tenant_id UUID;
ALTER TABLE connect_session_events ADD COLUMN IF NOT EXISTS tenant_id UUID;
ALTER TABLE users ADD COLUMN IF NOT EXISTS tenant_id UUID;

UPDATE connect_machines
SET tenant_id = '00000000-0000-0000-0000-000000000001'
WHERE tenant_id IS NULL;

UPDATE connect_sessions
SET tenant_id = '00000000-0000-0000-0000-000000000001'
WHERE tenant_id IS NULL;

UPDATE connect_support_codes
SET tenant_id = '00000000-0000-0000-0000-000000000001'
WHERE tenant_id IS NULL;

UPDATE connect_session_events
SET tenant_id = '00000000-0000-0000-0000-000000000001'
WHERE tenant_id IS NULL;

UPDATE users
SET tenant_id = '00000000-0000-0000-0000-000000000001'
WHERE tenant_id IS NULL;

CREATE INDEX IF NOT EXISTS idx_connect_machines_tenant ON connect_machines(tenant_id);
CREATE INDEX IF NOT EXISTS idx_connect_sessions_tenant ON connect_sessions(tenant_id);
CREATE INDEX IF NOT EXISTS idx_connect_support_codes_tenant ON connect_support_codes(tenant_id);
CREATE INDEX IF NOT EXISTS idx_connect_session_events_tenant ON connect_session_events(tenant_id);
CREATE INDEX IF NOT EXISTS idx_users_tenant ON users(tenant_id);

-- ============================================================================
-- Session state columns (managed/unattended + source + consent)
-- ============================================================================

ALTER TABLE connect_sessions
    ADD COLUMN IF NOT EXISTS is_managed BOOLEAN NOT NULL DEFAULT false;

-- source: 'standalone' (ad-hoc support code) | 'gururmm' (managed via RMM).
ALTER TABLE connect_sessions
    ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'standalone'
    CHECK (source IN ('standalone', 'gururmm'));

-- consent_state: not_required (managed/unattended) | pending | granted | denied.
-- Attended-consent enforcement is Task 5; this is the schema column only.
ALTER TABLE connect_sessions
    ADD COLUMN IF NOT EXISTS consent_state TEXT NOT NULL DEFAULT 'not_required'
    CHECK (consent_state IN ('not_required', 'pending', 'granted', 'denied'));

-- ============================================================================
-- Support-code single-use marker (consumed in Task 4 - schema only here)
-- ============================================================================

ALTER TABLE connect_support_codes ADD COLUMN IF NOT EXISTS consumed_at TIMESTAMPTZ;
