# NODE.DC current infra handoff

Last updated: 2026-06-23.

This document is the fast context entrypoint for a new engineering chat. Read it first before touching deploy, Synology, Authentik, Launcher, or Tasker.

## Product shape

NODE.DC is intentionally modular. It is not a single monorepo with all products merged into one codebase.

Source-of-truth repositories:

| Module | Responsibility | Local source |
| --- | --- | --- |
| Platform | Infra, Authentik, reverse proxy, Synology deploy scripts, architecture docs | `/Users/dcconstructions/Downloads/mnt/NODEDC/platform` |
| Launcher / Hub | NODE.DC control plane, user/admin UI, access requests, access matrix, Authentik sync | `/Users/dcconstructions/Downloads/mnt/data/nodedc_launcher` |
| Tasker / Operational Core | Plane fork, tasks/workspaces/projects, standalone-capable product module | `/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER` |
| Ops Agents Gateway | Standalone MCP/API router for Tasker operational agents | `/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXAPI` |
| BIM Viewer | Standalone BIM/CAD/point-cloud viewer, public share links, model runtime storage | `/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_BIM_VIEWER` |

Current Git branches:

- Platform: `main`
- Launcher: `main`
- Tasker: `master`
- Ops Agents Gateway: `main`
- BIM Viewer: `beam`

The modules communicate through HTTP/OIDC/internal APIs. They must remain independently buildable and deployable.

## Ownership boundaries

Do not collapse data into one shared database.

| Area | Owner | Runtime state |
| --- | --- | --- |
| Identity, SSO, OIDC providers | Authentik | Authentik PostgreSQL volume in `nodedc-platform` |
| Clients, users, groups, Launcher access matrix | Launcher | Launcher JSON/runtime storage under `/volume1/docker/nodedc-platform/launcher` |
| Workspaces, projects, issues, comments, files | Tasker | Tasker PostgreSQL + MinIO/RabbitMQ/Redis volumes under `nodedc-tasker` |

Launcher can project access into Tasker, but it must not become the owner of Tasker domain tables. Tasker can run standalone if NODE.DC integration env vars are disabled or pointed elsewhere.

## Synology topology

Current NAS root:

```text
/volume1/docker/nodedc-platform
```

Mounted on macOS as:

```text
/Volumes/docker/nodedc-platform
```

Public domains:

```text
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 endpoint
https://bim.nodedc.tech -> BIM Viewer
```

`id.nodedc.ru` is only the public OIDC/login host. Authentik Admin is deliberately kept off that public host; `/if/admin/*` returns `404` there.

Local/NAS check domains used during rollout:

```text
auth.nas.nodedc
auth-admin.nas.nodedc
172.22.0.222
launcher.nas.nodedc
task.nas.nodedc
auth.local.nodedc
auth-admin.local.nodedc
launcher.local.nodedc
task.local.nodedc
```

Use `http://auth-admin.nas.nodedc:18080/if/admin/` for technical Authentik Admin access from the NAS/local network. If a workstation does not resolve `auth-admin.nas.nodedc`, use `http://172.22.0.222:18080/if/admin/` as the local IP fallback. Both entrypoints keep Authentik access separate from the public `id.nodedc.ru` session and must not load NODE.DC auth-flow CSS.

### Platform compose project

Compose project:

```text
nodedc-platform
```

Compose file:

```text
/volume1/docker/nodedc-platform/platform/docker-compose.platform-http.yml
```

Source copy:

```text
/Users/dcconstructions/Downloads/mnt/NODEDC/platform/infra/synology/docker-compose.platform-http.yml
```

Main services:

- `reverse-proxy`: Caddy HTTP edge, publishes host port `18080`.
- `launcher`: `nodedc/launcher:local`, serves Hub on container port `5173`.
- `postgresql-authentik`: Authentik PostgreSQL.
- `authentik-server`: Authentik web/server.
- `authentik-worker`: Authentik worker.

Main Docker volumes:

- `authentik-database`
- `authentik-data`
- `authentik-certs`
- `caddy-data`
- `caddy-config`

Launcher bind-mounted runtime state:

```text
/volume1/docker/nodedc-platform/launcher/server-storage -> /app/server/storage
/volume1/docker/nodedc-platform/launcher/uploads        -> /app/server/storage/uploads
```

These directories must be writable by container user `node` / UID `1000`.

### Tasker compose project

Compose project:

```text
nodedc-tasker
```

NAS runtime/deploy directory:

```text
/volume1/docker/nodedc-platform/tasker/plane-app
```

NAS source/deploy copy:

```text
/volume1/docker/nodedc-platform/tasker/plane-src
```

