Files
nis2-agile/docs/sql/039_integrity_keys.sql
T
DevEnv nis2-agileandClaude Opus 4.8 b80bf2361c [BACKUP] Sessione 2026-06-14: supervisore autonomo + contesto + mig.039 + UI V2 plan
- Supervisore autonomo ticket: prompt operativo + dry-run (scripts/), DRAFT rimosso; gate normativo gia' committato
- docs/CONTEXT_LAST_SESSION.md: sessione 2026-06-14 (supervisore LIVE, run#1/#2, rotazione Anthropic rinviata)
- docs/sql/039_integrity_keys.sql: migrazione integrita' DB (PK/UNIQUE/FK) gia' applicata in prod 12/6
- docs/MIGRATION_UI_V2.md: piano migrazione UI V2
- docs/nis2/incidente_r00/: 2 mockup incidente (gateway+dashboard)
- .gitignore: versiona public/vendor/ (asset Bootstrap Italia self-hosted)
- Fix accumulati: EmailService (kill-switch email), Incident/Onboarding/Organization/Services controllers, questionnaire, ReportService, CLAUDE.md standard

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 16:35:41 +02:00

77 lines
5.1 KiB
SQL

-- =====================================================================
-- 039_integrity_keys.sql
-- Hardening integrità referenziale: UNIQUE su chiavi naturali mancanti +
-- FOREIGN KEY mancanti (stesso-DB) + rimozione indice UNIQUE ridondante.
--
-- Applicato su PRODUZIONE (nis2_agile_db) il 2026-06-12 tramite runner
-- idempotente PHP (pre-check duplicati/orfani/tipi). Risultato: 18 applicati,
-- 0 errori, 2 differiti (vedi sezione DEFERRED in coda).
--
-- NB: MySQL 8 standard NON supporta "ADD ... IF NOT EXISTS" su indici/FK:
-- questo file documenta il DDL applicato. Per ri-applicare in modo sicuro
-- usare il runner con guardie su information_schema (controllo esistenza +
-- duplicati + righe orfane), NON eseguire ciecamente su un DB già migrato.
-- =====================================================================
-- 1) Rimozione UNIQUE ridondante: invites aveva due indici unique identici
-- su token_hash (token_hash + uq_invites_token). Si tiene uq_invites_token.
ALTER TABLE invites DROP INDEX token_hash;
-- 2) UNIQUE mancanti su chiavi naturali (0 duplicati verificati sul dato reale)
ALTER TABLE api_keys ADD UNIQUE KEY uq_api_keys_key_hash (key_hash);
ALTER TABLE refresh_tokens ADD UNIQUE KEY uq_refresh_tokens_token (token);
ALTER TABLE consulting_firms ADD UNIQUE KEY uq_consulting_firms_vat (vat_number);
-- 3) FOREIGN KEY mancanti (stesso-DB, 0 righe orfane verificate).
-- Convenzione ON DELETE coerente con lo schema esistente:
-- organization_id / entità-padre -> CASCADE; link nullable -> SET NULL.
ALTER TABLE policy_attestations
ADD CONSTRAINT fk_policy_attestations_policy_id FOREIGN KEY (policy_id) REFERENCES policies(id) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT fk_policy_attestations_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT fk_policy_attestations_organization_id FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE policy_versions
ADD CONSTRAINT fk_policy_versions_policy_id FOREIGN KEY (policy_id) REFERENCES policies(id) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT fk_policy_versions_organization_id FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE org_acn_requirement_status
ADD CONSTRAINT fk_org_acn_requirement_status_organization_id FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT fk_org_acn_requirement_status_requirement_id FOREIGN KEY (requirement_id) REFERENCES acn_requirements(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE supplier_questionnaires
ADD CONSTRAINT fk_supplier_questionnaires_organization_id FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT fk_supplier_questionnaires_supplier_id FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE org_connectors
ADD CONSTRAINT fk_org_connectors_organization_id FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE control_evidence_auto
ADD CONSTRAINT fk_control_evidence_auto_organization_id FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE firm_org_assignments
ADD CONSTRAINT fk_firm_org_assignments_consulting_firm_id FOREIGN KEY (consulting_firm_id) REFERENCES consulting_firms(id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE kri
ADD CONSTRAINT fk_kri_linked_risk_id FOREIGN KEY (linked_risk_id) REFERENCES risks(id) ON DELETE SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT fk_kri_organization_id FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE;
-- =====================================================================
-- DEFERRED (NON applicate il 2026-06-12) — richiedono decisione/bonifica:
--
-- a) supplier_categories.organization_id -> organizations
-- 10 righe con organization_id = 0 = SENTINEL "categoria di sistema/globale"
-- (seed migrazione 033). Una FK qui è SBAGLIATA per design (0 non è una org).
-- Azione corretta: lasciare il sentinel; eventualmente in futuro rendere la
-- colonna nullable usando NULL per le categorie globali + FK. NON fatto per
-- non toccare la semantica delle query applicative.
--
-- b) firm_org_assignments.organization_id -> organizations
-- 9 righe puntano a org 126/127/128/129 (consulting_firm 1 "Agile", dogfooding)
-- che NON esistono in questo DB. Riferimenti rotti/parziali. Servono:
-- (1) seed delle org 126-129, OPPURE (2) DELETE delle 9 righe stale,
-- poi: ALTER TABLE firm_org_assignments
-- ADD CONSTRAINT fk_firm_org_assignments_organization_id
-- FOREIGN KEY (organization_id) REFERENCES organizations(id)
-- ON DELETE CASCADE ON UPDATE CASCADE;
-- =====================================================================