[DB] Hardening integrità chiavi (mig.058): +4 UNIQUE +8 FK, retry-on-1062, bonifica 16 righe stale — v1.23.1
Estende l'audit mig.039 ai moduli 040-057 (non coperti). TIER1 additivo (0 dup/0 orfani verificati su DB live): - UNIQUE internal_audits/management_reviews (org,code), kb_uploaded_documents.qdrant_doc_uuid, whistleblowing_reports.anonymous_token (drop idx_token ridondante) - retry-on-1062 in InternalAuditController/ManagementReviewController (allineati a periodic_controls) - 6 FK: consulting_firm_id (organizations/users/kb)->consulting_firms; isms_soa.linked_control_id; isms_documents.linked_policy_id; management_review_decisions.capa_id (tutte SET NULL) TIER2 bonifica (backup pre-DELETE in .backups/): -9 firm_org_assignments orfane (org 126-129, chiude deferred-b mig.039) -7 active_sessions scadute, +2 FK CASCADE. FK totali 196->204. Sonda diagnostica db_integrity_probe.php. audit_logs lasciato by-design. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f32b6f28f5
commit
2b6c5087ad
@@ -2,6 +2,23 @@
|
||||
|
||||
> Il 2026-05-29 ci sono state DUE sessioni: **pomeriggio** e **mattina** (TRPG). Il 2026-05-30 sessione lunga: gap competitivi P1/P2/P3 + connettori + review multi-agente + fix.
|
||||
|
||||
## 2026-06-18 — 🟢 Hardening integrità DB (mig.058) — v1.23.1
|
||||
|
||||
Richiesta utente: *"analizzare DB e chiavi per garantire integrità db"*. Esteso l'audit chiavi della **mig.039** (12/6, fermo a ~tab.039) ai **moduli 040-057** non ancora coperti. Memoria: [[project_db_integrity]].
|
||||
|
||||
**Stato base sano**: 103 tabelle, tutte con PK, tutte InnoDB. Sonda live read-only nuova: `application/cli/db_integrity_probe.php` (PK/engine/UNIQUE/FK/orfani + pre-check duplicati `(org,code)`; etichetta `audit_logs` come **by-design**, non bloccante).
|
||||
|
||||
**mig.058 applicata (runner guardato `application/cli/migrate_058_integrity_keys.php`, idempotente, 15/15 OK, re-run = 12 SKIP)**:
|
||||
- **TIER 1 additivo** (0 dup/0 orfani verificati): +4 UNIQUE [`internal_audits`/`management_reviews` `(org,code)`, `kb_uploaded_documents.qdrant_doc_uuid`, `whistleblowing_reports.anonymous_token` (drop `idx_token` ridondante)] + retry-on-1062 nei controller `InternalAudit`/`ManagementReview` (allineati a `periodic_controls`); +6 FK [`consulting_firm_id` su `organizations`/`users`/`kb_uploaded_documents`→`consulting_firms`; `isms_soa.linked_control_id`→`compliance_controls`; `isms_documents.linked_policy_id`→`policies`; `management_review_decisions.capa_id`→`capa_actions`, tutte SET NULL].
|
||||
- **TIER 2 bonifica** (confermata dall'utente, backup pre-DELETE in `.backups/mig058_pre_cleanup_20260618-075418.sql`): cancellate **9** righe stale `firm_org_assignments`→org 126-129 (eliminate nella pulizia demo 12/6; chiude il *deferred-b* mig.039) + **7** sessioni scadute `active_sessions`→org inesistenti, poi 2 FK CASCADE.
|
||||
- **FK totali 196 → 204**. Verdetto sonda post-fix: **0 problemi bloccanti** (resta solo `audit_logs` by-design: trail immutabile mig.006). Smoke prod: api-status 200, controller list 401 (caricano OK post-reload).
|
||||
|
||||
**By-design lasciato**: `audit_logs` (no FK, immutabile), sentinel `supplier_categories.org=0` (deferred-a mig.039), colonne polimorfiche (`object_id`/`entity_id`/...) e cross-DB (`sso_identity_id`/`lg231_*`).
|
||||
|
||||
**Deploy**: reload opcache `systemctl reload php8.4-fpm` (PROD=host) + USR2 `nis2-app`. version.json → **1.23.1**. **Prossima mig = 059.** Pulizia: rimossi 4 file `* copy.html` residui in `docs/nis2/`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-17 (seguito) — 🟢 Modulo CONTROLLI PERIODICI (4° modulo ISO-readiness, §9.1/A.8.16) — v1.23.0, mig.057, commit `4fdeae7`
|
||||
|
||||
Richiesta utente: *"oltre al modulo audit un modulo controlli con frequenza e generazione nc o ac"* + *"fai analisi anche di questo modulo / documentati con altri esempi"* → analisi CCM (Continuous Control Monitoring, pattern Eramba/Drata/Vanta) in `docs/DESIGN_CONTROLLI_PERIODICI.md`. Memoria: [[project-iso-readiness-modules]] (punto D).
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
Nessun ticket aperto.
|
||||
|
||||
---
|
||||
_Ultimo sync: 2026-06-17 12:10:01_
|
||||
_Ultimo sync: 2026-06-18 07:55:01_
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
-- =====================================================================
|
||||
-- 058_integrity_keys.sql
|
||||
-- Hardening integrità chiavi — estende l'audit della mig.039 alle tabelle
|
||||
-- aggiunte dopo (moduli 040-057: stakeholder, ISO-readiness, KB, ...).
|
||||
--
|
||||
-- DOC-RECORD del DDL applicato dal runner idempotente GUARDATO:
|
||||
-- application/cli/migrate_058_integrity_keys.php
|
||||
-- (pre-check duplicati/orfani su information_schema + dato reale, try/catch
|
||||
-- su 1061/1826/1062). NON eseguire ciecamente questo .sql su un DB migrato.
|
||||
--
|
||||
-- Verificato sul dato reale (db_integrity_probe.php, 2026-06-18, nis2_agile_db):
|
||||
-- 103 tabelle, tutte con PK, tutte InnoDB, 196 FK pre-esistenti.
|
||||
-- 0 duplicati e 0 orfani su tutte le voci TIER 1 (sotto).
|
||||
-- =====================================================================
|
||||
|
||||
-- ── TIER 1: UNIQUE su chiavi naturali (additivo, nessuna modifica dato) ──
|
||||
-- Codici progressivi per-org (race su create concorrenti, ora con retry-on-1062
|
||||
-- nei rispettivi controller). periodic_controls aveva già uk_pctl_code (mig.057).
|
||||
ALTER TABLE internal_audits ADD UNIQUE KEY uk_intaud_code (organization_id, code);
|
||||
ALTER TABLE management_reviews ADD UNIQUE KEY uk_mgr_code (organization_id, code);
|
||||
|
||||
-- 1:1 con il documento vettoriale in Qdrant (16 righe, 0 dup).
|
||||
ALTER TABLE kb_uploaded_documents ADD UNIQUE KEY uk_kbdoc_qdrant (qdrant_doc_uuid);
|
||||
|
||||
-- Token di tracking segnalazione anonima = chiave di retrieval (WHERE token=?).
|
||||
-- Sostituisce l'indice non-unique idx_token ridondante.
|
||||
ALTER TABLE whistleblowing_reports DROP INDEX idx_token;
|
||||
ALTER TABLE whistleblowing_reports ADD UNIQUE KEY uq_wb_anon_token (anonymous_token);
|
||||
|
||||
-- ── TIER 1: FOREIGN KEY mancanti (stesso-DB, 0 orfani verificati) ──
|
||||
-- consulting_firm_id: la mig.039 aggiunse solo la FK su firm_org_assignments.
|
||||
ALTER TABLE organizations ADD CONSTRAINT fk_org_consulting_firm FOREIGN KEY (consulting_firm_id) REFERENCES consulting_firms(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE users ADD CONSTRAINT fk_users_consulting_firm FOREIGN KEY (consulting_firm_id) REFERENCES consulting_firms(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE kb_uploaded_documents ADD CONSTRAINT fk_kbdoc_consulting_firm FOREIGN KEY (consulting_firm_id) REFERENCES consulting_firms(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
-- link nullable verso entità dello stesso DB (SET NULL coerente con lo schema).
|
||||
ALTER TABLE isms_soa ADD CONSTRAINT fk_isms_soa_control FOREIGN KEY (linked_control_id) REFERENCES compliance_controls(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE isms_documents ADD CONSTRAINT fk_isms_doc_policy FOREIGN KEY (linked_policy_id) REFERENCES policies(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
ALTER TABLE management_review_decisions ADD CONSTRAINT fk_mrd_capa FOREIGN KEY (capa_id) REFERENCES capa_actions(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- =====================================================================
|
||||
-- TIER 2 — bonifica righe STALE + FK (richiede --with-cleanup nel runner;
|
||||
-- CANCELLA righe orfane → conferma esplicita necessaria)
|
||||
--
|
||||
-- C1) firm_org_assignments: 9 righe (consulting_firm 1 "Agile", dogfooding,
|
||||
-- create 2026-05-29) verso org 126/127/128/129 ELIMINATE nella pulizia
|
||||
-- demo del 2026-06-12. Risolve il "deferred-b" della mig.039.
|
||||
-- DELETE FROM firm_org_assignments WHERE organization_id NOT IN (SELECT id FROM organizations);
|
||||
-- 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;
|
||||
--
|
||||
-- C2) active_sessions: 7 sessioni verso org inesistenti (effimere).
|
||||
-- DELETE FROM active_sessions WHERE organization_id<>0 AND organization_id NOT IN (SELECT id FROM organizations);
|
||||
-- ALTER TABLE active_sessions ADD CONSTRAINT fk_active_sessions_organization_id
|
||||
-- FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
-- =====================================================================
|
||||
|
||||
-- ── NON TOCCATE — pattern "by design" (documentato, NESSUNA azione) ──
|
||||
-- • audit_logs.organization_id: 1996 "orfani" + 408 org_id=0 → audit trail
|
||||
-- IMMUTABILE (trigger mig.006) che DEVE sopravvivere alla cancellazione org.
|
||||
-- Nessuna FK per scelta architetturale.
|
||||
-- • supplier_categories.organization_id = 0: sentinel "categoria di sistema"
|
||||
-- (deferred-a mig.039).
|
||||
-- • Colonne *_id polimorfiche (object_id, entity_id, source_entity_id, ...) e
|
||||
-- cross-DB (sso_identity_id, lg231_company_id/order_id): nessuna FK possibile.
|
||||
Reference in New Issue
Block a user