The toolchain requirement
Two constraints, neither of them chosen:
Building without the experiment fails with a long import chain ending in:
scripts/ci/check-toolchain.sh verifies it and prints the fix.
Set it once per machine and bare go build works too:
encoding/json/v2 failure fires
first and the friendly message is never reached.
The three binaries
cmd/api can run the worker in-process, which is the default. A single api
binary with a PostgreSQL and a Redis is a complete TRUSTIVAN. cmd/worker exists
so that the durability claim is testable rather than aspirational: a worker that
can only run inside the API process cannot be restarted independently of it.
Building
Running
You still need PostgreSQL and Redis. The simplest arrangement is to run those two from Compose and the Go processes on the host:SCAN_WORKER_ENABLED=false for the API and start the worker separately:
Building an image
The Dockerfile atbackend/Dockerfile builds both the API and the worker into
one image and selects between them by command. Two details are worth knowing if
you adapt it:
- The final stage runs as an unprivileged
trustowluser. The image previously ran as root withWORKDIR /root/, which gave a process handling untrusted customer input full privileges inside the container. /cacheis created and owned by that user, because a worker that cannot write its cache re-downloads the vulnerability database on every scan.
Verifying the build
make ci-guards runs the same architecture guards CI runs, including the
toolchain preflight that produces the readable version of the
encoding/json/v2 error.
The end-to-end scan is separate because it pulls roughly 100 MB from a real
registry:
Next
- Database migrations — what runs at startup, and how to run it by hand.
- Configuration overview — how settings are resolved and validated.