Repository source:

```text
/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/plane-src
```

Repository compose/runtime template:

```text
/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/plane-app/docker-compose.yaml
```

Main services:

- `web`: Tasker frontend, image `nodedc/plane-frontend:ru`.
- `admin`: Tasker admin frontend, image `nodedc/plane-admin:ru`.
- `space`: public/space frontend, image `nodedc/plane-space:ru`.
- `live`: live server, image `nodedc/plane-live:local`.
- `api`: backend API, image `nodedc/plane-backend:local`.
- `worker`, `beat-worker`, `migrator`: backend workers/migrations.
- `plane-db`: PostgreSQL.
- `plane-redis`: Valkey/Redis.
- `plane-mq`: RabbitMQ.
- `plane-minio`: uploads/files.
- `proxy`: Tasker edge proxy, publishes `LISTEN_HTTP_PORT` / current NAS port `18090`.

Main Docker volumes under the `nodedc-tasker` project:

- `nodedc-tasker_pgdata`
- `nodedc-tasker_redisdata`
- `nodedc-tasker_rabbitmq_data`
- `nodedc-tasker_uploads`
- log and proxy volumes from `plane-app/docker-compose.yaml`

NAS-only runtime files currently exist and are intentionally not committed with secrets:

```text
/volume1/docker/nodedc-platform/tasker/plane-app/.env.synology
/volume1/docker/nodedc-platform/tasker/plane-app/docker-compose.synology.override.yml
```

The current override only adds `extra_hosts` entries so Tasker backend containers can resolve `id.nodedc.ru`, `hub.nodedc.ru`, `ops.nodedc.ru`, local domains, NAS domains, and `host.docker.internal` through `host-gateway`.

### Ops Agents Gateway compose project

Compose project:

```text
nodedc-ops-agents
```

Recommended NAS runtime/deploy directory:

```text
/volume1/docker/nodedc-platform/ops-agents
```

Repository source:

```text
/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXAPI
```

Public entrypoint:

```text
https://ops-agents.nodedc.ru
```

Synology reverse proxy should route:

```text
HTTPS ops-agents.nodedc.ru:443 -> HTTP 172.22.0.222:18190
```

Do not use host port `18090` for this module: `18090` is the Tasker proxy port. Gateway container port remains `4100`; host bind/port are controlled by `HOST_BIND=172.22.0.222` and `HOST_PORT=18190`.

Main services:

- `agent-gateway`: NODE.DC Operational Agents Gateway, image built from source by compose.
- `postgres`: Gateway-owned PostgreSQL database for agents, grants, tokens, idempotency, and audit.

Deployment checklist:

```text
/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXAPI/docs/SYNOLOGY_DEPLOY.md
```

## Deploy model

NAS is a deploy target and runtime state holder. It is not the source of truth for code.

Normal direction:

```text
Git repo -> build image / sync deploy files -> Synology compose recreate selected service
```

Do not edit NAS copies as the long-term fix. If an emergency live edit is made on NAS, port it back into the relevant repo before continuing product work.

## Auth/session sync status

Read `docs/AUTH_MODEL.md` before changing cross-app auth/session behavior.

As of 2026-06-23, the proven shared live-session path was logout-first: Launcher publishes `nodedc:session:logout` through `/auth/session-sync` and frontchannel app logout URLs, and Engine subscribes to that logout event. BIM Viewer has now been aligned with that logout path.

BIM also introduced a BIM-first login-sync slice for share links: Launcher service registry can call BIM `loginSyncUrl`; BIM records only a short-lived marker and then revalidates through Launcher optional-launch/handoff. This marker is not auth and must not grant controls directly.

This is not yet a platform-wide login/change canon. Before adding another service, define the shared `ndcauth.session` contract in Platform/Auth SDK terms and verify HUB/OPS/ENGINE/BIM with a browser matrix: login from any surface, logout from any surface, already-open apps update without refresh.

## Platform / Launcher deploy

From macOS with `/Volumes/docker` mounted:

```bash
cd /Users/dcconstructions/Downloads/mnt/NODEDC/platform
NAS_ROOT=/Volumes/docker/nodedc-platform \
LAUNCHER_REPO=/Users/dcconstructions/Downloads/mnt/data/nodedc_launcher \
TASKER_REPO=/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER \
TASKER_CHANGED_BASE=533f8c6 \
GATEWAY_REPO=/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXAPI \
./infra/synology/deploy-current.sh
```

The script syncs platform deploy files plus optional Launcher, Tasker, and Ops Agents Gateway source copies. Authentik custom templates are not synced by default; set `SYNC_AUTHENTIK_TEMPLATES=1` only for a deliberate Authentik UI/theme rollout. The script prints the Docker commands that must be run on Synology, because Docker there requires interactive `sudo`.

