-- IT operations controller — entitlements + metering (Phase 4 skeleton) -- Postgres 14+. Run on dedicated IT DB CT; do not share with app OLTP. -- Link to dbis_core marketplace via external_sku_id / iru_offering_ref. CREATE TABLE IF NOT EXISTS entitlement ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), org_id TEXT NOT NULL, sku_code TEXT NOT NULL, external_sku_id TEXT, seat_count INT NOT NULL DEFAULT 1 CHECK (seat_count >= 0), valid_from TIMESTAMPTZ NOT NULL DEFAULT now(), valid_to TIMESTAMPTZ, stripe_subscription_id TEXT, stripe_customer_id TEXT, metadata JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_entitlement_org ON entitlement (org_id); CREATE INDEX IF NOT EXISTS idx_entitlement_stripe_sub ON entitlement (stripe_subscription_id); CREATE TABLE IF NOT EXISTS usage_snapshot ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), collected_at TIMESTAMPTZ NOT NULL DEFAULT now(), vmid TEXT NOT NULL, node TEXT, vcpus REAL, memory_mb REAL, disk_gb REAL, source TEXT NOT NULL DEFAULT 'proxmox_api', raw JSONB ); CREATE INDEX IF NOT EXISTS idx_usage_snapshot_time ON usage_snapshot (collected_at); CREATE TABLE IF NOT EXISTS stripe_webhook_event ( id TEXT PRIMARY KEY, received_at TIMESTAMPTZ NOT NULL DEFAULT now(), event_type TEXT NOT NULL, payload JSONB NOT NULL, processed BOOLEAN NOT NULL DEFAULT false, error TEXT ); -- Optional: map Keycloak group / subject to org for RBAC in BFF CREATE TABLE IF NOT EXISTS it_operator_org ( keycloak_sub TEXT PRIMARY KEY, org_id TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() );