CREATE TABLE firewall_client ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES tenant (id) ON DELETE CASCADE, name TEXT NOT NULL, hostname TEXT, token_prefix TEXT NOT NULL, token_hash BYTEA NOT NULL, status TEXT NOT NULL DEFAULT 'pending', enroll_seed_used BOOLEAN NOT NULL DEFAULT TRUE, last_seen_at TIMESTAMPTZ, last_seen_at_source TEXT, last_seen_ip TEXT, last_apply_at TIMESTAMPTZ, last_apply_status TEXT, last_apply_error TEXT, last_apply_prefix_count INTEGER DEFAULT 0, last_apply_ip_count INTEGER DEFAULT 0, last_apply_source TEXT, client_version TEXT, settings_json JSONB NOT NULL DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), approved_at TIMESTAMPTZ, approved_by_api_key_id UUID, revoked_at TIMESTAMPTZ, CONSTRAINT firewall_client_status_chk CHECK (status IN ('pending', 'approved', 'revoked')), CONSTRAINT firewall_client_name_chk CHECK (length(trim(name)) > 0), CONSTRAINT firewall_client_token_hash_len_chk CHECK (octet_length(token_hash) = 32) ); CREATE UNIQUE INDEX idx_firewall_client_token_hash ON firewall_client (token_hash); CREATE INDEX idx_firewall_client_tenant_status ON firewall_client (tenant_id, status); CREATE INDEX idx_firewall_client_last_seen ON firewall_client (last_seen_at DESC) WHERE status = 'approved'; CREATE TABLE firewall_rule ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES tenant (id) ON DELETE CASCADE, client_id UUID REFERENCES firewall_client (id) ON DELETE CASCADE, priority INTEGER NOT NULL, action TEXT NOT NULL, community_id UUID REFERENCES bgp_community (id) ON DELETE CASCADE, comment TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), CONSTRAINT firewall_rule_action_chk CHECK (action IN ('block', 'accept')), CONSTRAINT firewall_rule_priority_chk CHECK (priority >= 1 AND priority <= 10000), CONSTRAINT firewall_rule_scope_uniq UNIQUE (tenant_id, client_id, priority) ); CREATE INDEX idx_firewall_rule_tenant_priority ON firewall_rule (tenant_id, priority); CREATE INDEX idx_firewall_rule_client ON firewall_rule (client_id) WHERE client_id IS NOT NULL; CREATE INDEX idx_firewall_rule_tenant_default ON firewall_rule (tenant_id, priority) WHERE client_id IS NULL;