diff --git a/platform/docker-compose.dev.yml b/platform/docker-compose.dev.yml index 27cc81e..31e0e73 100644 --- a/platform/docker-compose.dev.yml +++ b/platform/docker-compose.dev.yml @@ -1,19 +1,19 @@ -# Phase 2A full-stack local dev/test — Postgres + egress-proxy + Provisioner + a persistent -# "identity" instance + the Gateway, all on one machine (the documented Phase 1/2A dev -# exception; production is the two-VM Proxmox split, see docs/LAB_ARCHITECTURE.md §1). +# Phase 2B full-stack local dev/test — Postgres + egress-proxy + Provisioner + the lightweight +# Platform API + the Gateway, all on one machine (the documented Phase 1/2A/2B dev exception; +# production is the two-VM Proxmox split, see docs/LAB_ARCHITECTURE.md §1). # -# "identity" is a plain, non-ephemeral instance of the existing, unmodified rootnode-academy -# image — it's what holds the canonical roster/curriculum/progress SQLite and serves the -# platform-shell frontend. It is NOT managed by the Provisioner and never gets destroyed/reset; -# it's infrastructure, the same way Postgres or the egress proxy are. See -# docs/PHASE2A_GATEWAY_AND_STUDENT_FLOW.md for why this role exists and its Phase 2B -# optimization opportunity (it currently boots a full unused k3s cluster just to serve as the -# identity backend — wasteful but zero-new-code, matching "don't redesign the Lab image"). +# `api` (platform/api) replaces Phase 2A's "identity" service — that was a full, --privileged +# Lab image booting an unused k3s cluster just to serve roster/curriculum/progress APIs. This +# is a plain Node process: no k3s, no --privileged, no terminal runtime. It owns +# students/cohorts/enrollments/curriculum/progress/scenario_attempts in Postgres and is the +# only service that talks to the Provisioner (student launch/reset AND instructor/admin +# actions) — see docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md. # -# gateway and provisioner both run with network_mode: host — both need to reach ephemeral -# per-student Lab containers by their internal Docker-network IP, the same requirement that -# already applies to the Provisioner's own firewall management (see -# platform/provisioner/docker-compose.dev.yml). +# gateway, provisioner, and api's egress-adjacent needs aside, `api` does NOT need +# network_mode: host — it never touches Docker networking or firewall rules itself, it only +# calls the Provisioner's HTTP API and Postgres. gateway and provisioner keep network_mode: +# host because they need to reach ephemeral per-student Lab containers by internal IP / +# manage firewall rules on the host network namespace. services: postgres: @@ -54,14 +54,27 @@ services: postgres: condition: service_healthy - identity: - image: ${LAB_IMAGE_REF:-rootnode-academy:test} - privileged: true - network_mode: bridge - ports: - - "7554:80" - volumes: - - identity-data:/data + api: + build: + context: .. + dockerfile: platform/api/Dockerfile + network_mode: host # needs to reach the Provisioner at localhost:4100 (host-networked); + # port 4300 is directly the host's port under host networking, no + # `ports:` mapping needed (and compose rejects one with this mode). + environment: + # localhost:5433, not the "postgres" compose hostname — network_mode: host means this + # container is on the host's network namespace, not the compose bridge network, so + # compose's internal DNS doesn't resolve here (same reason Provisioner uses localhost too). + PLATFORM_DB_URL: postgres://postgres:postgres@localhost:5433/rootnode_platform + PROVISIONER_URL: "http://localhost:4100" + PROVISIONER_SHARED_SECRET: ${PROVISIONER_SHARED_SECRET:?set a real secret, do not use a default} + ADMIN_PASSWORD: ${ADMIN_PASSWORD:?set an instructor password, do not use a default} + PLATFORM_API_PORT: "4300" + depends_on: + postgres: + condition: service_healthy + provisioner: + condition: service_started gateway: build: ./gateway @@ -70,10 +83,7 @@ services: GATEWAY_PORT: "4200" PROVISIONER_URL: "http://localhost:4100" PROVISIONER_SHARED_SECRET: ${PROVISIONER_SHARED_SECRET:?set a real secret, do not use a default} - IDENTITY_BACKEND_URL: "http://localhost:7554" + PLATFORM_API_URL: "http://localhost:4300" depends_on: - provisioner - - identity - -volumes: - identity-data: + - api