diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 155d609f..3c07a165 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -25,3 +25,16 @@ updates: directory: / schedule: { interval: weekly } open-pull-requests-limit: 3 + # Container base images: auto-bump the @sha256 digests pinned in each Dockerfile FROM line. + - package-ecosystem: docker + directory: /services/api + schedule: { interval: weekly } + open-pull-requests-limit: 3 + - package-ecosystem: docker + directory: /apps/web + schedule: { interval: weekly } + open-pull-requests-limit: 3 + - package-ecosystem: docker + directory: /services/converter + schedule: { interval: weekly } + open-pull-requests-limit: 3 diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index bd10b9d9..fb97153d 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -1,6 +1,6 @@ # Build the Vite app, then serve the static bundle with nginx. # Build context = repo root (this is an npm workspace: the only lockfile is the root package-lock.json). -FROM node:20-slim AS build +FROM node:20-slim@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0 AS build WORKDIR /repo # Manifests + lockfile first, so `npm ci` is a reproducible, cache-friendly layer that only re-runs when # deps change — not on every source edit. `npm ci` (vs `npm install`) installs EXACTLY the locked tree @@ -11,7 +11,7 @@ RUN npm ci COPY apps/web/ apps/web/ RUN npm run build --workspace apps/web # prebuild copies web-ifc WASM into public/wasm/ -FROM nginx:alpine +FROM nginx:alpine@sha256:4a73073bd557c65b759505da037898b61f1be6cbcc3c2c3aeac22d2a470c1752 COPY apps/web/nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /repo/apps/web/dist /usr/share/nginx/html EXPOSE 80 diff --git a/package-lock.json b/package-lock.json index af310703..8e499ee1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ }, "apps/web": { "name": "@aec/web", - "version": "0.3.560", + "version": "0.3.584", "dependencies": { "@mkkellogg/gaussian-splats-3d": "^0.4.7", "@tauri-apps/plugin-dialog": "^2.7.1", @@ -4297,6 +4297,23 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv/node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -5630,22 +5647,6 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] - }, "node_modules/fast-xml-builder": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", diff --git a/services/api/Dockerfile b/services/api/Dockerfile index 07157946..7407140e 100644 --- a/services/api/Dockerfile +++ b/services/api/Dockerfile @@ -5,7 +5,7 @@ # Pin the fragments/web-ifc pair to the SAME versions as the client parser (apps/web/package.json). # CI enforces this (scripts/check-fragments-version.mjs) — a mismatch means the server emits .frag the # browser can't parse. -FROM node:20-slim AS converter +FROM node:20-slim@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0 AS converter WORKDIR /conv ARG FRAGMENTS_VERSION=3.4.5 ARG WEBIFC_VERSION=0.0.77 @@ -15,7 +15,7 @@ RUN npm init -y >/dev/null 2>&1 && npm install --no-audit --no-fund \ # --- python build stage (B3): a full toolchain compiles any source-only wheel HERE, then we lift only # the installed packages into the runtime image below. gcc + headers never ship to production, so the # runtime image is smaller and carries no compiler in its attack surface. --- -FROM python:3.12-slim AS pybuild +FROM python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de AS pybuild # build toolchain + the same shared libs, so wheels that need to compile can link during install RUN apt-get update && apt-get install -y --no-install-recommends \ libgl1 libglib2.0-0 build-essential python3-dev \ @@ -29,7 +29,7 @@ COPY services/api/requirements.lock /tmp/req/requirements.lock # wholesale into the runtime stage. RUN pip install --prefix=/install --require-hashes -r /tmp/req/requirements.lock -FROM python:3.12-slim +FROM python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de WORKDIR /app ENV PYTHONUNBUFFERED=1 \ diff --git a/services/converter/Dockerfile b/services/converter/Dockerfile index 4f7ab32f..e658d552 100644 --- a/services/converter/Dockerfile +++ b/services/converter/Dockerfile @@ -1,5 +1,5 @@ # IFC→Fragments converter (Node). Build context = repo root. -FROM node:20-slim +FROM node:20-slim@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0 WORKDIR /app # install just what the converter needs; web-ifc ships its own WASM. Pin to the SAME versions as the