fix(dashboard): switch backend+web Dockerfiles to pnpm; add missing pino dep

The image rebuilds were broken because `backend/package-lock.json` and
`web/package-lock.json` had been regenerated inside the pnpm workspace
and contained pnpm-store symlinks (e.g. `node_modules/typescript` →
`../node_modules/.pnpm/typescript@5.9.3/...` with `link: true`). When
`npm ci` ran in Docker outside the pnpm workspace, those link targets
didn't exist, so devDeps including TypeScript were silently not
installed — leaving `tsc: not found` at build time.

Fix aligns Docker builds with the declared `packageManager: pnpm@10.6.5`
field:

  - Both Dockerfiles now use corepack + pnpm with the workspace
    `pnpm-lock.yaml` and `--filter ... --frozen-lockfile`
  - Production stage uses `pnpm deploy --prod --legacy` to carve out a
    devDep-free node_modules
  - Drop the stale `backend/package-lock.json` and
    `web/package-lock.json` (they're regenerated wrong every time anyone
    runs npm in here)
  - Add `pino` + `pino-pretty` to backend deps (used by
    `src/lib/logger.ts` from the Phase 5 P1 structured-logging work but
    never declared)
  - Fix pre-existing bug in backend runtime stage: `docker.io` package
    in debian:bookworm-slim pre-creates a `docker` group at GID ~101,
    so `groupadd --gid 999` then `useradd --gid 999` failed. Use
    `groupmod` when the group already exists.

After this commit:
  - 87/87 tests pass (74 backend + 13 web)
  - typecheck clean
  - lint: 0 errors (only pre-existing unused-var warnings)
  - `docker compose build && up` succeeds end-to-end
  - Tailscale URL serves the new dashboard with all Phase 1-7 work live
  - CORS allow-list driven by `EXTRA_CORS_ORIGINS` env var (no hot-patch
    needed in the running container)

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Hermes VM 2026-05-30 10:13:37 +00:00
parent 2056883198
commit 254ef2704c
6 changed files with 168 additions and 6318 deletions

View File

@ -1,14 +1,34 @@
# Build context: bytelyst-devops-tools/dashboard/ (monorepo root)
#
# Uses pnpm (matches `packageManager` field in package.json) and the
# workspace `pnpm-lock.yaml` at the dashboard root. The previously-used
# `npm ci` against `backend/package-lock.json` was broken because the
# npm lockfile had been regenerated inside the pnpm workspace and
# contained pnpm-store symlinks (e.g. node_modules/typescript pointing
# at ../node_modules/.pnpm/typescript@5.9.3/...), which npm treated as
# `link: true` and skipped installing — leaving `tsc` missing.
#
# BYTELYST_PACKAGE_SOURCE=gitea disables the `.pnpmfile.cjs` filesystem
# lookup of `learning_ai_common_plat` (which isn't in the build context).
# Backend has no `@bytelyst/*` deps so the pnpmfile is a no-op for it,
# but we set the env explicitly for clarity.
# --- Stage 1: Build ---
FROM node:20-alpine AS builder
WORKDIR /app/backend
ENV BYTELYST_PACKAGE_SOURCE=gitea
RUN corepack enable && corepack prepare pnpm@10.6.5 --activate
COPY backend/package.json backend/package-lock.json ./
RUN npm ci --ignore-scripts
WORKDIR /app
COPY backend/tsconfig.json ./
COPY backend/src/ ./src/
# Workspace metadata (pnpm needs the root files to resolve the workspace).
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.cjs ./
COPY backend/package.json ./backend/
RUN pnpm install --frozen-lockfile --filter "@bytelyst/devops-backend..." --ignore-scripts
COPY backend/tsconfig.json ./backend/
COPY backend/src/ ./backend/src/
# Build-time env vars (baked into the bundle)
ARG BYTELYST_COMMIT_SHA=unknown
@ -27,7 +47,11 @@ ENV BYTELYST_COMMIT_SHA=${BYTELYST_COMMIT_SHA} \
BYTELYST_COMMIT_MESSAGE=${BYTELYST_COMMIT_MESSAGE} \
BYTELYST_DOCKER_IMAGE=${BYTELYST_DOCKER_IMAGE}
RUN npm run build
WORKDIR /app/backend
RUN pnpm run build
# Carve out a production-only deploy bundle (node_modules without devDeps).
RUN pnpm --filter "@bytelyst/devops-backend" deploy --prod --legacy /deploy
# --- Stage 2: Run ---
# Use Debian slim (not Alpine) because vm-health-check.sh uses GNU df flags
@ -36,9 +60,6 @@ FROM node:20-slim AS runner
WORKDIR /app/backend
COPY backend/package.json backend/package-lock.json ./
RUN npm ci --omit=dev --ignore-scripts
# Install tools needed by the VM management module:
# bash — vm-health-check.sh and vm-cleanup.sh require bash
# docker.io — docker CLI to communicate with the host daemon via socket
@ -61,10 +82,21 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# `dashboard/DEPLOYMENT.md` Privilege Surface → "Running non-root".
ARG BACKEND_USER=root
ARG DOCKER_GID=999
RUN groupadd --system --gid "${DOCKER_GID}" docker || true \
# `docker.io` in debian:bookworm-slim creates a `docker` group at a
# distro-chosen GID (commonly 101). Reconcile it to ${DOCKER_GID} so the
# in-container group matches the host's docker GID. If no `docker` group
# exists yet, create one at ${DOCKER_GID}.
RUN if getent group docker >/dev/null; then \
groupmod --gid "${DOCKER_GID}" docker; \
else \
groupadd --system --gid "${DOCKER_GID}" docker; \
fi \
&& useradd --system --create-home --uid 1001 --gid "${DOCKER_GID}" --shell /sbin/nologin app \
&& chown -R app:"${DOCKER_GID}" /app
# Bring in the deploy bundle (package.json, prod node_modules) and compiled JS.
COPY --from=builder --chown=app:${DOCKER_GID} /deploy/package.json ./package.json
COPY --from=builder --chown=app:${DOCKER_GID} /deploy/node_modules ./node_modules
COPY --from=builder --chown=app:${DOCKER_GID} /app/backend/dist ./dist
ENV NODE_ENV=production