Tasker full source sync over SMB is intentionally not the default. Use `TASKER_CHANGED_BASE=<commit>` for normal deploys, or `TASKER_SYNC_SOURCE=1` only when a full source refresh is required.

The script does not overwrite live secret files:

```text
/volume1/docker/nodedc-platform/platform/.env.synology
/volume1/docker/nodedc-platform/tasker/plane-app/.env.synology
/volume1/docker/nodedc-platform/ops-agents/.env
```

Launcher must use the platform Authentik alias for internal API sync:

```env
NODEDC_AUTHENTIK_BASE_URL=http://nodedc-platform-authentik-server:9000
AUTHENTIK_BASE_URL=http://nodedc-platform-authentik-server:9000
```

Do not use `http://authentik-server:9000` in Launcher env after attaching Launcher to the Engine Docker network. The Engine stack also has an `authentik-server` service name, so Docker DNS can resolve the name to the wrong Authentik and valid platform tokens will fail with `403 Token invalid/expired`.

The platform Authentik service exposes a stable identity-network alias in the Synology compose:

```text
nodedc-platform-authentik-server
```

When changing this alias or Authentik env wiring, recreate `authentik-server`, `authentik-worker`, and `launcher` together. A freshly recreated Authentik server can temporarily return `503 Service Unavailable` until the worker/bootstrap path is ready, so verify with retry from inside the launcher container. For Launcher-only BFF/frontend fixes, rebuild `nodedc/launcher:local` with `--no-cache` and recreate only `launcher`.

Authentik Brand custom CSS must stay empty in live DB. NODE.DC auth/login styling is injected only by templates on the public auth-flow host. After any Authentik template rollout run:

```bash
cd /volume1/docker/nodedc-platform/platform
sudo bash clear-authentik-brand-css.sh
```

Launcher image build is done from the Launcher repo when frontend/backend code changes:

```bash
cd /volume1/docker/nodedc-platform/launcher/source
sudo /usr/local/bin/docker build --no-cache -t nodedc/launcher:local .
```

Launcher container recreate:

```bash
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
```

## Tasker deploy

Tasker rebuild script is in the Tasker repo and copied to NAS:

```text
/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/plane-src/rebuild-nas-legacy.sh
```

Production-style frontend rebuild on NAS:

```bash
cd /volume1/docker/nodedc-platform/tasker/plane-src
BUILD_BACKEND=0 BUILD_WEB=1 BUILD_ADMIN=0 sh rebuild-nas-legacy.sh
```

Admin frontend rebuild:

```bash
cd /volume1/docker/nodedc-platform/tasker/plane-src
BUILD_BACKEND=0 BUILD_WEB=0 BUILD_ADMIN=1 sh rebuild-nas-legacy.sh
```

Combined web/admin rebuild:

```bash
cd /volume1/docker/nodedc-platform/tasker/plane-src
BUILD_BACKEND=0 BUILD_WEB=1 BUILD_ADMIN=1 sh rebuild-nas-legacy.sh
```

The script defaults production frontend links to:

```text
VITE_NODEDC_LAUNCHER_URL=https://hub.nodedc.ru
```

Local/staging can override:

```bash
VITE_NODEDC_LAUNCHER_URL=http://launcher.local.nodedc \
BUILD_BACKEND=0 BUILD_WEB=1 BUILD_ADMIN=0 \
sh rebuild-nas-legacy.sh
```

Manual recreate command used on NAS:

```bash
cd /volume1/docker/nodedc-platform/tasker/plane-app
sudo /usr/local/bin/docker compose -p nodedc-tasker \
  --env-file .env.synology \
  -f docker-compose.yaml \
  -f docker-compose.synology.override.yml \
  up -d --no-build --force-recreate web
```

Replace `web` with `admin`, `api`, or another service only when that service image was intentionally rebuilt.

Tasker backend must receive the Gateway internal URL/token before Codex/Ops Agent UI can create agents in production:

```env
PLANE_NODEDC_AGENT_GATEWAY_URL=http://172.22.0.222:18190
PLANE_NODEDC_AGENT_GATEWAY_TOKEN=<same value as NODEDC_AGENT_GATEWAY_INTERNAL_TOKEN>
```

After changing these env vars, rebuild/recreate Tasker backend services: `api`, `worker`, `beat-worker`, and `migrator` when migrations are expected.

## Ops Agents Gateway deploy

From the Gateway repo on Synology or from a synced source copy:

