Rela AIRela AI Docs
Sicurezza Alimentare

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

DimensionePrimaDopo
Transitori (apertura porta, defrost)9 deviazioni false per apertura0 — grace_period_seconds rispettato
Sensore morto che invia 0"Critical low" fantasmaSoppresso da sensor_watchdog + H2
Inbox operatore3 silos: anomaly, energy, HACCP1 riga consolidata, severità canonica
Escursione sostenuta 30 min~180 deviazioni persistite1 deviazione con sample_count=180 e max_deviation
Azione correttivaRecord testuale senza ownerWork order urgente prefix HAC-, assegnato, tracciabile
Cambio limite criticoNessuna traccia_audit_trail con prev→new, actor, timestamp
Piano HACCP da revisionareNessuno se ne accorgeAlert plan_review_overdue via heartbeat
Lotto in hold per deviazioneRicerca free-textQuery 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_days e next_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

  1. Sicurezza Alimentare → HACCP → Piani.
  2. Crea un piano con analisi pericoli, diagramma di flusso, cadenza di revisione.
  3. 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:

HazardSeverità
biologicalcritical
chemicalhigh
physicalwarning
allergen / unknownwarning (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 manutenzione MAI-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/history

Un 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_alert e audit_trail_service.log_action.

Limitazioni

  • ProductDisposition non blocca sistemi downstream. Un hold registra 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).
  • CorrectiveStep non 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.

In questa pagina