L’Invariante
Ogni motore di Axiom-Trace possiede esattamente un bounded context e parla col resto del sistema solo tramite eventi di produzione — mai tabelle condivise, mai chiamate dirette.
L’isolamento rigoroso delle responsabilità è l’unico scudo contro il debito tecnico e la fine della scalabilità.
Violarlo — una foreign key verso la tabella di un altro motore, una chiamata sincrona cross-engine — crea un monolite distribuito. L’architettura esiste proprio per impedirlo.
Il Contratto
La mappa dei motori — una responsabilità ciascuno, zero sovrapposizioni:
| Motore | Possiede | Pubblica |
|---|---|---|
| Runtime edge (manifest-driven) | Scritture business: RBAC, FSM, constraint, data-link, audit | ax_cdc_outbox → cp_events |
| CDC sync engine | Drain outbox, retry, backoff, buste firmate | POST /sync/ingest → Control Plane |
| Control Plane | Tenancy, billing, sync flotta, autorità manifest/licenze | Manifest/licenze firmate → edge |
| Worker di notifica | Consegna outbox (mail, webhook SIEM), retention | Legge cp_notification_outbox / cp_audit_outbox |
Profili verticali (profiles/) |
Trigger/query di dominio via manifest | Read model su cp_events, biz_* sull’edge |
Regola cross-engine: i motori possono leggere lo stream eventi condiviso e le proprie tabelle — nient’altro. Un nuovo verticale riceve lo stesso patto: un bounded context, eventi in ingresso, proiezioni in uscita.
Il Flusso
produttore (dashboard / client macchina)
│ POST /actions/:trigger
▼
runtime edge ── FSM + RBAC + constraint ──► biz_* + audit + ax_cdc_outbox
│ drain, firmato
▼
cp_events ──► cp_aggregates
│
┌──────────────┬──────────────────────┤
▼ ▼ ▼
portale legge webhook SIEM leggono admin legge
(usage/audit) (push firmato) (fleet/events)
Nessuna freccia bypassa mai lo stream eventi. Il worker di notifica non interroga l’edge; il portale non interroga il canale sync; i profili non scrivono le tabelle degli altri. Tutti leggono fatti.
Esempio di Payload
Esiste intenzionalmente nessun esempio di chiamata cross-engine — non è esprimibile nel contratto. Ciò che puoi scrivere:
# Una superficie di lettura che consuma fatti committati (l'unica forma di integrazione esistente)
curl -s "https://cp.axiom-trace.eu/api/v1/tenant/audit?limit=100" \
-H "Authorization: Bearer $PORTAL_TOKEN"
Per produrre fatti, un nuovo verticale registra trigger nel manifest — vedi Playbook: aggiungere un verticale.
I Fallimenti Noti
| Tentazione | Perché fallisce |
|---|---|
| “Leggo i file locali dell’edge” | Accoppiamento su filesystem — il formato del FileEventStore è privato del runtime |
| “Un profilo scrive direttamente la riga di business” | Bypassa RBAC/FSM/audit/dedup — la riga è un fatto, solo l’action engine scrive fatti |
| “Chiamo il worker notifiche in sincrono dall’azione” | Accoppiamento di latenza: un mailer lento ora blocca le scritture di produzione — per questo esiste l’outbox |
| Tabella “comune” tra due motori | Contratto nascosto — il seme classico del monolite distribuito |