View File

@ -1,885 +0,0 @@
{
"name": "@bytelyst/devops-backend",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@bytelyst/devops-backend",
"version": "0.1.0",
"dependencies": {
"@azure/cosmos": "^4.1.0",
"@azure/identity": "^4.5.0",
"@azure/keyvault-secrets": "^4.9.0",
"@fastify/rate-limit": "^10.2.1",
"@fastify/swagger": "^9.0.0",
"@fastify/swagger-ui": "^5.2.1",
"dotenv": "^16.4.5",
"fastify": "^5.2.1",
"jose": "^6.1.2",
"zod": "^3.24.1"
},
"devDependencies": {
"@eslint/js": "^9.18.0",
"@types/node": "^25.0.3",
"@vitest/coverage-v8": "3.2.4",
"eslint": "^9.18.0",
"globals": "^15.14.0",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.20.0",
"vitest": "^3.1.2"
}
},
"../node_modules/.pnpm/@azure+cosmos@4.9.3_@azure+core-client@1.10.1/node_modules/@azure/cosmos": {
"version": "4.9.3",
"license": "MIT",
"dependencies": {
"@azure/abort-controller": "^2.1.2",
"@azure/core-auth": "^1.9.0",
"@azure/core-rest-pipeline": "^1.19.1",
"@azure/core-tracing": "^1.2.0",
"@azure/core-util": "^1.11.0",
"@azure/keyvault-keys": "^4.9.0",
"@azure/logger": "^1.1.4",
"fast-json-stable-stringify": "^2.1.0",
"priorityqueuejs": "^2.0.0",
"semaphore": "^1.1.0",
"tslib": "^2.8.1"
},
"devDependencies": {
"@azure-tools/test-utils-vitest": "^2.0.1",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@azure/identity": "4.13.0",
"@types/debug": "^4.1.4",
"@types/node": "^20.19.25",
"@types/priorityqueuejs": "^1.0.1",
"@types/semaphore": "^1.1.0",
"@vitest/browser-playwright": "^4.1.2",
"@vitest/coverage-istanbul": "^4.1.2",
"assertion-error": "^2.0.1",
"cross-env": "^10.1.0",
"dotenv": "^16.6.1",
"eslint": "^9.39.1",
"nock": "^13.5.6",
"playwright": "^1.58.2",
"prettier": "^3.6.2",
"rimraf": "^6.1.0",
"typescript": "~6.0.2",
"vitest": "^4.1.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"../node_modules/.pnpm/@azure+identity@4.13.1/node_modules/@azure/identity": {
"version": "4.13.1",
"license": "MIT",
"dependencies": {
"@azure/abort-controller": "^2.0.0",
"@azure/core-auth": "^1.9.0",
"@azure/core-client": "^1.9.2",
"@azure/core-rest-pipeline": "^1.17.0",
"@azure/core-tracing": "^1.0.0",
"@azure/core-util": "^1.11.0",
"@azure/logger": "^1.0.0",
"@azure/msal-browser": "^5.5.0",
"@azure/msal-node": "^5.1.0",
"open": "^10.1.0",
"tslib": "^2.2.0"
},
"devDependencies": {
"@azure-tools/test-recorder": "^4.1.1",
"@azure-tools/test-utils-vitest": "^2.0.1",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@azure/keyvault-keys": "4.10.0",
"@types/jsonwebtoken": "^9.0.0",
"@types/ms": "^2.1.0",
"@types/node": "^20.19.0",
"@vitest/browser": "^3.2.3",
"@vitest/coverage-istanbul": "^3.2.3",
"assertion-error": "^2.0.1",
"dotenv": "^16.0.0",
"eslint": "^9.33.0",
"jsonwebtoken": "^9.0.0",
"ms": "^2.1.3",
"playwright": "^1.50.1",
"typescript": "~5.8.3",
"vitest": "^3.2.3"
},
"engines": {
"node": ">=20.0.0"
}
},
"../node_modules/.pnpm/@azure+keyvault-secrets@4.11.2/node_modules/@azure/keyvault-secrets": {
"version": "4.11.2",
"license": "MIT",
"dependencies": {
"@azure-rest/core-client": "^2.3.3",
"@azure/abort-controller": "^2.1.2",
"@azure/core-auth": "^1.9.0",
"@azure/core-lro": "^2.7.2",
"@azure/core-paging": "^1.6.2",
"@azure/core-rest-pipeline": "^1.19.0",
"@azure/core-tracing": "^1.2.0",
"@azure/core-util": "^1.11.0",
"@azure/keyvault-common": "^2.1.0",
"@azure/logger": "^1.1.4",
"tslib": "^2.8.1"
},
"devDependencies": {
"@azure-tools/test-credential": "^2.1.2",
"@azure-tools/test-recorder": "^4.1.1",
"@azure-tools/test-utils-vitest": "^2.0.1",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@azure/identity": "4.13.0",
"@types/node": "^20.19.25",
"@vitest/browser-playwright": "^4.1.2",
"@vitest/coverage-istanbul": "^4.1.2",
"cross-env": "^10.1.0",
"dotenv": "^16.6.1",
"eslint": "^9.39.1",
"playwright": "^1.58.2",
"prettier": "^3.6.2",
"react-native": "^0.84.1",
"rimraf": "^6.1.0",
"typescript": "~6.0.2",
"vitest": "^4.1.2"
},
"engines": {
"node": ">=20.0.0"
}
},
"../node_modules/.pnpm/@eslint+js@9.39.4/node_modules/@eslint/js": {
"version": "9.39.4",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://eslint.org/donate"
}
},
"../node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit": {
"version": "10.3.0",
"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": "^5.0.0",
"toad-cache": "^3.7.0"
},
"devDependencies": {
"@fastify/pre-commit": "^2.1.0",
"@sinonjs/fake-timers": "^14.0.0",
"@types/node": "^22.0.0",
"c8": "^10.1.2",
"eslint": "^9.17.0",
"fastify": "^5.0.0",
"ioredis": "^5.4.1",
"knex": "^3.1.0",
"neostandard": "^0.12.0",
"sqlite3": "^5.1.7",
"tsd": "^0.32.0"
}
},
"../node_modules/.pnpm/@fastify+swagger-ui@5.2.6/node_modules/@fastify/swagger-ui": {
"version": "5.2.6",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT",
"dependencies": {
"@fastify/static": "^9.1.2",
"fastify-plugin": "^5.0.0",
"openapi-types": "^12.1.3",
"rfdc": "^1.3.1",
"yaml": "^2.4.1"
},
"devDependencies": {
"@apidevtools/swagger-parser": "^12.0.0",
"@fastify/basic-auth": "^6.0.0",
"@fastify/helmet": "^13.0.0",
"@fastify/swagger": "^9.0.0",
"@playwright/test": "^1.43.1",
"@types/node": "^25.0.3",
"ajv": "^8.12.0",
"c8": "^11.0.0",
"eslint": "^9.17.0",
"fastify": "^5.0.0",
"fs-extra": "^11.2.0",
"neostandard": "^0.13.0",
"qs": "^6.12.1",
"swagger-ui-dist": "5.32.1",
"tsd": "^0.33.0"
}
},
"../node_modules/.pnpm/@fastify+swagger@9.7.0/node_modules/@fastify/swagger": {
"version": "9.7.0",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT",
"dependencies": {
"fastify-plugin": "^5.0.0",
"json-schema-resolver": "^3.0.0",
"openapi-types": "^12.1.3",
"rfdc": "^1.3.1",
"yaml": "^2.4.2"
},
"devDependencies": {
"@apidevtools/swagger-parser": "^12.0.0",
"@fastify/cookie": "^11.0.1",
"@types/node": "^25.0.3",
"c8": "^10.1.3",
"eslint": "^9.17.0",
"fastify": "^5.0.0",
"fluent-json-schema": "^6.0.0",
"joi": "^17.13.1",
"joi-to-json": "^5.0.0",
"neostandard": "^0.12.0",
"qs": "^6.12.1",
"tsd": "^0.33.0"
}
},
"../node_modules/.pnpm/@types+node@25.6.2/node_modules/@types/node": {
"version": "25.6.2",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.19.0"
}
},
"../node_modules/.pnpm/@vitest+coverage-v8@3.2.4_vitest@3.2.4_@types+node@25.6.2_jiti@2.7.0_jsdom@26.1.0_light_dcd0c8ef67a5107c95df07389f58be52/node_modules/@vitest/coverage-v8": {
"version": "3.2.4",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
"@bcoe/v8-coverage": "^1.0.2",
"ast-v8-to-istanbul": "^0.3.3",
"debug": "^4.4.1",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
"istanbul-lib-source-maps": "^5.0.6",
"istanbul-reports": "^3.1.7",
"magic-string": "^0.30.17",
"magicast": "^0.3.5",
"std-env": "^3.9.0",
"test-exclude": "^7.0.1",
"tinyrainbow": "^2.0.0"
},
"devDependencies": {
"@types/debug": "^4.1.12",
"@types/istanbul-lib-coverage": "^2.0.6",
"@types/istanbul-lib-report": "^3.0.3",
"@types/istanbul-lib-source-maps": "^4.0.4",
"@types/istanbul-reports": "^3.0.4",
"@types/test-exclude": "^6.0.2",
"@vitest/browser": "3.2.4",
"pathe": "^2.0.3",
"v8-to-istanbul": "^9.3.0",
"vite-node": "3.2.4",
"vitest": "3.2.4"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@vitest/browser": "3.2.4",
"vitest": "3.2.4"
},
"peerDependenciesMeta": {
"@vitest/browser": {
"optional": true
}
}
},
"../node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv": {
"version": "16.6.1",
"license": "BSD-2-Clause",
"devDependencies": {
"@types/node": "^18.11.3",
"decache": "^4.6.2",
"sinon": "^14.0.1",
"standard": "^17.0.0",
"standard-version": "^9.5.0",
"tap": "^19.2.0",
"typescript": "^4.8.4"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"../node_modules/.pnpm/eslint@9.39.4_jiti@2.7.0/node_modules/eslint": {
"version": "9.39.4",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.21.2",
"@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.5",
"@eslint/js": "9.39.4",
"@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
"ajv": "^6.14.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
"eslint-scope": "^8.4.0",
"eslint-visitor-keys": "^4.2.1",
"espree": "^10.4.0",
"esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
"file-entry-cache": "^8.0.0",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
"ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.5",
"natural-compare": "^1.4.0",
"optionator": "^0.9.3"
},
"bin": {
"eslint": "bin/eslint.js"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.0",
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.4.3",
"@cypress/webpack-preprocessor": "^6.0.2",
"@eslint/json": "^0.13.2",
"@trunkio/launcher": "^1.3.4",
"@types/esquery": "^1.5.4",
"@types/node": "^22.13.14",
"@typescript-eslint/parser": "^8.4.0",
"babel-loader": "^8.0.5",
"c8": "^7.12.0",
"chai": "^4.0.1",
"cheerio": "^0.22.0",
"common-tags": "^1.8.0",
"core-js": "^3.1.3",
"cypress": "^14.1.0",
"ejs": "^3.0.2",
"eslint": "file:.",
"eslint-config-eslint": "file:packages/eslint-config-eslint",
"eslint-plugin-eslint-plugin": "^6.0.0",
"eslint-plugin-expect-type": "^0.6.0",
"eslint-plugin-yml": "^1.14.0",
"eslint-release": "^3.3.0",
"eslint-rule-composer": "^0.3.0",
"eslump": "^3.0.0",
"esprima": "^4.0.1",
"fast-glob": "^3.2.11",
"fs-teardown": "^0.1.3",
"glob": "^10.0.0",
"globals": "^16.2.0",
"got": "^11.8.3",
"gray-matter": "^4.0.3",
"jiti": "^2.6.1",
"jiti-v2.0": "npm:jiti@2.0.x",
"jiti-v2.1": "npm:jiti@2.1.x",
"knip": "^5.60.2",
"lint-staged": "^11.0.0",
"markdown-it": "^12.2.0",
"markdown-it-container": "^3.0.0",
"marked": "^4.0.8",
"metascraper": "^5.25.7",
"metascraper-description": "^5.25.7",
"metascraper-image": "^5.29.3",
"metascraper-logo": "^5.25.7",
"metascraper-logo-favicon": "^5.25.7",
"metascraper-title": "^5.25.7",
"mocha": "^11.7.1",
"node-polyfill-webpack-plugin": "^1.0.3",
"npm-license": "^0.3.3",
"pirates": "^4.0.5",
"progress": "^2.0.3",
"proxyquire": "^2.0.1",
"recast": "^0.23.0",
"regenerator-runtime": "^0.14.0",
"semver": "^7.5.3",
"shelljs": "^0.10.0",
"sinon": "^11.0.0",
"typescript": "^5.3.3",
"webpack": "^5.23.0",
"webpack-cli": "^4.5.0",
"yorkie": "^2.0.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://eslint.org/donate"
},
"peerDependencies": {
"jiti": "*"
},
"peerDependenciesMeta": {
"jiti": {
"optional": true
}
}
},
"../node_modules/.pnpm/fastify-sse-v2@4.2.2_fastify@5.8.5/node_modules/fastify-sse-v2": {
"version": "4.2.2",
"extraneous": true,
"license": "MIT",
"dependencies": {
"fastify-plugin": "^4.3.0",
"it-pushable": "^1.4.2",
"it-to-stream": "^1.0.0"
},
"devDependencies": {
"@chainsafe/eslint-config": "^2.0.0",
"@types/chai": "^4.1.7",
"@types/eventsource": "^1.1.2",
"@types/mocha": "^10.0.1",
"@types/node": "^16.0.0",
"@types/sinon": "^9.0.0",
"chai": "^4.2.0",
"eslint": "8.28.0",
"eventsource": "^1.0.7",
"fastify": "^4.10.2",
"mocha": "^10.2.0",
"sinon": "^9.0.2",
"ts-node": "^8.3.0",
"typescript": "~4.7"
},
"peerDependencies": {
"fastify": ">=4"
}
},
"../node_modules/.pnpm/fastify@5.8.5/node_modules/fastify": {
"version": "5.8.5",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT",
"dependencies": {
"@fastify/ajv-compiler": "^4.0.5",
"@fastify/error": "^4.0.0",
"@fastify/fast-json-stringify-compiler": "^5.0.0",
"@fastify/proxy-addr": "^5.0.0",
"abstract-logging": "^2.0.1",
"avvio": "^9.0.0",
"fast-json-stringify": "^6.0.0",
"find-my-way": "^9.0.0",
"light-my-request": "^6.0.0",
"pino": "^9.14.0 || ^10.1.0",
"process-warning": "^5.0.0",
"rfdc": "^1.3.1",
"secure-json-parse": "^4.0.0",
"semver": "^7.6.0",
"toad-cache": "^3.7.0"
},
"devDependencies": {
"@jsumners/line-reporter": "^1.0.1",
"@sinonjs/fake-timers": "^11.2.2",
"@stylistic/eslint-plugin": "^5.1.0",
"@stylistic/eslint-plugin-js": "^4.1.0",
"@types/node": "^25.0.3",
"ajv": "^8.12.0",
"ajv-errors": "^3.0.0",
"ajv-formats": "^3.0.1",
"ajv-i18n": "^4.2.0",
"ajv-merge-patch": "^5.0.1",
"autocannon": "^8.0.0",
"borp": "^1.0.0",
"branch-comparer": "^1.1.0",
"concurrently": "^9.1.2",
"cross-env": "^10.0.0",
"eslint": "^9.0.0",
"fast-json-body": "^1.1.0",
"fastify-plugin": "^5.0.0",
"fluent-json-schema": "^6.0.0",
"h2url": "^0.2.0",
"http-errors": "^2.0.0",
"joi": "^18.0.1",
"json-schema-to-ts": "^3.0.1",
"JSONStream": "^1.3.5",
"markdownlint-cli2": "^0.22.0",
"neostandard": "^0.12.0",
"node-forge": "^1.3.1",
"proxyquire": "^2.1.3",
"split2": "^4.2.0",
"tsd": "^0.33.0",
"typebox": "^1.0.81",
"typescript": "~6.0.2",
"undici": "^7.11.0",
"vary": "^1.1.2",
"yup": "^1.4.0"
}
},
"../node_modules/.pnpm/globals@15.15.0/node_modules/globals": {
"version": "15.15.0",
"dev": true,
"license": "MIT",
"devDependencies": {
"@vitest/eslint-plugin": "^1.1.30",
"ava": "^6.1.3",
"cheerio": "^1.0.0-rc.12",
"eslint-plugin-jest": "^28.8.3",
"execa": "^9.4.0",
"get-port": "^7.1.0",
"npm-run-all2": "^6.2.3",
"outdent": "^0.8.0",
"puppeteer": "^23.4.1",
"shelljs": "^0.8.5",
"tsd": "^0.31.2",
"type-fest": "^4.26.1",
"xo": "^0.59.3"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"../node_modules/.pnpm/jose@6.2.3/node_modules/jose": {
"version": "6.2.3",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"../node_modules/.pnpm/tsx@4.21.0/node_modules/tsx": {
"version": "4.21.0",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "~0.27.0",
"get-tsconfig": "^4.7.5"
},
"bin": {
"tsx": "dist/cli.mjs"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
}
},
"../node_modules/.pnpm/typescript-eslint@8.60.0_eslint@9.39.4_jiti@2.7.0__typescript@5.9.3/node_modules/typescript-eslint": {
"version": "8.60.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.60.0",
"@typescript-eslint/parser": "8.60.0",
"@typescript-eslint/typescript-estree": "8.60.0",
"@typescript-eslint/utils": "8.60.0"
},
"devDependencies": {
"@vitest/coverage-v8": "^4.0.18",
"eslint": "^10.0.0",
"rimraf": "^5.0.10",
"typescript": ">=4.8.4 <6.1.0",
"vitest": "^4.0.18"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
},
"../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript": {
"version": "5.9.3",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"devDependencies": {
"@dprint/formatter": "^0.4.1",
"@dprint/typescript": "0.93.4",
"@esfx/canceltoken": "^1.0.0",
"@eslint/js": "^9.20.0",
"@octokit/rest": "^21.1.1",
"@types/chai": "^4.3.20",
"@types/diff": "^7.0.1",
"@types/minimist": "^1.2.5",
"@types/mocha": "^10.0.10",
"@types/ms": "^0.7.34",
"@types/node": "latest",
"@types/source-map-support": "^0.5.10",
"@types/which": "^3.0.4",
"@typescript-eslint/rule-tester": "^8.24.1",
"@typescript-eslint/type-utils": "^8.24.1",
"@typescript-eslint/utils": "^8.24.1",
"azure-devops-node-api": "^14.1.0",
"c8": "^10.1.3",
"chai": "^4.5.0",
"chokidar": "^4.0.3",
"diff": "^7.0.0",
"dprint": "^0.49.0",
"esbuild": "^0.25.0",
"eslint": "^9.20.1",
"eslint-formatter-autolinkable-stylish": "^1.4.0",
"eslint-plugin-regexp": "^2.7.0",
"fast-xml-parser": "^4.5.2",
"glob": "^10.4.5",
"globals": "^15.15.0",
"hereby": "^1.10.0",
"jsonc-parser": "^3.3.1",
"knip": "^5.44.4",
"minimist": "^1.2.8",
"mocha": "^10.8.2",
"mocha-fivemat-progress-reporter": "^0.1.0",
"monocart-coverage-reports": "^2.12.1",
"ms": "^2.1.3",
"picocolors": "^1.1.1",
"playwright": "^1.50.1",
"source-map-support": "^0.5.21",
"tslib": "^2.8.1",
"typescript": "^5.7.3",
"typescript-eslint": "^8.24.1",
"which": "^3.0.1"
},
"engines": {
"node": ">=14.17"
}
},
"../node_modules/.pnpm/vitest@3.2.4_@types+node@25.6.2_jiti@2.7.0_jsdom@26.1.0_lightningcss@1.32.0_tsx@4.21.0_yaml@2.8.4/node_modules/vitest": {
"version": "3.2.4",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/expect": "3.2.4",
"@vitest/mocker": "3.2.4",
"@vitest/pretty-format": "^3.2.4",
"@vitest/runner": "3.2.4",
"@vitest/snapshot": "3.2.4",
"@vitest/spy": "3.2.4",
"@vitest/utils": "3.2.4",
"chai": "^5.2.0",
"debug": "^4.4.1",
"expect-type": "^1.2.1",
"magic-string": "^0.30.17",
"pathe": "^2.0.3",
"picomatch": "^4.0.2",
"std-env": "^3.9.0",
"tinybench": "^2.9.0",
"tinyexec": "^0.3.2",
"tinyglobby": "^0.2.14",
"tinypool": "^1.1.1",
"tinyrainbow": "^2.0.0",
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
"vite-node": "3.2.4",
"why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
},
"devDependencies": {
"@ampproject/remapping": "^2.3.0",
"@antfu/install-pkg": "^1.1.0",
"@edge-runtime/vm": "^5.0.0",
"@sinonjs/fake-timers": "14.0.0",
"@types/debug": "^4.1.12",
"@types/estree": "^1.0.8",
"@types/istanbul-lib-coverage": "^2.0.6",
"@types/istanbul-reports": "^3.0.4",
"@types/jsdom": "^21.1.7",
"@types/mime": "^4.0.0",
"@types/node": "^22.15.32",
"@types/picomatch": "^4.0.0",
"@types/prompts": "^2.4.9",
"@types/sinonjs__fake-timers": "^8.1.5",
"acorn-walk": "^8.3.4",
"birpc": "2.4.0",
"cac": "^6.7.14",
"chai-subset": "^1.6.0",
"find-up": "^6.3.0",
"flatted": "^3.3.3",
"happy-dom": "^17.6.3",
"jsdom": "^26.1.0",
"local-pkg": "^1.1.1",
"mime": "^4.0.7",
"pretty-format": "^29.7.0",
"prompts": "^2.4.2",
"strip-literal": "^3.0.0",
"ws": "^8.18.2"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/debug": "^4.1.12",
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
"@vitest/browser": "3.2.4",
"@vitest/ui": "3.2.4",
"happy-dom": "*",
"jsdom": "*"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
"optional": true
},
"@types/debug": {
"optional": true
},
"@types/node": {
"optional": true
},
"@vitest/browser": {
"optional": true
},
"@vitest/ui": {
"optional": true
},
"happy-dom": {
"optional": true
},
"jsdom": {
"optional": true
}
}
},
"../node_modules/.pnpm/zod@3.25.76/node_modules/zod": {
"version": "3.25.76",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/@azure/cosmos": {
"resolved": "../node_modules/.pnpm/@azure+cosmos@4.9.3_@azure+core-client@1.10.1/node_modules/@azure/cosmos",
"link": true
},
"node_modules/@azure/identity": {
"resolved": "../node_modules/.pnpm/@azure+identity@4.13.1/node_modules/@azure/identity",
"link": true
},
"node_modules/@azure/keyvault-secrets": {
"resolved": "../node_modules/.pnpm/@azure+keyvault-secrets@4.11.2/node_modules/@azure/keyvault-secrets",
"link": true
},
"node_modules/@eslint/js": {
"resolved": "../node_modules/.pnpm/@eslint+js@9.39.4/node_modules/@eslint/js",
"link": true
},
"node_modules/@fastify/rate-limit": {
"resolved": "../node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit",
"link": true
},
"node_modules/@fastify/swagger": {
"resolved": "../node_modules/.pnpm/@fastify+swagger@9.7.0/node_modules/@fastify/swagger",
"link": true
},
"node_modules/@fastify/swagger-ui": {
"resolved": "../node_modules/.pnpm/@fastify+swagger-ui@5.2.6/node_modules/@fastify/swagger-ui",
"link": true
},
"node_modules/@types/node": {
"resolved": "../node_modules/.pnpm/@types+node@25.6.2/node_modules/@types/node",
"link": true
},
"node_modules/@vitest/coverage-v8": {
"resolved": "../node_modules/.pnpm/@vitest+coverage-v8@3.2.4_vitest@3.2.4_@types+node@25.6.2_jiti@2.7.0_jsdom@26.1.0_light_dcd0c8ef67a5107c95df07389f58be52/node_modules/@vitest/coverage-v8",
"link": true
},
"node_modules/dotenv": {
"resolved": "../node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv",
"link": true
},
"node_modules/eslint": {
"resolved": "../node_modules/.pnpm/eslint@9.39.4_jiti@2.7.0/node_modules/eslint",
"link": true
},
"node_modules/fastify": {
"resolved": "../node_modules/.pnpm/fastify@5.8.5/node_modules/fastify",
"link": true
},
"node_modules/globals": {
"resolved": "../node_modules/.pnpm/globals@15.15.0/node_modules/globals",
"link": true
},
"node_modules/jose": {
"resolved": "../node_modules/.pnpm/jose@6.2.3/node_modules/jose",
"link": true
},
"node_modules/tsx": {
"resolved": "../node_modules/.pnpm/tsx@4.21.0/node_modules/tsx",
"link": true
},
"node_modules/typescript": {
"resolved": "../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript",
"link": true
},
"node_modules/typescript-eslint": {
"resolved": "../node_modules/.pnpm/typescript-eslint@8.60.0_eslint@9.39.4_jiti@2.7.0__typescript@5.9.3/node_modules/typescript-eslint",
"link": true
},
"node_modules/vitest": {
"resolved": "../node_modules/.pnpm/vitest@3.2.4_@types+node@25.6.2_jiti@2.7.0_jsdom@26.1.0_lightningcss@1.32.0_tsx@4.21.0_yaml@2.8.4/node_modules/vitest",
"link": true
},
"node_modules/zod": {
"resolved": "../node_modules/.pnpm/zod@3.25.76/node_modules/zod",
"link": true
}
}
}

