HACCP — Controllo Sanitario Verificabile
Piani HACCP, CCP con grace period reale, azioni correttive che generano work order, e chain-of-custody per lotto. Certificabile sotto SQF / BRC / FSSC 22000.
HACCP — Controllo Sanitario Verificabile
Il modulo HACCP di Rela AI non è un registro di deviazioni. È un'implementazione auditabile dei 7 principi HACCP integrata con il resto della pipeline industriale: dal sensore di temperatura all'ordine di lavoro che l'operatore chiude con prova.
A cosa serve
- Monitorare online ogni Punto Critico di Controllo (CCP) del piano HACCP con range, grace period e soppressione dei sensori morti.
- Innescare azione correttiva + work order assegnato con scadenza a ogni deviazione reale.
- Generare evidenza auditabile (catena di custodia per lotto, audit trail con hash) accettabile per SQF / BRC / FSSC 22000.
Come funziona
Ogni CCP definisce un range accettabile + grace period + regola di soppressione sensori morti. Le letture arrivano via POST /api/v1/haccp/readings (push dal sensore) o MQTT/OPC UA; il pipeline valida rispetto al range, scarta transienti dentro il grace period, sopprime lo 0 falso dei sensori morti, e su deviazione reale apre azione correttiva + work order + voce nella catena di custodia del lotto.
Riepilogo esecutivo
Da registro reattivo a sistema di controllo. Prima, una deviazione di temperatura produceva un record testuale senza tracciabilità. Oggi produce: alert consolidato nell'inbox unificato, work order urgente assegnato al responsabile, voce di audit di configurazione, e — se il lotto è stato trattenuto — voce nella chain-of-custody del batch.
Prima vs Dopo
| Dimensione | Prima | Dopo |
|---|---|---|
| Transitori (apertura porta, defrost) | 9 deviazioni false per apertura | 0 — grace_period_seconds rispettato |
| Sensore morto che invia 0 | "Critical low" fantasma | Soppresso da sensor_watchdog + H2 |
| Inbox operatore | 3 silos: anomaly, energy, HACCP | 1 riga consolidata, severità canonica |
| Escursione sostenuta 30 min | ~180 deviazioni persistite | 1 deviazione con sample_count=180 e max_deviation |
| Azione correttiva | Record testuale senza owner | Work order urgente prefix HAC-, assegnato, tracciabile |
| Cambio limite critico | Nessuna traccia | _audit_trail con prev→new, actor, timestamp |
| Piano HACCP da revisionare | Nessuno se ne accorge | Alert plan_review_overdue via heartbeat |
| Lotto in hold per deviazione | Ricerca free-text | Query diretta GET /batches/{id}/history |
CCP e Piano HACCP
- Piano HACCP: il documento regolatorio. Raggruppa analisi dei pericoli, diagramma di flusso, CCP che controllano i rischi, procedure di verifica. Ogni piano ha
review_frequency_daysenext_review_at. - CCP (Critical Control Point): punto specifico del processo dove un pericolo è controllato. Appartiene a un piano (o è legacy senza piano), monitora una metrica di un
asset_id, ha limiti critici, grace period, azioni correttive e responsabile.
flowchart LR
A[Sensore/PLC/SCADA] --> B[Ingestione via machine_events<br/>o POST /haccp/readings]
B --> C{Sensore stale?}
C -- Sì --> SKIP[Skip: sensor_watchdog]
C -- No --> D[evaluate_limits<br/>banda high/low]
D -->|Dentro| BUF[Pulisci buffer]
D -->|Fuori| E{grace_period<br/>trascorso?}
E -- No --> BUF2[Apri/estendi buffer]
E -- Sì --> F[record_deviation<br/>con M3 dedup]
F -->|is_new=true| G[alert_aggregator<br/>source_system=haccp]
F -->|is_new=false| H[merge in deviation esistente]
G --> I[Inbox unificato]
F --> J[Azione Correttiva]
J --> K[Work Order HAC-xxx]
J --> L[Batch disposition<br/>se hold/rework/destroy]Creare un CCP
Dashboard
- Sicurezza Alimentare → HACCP → Piani.
- Crea un piano con analisi pericoli, diagramma di flusso, cadenza di revisione.
- Nuovo CCP dentro il piano con hazard type (biological/chemical/physical/allergen), limiti critici, grace period in secondi, corrective steps strutturati, responsabile.
API
POST /api/v1/haccp/plans
{
"name": "Piano UHT Latte 1L",
"product_type": "Latte UHT 1L",
"process_flow": ["Ricezione", "Filtraggio", "Pastorizzazione", "Confezionamento"],
"hazards": [ { "stage_name": "Pastorizzazione", "hazard_description": "Sopravvivenza patogeni se T<72°C",
"hazard_type": "biological", "severity": "critical", "control_measure": "T ≥ 72°C per 15s",
"is_ccp": true } ],
"review_frequency_days": 365
}
POST /api/v1/haccp/ccps
{
"name": "Temperatura Pastorizzatore",
"asset_id": "64f...pasteurizer",
"source_id": "src_plc_uht",
"monitoring_metric": "temperature",
"hazard_type": "biological",
"critical_limit_high": 85,
"critical_limit_low": 72,
"unit": "C",
"grace_period_seconds": 15,
"corrective_steps": [
{ "description": "Arresta feed pump", "estimated_minutes": 1, "required_role": "operator" },
{ "description": "Verifica temperatura hold tank", "estimated_minutes": 5, "required_role": "qa_lead",
"verification_method": "Firma QA su CCP-01" }
],
"plan_id": "64f...plan"
}Monitoraggio — quattro livelli di protezione
1. Sensor staleness (HACCP-H2)
Se sensor_watchdog marca la sorgente come stale, HACCP salta la valutazione. Un termometro morto che invia 0.0 non può fabbricare un falso "critical low".
2. Grace period reale (HACCP-H1)
Una lettura fuori banda apre un buffer persistente in _haccp_deviation_buffers (MongoDB, non memoria — un restart del worker non può scartare il tempo accumulato). Solo quando elapsed >= grace_period_seconds E la lettura è ancora fuori banda, la deviation si persiste. Transitori risolti non lasciano traccia.
3. Dedup per incidente (HACCP-M3)
Un'escursione di 30 min non produce 5 righe separate. Entro _HACCP_DEDUP_WINDOW_MINUTES (default 15) i sample successivi dello stesso (ccp_id, direction) si fondono nella deviation esistente: sample_count++, last_seen_at, max_reading/max_deviation tracciano il peak dell'incidente.
4. Inbox unificato (HACCP-H3)
Ogni deviation confermata pubblica all'Alert Aggregator con source_system="haccp". Severità canonica mappata da hazard_type:
| Hazard | Severità |
|---|---|
| biological | critical |
| chemical | high |
| physical | warning |
| allergen / unknown | warning (HACCP non scende mai a info) |
Ingestione diretta — POST /api/v1/haccp/readings (HACCP-L2)
Per sorgenti fuori da /machine/events (tablet di registrazione manuale, termometro HACCP dedicato):
POST /api/v1/haccp/readings
{ "source_id": "tablet-qa-01", "metadata": { "temperature": 80.5 } }Stessa pipeline completa. Nessun "secondo percorso".
Azione correttiva → Work Order (HACCP-H5)
Quando un operatore registra una corrective action, il sistema crea un task nel kanban:
task_code = HAC-xxx(distinguibile da manutenzioneMAI-xxx).priority = urgent.- Back-link denormalizzati:
haccp_deviation_id,haccp_ccp_id,haccp_batch_id,haccp_product_disposition.
Chain-of-custody per lotto (HACCP-L4)
Se la corrective action include batch_id + product_disposition != "none", voce immutabile in _haccp_batch_dispositions:
GET /api/v1/haccp/batches/B-2026-03-15-A/historyUn ispettore che chiede "cos'è successo al lotto X?" ottiene la catena completa con una query.
Audit trail di configurazione (HACCP-M5)
Ogni mutazione di un CCP registra in _audit_trail con actor, timestamp e diff prev→new:
ccp_created/ccp_updated(solo campi cambiati) /ccp_deleted.
"Chi ha cambiato critical_limit_high da 75 a 72 il 3 marzo?" ha risposta verificabile.
Heartbeat di revisione piani (HACCP-M6)
POST /internal/haccp-health-check — job periodico che emette alert warning per ogni piano con next_review_at <= now. Non duplica silent-sensor detection (già coperto da sensor_watchdog + H2).
Architettura tecnica
haccp_service— CRUD CCP + piani + pipeline di checking.thresholds.py(condiviso) —evaluate_limits()riusato da HACCP e cold_chain (HACCP-M4).- Collezioni per-tenant:
_haccp_ccps,_haccp_plans,_haccp_deviations,_haccp_deviation_buffers,_haccp_corrective_actions,_haccp_batch_dispositions. - Integrazione fire-and-forget con
alert_aggregator_service.ingest_alerteaudit_trail_service.log_action.
Limitazioni
ProductDispositionnon blocca sistemi downstream. Unholdregistra la disposizione ma non integra con ERP/MES per impedire la spedizione. Lavoro di operations, non HACCP.- Nessun heartbeat silent-sensor proprio. Riusiamo
sensor_watchdog; se quella catena si rompe, HACCP non rileva silenzi (li filtra solo se già marcati stale). CorrectiveStepnon eseguito come checklist. La UI può renderizzare i passi, ma il backend non verifica completamento individuale.
Benefici chiave
- Transitori non contaminano il registro — grace rispettato.
- Sensori morti non fabbricano falsi positivi — filtro staleness.
- Un inbox, non quattro — integrazione con alert_aggregator.
- Incidente = una riga anche se dura ore — dedup interno con peak tracking.
- Azioni correttive sono lavoro reale nel kanban — work orders urgenti con back-link.
- Auditabilità completa — CCP audit trail + chain-of-custody per lotto.
- Piani HACCP formali — certificabili SQF/BRC/FSSC 22000.
- Logica condivisa con cold_chain — una sola matematica threshold-detection.