diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index 08a3a33..bb9aecc 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -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 `), 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. diff --git a/n8n/workflows/MANIFEST.md b/n8n/workflows/MANIFEST.md index a0335ab..145f05b 100644 --- a/n8n/workflows/MANIFEST.md +++ b/n8n/workflows/MANIFEST.md @@ -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 `), 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 | |---|---|