```bash
cd /volume1/docker/nodedc-platform/ops-agents
sudo /usr/local/bin/docker compose --env-file .env -f docker-compose.synology.yml up -d --build
```

Required Synology `.env` values are documented in:

```text
/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXAPI/docs/SYNOLOGY_DEPLOY.md
```

Minimum checks:

```bash
curl -fsS http://172.22.0.222:18190/healthz
curl -fsS http://172.22.0.222:18190/readyz
curl -fsS -i https://ops-agents.nodedc.ru/mcp | head
```

## Backup rules

Platform backup script:

```bash
cd /Users/dcconstructions/Downloads/mnt/NODEDC/platform
NAS_ROOT=/Volumes/docker/nodedc-platform ./infra/synology/backup-current.sh
```

It creates filesystem backups and generates a Synology-side Authentik database dump command.

Tasker safety:

- Frontend-only Tasker rebuilds do not touch Tasker PostgreSQL or MinIO uploads.
- Backend image rebuild is not enough to lose data by itself, but backend migrations can change DB schema.
- Before backend migrations, backup `nodedc-tasker_pgdata` and `nodedc-tasker_uploads`.
- Never run destructive volume commands on NAS production data.

Hard rules:

```text
Never run docker compose down -v on production/staging data.
Never delete nodedc-tasker_* volumes without a verified backup.
Never use docker system prune blindly on the NAS.
Never commit .env.synology or real secrets.
Never deploy Launcher with NODEDC_AUTHENTIK_BASE_URL=http://authentik-server:9000 on NAS.
```

## Local development model

The same codebase must support local and production-like runs. Differences must come from env vars and build args, not branches with hardcoded production URLs.

Local target domains:

```text
127.0.0.1 auth.local.nodedc
127.0.0.1 launcher.local.nodedc
127.0.0.1 task.local.nodedc
```

Platform local docs:

```text
/Users/dcconstructions/Downloads/mnt/NODEDC/platform/docs/DEPLOYMENT_LOCAL.md
/Users/dcconstructions/Downloads/mnt/NODEDC/platform/infra/README.md
```

Tasker local/prod integration env contract:

```text
/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/NODEDC_TASKER_DEPLOY_MODEL.md
```

Useful local Tasker frontend build checks:

```bash
cd /Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/plane-src
pnpm turbo run build --filter=web
pnpm turbo run build --filter=admin
```

Known current validation note: `admin` typecheck passes. Full `web` typecheck currently has pre-existing upstream/local Plane TypeScript debt unrelated to the NODE.DC logo/deploy baseline work.

## Current docs map

Read these in order:

1. This file: `/Users/dcconstructions/Downloads/mnt/NODEDC/platform/docs/CURRENT_INFRA_HANDOFF.md`
2. Architecture: `/Users/dcconstructions/Downloads/mnt/NODEDC/platform/docs/ARCHITECTURE.md`
3. Synology deploy: `/Users/dcconstructions/Downloads/mnt/NODEDC/platform/infra/synology/README.md`
4. Local deploy: `/Users/dcconstructions/Downloads/mnt/NODEDC/platform/docs/DEPLOYMENT_LOCAL.md`
5. Tasker deploy model: `/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/NODEDC_TASKER_DEPLOY_MODEL.md`
6. Ops Agents Gateway deploy: `/Users/dcconstructions/Downloads/mnt/data/NODEDC_TASKMANAGER_CODEXAPI/docs/SYNOLOGY_DEPLOY.md`

## New-chat bootstrap prompt

Use this when starting a new engineering chat:

```text
We are working on NODE.DC. First read:
/Users/dcconstructions/Downloads/mnt/NODEDC/platform/docs/CURRENT_INFRA_HANDOFF.md

Respect the modular architecture:
- Platform repo owns infra/Synology/Auth/reverse-proxy docs and scripts.
- Launcher repo owns Hub/control-plane.
- Tasker repo owns Plane fork and must remain standalone-capable.
- Ops Agents Gateway repo owns MCP/API routing for external operational agents.
- NAS is deploy target/runtime state, not source of truth.
- Do not touch production volumes destructively.
- Do not commit secrets or .env.synology.
```

## Known follow-up hardening

- Add a sanitized committed Tasker `docker-compose.synology.override.example.yml`.
- Add a Tasker volume backup script equivalent to Platform `backup-current.sh`.
- Add an Ops Agents Gateway backup script for its Postgres volume/dump.
- Add a single smoke-check script for public domains: `id.nodedc.ru`, `hub.nodedc.ru`, `ops.nodedc.ru`, `ops-agents.nodedc.ru`.
- Decide whether release tags should be coordinated across the three repos after stable production milestones.
