# n8n integration ## Role n8n orchestrates secondary cross-system work after MobilityOps commits canonical state. It is not the domain engine. ## Required live workflow: return processing Input: `vehicle.returned.v1` webhook event. Steps: 1. validate event type and schema; 2. derive a follow-up category from the already-calculated state; 3. call the narrow MobilityOps callback endpoint with event ID and follow-up summary; 4. return a stable workflow result; 5. on errors, fail visibly so the outbox dispatcher can retry. The starter export is `n8n/mobilityops-return-processing.json`. Claude may correct its credentials and callback route but must preserve idempotency. ## Second live workflow: scheduled quality scan RAGcore is not connected in this environment, so the originally sketched "knowledge sync" workflow below remains deferred (see "Deferred: knowledge sync"). The second implemented workflow does not depend on RAGcore or MCP Hub, so it is not blocked by them. Input: hourly schedule trigger, or a manual trigger for on-demand testing. Steps: 1. call the narrow, service-token-protected `POST /api/v1/integrations/n8n/scheduled-scan` endpoint; 2. the endpoint runs the same deterministic `run_scan()` domain function the manual "Run quality scan" UI action uses, and records a `data_quality_scan_run` audit event with `actor_type=service`; 3. return counts of newly created issues per rule type. `run_scan()` only ever creates an issue for a condition that does not already have one open, so a duplicate or overlapping trigger (a manual test run firing close to the scheduled one, or a retried HTTP call) does no duplicate domain work. The starter export is `n8n/mobilityops-scheduled-quality-scan.json`, imported and published the same way as the return-processing workflow (see `deploy/unraid/setup-scheduled-scan.sh` and `docs/17-runbook.md`). It ships with `"active": false` so it cannot fire against any environment until deliberately published with a real service token. ## Deferred: knowledge sync Input: manual trigger or manifest-changed event. Steps: 1. read the fixed knowledge manifest; 2. call RAGcore ingestion/sync API; 3. record per-document results through MobilityOps integration status API. Deferred until RAGcore's live ingestion API is available in this environment; must not delay or block the core demo. ## Outbox dispatcher - polls pending records; - claims with `FOR UPDATE SKIP LOCKED` or equivalent; - sends event with timeout; - exponential backoff with a small maximum attempt count; - supports explicit manual retry; - preserves last error and response metadata; - does not hold a database transaction open during network I/O.