docs: record root cause and fix for the RAGcore credential-issuance bug

With explicit owner approval, traced the persistent credential-issuance
rejection to a cross-transaction race in RAGcore's own dependency
injection (two independent DB transactions per request instead of one
shared transaction), fixed and deployed it in RAGcore, and verified a
working "RAGcore Sync Token" n8n credential now exists. Unblocks
workflow 3 and the RAGcoreKnowledgeProvider adapter rewrite.
This commit is contained in:
NuklearRabbit
2026-08-04 18:11:34 +02:00
parent cf4d8e3649
commit 2afceea5e4
2 changed files with 46 additions and 20 deletions
+33 -9
View File
@@ -1260,12 +1260,36 @@ Handler — both net-new, not yet built.
failed error-report is visible in n8n's own execution history even without retries) —
not blocking, but worth finishing once someone re-authenticates the n8n browser
session.
- **Exact next action**: workflow 3 (RAGcore Procedure Sync) and the
`RAGcoreKnowledgeProvider` adapter fix stay blocked on RAGcore's own credential-issuance
rejection (not a Fleet Ops-side gap) — this is the only remaining blocker for task #86
and, transitively, the RAGcore-sync portion of #90/#91. WF1 and WF2's
timeouts/bounded-retries gaps are now fixed and live; WF4's matching gap on its own
outbound call is identified but not yet fixed (n8n browser session expired mid-edit —
needs re-authentication to finish, see above). Writing the final evidence doc (#91) next,
honestly documenting workflow 3 as blocked on RAGcore and the WF4 retry hardening as a
minor open follow-up.
- **RAGcore credential-issuance blocker root-caused and fixed (in RAGcore itself, with
explicit owner approval)**: with read access to the sibling `C:\Projects\RAGcore`
checkout, traced "authoritative service-account state rejected issuance" to a genuine
cross-transaction race in RAGcore's own dependency injection
(`src/ragcore/api/v1/control/dependencies.py`). `get_control_application` and
`get_credential_service` each independently opened their own `factory.begin()`
database transaction. Issuing a credential for a brand-new service account does, in one
request: (1) INSERT the service account via the first dependency's transaction, then
(2) immediately re-read it via the second dependency's *separate, uncommitted* transaction
— invisible under READ COMMITTED isolation until the first transaction commits, which
only happens after the endpoint returns. This made every fresh-service-account credential
issuance fail, 100% of the time, via both the raw API and the admin UI (explaining the
identical failure signature on both paths). RAGcore's own tests never caught this because
they override these dependencies with an in-memory fake that ignores transaction boundaries
entirely. Fixed by introducing one shared, cached `get_control_session` dependency that
both providers now depend on via `Depends(...)`, so they share one transaction per request.
Verified: RAGcore's own test suite (64 tests across `tests/web`, `tests/contract/api/control`,
`tests/security/identity`, `tests/unit/domain/control`, `tests/api`) passes, ruff and mypy
clean. Deployed to the live RAGcore instance (also on the Unraid host, `ragcore-app-1` on
port 1237 — a shared service also used by other ITWorx projects) via `docker compose build`
+ `up -d`, with explicit owner approval before both the code change and the deploy.
Confirmed fixed live: issuing a credential for `fleet-ops` (name
`n8n-ragcore-procedure-sync`, scope `sources:sync`) now succeeds (prefix `rc_sa_6fc51e`).
The plaintext token was never printed/logged — copied via RAGcore's own "Copy" button and
pasted directly into a new n8n Header Auth credential named **"RAGcore Sync Token"**
(header `Authorization: Bearer <token>`), ready for workflow 3.
- **Exact next action**: task #86 (build workflow 3, RAGcore Procedure Sync) and the
`RAGcoreKnowledgeProvider` adapter rewrite (to the real inspected contract — `/health/live`,
`/health/ready`, `POST /v1/uploads`, `POST /v1/search`/`/v1/context`/`/v1/answers`) are now
unblocked — the "RAGcore Sync Token" n8n credential exists and works. WF4's own
timeout/retry gap is still open pending n8n browser re-authentication (minor, non-blocking,
see above). Both #90 and #91 should be revisited once workflow 3 is actually built, since
they currently document it as blocked.
+13 -11
View File
@@ -37,20 +37,22 @@ credential values are never embedded; nodes reference named n8n credentials inst
## 3. Fleet Ops — RAGcore Procedure Sync
Not yet built. Blocked on a RAGcore application credential (scope `sources:sync`) for the
`fleet-ops` application. Two independent issuance attempts have failed with an opaque
server-side rejection: the raw API (`POST /v1/applications/{id}/credentials`, 400
"authoritative service-account state rejected issuance") and the RAGcore admin UI's
"Issue credential" form as the Platform Admin role (generic "Something went wrong",
trace reference `1955c6a8968c4941a22a1faef39e17a7`). The `fleet-ops` application itself
shows as ordinary/`Active` with no visible lock in the RAGcore admin UI, and the OpenAPI
spec documents no validation constraint that would explain either rejection — this is a
RAGcore-side policy or bug, not a Fleet Ops request-shape or permission problem. Needs
RAGcore's own operator to look up the trace IDs above in RAGcore's logs. Will sync
Not yet built, but no longer blocked. Credential issuance for the `fleet-ops` application
previously failed 100% of the time with an opaque rejection ("authoritative service-account
state rejected issuance" via the raw API; a generic error via the admin UI). Root-caused to
a genuine bug in RAGcore itself — a cross-transaction race in
`src/ragcore/api/v1/control/dependencies.py` where `get_control_application` and
`get_credential_service` each opened their own independent database transaction, so a
freshly-created service account was invisible to the immediately-following credential-issue
read. Fixed in RAGcore (with explicit owner approval) by sharing one request-scoped
transaction between both dependencies; verified against RAGcore's own test suite (64
passing) and deployed to the live instance. A working credential now exists: n8n credential
**"RAGcore Sync Token"** (Header Auth, `Authorization: Bearer <token>`), scope
`sources:sync` for `fleet-ops`. Will build
`n8n/workflows/fleet-ops-ragcore-procedure-sync.json` against the real RAGcore contract
(`POST /v1/uploads`, `GET /v1/knowledge-spaces`, etc. — see
`contracts/ragcore-contract-assumptions.md` and the live inspection notes in
`docs/live-ai-integration/n8n-current-state.md`) once a working credential exists.
`docs/live-ai-integration/n8n-current-state.md`) next.
| Field | Value |
|---|---|