Files
rootnode-academy/platform/api/Dockerfile
T
ced4568andClaude Sonnet 5 e2298e95de feat(root): wire course/module/activity routes into the Platform API
course-routes.js — student-facing: the full course tree through an
enrollment (GET /api/student/programs/:id/courses) and the lesson
completion marker (POST /api/student/activities/:id/complete, refused
for anything but a manual_marker activity — a lab/assessment can never
be faked complete through this route).

admin-course-routes.js — instructor-facing, read-only (no WYSIWYG CMS
this phase): program structure with instructor notes
(GET /api/admin/programs/:id/courses) and per-student progress
(GET /api/admin/students/:id/courses), scoped via
requireStudentRelationshipAccess — the same self-paced-no-cohort rule
Phase 5C's notification routes already established, not
requireStudentCohortAccess (which would 403 a plain instructor out of
every self-paced student).

Dockerfile now also COPYs content/ alongside the existing scenarios/ —
same 'read-only, never executed' reasoning as that line.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 23:29:24 -05:00

47 lines
2.1 KiB
Docker

# RootNode Platform API — lightweight, no k3s, no --privileged, no Lab terminal runtime.
# This is the fix for the Phase 2A "identity" instance problem: that was a full,
# --privileged Lab image booting a k3s cluster nobody used, just to serve roster/curriculum/
# progress APIs. This image never runs k3s and needs no elevated privileges at all.
#
# Built from the REPO ROOT as build context (see platform/docker-compose.dev.yml's
# `context: .. / dockerfile: platform/api/Dockerfile`), because it needs read-only access to
# scenarios/ and the frontend source — both live outside platform/api/'s own directory.
#
# Multi-stage: the root .dockerignore excludes frontend/dist/ from every build context (it's a
# build artifact, and the main Lab image always builds it fresh — see that Dockerfile's
# node-pty fix commit for why leaking host-built artifacts into an image is actively
# dangerous). Rather than special-case that, this image builds the frontend fresh too, the
# same way the Lab image does, then discards the Node/npm frontend toolchain from the final
# stage — the running image only ever needs the static output.
FROM node:20-slim AS frontend-build
WORKDIR /fe
COPY frontend/package.json frontend/vite.config.js ./
RUN npm install
COPY frontend/ ./
RUN npm run build
FROM node:20-slim
WORKDIR /app
COPY platform/api/package.json ./
RUN npm install --production
COPY platform/api/src/ ./src/
COPY platform/api/migrations/ ./migrations/
COPY platform/api/migrate-sqlite.js ./
# Read-only curriculum content — same source the Lab image ships, needed here purely for
# listing/progress-shaping (never executed; setup/validate/teardown stay Lab-only).
COPY scenarios/ ./scenarios/
# Phase 6A — course/module lesson prose (content.js). Git-tracked Markdown, read-only, same
# reasoning as scenarios/ above: this image only ever reads it, never executes anything from it.
COPY content/ ./content/
# Platform-shell + admin frontend, built in the stage above — served statically, no nginx
# needed for a lightweight Node API+static server.
COPY --from=frontend-build /fe/dist/ /frontend-dist/
ENV FRONTEND_DIST_DIR=/frontend-dist
EXPOSE 4300
CMD ["node", "src/server.js"]