← Developers

02.2 — Motore 2: Regole (formule, constraint, data-link)

Spec riferita a SPEC-DX-01 / rules v1

L’Invariante

Ogni regola valutata dalla piattaforma è una funzione pura di (payload, contesto, stato db). Il linguaggio delle espressioni è deterministico per costruzione — la grammatica non ha chiamate a funzione, quindi un manifest non può esprimere now(), random() o uuid(). Lo stesso evento ri-eseguito sullo stesso stato produce sempre lo stesso verdetto.

Il Contratto

Tre motori condividono lo stesso valutatore di espressioni:

Prefissi di scope: $payload (input del chiamante), $context (sessione: operatorId, tenant), $db (lookup), $formula (valori calcolati). Qualsiasi scope diverso viene rifiutato al caricamento del manifest.

Il Flusso

  1. L’action engine lega $payload dalla richiesta e $context dalla sessione.
  2. Le formule riferite dai constraint del trigger vengono valutate per prime.
  3. Ogni pre_commit_rule del trigger viene valutata; qualsiasi false → CONSTRAINT_VIOLATED, rollback.
  4. In caso di successo viene eseguita la query data-link del trigger — l’SQL è generato dal mapping del manifest, mai interpolato dall’input grezzo.
  5. I risultati finiscono nello stesso commit della transizione FSM e della riga di audit.

Esempio di Payload

// frammento di manifests/LayoutManifest.production-line.example.json
{
  "formula_engine": {
    "weight_delta_pct": "(($payload.peso_misurato - $payload.peso_dichiarato) / $payload.peso_dichiarato) * 100"
  },
  "constraint_engine": {
    "pre_commit_rules": [{
      "id": "peso_coerente",
      "expression": "$formula.weight_delta_pct <= 0.5 && $formula.weight_delta_pct >= -0.5",
      "error_message": "Peso misurato fuori tolleranza rispetto al dichiarato",
      "triggers": ["ACCEPT_LOT"]
    }]
  },
  "data_link_engine": {
    "queries": {
      "ACCEPT_LOT": {
        "type": "INSERT", "table": "biz_lotti",
        "mapping": { "lotto": "$payload.lot_id",
                     "peso_misurato": "$payload.peso_misurato",
                     "operator_id": "$context.operatorId" }
      }
    }
  }
}

I Fallimenti Noti

Sintomo Causa
Manifest rifiutato al load Espressione fuori grammatica (chiamata a funzione, scope sconosciuto) — riscrivere su $payload/$context/$db/$formula
CONSTRAINT_VIOLATED su dati apparentemente validi Una formula a monte ha prodotto un valore fuori inviluppo — valutarla sullo stesso payload
Errore su tabella non biz_ Le scritture data-link sono ristrette alla superficie biz_ dalla SQL guard
Regola scattata sul trigger sbagliato Lista triggers: [...] troppo ampia — i constraint sono opt-in per trigger