Runtime Dependency Build
This directory records the public build inputs and pip-tools generator. It is not an application configuration directory and must never contain credentials.
Pins
| Input | Pin |
|---|---|
| Python image | python:3.12-slim-bookworm@sha256:782412e85d0f0984994c290652577d4018aff08145c85b262bb63dc0c7522254 |
| Python version | 3.12.14 |
| Linux amd64 manifest | sha256:9c47360a2a0355e2da18516d0b1c2126ec22c195d2185e97347c9d98398c5bef |
| Linux arm64/v8 manifest | sha256:d04f49f5882f49a3b91f874e75e19f0c265f7222da8659741a9d7eab148f22a9 |
| Debian and Debian security snapshots | 20260914T000000Z |
| Git and git-man | 1:2.39.5-0+deb12u3 |
| tini | 0.19.0-1+b3 |
| CA certificates (already present in the pinned base) | 20250419~deb12u1 |
| PGDG server, client, libpq | 16.15-1.pgdg12+2 |
| PGDG common and client-common | 293.pgdg12+1 |
| PGDG signing-key fingerprint | B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 |
| PGDG signing-key SHA-256 | 0144068502a1eddd2a0280ede10ef607d1ec592ce819940991203941564e8e76 |
| TruffleHog | 3.97.4 |
| TruffleHog Linux amd64 archive SHA-256 | dc24007c2f233bd61c05beabeb44aa27ea9b43288166279209abe0458c5ce76b |
| TruffleHog Linux amd64 archive size | 34970205 bytes |
| TruffleHog Linux arm64 archive SHA-256 | 7e65e771d2a247964056aa5edba0f8ae3945895e5dce867fe0ffbc7b0128239a |
| TruffleHog Windows amd64 archive SHA-256 | 6ce9a957ac62bfb19463048333d9e8481327dbbf5bdc0c43f5ab5327b9631fb9 |
| Windows embeddable Python | 3.12.10, SHA-256 4acbed6dd1c744b0376e3b1cf57ce906f9dc9e95e68824584c8099a63025a3c3 |
| Windows MinGit | 2.47.1.windows.1, SHA-256 50b04b55425b5c465d076cdb184f63a0cd0f86f6ec8bb4d5860114a713d2c29a |
| pip-tools | 7.6.1 |
| Generator pip | 26.2.1 |
| pytest | 8.4.2 |
| httpx (test target only) | 0.28.1 |
| zstandard | 0.23.0 |
| pandas | 3.0.5 |
| plotly | 7.0.0 |
| streamlit | 1.63.0 |
| psycopg and psycopg-binary | 3.3.5 |
| boto3 and botocore | 1.43.94 |
TruffleHog's expected hashes were checked against the public release's
trufflehog_3.97.4_checksums.txt.
The PGDG key's primary OpenPGP fingerprint was independently calculated from the
hash-pinned public key and matches the fingerprint above.
The Dockerfile pins the base index, download digests, PGDG package versions, and
Debian snapshot. Apt verifies Debian signatures with its shipped archive keyring
and PGDG signatures with the separately hash-pinned, repository-scoped armored
key. Full GnuPG is not installed. Expired Valid-Until checks are disabled only
for the immutable Debian snapshots, never signature verification. The official
PGDG archive retains older package versions; apt preferences exclude every PGDG
package except the five exact pins above.
The complete Debian Git package and HTTPS helper are retained. Native executable
symlinks in the Python/Git tool directories, and PG client version-wrapper links,
are replaced with root-owned regular hard links. Dependencies stay in the
interpreter's /usr/local/lib/python3.12/site-packages, not a virtual environment
or user site. Installation requires hashes and binary wheels and disables
bytecode generation. The application lock includes both manifests, optional
dashboard packages, and pytest in one environment. The test target layers its
separate hash lock containing Starlette TestClient's httpx dependency; the
runtime target does not contain httpx. The separate worker lock contains only
Requests, PyYAML, zstandard, and their four transitives; it excludes PostgreSQL,
server, dashboard, test, and detailed-keycheck dependencies.
docker/worker-package-pins.json is the canonical public build-input record for
Linux and Windows worker artifacts. Worker manifests hash every application,
dependency, scanner, detector-policy, Python-runtime, and complete Git-runtime
file. The package grants no provider or detailed keycheck authority and contains
no server or database credentials.
PostgreSQL service starts and automatic cluster creation are disabled during installation. No database is initialized by the build. Generated distribution snakeoil TLS keys are removed in the same layer. Package pins make dependency selection repeatable; this is not a claim of byte-for-byte identical OCI images across BuildKit versions or package-maintainer timestamp generation.
Generate Locks
All four requirements lock files are generated by pip-tools on Linux with the pinned
Python 3.12.14 interpreter. Do not edit any generated lock by hand. The initial
compiler bootstrap installs only public pip==26.2.1 and pip-tools==7.6.1, then
resolves and hashes the compiler's entire dependency closure. Subsequent compiler
installs use that generated hash lock.
The generator also copies the existing locks, so normal regeneration retains
valid pins. Use pip-compile's --upgrade only for an intentional dependency
refresh, then rebuild and revalidate the dependency image.
Run these Docker commands from the isolated source checkout (D:\truf-workers for
this change), using WSL's
sudo -n docker -H unix:///var/run/docker.sock in place of docker on this host.
The generator receives only the three public application manifests and compiler
inputs. There are no host bind mounts.
docker build --target lock-generator -t truf-lock-generator:py3.12.14 .
docker run --name truf-runtime-lock truf-lock-generator:py3.12.14
docker cp truf-runtime-lock:/src/docker/requirements.lock docker/requirements.lock
docker rm truf-runtime-lock
docker run --name truf-test-lock truf-lock-generator:py3.12.14 \
python3 -m piptools compile --generate-hashes --allow-unsafe \
--resolver=backtracking --strip-extras --no-emit-index-url \
--no-emit-trusted-host --index-url=https://pypi.org/simple \
--pip-args=--only-binary=:all: \
--output-file=docker/requirements-test.lock docker/requirements-test.in
docker cp truf-test-lock:/src/docker/requirements-test.lock docker/requirements-test.lock
docker rm truf-test-lock
docker run --name truf-worker-lock truf-lock-generator:py3.12.14 \
python3 -m piptools compile --generate-hashes --allow-unsafe \
--resolver=backtracking --strip-extras --no-emit-index-url \
--no-emit-trusted-host --index-url=https://pypi.org/simple \
--pip-args=--only-binary=:all: \
--output-file=docker/requirements-worker.lock docker/requirements-worker.in
docker cp truf-worker-lock:/src/docker/requirements-worker.lock docker/requirements-worker.lock
docker rm truf-worker-lock
docker run --name truf-compiler-lock truf-lock-generator:py3.12.14 \
python3 -m piptools compile --generate-hashes --allow-unsafe \
--resolver=backtracking --strip-extras --no-emit-index-url \
--no-emit-trusted-host --index-url=https://pypi.org/simple \
--pip-args=--only-binary=:all: \
--output-file=docker/build-dependencies/requirements.lock \
docker/build-dependencies/requirements.in
docker cp truf-compiler-lock:/src/docker/build-dependencies/requirements.lock docker/build-dependencies/requirements.lock
docker rm truf-compiler-lock
Build Targets
docker build --target dependencies -t truf-dependencies:py3.12.14-pg16.15-th3.97.4 .
docker build --target runtime -t truf-runtime:local .
docker build --target test -t truf-test:local .
docker build --target worker -t truf-remote-worker:linux-x86_64 .
Remote Worker Artifacts
The worker target is independent of the server runtime. It uses the pinned image
Python and includes the worker authority, required shared DB-free modules, worker
dependency lock, detector policy, TruffleHog, CA roots, tini, and a package-local
complete Git helper tree. The final build executes the scanner and Git version
checks and verifies the full schema-3/protocol-2 capability package as unprivileged UID 10001. PostgreSQL
tools, server runtime/control authority, test code, httpx, provider and detailed
keycheck authority, server credentials, and database credentials are absent.
Build the Windows amd64 portable directory and deterministic ZIP from the same isolated checkout:
New-Item -ItemType Directory -Path dist -Force | Out-Null
python -B app/worker_package_builder.py windows `
--project-root . `
--output dist/truf-worker-windows-x86_64 `
--archive dist/truf-worker-windows-x86_64.zip `
--cache build/worker-cache
The builder downloads the hash-and-size-pinned Python 3.12.10 embeddable runtime,
MinGit 2.47.1, and TruffleHog 3.97.4, installs the cross-platform worker lock with
hash checking, verifies the complete package, and writes adjacent release JSON.
After extracting the ZIP, run prepare-worker.ps1 once to replace inherited ACLs,
then use run-worker.cmd. Local files rely on private OS ACLs rather than
application-layer encryption; the client has no TLS-verification bypass.
Build a complete distributable release (Windows ZIP, Linux image archive, Docker bundle, manifests, README, Compose file, and SHA-256 lists) with one PowerShell command:
.\build_worker_release.ps1 -ReleaseName release-YYYYMMDD-vN
The script uses native Docker when available and otherwise uses the Docker Engine
in Ubuntu-24.04 through WSL. Use -WslDistro NAME for another distribution.
The destination must not already exist; a failed build remains on disk for
inspection and is never published as a partial replacement.
While the main context allowlist is pending, the dependency build can use this explicit two-file context from WSL. It does not send any application code, secret files, findings, state, or original checkout directories to the builder:
tar -C /mnt/d/truf-docker -cf - Dockerfile docker/requirements.lock \
| sudo -n docker -H unix:///var/run/docker.sock build --file Dockerfile \
--target dependencies -t truf-dependencies:py3.12.14-pg16.15-th3.97.4 -
dependencies stops before copying application code. runtime-base holds the
production filesystem and launch configuration; test inherits those exact
contents and adds private test sources. The last/default target, runtime, is a
direct alias of runtime-base and contains no test tree. The test entrypoint uses
the same interpreter isolation flags and the real child_bootstrap.py dependency
path loader, without processing .pth files or starting the application.
Application and test copies are owned by 10001:10001; their directories are
0700 and regular files 0600. Build-time checks reject symlinks, special files,
and cached bytecode in these controlled copies. No recursive permission changes
are made to host paths or runtime-mounted data. The default user is 10001:10001;
the image precreates private /data and /data/home directories.
Verified Results
Validated on 2026-09-15 using Ubuntu 24.04 under WSL2, stock Docker Engine 29.8.0,
the local Unix socket, and sudo -n. Builds and generation were polled without
printing full dependency logs. A temporary WSL keepalive prevented idle shutdown
during detached lock generation; no host configuration changes were made.
| Result | Value |
|---|---|
| Dependency image tag | truf-dependencies:py3.12.14-pg16.15-th3.97.4 |
| Local dependency image ID | sha256:3fbdc2ea6fd1199aa742f54fb653e433d79ad3f1a5e4bfeed8b413dc9f704eb5 |
| Built and executed platform | linux/amd64 |
| Runtime lock | 49 exact package pins, 1059 SHA-256 wheel hashes |
| Runtime lock SHA-256 | 82c69394b116fd8a762c3dea481682045af87c013974fcb78ac0529892188537 |
| Compiler lock | 8 exact package pins, 8 SHA-256 wheel hashes |
| Compiler lock SHA-256 | 0172b08004c6f2b0702ea9a472300cc63243492df2d3d782fd4dbaa612497fd2 |
| Lock replay in the hash-locked generator image | Both files byte-for-byte identical |
pip check |
No broken requirements |
- The
dependenciesandlock-generatortargets built successfully with hash-required, binary-wheel-only installs. - All 49 package import checks passed normally, then with
-I -S -Bthrough the actualchild_bootstrap.pyloader for all 10 child kinds. Application entrypoints and providers were not executed. - Isolated
sys.pathcontained only the interpreter ZIP path, standard library,lib-dynload, and/usr/local/lib/python3.12/site-packages. Neither the working directory nor the user site was added. - 14,202 dependency-tree permission checks found root ownership, no group/world write access, and no symlinks or bytecode files. The unprivileged UID could not write these dependencies.
- Eleven selected native executables were regular root-owned files. Version and
lddchecks passed for Python, Git, the Git HTTPS helper, tini, TruffleHog, and the six PG16 tools. TruffleHog is static; other checked ELF binaries had no missing shared libraries. - TruffleHog global, Git, filesystem, Docker, and Hugging Face help flags were checked, including the scanner's legacy
--local-devand--log-leveloptions. No scans or provider requests were made. - No PostgreSQL
PG_VERSIONfile or initialized cluster was present. No PostgreSQL server, application, or provider was started. Full GnuPG is absent. - Minimal bootstrap-only runtime and test fixtures exercised the actual copy stages:
10001:10001, directories0700, files0600. Generated in-memory contexts containing a symlink or.pycfile were rejected by the build. - The test target's real tini/Python/bootstrap entrypoint reported
pytest 8.4.2with networking disabled, a read-only root, and a UID-10001 private/tmptmpfs. Pytest capture needs writable temporary storage even for--version.
The temporary runtime/test fixtures were deliberately incomplete and were used only for dependency and filesystem-policy verification. They are not deployable application images. No application test suite, PostgreSQL initialization test, provider integration, or arm64 build was run. The arm64 base and TruffleHog assets are pinned, but that platform still requires a native or emulated build/test.
Integration Boundary
The main integration owns .dockerignore, app/container_runtime.py, Compose,
and tests. The context allowlist must include the exact Dockerfile, dependency
input/lock paths, this metadata file, the new runtime entrypoint, and the intended
test files. Do not replace the deny-by-default context rules with directory-wide
or wildcard exceptions. Keep .env, credentials, findings, original runtime
directories, and generated caches excluded.
New exact metadata/input exceptions required in the main-owned .dockerignore:
!docker/requirements.in
!docker/requirements.lock
!docker/build-dependencies/requirements.in
!docker/build-dependencies/requirements.lock
!docker/build-dependencies/README.md
The Dockerfile is already allowlisted. Main must separately allowlist its
app/container_runtime.py and intended test source files once they exist. The
test target copies only app/ and tests/; repository tests that read root-level
Compose, Docker, or PowerShell fixtures still need main-owned fixture integration.
Compose must select the runtime target, enforce a read-only root filesystem, provide newly initialized Linux writable volumes and a temporary filesystem as needed, and preserve the unprivileged UID/GID. Runtime startup, PostgreSQL initialization, provider execution, and existing-data integration are explicitly outside dependency-build validation.
For a read-only test image, provide private temporary storage, for example
--tmpfs /tmp:rw,nosuid,nodev,noexec,size=64m,mode=0700,uid=10001,gid=10001 for
version/import checks. Main must choose temporary-storage size and execution
policy appropriate for its full tests. After the entrypoint, allowlist, fixtures,
and Compose changes are integrated, rebuild complete runtime and test images
and perform the separately authorized integration checks. No files outside the
Dockerfile and docker/ build inputs were edited, and nothing was staged,
committed, or pushed.