From d464f3a98253d81dcb2d20c0666de4c17b4b1035 Mon Sep 17 00:00:00 2001 From: mptyl Date: Sun, 16 Aug 2026 17:13:55 +0200 Subject: [PATCH] build: align authentication runtime on Node 24 --- backend/package-lock.json | 155 ++++++++++++++++++++++++++++++++++-- backend/package.json | 5 +- backend/test/health.test.ts | 4 + docker/core.Dockerfile | 14 ++-- docker/frontend.Dockerfile | 2 +- docker/smoke/core-smoke.sh | 4 +- 6 files changed, 165 insertions(+), 19 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index a261691e..9478eec4 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -6,15 +6,18 @@ "": { "name": "thothii-backend", "dependencies": { + "@fastify/cookie": "11.1.2", "@fastify/cors": "^11.2.0", + "@fastify/rate-limit": "11.2.0", "@types/pg": "^8.20.3", "fastify": "^5.0.0", + "openid-client": "6.8.5", "pg": "^8.22.0", "yaml": "^2.9.0", "zod": "^4.4.3" }, "devDependencies": { - "@types/node": "^22.0.0", + "@types/node": "24.13.3", "tsx": "^4.19.0", "typescript": "^5.6.0", "vitest": "^2.1.0" @@ -483,6 +486,55 @@ "fast-uri": "^3.0.0" } }, + "node_modules/@fastify/cookie": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-11.1.2.tgz", + "integrity": "sha512-Dtrpk/YOGUsbRMvP/8ZqPpwnMRv0qSqodFdoQ2B589Obc7jw4s4Qla+cV72Bsm7WsZJnqlYFX/i7uSBq0xzg6g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "cookie": "^2.0.0", + "fastify-plugin": "^6.0.0" + } + }, + "node_modules/@fastify/cookie/node_modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==", + "license": "MIT", + "engines": { + "node": ">=22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@fastify/cookie/node_modules/fastify-plugin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-6.0.0.tgz", + "integrity": "sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/@fastify/cors": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-11.2.0.tgz", @@ -593,6 +645,44 @@ "ipaddr.js": "^2.1.0" } }, + "node_modules/@fastify/rate-limit": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@fastify/rate-limit/-/rate-limit-11.2.0.tgz", + "integrity": "sha512-X7osJd4XSvMoejYrnJkSZYYjY1eNYoBqhjlzf1RakC2204qExFqZFTKj5+T7VuzA/iUI9Z3UoSqQRkB2HpG0oQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "fastify-plugin": "^6.0.0", + "ip-address": "^10.2.0", + "toad-cache": "^3.7.0" + } + }, + "node_modules/@fastify/rate-limit/node_modules/fastify-plugin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-6.0.0.tgz", + "integrity": "sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -600,6 +690,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@pinojs/redact": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", @@ -964,12 +1063,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.20.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.0.tgz", - "integrity": "sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==", + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.18.0" } }, "node_modules/@types/pg": { @@ -1478,6 +1577,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/ip-address": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz", + "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", @@ -1487,6 +1595,15 @@ "node": ">= 10" } }, + "node_modules/jose": { + "version": "6.2.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.9.tgz", + "integrity": "sha512-XrchZOFZUl/T3vTwRe8XK+cJrGtMF4th1ARnDfwbBXFKThGhlsxEE4Zu03AD/bjJSt/9jT/mxrOCkJWOg77aPA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/json-schema-ref-resolver": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-3.0.0.tgz", @@ -1592,6 +1709,15 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/oauth4webapi": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.7.tgz", + "integrity": "sha512-4RxcKxXjuItDFZ20RRPf4YTw3kpeXJyCgJFxVzJ068A7PNJ18st2Dg90tlC1LkSDS0GecroagCLHYEIVUhCAkw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/on-exit-leak-free": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", @@ -1601,6 +1727,19 @@ "node": ">=14.0.0" } }, + "node_modules/openid-client": { + "version": "6.8.5", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.5.tgz", + "integrity": "sha512-jNGC/5wnTYwCcEUe2ss0IRUmVRQcgxM0A1nLb3eX/9llqNbMWOQd2xd+qDAgfVCpA5Qh96Y1cdnkfbva6+bSdA==", + "license": "MIT", + "dependencies": { + "jose": "^6.2.8", + "oauth4webapi": "^3.8.7" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/pathe": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", @@ -2148,9 +2287,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "license": "MIT" }, "node_modules/vite": { diff --git a/backend/package.json b/backend/package.json index 476bf99f..359c7605 100644 --- a/backend/package.json +++ b/backend/package.json @@ -11,15 +11,18 @@ "test:schema-v3-verifier": "python3 -I -B scripts/test_revision_state_policy.py && node --test scripts/verify-workspace-descriptor-files.test.mjs scripts/revision-state-policy.test.mjs" }, "dependencies": { + "@fastify/cookie": "11.1.2", "@fastify/cors": "^11.2.0", + "@fastify/rate-limit": "11.2.0", "@types/pg": "^8.20.3", "fastify": "^5.0.0", + "openid-client": "6.8.5", "pg": "^8.22.0", "yaml": "^2.9.0", "zod": "^4.4.3" }, "devDependencies": { - "@types/node": "^22.0.0", + "@types/node": "24.13.3", "tsx": "^4.19.0", "typescript": "^5.6.0", "vitest": "^2.1.0" diff --git a/backend/test/health.test.ts b/backend/test/health.test.ts index 6c2008ac..1be89fb1 100644 --- a/backend/test/health.test.ts +++ b/backend/test/health.test.ts @@ -2,6 +2,10 @@ import { test, expect } from "vitest"; import { buildApp } from "../src/app.js"; import { loadConfig } from "../src/config.js"; +test("runtime exposes the Node 24 compatibility contract", () => { + expect(Number(process.versions.node.split(".")[0])).toBe(24); +}); + test("GET /health reports process readiness without external services", async () => { const app = buildApp(loadConfig({ THT_HARNESS_DIR: "/tmp/h" })); const res = await app.inject({ method: "GET", url: "/health" }); diff --git a/docker/core.Dockerfile b/docker/core.Dockerfile index 258a7148..0d37203c 100644 --- a/docker/core.Dockerfile +++ b/docker/core.Dockerfile @@ -1,14 +1,14 @@ # syntax=docker/dockerfile:1.7 -# thothii-core: Fastify (Node 22) + harness Python 3.12 (tht CLI) + runtime Pi. +# thothii-core: Fastify (Node 24.16) + harness Python 3.12 (tht CLI) + runtime Pi. # Singolo container, entrypoint logico "server" (default). ARG PI_VERSION=0.80.3 ARG IMAGE_VERSION=local # ---- Pinned Node source for the runtime binary and npm ---- -FROM node:22-bookworm@sha256:7725a5c2c83eed1d36258c66efae14b1ceccd021db9ed1d9559d3335ed3d68ed AS node-runtime +FROM node:24.16.0-bookworm@sha256:40ad9f3064e67d6860b4bc3fe1880b2953934fd6320ada990e45fe0efa6badd7 AS node-runtime # ---- Stage 0: locked Pi runtime ---- -FROM node:22-bookworm@sha256:7725a5c2c83eed1d36258c66efae14b1ceccd021db9ed1d9559d3335ed3d68ed AS pi-runtime-build +FROM node:24.16.0-bookworm@sha256:40ad9f3064e67d6860b4bc3fe1880b2953934fd6320ada990e45fe0efa6badd7 AS pi-runtime-build ARG PI_VERSION ARG PI_RUNTIME_PACKAGE_VERSION ARG PI_PACKAGE_NAME=@earendil-works/pi-coding-agent @@ -22,14 +22,14 @@ RUN if [ -n "$PI_RUNTIME_PACKAGE_VERSION" ]; then \ && test "$(./node_modules/.bin/pi --version)" = "$PI_VERSION" # ---- Stage 1: backend TypeScript -> dist ---- -FROM node:22-bookworm@sha256:7725a5c2c83eed1d36258c66efae14b1ceccd021db9ed1d9559d3335ed3d68ed AS backend-build +FROM node:24.16.0-bookworm@sha256:40ad9f3064e67d6860b4bc3fe1880b2953934fd6320ada990e45fe0efa6badd7 AS backend-build WORKDIR /src/backend COPY backend/package*.json ./ RUN npm ci COPY backend/ ./ RUN npm run build -# ---- Stage 2: runtime (Python 3.12 nativo + Node 22 copiato, stesso glibc bookworm) ---- +# ---- Stage 2: runtime (Python 3.12 nativo + Node 24.16 copiato, stesso glibc bookworm) ---- FROM python:3.12-slim-bookworm@sha256:d50fb7611f86d04a3b0471b46d7557818d88983fc3136726336b2a4c657aa30b AS runtime ARG PI_VERSION ARG IMAGE_VERSION @@ -50,7 +50,7 @@ RUN set -eux; \ command -v flock >/dev/null 2>&1; \ ln -s /usr/bin/fdfind /usr/local/bin/fd -# Node 22 + npm copiati dall'immagine ufficiale (stesso Debian bookworm → binario compatibile) +# Node 24.16 + npm copiati dall'immagine ufficiale (stesso Debian bookworm → binario compatibile) COPY --from=node-runtime /usr/local/bin/node /usr/local/bin/node COPY --from=node-runtime /usr/local/lib/node_modules /usr/local/lib/node_modules RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \ @@ -83,7 +83,7 @@ RUN mkdir -p /app/harness/config \ # PiProcessManager (backend) prepende harnessDir/.venv/bin al PATH del child Pi → symlink al venv reale RUN ln -s /opt/venv /app/harness/.venv -# Backend: dist + node_modules (stesso Node major 22 + glibc bookworm → compatibili) +# Backend: dist + node_modules (stesso Node major 24 + glibc bookworm → compatibili) COPY --from=backend-build /src/backend/dist /app/backend/dist COPY --from=backend-build /src/backend/node_modules /app/backend/node_modules COPY backend/package*.json /app/backend/ diff --git a/docker/frontend.Dockerfile b/docker/frontend.Dockerfile index 4f3fa076..f1324f2d 100644 --- a/docker/frontend.Dockerfile +++ b/docker/frontend.Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1.7 # thothii-frontend: build Vite (React) + nginx-unprivileged (porta 8080). ARG IMAGE_VERSION=local -FROM node:22-bookworm@sha256:7725a5c2c83eed1d36258c66efae14b1ceccd021db9ed1d9559d3335ed3d68ed AS build +FROM node:24.16.0-bookworm@sha256:40ad9f3064e67d6860b4bc3fe1880b2953934fd6320ada990e45fe0efa6badd7 AS build WORKDIR /src COPY frontend/package*.json ./ RUN npm ci diff --git a/docker/smoke/core-smoke.sh b/docker/smoke/core-smoke.sh index 61515f15..82b8c745 100755 --- a/docker/smoke/core-smoke.sh +++ b/docker/smoke/core-smoke.sh @@ -7,8 +7,8 @@ test -n "${PI_VERSION:-}" node_version="$(node --version)" python_version="$(python --version 2>&1)" case "$node_version" in - v22.19.*|v22.2[0-9].*|v2[3-9].*|v[3-9][0-9].*) ;; - *) echo "Node 22.19+ required, found $node_version" >&2; exit 1 ;; + v24.16.*) ;; + *) echo "Node 24.16 required, found $node_version" >&2; exit 1 ;; esac case "$python_version" in "Python 3.1"[1-9].*|"Python 3."[2-9][0-9].*) ;;