Consolidates this effort's outcome across all four canonical workflows: WF1/WF2 hardened and live, WF3 blocked on a RAGcore-side credential rejection (with trace IDs for the operator to investigate), WF4 built and live-validated with one open non-blocking follow-up. No credential values or secrets included.
12 KiB
Live n8n + RAGcore integration — final evidence
No credential values, tokens, or secrets appear anywhere in this document. Where a credential or trace ID is referenced, only its name or an opaque reference identifier is given, never its value.
Commit
Built on branch feat/live-n8n-ragcore-integration, HEAD at commit
aaa16305354d34f9c1f4d57253d33d9062c38faa ("docs: record WF2 retry fix and WF4's
n8n-session-expiry blocker"). Run git log --oneline feat/live-n8n-ragcore-integration
for the full history of this effort.
Scope
The brief required treating n8n (https://n8n.itworx.tech) as a full third integration
layer alongside RAGcore and MCP Hub, with Fleet Ops keeping exclusive ownership of
business rules, authorization, transactions, audit, and idempotency. Four canonical n8n
workflows were required. The repository (n8n/workflows/*.json + MANIFEST.md +
n8n/workflows/check_drift.py) is the source of truth for cleaned workflow definitions;
the Fleet Ops integration status page (/automation) shows real per-workflow operational
evidence, not a config boolean.
Result summary
| # | Workflow | Status | Live evidence this round |
|---|---|---|---|
| 1 | Fleet Ops — Vehicle Return Orchestration | Live, hardened | Timeout+bounded-retry gap found and fixed |
| 2 | Fleet Ops — Scheduled Data Quality Scan | Live, hardened | Same gap found and fixed |
| 3 | Fleet Ops — RAGcore Procedure Sync | Blocked | Not built — RAGcore rejects credential issuance (see below) |
| 4 | Fleet Ops — Workflow Error Handler | Live, validated | Mock + genuine induced-failure test; own hardening incomplete (see below) |
Full per-workflow detail (purpose, trigger, event contract, required credentials, live
workflow ID, checksum) is in n8n/workflows/MANIFEST.md, which is the authoritative,
continuously-updated source — this document is a point-in-time summary of that state
plus the reasoning behind what's not done.
Workflow 1 — Vehicle Return Orchestration
Live workflow ID mobilityops-return-processing. Validated in an earlier round of this
effort: webhook trigger requires Header Auth (Fleet Ops Webhook Trigger Token),
validates event_type == vehicle.returned.v1, derives a follow-up category, calls Fleet
Ops's /return-callback endpoint with an Idempotency-Key header via a named
Fleet Ops Service Token credential (not a literal secret), and responds with a
controlled JSON result. Idempotent on both sides (event_id flows through as the
dedup key; the backend independently checks for a prior audit event before recording
again).
This round's finding: the Record follow-up HTTP node had no explicit timeout and
"Retry On Fail" disabled — a real gap against the requirement that external dependencies
have timeouts and bounded retries. Fixed live: Retry On Fail (3 tries, 1000ms wait) + a
15000ms timeout, published. Safe to retry because the callback is idempotent. Repo
definition and manifest checksum synced (commit 0562893).
Attached to workflow 4 as its Error Workflow.
Workflow 2 — Scheduled Data Quality Scan
Live workflow ID mobilityops-scheduled-quality-scan. Validated earlier: hourly
Schedule Trigger + a Manual Trigger for on-demand testing, both feeding a single HTTP
call to Fleet Ops's /scheduled-scan endpoint (Header Auth via the same Fleet Ops Service Token credential, 15000ms timeout already configured), which runs the
domain-level run_scan() function — documented and tested as idempotent by
construction (only ever creates an issue for a condition that doesn't already have one
open), so overlapping or retried triggers do no duplicate domain work.
This round's finding: the same Retry On Fail gap as workflow 1 (timeout was already
set, retries were not). Fixed live the same way (3 tries, 1000ms wait), published. Repo
definition and manifest checksum synced (commit 167bf49).
Attached to workflow 4 as its Error Workflow.
Workflow 3 — RAGcore Procedure Sync — blocked
Not built. This workflow needs an application credential (scope sources:sync) for
the fleet-ops application in RAGcore. Two independent issuance attempts, in two
separate rounds of this effort, both failed with an opaque server-side rejection:
- Raw API:
POST /v1/applications/{id}/credentials→400, "authoritative service-account state rejected issuance". - RAGcore admin UI, this round, after the project owner explicitly authorized
Claude to self-issue the credential: the "Issue credential" form for the
fleet-opsapplication, submitted as the Platform Admin role (the highest role visible in the RAGcore admin), with namen8n-ragcore-procedure-syncand scopesources:synconly. Result: "Something went wrong. The credential could not be issued with those values.", trace reference1955c6a8968c4941a22a1faef39e17a7.
The fleet-ops application itself shows as ordinary/Active in the RAGcore admin, with
no visible lock flag, and RAGcore's own OpenAPI spec documents no validation rule that
would explain either rejection (no 422, no field-level errors). Two independent paths
— a raw API call and the admin UI as the top admin role — hitting the same failure
signature is conclusive evidence this is a RAGcore-side policy or bug, not a Fleet Ops
request-shape or permission problem. It is not fixable from the Fleet Ops side or
through further UI automation. Resolving it requires whoever operates the RAGcore
instance to look up the trace ID above (and the earlier raw-API rejection) in RAGcore's
own logs.
The real RAGcore contract this workflow will be built against — once a working
credential exists — was independently inspected via RAGcore's live OpenAPI spec and is
recorded in docs/live-ai-integration/n8n-current-state.md and
contracts/ragcore-contract-assumptions.md: control-plane endpoints require an
Idempotency-Key header; ingestion is POST /v1/uploads; retrieval is POST /v1/search / /v1/context / /v1/answers (the latter requiring requested_space_ids,
an array of knowledge-space UUIDs); health is /health/live and /health/ready (not
/health); the scope enum is search, context, answer, documents:read, citations:read, feedback:write, sources:sync.
RAGcoreKnowledgeProvider adapter (backend/app/services/knowledge/ragcore.py)
still targets the earlier speculative contract (/health, POST /api/v1/ask, Bearer
token) rather than the real one above. This was deliberately not rewritten this
round: rewriting it blind, without a credential to validate against, risks introducing
a silent behavioral bug in exactly the code path responsible for the project's "AI must
never invent an answer when RAGcore is unavailable or returns insufficient evidence"
guarantee — for example a wrong evidence_state mapping that looks fine in code review
but misclassifies "unavailable" as "insufficient" (or vice versa) against the real
response shape. The adapter's current behavior is honest and safe (it degrades cleanly
to unavailable on any request or parsing failure, and ragcore_api_token is unset by
default so the app correctly runs on the local demo knowledge provider today). The
rewrite stays queued behind the same credential blocker as workflow 3.
Workflow 4 — Workflow Error Handler
Live workflow ID Xppn2rAEqUuyiCJF. Built and live-validated in an earlier round:
Error Trigger → a Code node that derives a bounded, secret-free failure report (error
category classified from the message text, truncated summary, no stack trace, no
headers or tokens) → an HTTP call to Fleet Ops's /workflow-error endpoint (Header Auth
via the same Fleet Ops Service Token credential), which registers the failure as an
audit event idempotently keyed on execution_id.
Set as the Error Workflow on both workflow 1 and workflow 2. Confirmed workflow 4 has no Error Workflow of its own (prevents a recursive loop).
Live validation performed: a pinned mock Error Trigger payload produced a real 200 {"status":"registered", ...} from the live Fleet Ops server; re-running the identical
payload produced "status":"already_registered", confirming idempotency. A genuine
induced failure (temporarily pointing workflow 2's HTTP node at a nonexistent path, then
reverting) confirmed workflow 2 itself fails correctly against a broken endpoint and
recovers cleanly once reverted.
Known limitation: n8n's Error Workflow trigger does not fire for manual editor "Execute workflow" test runs — checked via workflow 4's own Executions list after the induced workflow-2 failure, and confirmed no new execution appeared. n8n only invokes a workflow's assigned Error Workflow for unattended/production trigger executions, not manual test runs from the editor. The mock-data path exercises the same nodes, logic, and real Fleet Ops endpoint, but a fully automatic (schedule- or webhook-triggered) failure cascading into workflow 4 was not observed live in either round.
Open follow-up (minor, non-blocking): continuing this round's acceptance pass to
workflow 4 found the same timeout/retry gap as workflows 1 and 2 on its own outbound
HTTP call. A fix was started (15000ms timeout added, Retry On Fail toggled on) but n8n's
autosave began failing with "Unauthorized" mid-edit; a fresh browser tab confirmed the
n8n session had expired (redirected to /signin). Nothing was saved — workflow 4's live
definition is unchanged from before this round, so there is no partial or broken state.
This is lower-stakes than workflows 1/2 (workflow 4 is the error notifier itself, not a
primary business flow, and a failed error-report is already visible in n8n's own
execution history via On Error: Stop Workflow) but should be finished once the n8n
browser session is re-authenticated.
Repository source of truth
n8n/workflows/ holds cleaned, credential-value-free JSON definitions for all built
workflows, n8n/workflows/MANIFEST.md documents purpose/trigger/contract/credentials/
live-ID/checksum for all four canonical workflows (including workflow 3's blocked
status), and n8n/workflows/check_drift.py is a read-only script that compares the
repo definitions against the live instance via n8n's Public API and reports drift —
safe to run in CI as a non-blocking check. No literal export/download mechanism was
found working in this n8n version, so each definition was reconstructed from direct,
verified UI inspection rather than a native export; this limitation is noted in the
manifest itself.
Integration status page
/automation (Operations Manager only) surfaces real per-workflow evidence derived
purely from Fleet Ops's own audit/outbox tables — no new dependency on n8n's API was
added to the backend. Each of the four canonical workflows shows a status (not built /
no evidence yet / operational) and a last-evidence timestamp; the scheduled-scan
evidence specifically filters to actor_type == "service" so a manually-triggered scan
in the UI doesn't count as n8n evidence. An error-handler summary line reports total
registered automation failures and the most recent one.
Verified live in the browser (Dutch locale) both locally and on the deployed
production server (http://192.168.10.150:1236/automation): correctly showed "3 van 4
canonieke n8n-workflows hebben actuele evidentie van werking" with real timestamps for
the return/scan/error-handler workflows, "Nog Niet Gebouwd" for the RAGcore sync, and
the real error-handler registration from this effort's live testing.
Deployments performed (all explicitly user-approved)
- Backend
/workflow-errorendpoint (commitbbdb4a9) — deployed and verified (/healthOK, new endpoint returns422not404on an empty POST body). - Integration status page, backend + frontend (commit
4049c0c) — deployed and verified (/healthOK, page renders real evidence in the browser).
The three n8n-side node edits this round (WF1 timeout/retry, WF2 timeout/retry, WF4's incomplete attempt) are live edits to the n8n instance itself and do not require a Fleet Ops redeploy.
What's left
- RAGcore credential issuance — blocked on RAGcore's own server-side rejection
(trace
1955c6a8968c4941a22a1faef39e17a7and the earlier raw-API400). Needs RAGcore's operator to investigate. Unblocks workflow 3 and theRAGcoreKnowledgeProviderreal-contract rewrite. - Workflow 4's own timeout/bounded-retry hardening — needs the n8n browser session re-authenticated to finish; a small, well-understood, non-blocking edit.
- Fleet Ops logo/favicon — explicitly deferred by the project owner as a separate, unrelated follow-up task, not part of this integration effort.