diff --git a/infra/synology/.env.synology.example b/infra/synology/.env.synology.example index 2a0eecc..71aba0d 100644 --- a/infra/synology/.env.synology.example +++ b/infra/synology/.env.synology.example @@ -65,3 +65,5 @@ NODEDC_AI_WORKSPACE_ASSISTANT_URL=http://ai-workspace-assistant:18082 AI_WORKSPACE_HUB_TOKEN=replace-with-random-synology-secret AI_WORKSPACE_HUB_HOST_BIND=0.0.0.0:18081 +AI_WORKSPACE_HUB_PUBLIC_URL=wss://ai-hub.nodedc.ru/api/ai-workspace/hub +AI_WORKSPACE_HUB_FALLBACK_URLS= diff --git a/infra/synology/README.md b/infra/synology/README.md index d6a22f0..54b13ba 100644 --- a/infra/synology/README.md +++ b/infra/synology/README.md @@ -26,6 +26,26 @@ https://ai-hub.nodedc.ru -> AI Workspace Hub / WebSocket relay В `Caddyfile.http` эти домены проксируются через локальный HTTP edge, но upstream получает `X-Forwarded-Proto: https` и `X-Forwarded-Port: 443`. +## AI Workspace Hub / Assistant contract + +`ai-workspace-hub` remains a thin public WebSocket relay. It is the only AI Workspace service exposed through DSM/Nginx as `https://ai-hub.nodedc.ru`. + +`ai-workspace-assistant` is an internal platform service for per-user executors, selected device, shared threads and installer generation. It must not be exposed as a public route. Launcher, Engine and Tasker use it through Docker networking: + +```env +NODEDC_AI_WORKSPACE_ASSISTANT_URL=http://ai-workspace-assistant:18082 +PLANE_NODEDC_AI_WORKSPACE_ASSISTANT_URL=http://ai-workspace-assistant:18082 +``` + +Installer generation must always point remote Codex workers to the deployed Hub: + +```env +AI_WORKSPACE_HUB_PUBLIC_URL=wss://ai-hub.nodedc.ru/api/ai-workspace/hub +AI_WORKSPACE_HUB_FALLBACK_URLS= +``` + +Server-side Hub API calls require a token accepted by Hub: `AI_WORKSPACE_HUB_TOKEN`, `NDC_AI_WORKSPACE_HUB_TOKEN`, or the shared `NODEDC_INTERNAL_ACCESS_TOKEN` where that token is intentionally common across platform services. + ## Локальные домены для первичной проверки На Mac для первичной проверки добавить в `/etc/hosts`: diff --git a/infra/synology/apply-current-runtime.sh b/infra/synology/apply-current-runtime.sh index ef025eb..677a33e 100755 --- a/infra/synology/apply-current-runtime.sh +++ b/infra/synology/apply-current-runtime.sh @@ -53,6 +53,10 @@ echo "== ai workspace assistant health check ==" "${DOCKER_BIN}" exec nodedc-platform-ai-workspace-assistant-1 sh -lc \ 'node -e '"'"'fetch("http://127.0.0.1:18082/healthz").then(async (response) => { console.log(await response.text()); process.exit(response.ok ? 0 : 1); }).catch((error) => { console.error(error); process.exit(1); })'"'"'' +echo "== ai workspace assistant hub target check ==" +"${DOCKER_BIN}" exec nodedc-platform-ai-workspace-assistant-1 sh -lc \ + 'test "$AI_WORKSPACE_HUB_PUBLIC_URL" = "wss://ai-hub.nodedc.ru/api/ai-workspace/hub" && test -z "$AI_WORKSPACE_HUB_FALLBACK_URLS" && echo ai-workspace-prod-hub-target-ok' + echo "== clear authentik global brand css ==" DOCKER_BIN="${DOCKER_BIN}" bash "${PLATFORM_DIR}/clear-authentik-brand-css.sh" diff --git a/infra/synology/docker-compose.platform-http.yml b/infra/synology/docker-compose.platform-http.yml index 7d38544..2b922d6 100644 --- a/infra/synology/docker-compose.platform-http.yml +++ b/infra/synology/docker-compose.platform-http.yml @@ -138,6 +138,8 @@ services: DATABASE_URL: postgres://${AI_WORKSPACE_PG_USER:-nodedc_ai_workspace}:${AI_WORKSPACE_PG_PASS:?ai workspace database password required}@ai-workspace-postgres:5432/${AI_WORKSPACE_PG_DB:-nodedc_ai_workspace} AI_WORKSPACE_ASSISTANT_TOKEN: ${AI_WORKSPACE_ASSISTANT_TOKEN:?ai workspace assistant token required} NODEDC_INTERNAL_ACCESS_TOKEN: ${NODEDC_INTERNAL_ACCESS_TOKEN:-} + AI_WORKSPACE_HUB_PUBLIC_URL: ${AI_WORKSPACE_HUB_PUBLIC_URL:-wss://ai-hub.nodedc.ru/api/ai-workspace/hub} + AI_WORKSPACE_HUB_FALLBACK_URLS: ${AI_WORKSPACE_HUB_FALLBACK_URLS:-} expose: - "18082" ports: diff --git a/infra/synology/verify-current-runtime.sh b/infra/synology/verify-current-runtime.sh index 9541a67..9944d96 100755 --- a/infra/synology/verify-current-runtime.sh +++ b/infra/synology/verify-current-runtime.sh @@ -63,6 +63,10 @@ echo "== ai workspace assistant health check ==" "${DOCKER_BIN}" exec nodedc-platform-ai-workspace-assistant-1 sh -lc \ 'node -e '"'"'fetch("http://127.0.0.1:18082/healthz").then(async (response) => { console.log(await response.text()); process.exit(response.ok ? 0 : 1); }).catch((error) => { console.error(error); process.exit(1); })'"'"'' +echo "== ai workspace assistant hub target check ==" +"${DOCKER_BIN}" exec nodedc-platform-ai-workspace-assistant-1 sh -lc \ + 'test "$AI_WORKSPACE_HUB_PUBLIC_URL" = "wss://ai-hub.nodedc.ru/api/ai-workspace/hub" && test -z "$AI_WORKSPACE_HUB_FALLBACK_URLS" && echo ai-workspace-prod-hub-target-ok' + echo "== auth flow check ==" auth_flow="$(fetch_with_retry https://id.nodedc.ru/if/flow/default-authentication-flow/)" printf '%s' "$auth_flow" \