[FEAT] #384 p.2.2/3 fondazione — modello relazionale REQUISITO<->POLICY (mig.059)
Migrazione 059 additiva/idempotente/reversibile: - policies.proc_code VARCHAR(16) NULL: ripristina la chiave di join verso il catalogo canonico (cfg_nis2_procedure/cfg_nis2_requisiti), che andava persa quando le 42 procedure di default venivano copiate nell'elenco Policy (mig.048). - tabella requisito_policy: M:N org-scoped requisito<->policy (un requisito puo' avere piu' policy e una policy piu' requisiti) — base per p.2.2 e p.3. - backfill sicuro: proc_code valorizzato su 42 policy (match esatto titolo) + 116 associazioni di default popolate (INSERT IGNORE, WHERE proc_code IS NULL). - PolicyController::ensureFrameworkProcedures: i nuovi seed conservano proc_code e popolano requisito_policy (try/catch dedicato, non blocca il seed). Nessun impatto utente in questo passo (nessuna superficie legge ancora i nuovi campi). UI multi-valore + link bidirezionali (2.2/3) nei prossimi cicli. v1.23.6. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
8a8045904b
commit
02f3e69227
@@ -0,0 +1,67 @@
|
||||
-- =====================================================================
|
||||
-- 059 — Modello relazionale REQUISITO <-> POLICY (Ticket #384, punti 2.2 + 3)
|
||||
-- =====================================================================
|
||||
-- Fonte spec: ticket #384 (super_admin) + istruzioni.pdf allegato.
|
||||
-- p.2.2 "ogni riga di requisito puo' avere piu' policy e ogni policy puo'
|
||||
-- avere piu' requisiti associati" -> serve una M:N esplicita.
|
||||
-- p.3 "i codici devono funzionare come link attivi" (Policy <-> Misure
|
||||
-- e Requisiti) -> serve poter risalire dalla policy ai requisiti
|
||||
-- e viceversa.
|
||||
--
|
||||
-- PROBLEMA STRUTTURALE risolto qui: quando le 42 procedure di default
|
||||
-- (cfg_nis2_procedure) vengono copiate nell'elenco `policies` di una org
|
||||
-- (PolicyController::ensureFrameworkProcedures, mig.048), il `proc_code`
|
||||
-- canonico NON veniva conservato sulla riga policy -> il legame
|
||||
-- requisito (cfg_nis2_requisiti.proc_code) <-> policy andava perso.
|
||||
--
|
||||
-- COSA FA (tutto ADDITIVO, IDEMPOTENTE, REVERSIBILE — nessun DROP/DELETE):
|
||||
-- 1) policies.proc_code VARCHAR(16) NULL — chiave di join verso il
|
||||
-- catalogo canonico (cfg_nis2_procedure.proc_code / cfg_nis2_requisiti.proc_code).
|
||||
-- 2) Tabella requisito_policy — M:N org-scoped requisito<->policy.
|
||||
-- requisito_id -> cfg_nis2_requisiti.id (canonico, SYSTEM-level)
|
||||
-- policy_id -> policies.id (per-org)
|
||||
-- organization_id -> organizations.id (lo stesso link e' per-org perche'
|
||||
-- le policy sono per-org).
|
||||
-- 3) Backfill SICURO (solo letture->scritture additive): valorizza
|
||||
-- policies.proc_code per match esatto title==proc_descr e popola
|
||||
-- requisito_policy con le associazioni di default gia' esistenti.
|
||||
--
|
||||
-- Runner: application/cli/migrate_059_requisito_policy.php (PDO app, TLS,
|
||||
-- guardato via information_schema, idempotente). NON usa DELIMITER/stored-proc.
|
||||
--
|
||||
-- ROLLBACK:
|
||||
-- DROP TABLE IF EXISTS requisito_policy;
|
||||
-- ALTER TABLE policies DROP COLUMN proc_code;
|
||||
-- =====================================================================
|
||||
|
||||
-- 1) chiave di join sulla riga policy (NULL = policy non legata al catalogo)
|
||||
ALTER TABLE policies
|
||||
ADD COLUMN proc_code VARCHAR(16) NULL AFTER nis2_article;
|
||||
|
||||
-- 2) M:N esplicita requisito <-> policy (org-scoped)
|
||||
CREATE TABLE IF NOT EXISTS requisito_policy (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
organization_id INT NOT NULL,
|
||||
requisito_id INT NOT NULL,
|
||||
policy_id INT NOT NULL,
|
||||
is_default TINYINT(1) NOT NULL DEFAULT 0, -- 1 = derivata dal framework
|
||||
created_by INT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uq_req_pol (organization_id, requisito_id, policy_id),
|
||||
KEY idx_rp_org (organization_id),
|
||||
KEY idx_rp_req (requisito_id),
|
||||
KEY idx_rp_pol (policy_id),
|
||||
CONSTRAINT fk_rp_org FOREIGN KEY (organization_id) REFERENCES organizations (id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_rp_req FOREIGN KEY (requisito_id) REFERENCES cfg_nis2_requisiti (id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_rp_pol FOREIGN KEY (policy_id) REFERENCES policies (id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_rp_user FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 3) Backfill (eseguito dal runner, qui documentato):
|
||||
-- UPDATE policies p JOIN cfg_nis2_procedure c ON p.title = c.proc_descr
|
||||
-- SET p.proc_code = c.proc_code WHERE p.proc_code IS NULL;
|
||||
-- INSERT IGNORE INTO requisito_policy (organization_id, requisito_id, policy_id, is_default)
|
||||
-- SELECT p.organization_id, q.id, p.id, 1
|
||||
-- FROM policies p JOIN cfg_nis2_requisiti q ON q.proc_code = p.proc_code
|
||||
-- WHERE p.proc_code IS NOT NULL;
|
||||
Reference in New Issue
Block a user