From 444e61253bf66141ba46a953f0bc574c1a273a4c Mon Sep 17 00:00:00 2001 From: NuklearRabbit <145918611+NuklearRabbit@users.noreply.github.com> Date: Mon, 24 Aug 2026 03:45:09 +0200 Subject: [PATCH] M55: restore private RAGcore routing --- .env.example | 3 +++ PROJECT_STATE.md | 21 ++++++++++++++++++++ deploy/unraid/README.md | 12 +++++++++++ deploy/unraid/deploy-release.sh | 35 ++++++++++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 9eb5d46..349b87e 100644 --- a/.env.example +++ b/.env.example @@ -96,6 +96,9 @@ MOBILITYOPS_WEBHOOK_TRIGGER_TOKEN=replace-me-n8n-webhook-trigger-token # RAGcore integration KNOWLEDGE_PROVIDER=demo RAGCORE_BASE_URL=http://ragcore-api:8000 +# Optional existing Docker network used by hosted deployments to reach RAGcore through +# its private service alias instead of exposing RAGcore on the LAN. +RAGCORE_DOCKER_NETWORK= RAGCORE_TENANT=northstar-mobility-demo RAGCORE_WORKSPACE=mobilityops RAGCORE_COLLECTION=internal-procedures diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index d949ae5..304f3ef 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -1,5 +1,26 @@ # Project state +## M55 — restore private cross-project RAGcore routing (2026-08-24) + +- M54 promoted successfully as `81e3fd63bdbcb2e9c4ae1d709ea46f40537b6f62`, with two + API and two web replicas, exact OCI revision labels, Alembic `4f2b9c8d7e61 (head)` and + healthy public/loopback readiness. The live browser canary then proved that all core routes + worked but RAGcore degraded honestly to unavailable in both browsers. +- The failure was infrastructure routing, not answer validation: the existing healthy + RAGcore app now publishes host port 1237 on loopback only, while Fleet Ops still targeted + the host LAN address and received TCP `connection refused` from inside its container. +- Extended the start-first deployer with a validated optional `RAGCORE_DOCKER_NETWORK`. + Candidate APIs join that pre-existing network and take the non-secret `RAGCORE_BASE_URL` + from the authoritative server `.env`; all secrets still come from the serving API's + resolved environment and are never printed. The hosted configuration can now use the + private `ragcore-app:8080` alias without exposing RAGcore on the LAN. +- Validation: Alpine `sh -n` passed for the deployer; base/Unraid Compose config, source + budgets and `git diff --check` pass. M54's complete **331 backend / 171 Playwright** gates + remain applicable because M55 changes deployment topology and documentation only. +- Exact next action: commit/push M55, safely update the two non-secret RAGcore routing keys + in the server `.env`, take a fresh verified backup, deploy the exact M55 archive and repeat + the four Chromium/Firefox live acceptance checks. + ## M54 — full logic, resilience and recruiter upgrade (2026-08-23, local candidate) - Replaced the static Engineering architecture row with an interactive, keyboard-operable diff --git a/deploy/unraid/README.md b/deploy/unraid/README.md index 9e85506..2b02948 100644 --- a/deploy/unraid/README.md +++ b/deploy/unraid/README.md @@ -22,6 +22,18 @@ Create `.env` from `.env.example`, replace every placeholder secret, set The internal `1236` listener is an upstream for the TLS proxy, not a user-facing URL. +When RAGcore runs as a separate Compose project on the same host, keep its HTTP listener +private and configure Fleet Ops through the existing shared Docker network, for example: + +```dotenv +RAGCORE_BASE_URL=http://ragcore-app:8080 +RAGCORE_DOCKER_NETWORK=ragcore-proxy +``` + +The release deployer validates the network, attaches only the API replicas and takes the +non-secret RAGcore URL from the server `.env` on every promotion. Tokens and the remaining +resolved API environment continue to be inherited without being printed. + ```bash cd /mnt/user/appdata/mobilityops ./deploy/unraid/configure-env.sh \ diff --git a/deploy/unraid/deploy-release.sh b/deploy/unraid/deploy-release.sh index b8c4b80..be9b94e 100755 --- a/deploy/unraid/deploy-release.sh +++ b/deploy/unraid/deploy-release.sh @@ -15,6 +15,33 @@ case "$revision" in *[!0-9a-f]*) echo "Revision must be lowercase hexadecimal" > [ -n "$expected_checksum" ] || { echo "Expected SHA-256 is required" >&2; exit 1; } [ -f "$root/.env" ] || { echo "Production .env is missing" >&2; exit 1; } +read_env_value() { + key="$1" + awk -v key="$key" ' + index($0, key "=") == 1 { + sub("^[^=]*=", "") + print + exit + } + ' "$root/.env" +} + +# Stateless replicas normally inherit the complete, already-secret-resolved environment +# from the serving API. RAGcore routing is an explicit exception: its private endpoint and +# cross-project Docker network are non-secret deployment topology and the server .env is +# authoritative so infrastructure changes take effect on the next release. +ragcore_base_url="$(read_env_value RAGCORE_BASE_URL)" +ragcore_network="$(read_env_value RAGCORE_DOCKER_NETWORK)" +case "$ragcore_base_url" in + http://*|https://*) ;; + *) echo "RAGCORE_BASE_URL must be an absolute HTTP(S) URL" >&2; exit 1 ;; +esac +case "$ragcore_network" in + "") ;; + *[!a-zA-Z0-9_.-]*) echo "RAGCORE_DOCKER_NETWORK contains invalid characters" >&2; exit 1 ;; + *) docker network inspect "$ragcore_network" > /dev/null ;; +esac + actual_checksum="$(sha256sum "$archive" | awk '{print $1}')" [ "$actual_checksum" = "$expected_checksum" ] || { echo "Archive checksum mismatch" >&2 @@ -123,7 +150,13 @@ for replica in 1 2; do --label "com.mobilityops.revision=$revision" \ --network "$network" --network-alias api --network-alias "api-$short_revision" \ --env-file "$api_environment" \ - --env RUN_MIGRATIONS=false "$api_image")" + --env RUN_MIGRATIONS=false --env "RAGCORE_BASE_URL=$ragcore_base_url" "$api_image")" + if [ -n "$ragcore_network" ] && ! docker network connect "$ragcore_network" "$id"; then + # shellcheck disable=SC2086 + docker rm -f $new_api_ids "$id" > /dev/null 2>&1 || true + echo "Could not attach API candidates to RAGcore network $ragcore_network" >&2 + exit 1 + fi new_api_ids="$new_api_ids $id" done