Add platform AI Workspace Hub

This commit is contained in:
Codex
2026-05-30 13:28:23 +03:00
parent e605e95920
commit 469657d526
13 changed files with 1403 additions and 7 deletions
+20
View File
@@ -18,6 +18,8 @@ services:
condition: service_started
notification-core:
condition: service_started
ai-workspace-hub:
condition: service_started
extra_hosts:
- "host.docker.internal:host-gateway"
@@ -126,6 +128,24 @@ services:
notification-postgres:
condition: service_healthy
ai-workspace-hub:
image: nodedc/ai-workspace-hub:local
build:
context: ../services/ai-workspace-hub
restart: unless-stopped
env_file:
- path: .env
required: false
environment:
NODE_ENV: production
PORT: 18081
AI_WORKSPACE_HUB_TOKEN: ${AI_WORKSPACE_HUB_TOKEN:-dev-ai-workspace-hub-token}
AI_WORKSPACE_HUB_WS_PATH: /api/ai-workspace/hub
expose:
- "18081"
ports:
- "${AI_WORKSPACE_HUB_HOST_BIND:-127.0.0.1:18081}:18081"
volumes:
authentik-database:
authentik-data:
+3
View File
@@ -56,3 +56,6 @@ NOTIFICATION_PG_DB=nodedc_notifications
NOTIFICATION_PG_USER=nodedc_notifications
NOTIFICATION_PG_PASS=replace-with-random-synology-secret
NODEDC_NOTIFICATION_CORE_URL=http://notification-core:5185
AI_WORKSPACE_HUB_TOKEN=replace-with-random-synology-secret
AI_WORKSPACE_HUB_HOST_BIND=0.0.0.0:18081
+8 -4
View File
@@ -7,7 +7,7 @@
- Не выполнять `docker stop`, `docker restart`, `docker compose down`, `docker system prune` для старых проектов.
- Новый compose project: `nodedc-platform`.
- Новая папка на NAS: `/volume1/docker/nodedc-platform`.
- Внутренний HTTP edge использует `18080`, Tasker upstream — `18090`, Ops Agents Gateway upstream — `18190`.
- Внутренний HTTP edge использует `18080`, AI Workspace Hub — `18081`, Tasker upstream — `18090`, Ops Agents Gateway upstream — `18190`.
- Старые порты `9000` и `5678` заняты старым `nodedc-demo` и не используются.
## Текущие внешние домены
@@ -17,10 +17,13 @@ https://id.nodedc.ru -> Authentik
https://hub.nodedc.ru -> Launcher / Hub
https://ops.nodedc.ru -> Tasker / Operational Core
https://ops-agents.nodedc.ru -> Ops Agents Gateway / MCP
https://ai-hub.nodedc.ru -> AI Workspace Hub / WebSocket relay
```
`id.nodedc.ru` is the user-facing OIDC/login host. Authentik Admin is intentionally not exposed through this public host; `/if/admin/*` returns `404` there.
`ai-hub.nodedc.ru` is intentionally routed by Synology DSM Reverse Proxy directly to `172.22.0.222:18081`, because this endpoint must carry WebSocket Upgrade traffic for remote Codex agents.
В `Caddyfile.http` эти домены проксируются через локальный HTTP edge, но upstream получает `X-Forwarded-Proto: https` и `X-Forwarded-Port: 443`.
## Локальные домены для первичной проверки
@@ -49,9 +52,9 @@ http://task.nas.nodedc:18090
## Что входит
- `docker-compose.platform-http.yml` поднимает новый Authentik, Launcher, Notification Core и Caddy edge.
- `docker-compose.platform-http.yml` поднимает новый Authentik, Launcher, Notification Core, AI Workspace Hub и Caddy edge.
- `Caddyfile.http` маршрутизирует локальные `auth/auth-admin/launcher/task.nas.nodedc`, IP fallback `172.22.0.222` для Authentik Admin и внешние `id/hub/ops.nodedc.ru`.
- `deploy-current.sh` синхронизирует compose, Caddyfile, Notification Core source и опционально Launcher source в NAS mount. Authentik templates синхронизируются только при явном `SYNC_AUTHENTIK_TEMPLATES=1`.
- `deploy-current.sh` синхронизирует compose, Caddyfile, Notification Core source, AI Workspace Hub source и опционально Launcher source в NAS mount. Authentik templates синхронизируются только при явном `SYNC_AUTHENTIK_TEMPLATES=1`.
- `backup-current.sh` делает snapshot Launcher runtime/uploads/Auth templates/config и готовит команду `pg_dump` для Authentik Postgres.
- Tasker поднимается отдельным compose из `NODEDC_TASKMANAGER/plane-app/docker-compose.yaml` на порту `18090`.
- Ops Agents Gateway поднимается отдельным compose из `NODEDC_TASKMANAGER_CODEXAPI/docker-compose.synology.yml` на `172.22.0.222:18190`; Synology reverse proxy должен вести `ops-agents.nodedc.ru` на этот порт, а не на `18090`.
@@ -117,6 +120,7 @@ GATEWAY_REPO=/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXA
- Platform compose/Caddy.
- Notification Core source в `/volume1/docker/nodedc-platform/platform/notification-core`.
- AI Workspace Hub source в `/volume1/docker/nodedc-platform/platform/ai-workspace-hub`.
- Authentik templates только при `SYNC_AUTHENTIK_TEMPLATES=1`; по умолчанию они не трогаются, чтобы лёгкий Hub deploy не уносил экспериментальную тему/брендинг в prod.
- Launcher source в `/volume1/docker/nodedc-platform/launcher/source`.
- Tasker `plane-app/docker-compose.yaml` и, если задан `TASKER_CHANGED_BASE`, только изменённые source-файлы из диапазона `TASKER_CHANGED_BASE..HEAD`.
@@ -148,7 +152,7 @@ cd /volume1/docker/nodedc-platform/platform
sudo /usr/local/bin/docker compose \
--env-file /volume1/docker/nodedc-platform/platform/.env.synology \
-f /volume1/docker/nodedc-platform/platform/docker-compose.platform-http.yml \
up -d --force-recreate --no-deps launcher
up -d --force-recreate --no-deps ai-workspace-hub launcher
```
После такого deploy проверить `healthz`, запись в launcher storage/uploads и сценарий пользователя без аппрува: сохранение аватара не должно показывать экран `Заявка ожидает подтверждения`. Дополнительно проверить, что live bundle больше не содержит старый pending gate:
+9 -1
View File
@@ -26,17 +26,25 @@ echo "== notification core image build =="
cd "${PLATFORM_DIR}/notification-core"
"${DOCKER_BIN}" build --no-cache -t nodedc/notification-core:local .
echo "== ai workspace hub image build =="
cd "${PLATFORM_DIR}/ai-workspace-hub"
"${DOCKER_BIN}" build --no-cache -t nodedc/ai-workspace-hub:local .
echo "== platform services recreate =="
cd "${PLATFORM_DIR}"
"${DOCKER_BIN}" compose \
--env-file "${ENV_FILE}" \
-f "${COMPOSE_FILE}" \
up -d --force-recreate reverse-proxy authentik-server authentik-worker notification-postgres notification-core launcher
up -d --force-recreate reverse-proxy authentik-server authentik-worker notification-postgres notification-core ai-workspace-hub launcher
echo "== notification core health check =="
"${DOCKER_BIN}" exec nodedc-platform-notification-core-1 sh -lc \
'wget -qSO- http://127.0.0.1:5185/healthz 2>&1 | head -n 25'
echo "== ai workspace hub health check =="
"${DOCKER_BIN}" exec nodedc-platform-ai-workspace-hub-1 sh -lc \
'node -e '"'"'fetch("http://127.0.0.1:18081/healthz").then(async (response) => { console.log(await response.text()); process.exit(response.ok ? 0 : 1); }).catch((error) => { console.error(error); process.exit(1); })'"'"''
echo "== clear authentik global brand css =="
DOCKER_BIN="${DOCKER_BIN}" bash "${PLATFORM_DIR}/clear-authentik-brand-css.sh"
+2
View File
@@ -45,6 +45,7 @@ rsync_dir "${NAS_ROOT}/launcher/uploads/" "${BACKUP_DIR}/files/launcher/uploads/
rsync_dir "${NAS_ROOT}/authentik/custom-templates/" "${BACKUP_DIR}/files/authentik/custom-templates/"
rsync_dir "${NAS_ROOT}/platform/authentik/" "${BACKUP_DIR}/files/platform/authentik/"
rsync_dir "${NAS_ROOT}/platform/notification-core/" "${BACKUP_DIR}/files/platform/notification-core/"
rsync_dir "${NAS_ROOT}/platform/ai-workspace-hub/" "${BACKUP_DIR}/files/platform/ai-workspace-hub/"
rsync_file "${NAS_ROOT}/platform/.env.synology" "${BACKUP_DIR}/files/platform/"
rsync_file "${NAS_ROOT}/platform/.env.synology.example" "${BACKUP_DIR}/files/platform/"
@@ -71,6 +72,7 @@ Contains:
- Authentik custom templates: authentik/custom-templates
- Platform runtime config: platform/.env.synology, compose, Caddyfile
- Notification Core source/config: platform/notification-core, platform compose/env
- AI Workspace Hub source/config: platform/ai-workspace-hub, platform compose/env
- Tasker runtime config: tasker/plane-app/.env.synology, compose, Synology override
- Ops Agents Gateway runtime config: ops-agents/.env, compose
+12 -2
View File
@@ -43,6 +43,14 @@ rsync -av --delete \
"${PLATFORM_REPO}/services/notification-core/" \
"${NAS_ROOT}/platform/notification-core/"
mkdir -p "${NAS_ROOT}/platform/ai-workspace-hub"
rsync -av --delete \
--exclude='node_modules/' \
--exclude='.env' \
--exclude='.env.*' \
"${PLATFORM_REPO}/services/ai-workspace-hub/" \
"${NAS_ROOT}/platform/ai-workspace-hub/"
if [[ "${SYNC_AUTHENTIK_TEMPLATES}" == "1" ]]; then
mkdir -p "${NAS_ROOT}/authentik/custom-templates"
rsync -av --delete \
@@ -193,14 +201,14 @@ cd /volume1/docker/nodedc-platform/platform
sudo /usr/local/bin/docker compose \
--env-file /volume1/docker/nodedc-platform/platform/.env.synology \
-f /volume1/docker/nodedc-platform/platform/docker-compose.platform-http.yml \
up -d --build --force-recreate --no-deps notification-core launcher
up -d --build --force-recreate --no-deps ai-workspace-hub notification-core launcher
Optional Platform/Auth infra apply, only after deliberate compose/proxy/Auth templates changes:
sudo /usr/local/bin/docker compose \
--env-file /volume1/docker/nodedc-platform/platform/.env.synology \
-f /volume1/docker/nodedc-platform/platform/docker-compose.platform-http.yml \
up -d --build --force-recreate --no-deps reverse-proxy authentik-server authentik-worker notification-core launcher
up -d --build --force-recreate --no-deps reverse-proxy authentik-server authentik-worker ai-workspace-hub notification-core launcher
After Authentik template rollout, clear global Brand custom CSS from the live DB.
NODE.DC login CSS must be template-scoped, not stored in Brand.branding_custom_css:
@@ -230,6 +238,8 @@ sudo /usr/local/bin/docker exec nodedc-platform-launcher-1 sh -lc '
curl -k -sS --compressed https://id.nodedc.ru/if/flow/default-authentication-flow/ \
| grep -aE 'syncFormFieldsBeforeSubmit|branding_custom_css = ""|hub.nodedc.ru|launcher.local|getLauncherBaseUrl|Запросить доступ'
curl -fsS http://172.22.0.222:18081/healthz
id_admin_status="$(
curl -k -sS -o /dev/null -w '%{http_code}' https://id.nodedc.ru/if/admin/
)"
@@ -19,6 +19,8 @@ services:
condition: service_started
notification-core:
condition: service_started
ai-workspace-hub:
condition: service_started
extra_hosts:
- "id.nodedc.ru:host-gateway"
- "hub.nodedc.ru:host-gateway"
@@ -100,6 +102,26 @@ services:
- identity
- engine
ai-workspace-hub:
image: nodedc/ai-workspace-hub:local
build:
context: ./ai-workspace-hub
restart: unless-stopped
env_file:
- ${NODEDC_SYNOLOGY_ENV_FILE:-.env.synology}
environment:
NODE_ENV: production
PORT: 18081
AI_WORKSPACE_HUB_TOKEN: ${AI_WORKSPACE_HUB_TOKEN:?ai workspace hub token required}
AI_WORKSPACE_HUB_WS_PATH: /api/ai-workspace/hub
expose:
- "18081"
ports:
- "${AI_WORKSPACE_HUB_HOST_BIND:-0.0.0.0:18081}:18081"
networks:
- edge
- engine
postgresql-authentik:
image: postgres:16-alpine
restart: unless-stopped
+4
View File
@@ -55,6 +55,10 @@ echo "== notification core health check =="
"${DOCKER_BIN}" exec nodedc-platform-notification-core-1 sh -lc \
'wget -qSO- http://127.0.0.1:5185/healthz 2>&1 | head -n 25'
echo "== ai workspace hub health check =="
"${DOCKER_BIN}" exec nodedc-platform-ai-workspace-hub-1 sh -lc \
'node -e '"'"'fetch("http://127.0.0.1:18081/healthz").then(async (response) => { console.log(await response.text()); process.exit(response.ok ? 0 : 1); }).catch((error) => { console.error(error); process.exit(1); })'"'"''
echo "== auth flow check =="
auth_flow="$(fetch_with_retry https://id.nodedc.ru/if/flow/default-authentication-flow/)"
printf '%s' "$auth_flow" \