- 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>
77 lines
5.1 KiB
SQL
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;
|
|
-- =====================================================================
|