View File

@ -27,6 +27,8 @@
"dotenv": "^16.4.5",
"fastify": "^5.2.1",
"jose": "^6.1.2",
"pino": "^10.3.1",
"pino-pretty": "^13.1.3",
"zod": "^3.24.1"
},
"devDependencies": {

View File

@ -39,6 +39,12 @@ importers:
jose:
specifier: ^6.1.2
version: 6.2.3
pino:
specifier: ^10.3.1
version: 10.3.1
pino-pretty:
specifier: ^13.1.3
version: 13.1.3
zod:
specifier: ^3.24.1
version: 3.25.76
@ -1391,6 +1397,9 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@ -1423,6 +1432,9 @@ packages:
resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==}
engines: {node: '>=18'}
dateformat@4.6.3:
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@ -1491,6 +1503,9 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
enhanced-resolve@5.21.2:
resolution: {integrity: sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==}
engines: {node: '>=10.13.0'}
@ -1571,6 +1586,9 @@ packages:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
fast-copy@4.0.3:
resolution: {integrity: sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==}
fast-decode-uri-component@1.0.1:
resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
@ -1589,6 +1607,9 @@ packages:
fast-querystring@1.1.2:
resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==}
fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
fast-uri@3.1.2:
resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==}
@ -1681,6 +1702,9 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
help-me@5.0.0:
resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==}
html-encoding-sniffer@4.0.0:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
@ -1789,6 +1813,10 @@ packages:
jose@6.2.3:
resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==}
joycon@3.1.1:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'}
js-tokens@10.0.0:
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
@ -2010,6 +2038,9 @@ packages:
resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
engines: {node: '>=16 || 14 >=14.17'}
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
minipass@7.1.3:
resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
engines: {node: '>=16 || 14 >=14.17'}
@ -2057,6 +2088,9 @@ packages:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
open@10.2.0:
resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
engines: {node: '>=18'}
@ -2119,6 +2153,10 @@ packages:
pino-abstract-transport@3.0.0:
resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
pino-pretty@13.1.3:
resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==}
hasBin: true
pino-std-serializers@7.1.0:
resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==}
@ -2164,6 +2202,9 @@ packages:
process-warning@5.0.0:
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
pump@3.0.4:
resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==}
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@ -2339,6 +2380,10 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
strip-json-comments@5.0.3:
resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==}
engines: {node: '>=14.16'}
strip-literal@3.1.0:
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
@ -2583,6 +2628,9 @@ packages:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
ws@8.20.0:
resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==}
engines: {node: '>=10.0.0'}
@ -3863,6 +3911,8 @@ snapshots:
color-name@1.1.4: {}
colorette@2.0.20: {}
concat-map@0.0.1: {}
content-disposition@1.1.0: {}
@ -3891,6 +3941,8 @@ snapshots:
whatwg-mimetype: 4.0.0
whatwg-url: 14.2.0
dateformat@4.6.3: {}
debug@4.4.3:
dependencies:
ms: 2.1.3
@ -3934,6 +3986,10 @@ snapshots:
emoji-regex@9.2.2: {}
end-of-stream@1.4.5:
dependencies:
once: 1.4.0
enhanced-resolve@5.21.2:
dependencies:
graceful-fs: 4.2.11
@ -4054,6 +4110,8 @@ snapshots:
expect-type@1.3.0: {}
fast-copy@4.0.3: {}
fast-decode-uri-component@1.0.1: {}
fast-deep-equal@3.1.3: {}
@ -4075,6 +4133,8 @@ snapshots:
dependencies:
fast-decode-uri-component: 1.0.1
fast-safe-stringify@2.1.1: {}
fast-uri@3.1.2: {}
fastify-plugin@5.1.0: {}
@ -4173,6 +4233,8 @@ snapshots:
has-flag@4.0.0: {}
help-me@5.0.0: {}
html-encoding-sniffer@4.0.0:
dependencies:
whatwg-encoding: 3.1.1
@ -4275,6 +4337,8 @@ snapshots:
jose@6.2.3: {}
joycon@3.1.1: {}
js-tokens@10.0.0: {}
js-tokens@4.0.0: {}
@ -4490,6 +4554,8 @@ snapshots:
dependencies:
brace-expansion: 2.1.1
minimist@1.2.8: {}
minipass@7.1.3: {}
ms@2.1.3: {}
@ -4528,6 +4594,10 @@ snapshots:
on-exit-leak-free@2.1.2: {}
once@1.4.0:
dependencies:
wrappy: 1.0.2
open@10.2.0:
dependencies:
default-browser: 5.5.0
@ -4590,6 +4660,22 @@ snapshots:
dependencies:
split2: 4.2.0
pino-pretty@13.1.3:
dependencies:
colorette: 2.0.20
dateformat: 4.6.3
fast-copy: 4.0.3
fast-safe-stringify: 2.1.1
help-me: 5.0.0
joycon: 3.1.1
minimist: 1.2.8
on-exit-leak-free: 2.1.2
pino-abstract-transport: 3.0.0
pump: 3.0.4
secure-json-parse: 4.1.0
sonic-boom: 4.2.1
strip-json-comments: 5.0.3
pino-std-serializers@7.1.0: {}
pino@10.3.1:
@ -4642,6 +4728,11 @@ snapshots:
process-warning@5.0.0: {}
pump@3.0.4:
dependencies:
end-of-stream: 1.4.5
once: 1.4.0
punycode@2.3.1: {}
quick-format-unescaped@4.0.4: {}
@ -4823,6 +4914,8 @@ snapshots:
strip-json-comments@3.1.1: {}
strip-json-comments@5.0.3: {}
strip-literal@3.1.0:
dependencies:
js-tokens: 9.0.1
@ -5050,6 +5143,8 @@ snapshots:
string-width: 5.1.2
strip-ansi: 7.2.0
wrappy@1.0.2: {}
ws@8.20.0: {}
wsl-utils@0.1.0:

