# Core runtime dependency locks The core image consumes committed, production-only locks for Pi and the Python harness. Refresh them from the repository root after intentionally changing the corresponding direct dependencies. ## Pi runtime Keep the exact Pi version in `docker/pi-runtime/package.json`, then regenerate its npm lock: ```sh npm install --package-lock-only --ignore-scripts --no-audit --no-fund \ --prefix docker/pi-runtime ``` The image installs this tree with `npm ci --omit=dev`; do not replace it with an unpinned global install. ## Python runtime Install [uv](https://docs.astral.sh/uv/) and compile the harness's production dependencies for Python 3.12. `--universal` retains platform markers and hashes for a cross-platform resolution; the `dev` extra is deliberately absent. ```sh uv pip compile harness/pyproject.toml docker/python-runtime/build-requirements.in \ --universal \ --python-version 3.12 \ --no-emit-package tht \ --generate-hashes \ --custom-compile-command \ 'uv pip compile harness/pyproject.toml docker/python-runtime/build-requirements.in --universal --python-version 3.12 --no-emit-package tht --generate-hashes --output-file docker/python-runtime/requirements.lock' \ --output-file docker/python-runtime/requirements.lock ``` The small input file pins the harness's PEP 517 build backend as well; it is not derived from a host environment. The image installs the resulting lock with pip's `--require-hashes`, then installs the local `tht` project with `--no-deps --no-build-isolation`. This prevents both project metadata and an isolated build environment from resolving unpinned packages. ## Base images Every `FROM` uses an exact tag plus a multi-platform manifest-list digest. To update one: 1. Choose an exact patch tag that publishes both `linux/amd64` and `linux/arm64`. 2. Inspect it with `docker buildx imagetools inspect `. 3. Replace both the human-readable tag and `@sha256:...` digest. 4. Run `./scripts/verify-container-images.sh` and the Compose smoke. 5. Review the generated inventory under `.artifacts/container-images/`. The digest freezes image layers, but `apt-get update` and `apk add` still consume mutable package repositories during a no-cache rebuild. Full OS-package immutability would require Debian/Alpine snapshot repositories and is not claimed by this deployment.