-- Policy sets + DNS hostname rules (v2) CREATE TABLE IF NOT EXISTS policy_sets ( id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT, enabled INTEGER NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), CHECK (enabled IN (0, 1)), CHECK (length(trim(name)) > 0) ); CREATE TABLE IF NOT EXISTS agent_policy_sets ( agent_id TEXT NOT NULL REFERENCES agents (id) ON DELETE CASCADE, set_id TEXT NOT NULL REFERENCES policy_sets (id) ON DELETE CASCADE, sort INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (agent_id, set_id) ); CREATE INDEX IF NOT EXISTS idx_agent_policy_sets_set ON agent_policy_sets (set_id); -- Rebuild policy_rules with set_id + hostname (drop agent_id) CREATE TABLE IF NOT EXISTS policy_rules_v2 ( id TEXT PRIMARY KEY, set_id TEXT NOT NULL REFERENCES policy_sets (id) ON DELETE CASCADE, priority INTEGER NOT NULL, action TEXT NOT NULL, list_id TEXT REFERENCES ip_lists (id) ON DELETE CASCADE, cidr TEXT, hostname TEXT, comment TEXT, created_by_user_id TEXT, created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), CHECK (action IN ('allow', 'deny')), CHECK (priority >= 1 AND priority <= 10000) ); -- Shared default set INSERT OR IGNORE INTO policy_sets (id, name, description, enabled) VALUES ( 'set-shared-default', 'Общие', 'Набор по умолчанию (бывшие tenant-правила). Назначается approved-агентам.', 1 ); -- Per-agent sets for agents that already have rules INSERT OR IGNORE INTO policy_sets (id, name, description, enabled) SELECT 'set-agent-' || a.id, 'Агент: ' || a.name, 'Мигрировано из правил агента', 1 FROM agents a WHERE EXISTS ( SELECT 1 FROM policy_rules r WHERE r.agent_id = a.id ); -- Copy tenant rules → Общие INSERT INTO policy_rules_v2 ( id, set_id, priority, action, list_id, cidr, hostname, comment, created_by_user_id, created_at, updated_at ) SELECT id, 'set-shared-default', priority, action, list_id, cidr, NULL, comment, created_by_user_id, created_at, updated_at FROM policy_rules WHERE agent_id IS NULL; -- Copy agent rules → per-agent sets INSERT INTO policy_rules_v2 ( id, set_id, priority, action, list_id, cidr, hostname, comment, created_by_user_id, created_at, updated_at ) SELECT id, 'set-agent-' || agent_id, priority, action, list_id, cidr, NULL, comment, created_by_user_id, created_at, updated_at FROM policy_rules WHERE agent_id IS NOT NULL; DROP TABLE policy_rules; ALTER TABLE policy_rules_v2 RENAME TO policy_rules; CREATE UNIQUE INDEX IF NOT EXISTS idx_policy_rules_set_priority ON policy_rules (set_id, priority); -- Assign «Общие» to all approved agents INSERT OR IGNORE INTO agent_policy_sets (agent_id, set_id, sort) SELECT id, 'set-shared-default', 0 FROM agents WHERE status = 'approved'; -- Assign per-agent migrated sets INSERT OR IGNORE INTO agent_policy_sets (agent_id, set_id, sort) SELECT substr(id, length('set-agent-') + 1), id, 10 FROM policy_sets WHERE id LIKE 'set-agent-%'; CREATE TABLE IF NOT EXISTS policy_rule_resolved ( id TEXT PRIMARY KEY, rule_id TEXT NOT NULL REFERENCES policy_rules (id) ON DELETE CASCADE, cidr TEXT NOT NULL, resolved_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) ); CREATE UNIQUE INDEX IF NOT EXISTS idx_policy_rule_resolved_rule_cidr ON policy_rule_resolved (rule_id, cidr); CREATE INDEX IF NOT EXISTS idx_policy_rule_resolved_rule ON policy_rule_resolved (rule_id);