View File

@ -1,19 +1,30 @@
# Build context: bytelyst-devops-tools/dashboard/ (monorepo root)
#
# Uses pnpm (matches `packageManager` field) and the workspace
# `pnpm-lock.yaml`. See backend/Dockerfile for the full background on
# why the previous `npm ci` based build was broken (pnpm-store symlinks
# leaking into the npm lockfile).
# --- Stage 1: Build ---
FROM node:20-alpine AS builder
WORKDIR /app/web
ENV BYTELYST_PACKAGE_SOURCE=gitea
RUN corepack enable && corepack prepare pnpm@10.6.5 --activate
COPY web/package.json web/package-lock.json ./
RUN npm ci --ignore-scripts
WORKDIR /app
COPY web/tsconfig.json ./
COPY web/next-env.d.ts ./
COPY web/next.config.js ./
COPY web/tailwind.config.ts ./
COPY web/postcss.config.js ./
COPY web/src/ ./src/
COPY web/public/ ./public/
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.cjs ./
COPY web/package.json ./web/
RUN pnpm install --frozen-lockfile --filter "@bytelyst/devops-web..." --ignore-scripts
COPY web/tsconfig.json ./web/
COPY web/next-env.d.ts ./web/
COPY web/next.config.js ./web/
COPY web/tailwind.config.ts ./web/
COPY web/postcss.config.js ./web/
COPY web/src/ ./web/src/
COPY web/public/ ./web/public/
# Build-time env vars (baked into the static bundle)
ARG NEXT_PUBLIC_PRODUCT_ID=devops
@ -40,16 +51,20 @@ ENV NEXT_PUBLIC_PRODUCT_ID=${NEXT_PUBLIC_PRODUCT_ID} \
NEXT_PUBLIC_BYTELYST_COMMIT_MESSAGE=${BYTELYST_COMMIT_MESSAGE} \
NEXT_PUBLIC_BYTELYST_DOCKER_IMAGE=${BYTELYST_DOCKER_IMAGE}
RUN npm run build
WORKDIR /app/web
RUN pnpm run build
# Carve out a production-only deploy bundle.
WORKDIR /app
RUN pnpm --filter "@bytelyst/devops-web" deploy --prod --legacy /deploy
# --- Stage 2: Serve ---
FROM node:20-alpine AS runner
WORKDIR /app/web
COPY web/package.json web/package-lock.json ./
RUN npm ci --omit=dev --ignore-scripts
COPY --from=builder /deploy/package.json ./package.json
COPY --from=builder /deploy/node_modules ./node_modules
COPY --from=builder /app/web/.next ./.next
COPY --from=builder /app/web/public ./public

File diff suppressed because it is too large Load Diff