M31: align RAG verification with provider contract
MobilityOps acceptance / backend (push) Canceled after 0s
MobilityOps acceptance / frontend (push) Canceled after 0s

This commit is contained in:
NuklearRabbit
2026-08-10 21:02:47 +02:00
parent efab8d816f
commit cb7edb0b84
8 changed files with 18 additions and 13 deletions
+3 -1
View File
@@ -2702,7 +2702,9 @@ evidence yet."
- RAGcore health now verifies every language-specific managed source through the - RAGcore health now verifies every language-specific managed source through the
documented exact `/v1/documents` identity lookup. Only an active document with a documented exact `/v1/documents` identity lookup. Only an active document with a
published active version and the authoritative Fleet Ops content hash is counted. published active version is counted. RAGcore's provider-owned `content_sha256` hashes
its canonical parsed artifact rather than the raw upload, so it is deliberately not
compared with Fleet Ops's source-file hash.
Lookups are bounded, concurrent and cached for five minutes; an unavailable verifier Lookups are bounded, concurrent and cached for five minutes; an unavailable verifier
remains explicitly unknown instead of being presented as zero or as a reported count. remains explicitly unknown instead of being presented as zero or as a reported count.
- Persisted n8n sync provenance no longer downgrades the stronger provider-verified - Persisted n8n sync provenance no longer downgrades the stronger provider-verified
+4 -3
View File
@@ -163,7 +163,7 @@ class RAGcoreKnowledgeProvider:
else: else:
detail += ( detail += (
f" {verified_document_count}/{len(documents)} managed sources have " f" {verified_document_count}/{len(documents)} managed sources have "
"an active published version with the expected content hash." "an exact active published document in the configured space."
) )
except (httpx.HTTPError, ValueError) as exc: except (httpx.HTTPError, ValueError) as exc:
available = False available = False
@@ -177,7 +177,9 @@ class RAGcoreKnowledgeProvider:
collection=self._settings.ragcore_collection, collection=self._settings.ragcore_collection,
# RAGcore deliberately has no browse/count endpoint. Fleet Ops instead # RAGcore deliberately has no browse/count endpoint. Fleet Ops instead
# verifies each managed source through its exact identity lookup and only # verifies each managed source through its exact identity lookup and only
# counts an active published version whose content hash still matches. # counts an active document with a published active version. RAGcore's
# content_sha256 describes its canonical parsed artifact, not the uploaded
# source bytes, so comparing it with Fleet Ops's source hash would be false.
document_count=verified_document_count, document_count=verified_document_count,
source_document_count=len(documents), source_document_count=len(documents),
reported_synced_document_count=None, reported_synced_document_count=None,
@@ -224,7 +226,6 @@ class RAGcoreKnowledgeProvider:
and item.get("status") == "active" and item.get("status") == "active"
and isinstance(active_version, dict) and isinstance(active_version, dict)
and active_version.get("status") == "published" and active_version.get("status") == "published"
and active_version.get("content_sha256") == document.content_hash
) )
try: try:
+1 -1
View File
@@ -346,7 +346,7 @@ def test_ragcore_provider_verifies_published_documents_and_caches_count(monkeypa
"status": "active", "status": "active",
"active_version": { "active_version": {
"status": "published", "status": "published",
"content_sha256": document.content_hash, "content_sha256": "provider-canonical-hash",
}, },
} }
] ]
+3 -1
View File
@@ -31,7 +31,9 @@ provide an exact identity lookup through `GET /v1/documents?source_id=...&extern
Fleet Ops uses that documented read contract concurrently and with bounded per-request Fleet Ops uses that documented read contract concurrently and with bounded per-request
timeouts for every managed source in the requested language. A document counts only when timeouts for every managed source in the requested language. A document counts only when
RAGcore returns exactly one active document in the configured space with a published active RAGcore returns exactly one active document in the configured space with a published active
version whose `content_sha256` matches Fleet Ops's authoritative file. Results are cached version. RAGcore's `content_sha256` represents its canonical parsed artifact rather than
the uploaded source bytes, so Fleet Ops deliberately does not compare that provider-owned
hash with its raw Markdown hash. Results are cached
for five minutes. This produces an independently verified `document_count` without changing for five minutes. This produces an independently verified `document_count` without changing
RAGcore or relabelling an upload/sync report as index evidence. If exact verification is RAGcore or relabelling an upload/sync report as index evidence. If exact verification is
temporarily unavailable, `document_count` remains `null` and the sync report stays visibly temporarily unavailable, `document_count` remains `null` and the sync report stays visibly
+1 -1
View File
@@ -80,5 +80,5 @@ test("Knowledge Hub renders independently verified RAGcore index evidence", asyn
await page.goto("/knowledge"); await page.goto("/knowledge");
await expect(page.getByText("11 procedures geïndexeerd")).toBeVisible(); await expect(page.getByText("11 procedures geïndexeerd")).toBeVisible();
await expect(page.getByText("actief gepubliceerd en inhoudelijk geverifieerd")).toBeVisible(); await expect(page.getByText("exact gevonden en actief gepubliceerd")).toBeVisible();
}); });
@@ -23,11 +23,11 @@
"checkout-procedure": "Required checkout controls" "checkout-procedure": "Required checkout controls"
}, },
"statistics": { "statistics": {
"verifiedIndexed": "actively published and content-verified", "verifiedIndexed": "exactly matched and actively published",
"sourceDocuments": "source documents in this language", "sourceDocuments": "source documents in this language",
"reportedSynced": "sync reported by n8n", "reportedSynced": "sync reported by n8n",
"reportedFailed": "sync failures reported", "reportedFailed": "sync failures reported",
"lastSync": "Latest sync report: {{when}}. Index state is independently checked against each managed source's active RAGcore version and content hash.", "lastSync": "Latest sync report: {{when}}. Index state is independently checked through each managed source's exact identity and active RAGcore version.",
"noSyncReport": "No sync report has been received yet. Index evidence is checked separately through active RAGcore versions." "noSyncReport": "No sync report has been received yet. Index evidence is checked separately through active RAGcore versions."
}, },
"providerNote": "This demo answers from a small, fixed set of indexed procedures — not a live RAGcore connection. A live RAGcore backend will later take over the same interface without changing how this page works.", "providerNote": "This demo answers from a small, fixed set of indexed procedures — not a live RAGcore connection. A live RAGcore backend will later take over the same interface without changing how this page works.",
@@ -23,11 +23,11 @@
"checkout-procedure": "Contrôles obligatoires au départ" "checkout-procedure": "Contrôles obligatoires au départ"
}, },
"statistics": { "statistics": {
"verifiedIndexed": "publiées activement et contenu vérifié", "verifiedIndexed": "correspondance exacte et publication active",
"sourceDocuments": "documents sources dans cette langue", "sourceDocuments": "documents sources dans cette langue",
"reportedSynced": "synchronisation signalée par n8n", "reportedSynced": "synchronisation signalée par n8n",
"reportedFailed": "échecs de synchronisation signalés", "reportedFailed": "échecs de synchronisation signalés",
"lastSync": "Dernier rapport de synchronisation : {{when}}. L’état de lindex est contrôlé indépendamment via la version RAGcore active et lempreinte de contenu de chaque source gérée.", "lastSync": "Dernier rapport de synchronisation : {{when}}. L’état de lindex est contrôlé indépendamment via lidentité exacte et la version RAGcore active de chaque source gérée.",
"noSyncReport": "Aucun rapport de synchronisation reçu. Les preuves dindexation sont contrôlées séparément via les versions RAGcore actives." "noSyncReport": "Aucun rapport de synchronisation reçu. Les preuves dindexation sont contrôlées séparément via les versions RAGcore actives."
}, },
"providerNote": "Cette démo répond à partir d'un petit ensemble fixe de procédures indexées — pas d'une connexion RAGcore en direct. Un backend RAGcore en direct reprendra plus tard la même interface sans changer le fonctionnement de cette page.", "providerNote": "Cette démo répond à partir d'un petit ensemble fixe de procédures indexées — pas d'une connexion RAGcore en direct. Un backend RAGcore en direct reprendra plus tard la même interface sans changer le fonctionnement de cette page.",
@@ -23,11 +23,11 @@
"checkout-procedure": "Verplichte vertrekcontroles" "checkout-procedure": "Verplichte vertrekcontroles"
}, },
"statistics": { "statistics": {
"verifiedIndexed": "actief gepubliceerd en inhoudelijk geverifieerd", "verifiedIndexed": "exact gevonden en actief gepubliceerd",
"sourceDocuments": "brondocumenten in deze taal", "sourceDocuments": "brondocumenten in deze taal",
"reportedSynced": "sync door n8n gerapporteerd", "reportedSynced": "sync door n8n gerapporteerd",
"reportedFailed": "syncfouten gerapporteerd", "reportedFailed": "syncfouten gerapporteerd",
"lastSync": "Laatste syncrapport: {{when}}. De indexstand wordt onafhankelijk gecontroleerd via de actieve RAGcore-versie en inhoudshash van elke beheerde bron.", "lastSync": "Laatste syncrapport: {{when}}. De indexstand wordt onafhankelijk gecontroleerd via de exacte bronidentiteit en actieve RAGcore-versie.",
"noSyncReport": "Nog geen syncrapport ontvangen. Indexbewijs wordt afzonderlijk via de actieve RAGcore-versies gecontroleerd." "noSyncReport": "Nog geen syncrapport ontvangen. Indexbewijs wordt afzonderlijk via de actieve RAGcore-versies gecontroleerd."
}, },
"providerNote": "Deze demo beantwoordt vanuit een kleine, vaste set geïndexeerde procedures — geen live RAGcore-koppeling. Een live RAGcore-backend zal later dezelfde interface overnemen, zonder dat deze pagina verandert.", "providerNote": "Deze demo beantwoordt vanuit een kleine, vaste set geïndexeerde procedures — geen live RAGcore-koppeling. Een live RAGcore-backend zal later dezelfde interface overnemen, zonder dat deze pagina verandert.",