The Docker runtime stage now copies config.docker.yml, which sets
only signing_key (from PIXA_SIGNING_KEY), state_dir, and port.
The public placeholder key and the baked-in five-host allowlist are
gone from the image; operators mount a file over /etc/pixa/config.yml for anything else.
Startup now refuses the exact config.example.yml placeholder with an
error naming signing_key (failing test committed first, then the
fix). The 45-character placeholder previously passed the 32-character
length check, letting a deployment sign URLs with a key that is public
in this repository.
README.md Getting Started documents the two container-config paths,
and the local-run example now copies the example file and sets a real signing_key, since the placeholder is refused.
Why
upaas configures apps with environment variables and mounts, injecting
no config file, so the key must come from the environment.
What a reader would trip over
validateSigningKey is extracted from validate(): the new
placeholder branch pushed validate() to cyclomatic complexity 16
(limit 15), so the signing-key checks moved into a helper.
The unset-variable abort message ("environment variable
PIXA_SIGNING_KEY not found") comes from smartconfig interpolation, not
from validate().
Disclosures
Judgement call: did not touch TODO.md; this issue is not the tracked
Next Step and the definition of done does not list it.
Deviation: five commits (failing test first per the repo TDD rule,
plus the rework commit) rather than one.
Pre-existing gomodguard deprecation warning in lint output; out of
scope, not acted on.
Model: opus-4-8
## What changed
- The Docker runtime stage now copies `config.docker.yml`, which sets
only `signing_key` (from `PIXA_SIGNING_KEY`), `state_dir`, and `port`.
The public placeholder key and the baked-in five-host allowlist are
gone from the image; operators mount a file over
`/etc/pixa/config.yml` for anything else.
- Startup now refuses the exact `config.example.yml` placeholder with an
error naming `signing_key` (failing test committed first, then the
fix). The 45-character placeholder previously passed the 32-character
length check, letting a deployment sign URLs with a key that is public
in this repository.
- `README.md` Getting Started documents the two container-config paths,
and the local-run example now copies the example file and sets a real
`signing_key`, since the placeholder is refused.
## Why
upaas configures apps with environment variables and mounts, injecting
no config file, so the key must come from the environment.
## What a reader would trip over
- `validateSigningKey` is extracted from `validate()`: the new
placeholder branch pushed `validate()` to cyclomatic complexity 16
(limit 15), so the signing-key checks moved into a helper.
- The unset-variable abort message ("environment variable
PIXA_SIGNING_KEY not found") comes from smartconfig interpolation, not
from `validate()`.
## Disclosures
- Judgement call: did not touch `TODO.md`; this issue is not the tracked
Next Step and the definition of done does not list it.
- Deviation: five commits (failing test first per the repo TDD rule,
plus the rework commit) rather than one.
- Pre-existing `gomodguard` deprecation warning in lint output; out of
scope, not acted on.
Model: opus-4-8
README.md, Getting Started — the local-run example ./bin/pixad --config config.example.yml. This change makes startup reject the placeholder signing_key in config.example.yml, so that exact documented command now aborts at startup instead of running (it previously ran). The Getting Started section was edited in this PR to add the container paragraph, but the line directly above it still tells a reader to run the example file unchanged, which the new code refuses. The README no longer describes what the binary does, and a newcomer following Getting Started hits an unexplained abort on the first run command. Acceptable: update the local-run example so it does not depend on the now-rejected placeholder — copy config.example.yml, set a real signing_key (or pass PIXA_SIGNING_KEY), then run — so the documented command matches the code.
PR body length — the description is about 264 words, over the roughly 250-word limit. Acceptable: trim to 250 words or fewer.
Model: opus-4-8
Findings (needs-rework):
1. `README.md`, Getting Started — the local-run example `./bin/pixad --config config.example.yml`. This change makes startup reject the placeholder `signing_key` in `config.example.yml`, so that exact documented command now aborts at startup instead of running (it previously ran). The Getting Started section was edited in this PR to add the container paragraph, but the line directly above it still tells a reader to run the example file unchanged, which the new code refuses. The README no longer describes what the binary does, and a newcomer following Getting Started hits an unexplained abort on the first run command. Acceptable: update the local-run example so it does not depend on the now-rejected placeholder — copy `config.example.yml`, set a real `signing_key` (or pass `PIXA_SIGNING_KEY`), then run — so the documented command matches the code.
2. PR body length — the description is about 264 words, over the roughly 250-word limit. Acceptable: trim to 250 words or fewer.
Model: opus-4-8
README.md Getting Started no longer runs config.example.yml unchanged: the local-run example copies it to config.yml and sets a real signing_key first, matching the new startup rejection. The two other mentions of the file only cite it as a key reference and remain accurate; the devserver target uses config.dev.yml, so no other stale run of the example existed.
PR body trimmed to 245 words.
Rebased onto current next and re-ran the local Docker builder gate before pushing.
Model: opus-4-8
Both findings addressed.
1. `README.md` Getting Started no longer runs `config.example.yml` unchanged: the local-run example copies it to `config.yml` and sets a real `signing_key` first, matching the new startup rejection. The two other mentions of the file only cite it as a key reference and remain accurate; the `devserver` target uses `config.dev.yml`, so no other stale run of the example existed.
2. PR body trimmed to 245 words.
Rebased onto current `next` and re-ran the local Docker builder gate before pushing.
Model: opus-4-8
README.md, Getting Started, the "build and run via Docker" block: the documented steps are make docker followed by docker run -p 8080:8080 -e PIXA_SIGNING_KEY="..." pixad:latest. make docker runs script/docker, which tags the image from script/projectname — that name is pixa, so the image built is pixa:latest. No Getting Started step creates pixad:latest (only make docker-versioned does), so a reader who follows these steps gets "no such image" from the docker run line. This PR edited that exact line to add the PIXA_SIGNING_KEY variable but left the image name that does not match what make docker builds. A newcomer following Getting Started hits a failure on the Docker run — the same class of broken Getting Started command the previous round was reworked to fix, in the same block. Acceptable: reference the image make docker actually builds (pixa:latest) in the run command, or change the build step to make docker-versioned (which tags pixad:latest), so the two lines agree and the documented command runs.
Model: opus-4-8
Findings (needs-rework):
1. `README.md`, Getting Started, the "build and run via Docker" block: the documented steps are `make docker` followed by `docker run -p 8080:8080 -e PIXA_SIGNING_KEY="..." pixad:latest`. `make docker` runs `script/docker`, which tags the image from `script/projectname` — that name is `pixa`, so the image built is `pixa:latest`. No Getting Started step creates `pixad:latest` (only `make docker-versioned` does), so a reader who follows these steps gets "no such image" from the `docker run` line. This PR edited that exact line to add the `PIXA_SIGNING_KEY` variable but left the image name that does not match what `make docker` builds. A newcomer following Getting Started hits a failure on the Docker run — the same class of broken Getting Started command the previous round was reworked to fix, in the same block. Acceptable: reference the image `make docker` actually builds (`pixa:latest`) in the run command, or change the build step to `make docker-versioned` (which tags `pixad:latest`), so the two lines agree and the documented command runs.
Model: opus-4-8
The placeholder is 45 characters, so it passes the length check and a
deployment could unknowingly sign URLs with a key that is public in
this repository. Add a failing validation case (and the placeholder
constant it references); the rejection follows.
Model: opus-4-8
Reject the exact config.example.yml placeholder in validate() with an
error naming signing_key, so a container or file-based deployment that
never changed it fails fast instead of signing URLs with a public key.
The signing-key checks move into a validateSigningKey helper, keeping
validate() within the cyclomatic-complexity limit.
Model: opus-4-8
The runtime stage now copies config.docker.yml, which sets only
signing_key (from PIXA_SIGNING_KEY), state_dir, and port. This drops
the public placeholder key and the baked-in allowlist from the image,
matching how upaas configures apps: environment variables and mounts,
no injected config file.
Model: opus-4-8
Getting Started now shows the docker run with PIXA_SIGNING_KEY and a
short paragraph: the key comes from that environment variable, and any
other setting is changed by mounting a file over /etc/pixa/config.yml.
Model: opus-4-8
The startup now rejects the config.example.yml placeholder signing_key,
so the documented `pixad --config config.example.yml` command aborts on
first run. Show copying the example to config.yml and setting a real
signing_key before running, matching the code.
Model: opus-4-8
make docker tags the image pixa:latest via script/projectname, so the
Getting Started run line must reference pixa:latest, not pixad:latest.
Model: opus-4-8
Fixed. The Getting Started Docker run line now names pixa:latest, the image make docker builds through script/projectname, so the build and run steps refer to the same image.
Checked the rest of the README's runnable commands (clone, build, the local run, and the Docker build and run) against the Makefile, the script/ entrypoints and the code; the others already match what they call. Ran the documented Docker build and run with a real signing key and confirmed the healthcheck responded, then removed the container and image.
Model: opus-4-8
Fixed. The Getting Started Docker run line now names `pixa:latest`, the image `make docker` builds through `script/projectname`, so the build and run steps refer to the same image.
Checked the rest of the README's runnable commands (clone, build, the local run, and the Docker build and run) against the Makefile, the `script/` entrypoints and the code; the others already match what they call. Ran the documented Docker build and run with a real signing key and confirmed the healthcheck responded, then removed the container and image.
Model: opus-4-8
Verified against #110: the definition of done is met — the image ships config.docker.yml reading signing_key from PIXA_SIGNING_KEY with no allowlist and no placeholder secret, a container without PIXA_SIGNING_KEY exits non-zero naming it while a real key serves /.well-known/healthcheck.json, the unchanged config.example.yml mounted over the config path is refused naming signing_key (failing test committed before the fix), README.md Getting Started's build, local-run and Docker commands run as written, only the runtime stage of the Dockerfile changed, and the local Docker gate is green.
Model: opus-4-8
Verified against https://git.eeqj.de/sneak/pixa/issues/110: the definition of done is met — the image ships `config.docker.yml` reading `signing_key` from `PIXA_SIGNING_KEY` with no allowlist and no placeholder secret, a container without `PIXA_SIGNING_KEY` exits non-zero naming it while a real key serves `/.well-known/healthcheck.json`, the unchanged `config.example.yml` mounted over the config path is refused naming `signing_key` (failing test committed before the fix), `README.md` Getting Started's build, local-run and Docker commands run as written, only the runtime stage of the `Dockerfile` changed, and the local Docker gate is green.
Model: opus-4-8
clawbot
merged commit 1798cba96c into next2026-09-21 21:59:25 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What changed
config.docker.yml, which setsonly
signing_key(fromPIXA_SIGNING_KEY),state_dir, andport.The public placeholder key and the baked-in five-host allowlist are
gone from the image; operators mount a file over
/etc/pixa/config.ymlfor anything else.config.example.ymlplaceholder with anerror naming
signing_key(failing test committed first, then thefix). The 45-character placeholder previously passed the 32-character
length check, letting a deployment sign URLs with a key that is public
in this repository.
README.mdGetting Started documents the two container-config paths,and the local-run example now copies the example file and sets a real
signing_key, since the placeholder is refused.Why
upaas configures apps with environment variables and mounts, injecting
no config file, so the key must come from the environment.
What a reader would trip over
validateSigningKeyis extracted fromvalidate(): the newplaceholder branch pushed
validate()to cyclomatic complexity 16(limit 15), so the signing-key checks moved into a helper.
PIXA_SIGNING_KEY not found") comes from smartconfig interpolation, not
from
validate().Disclosures
TODO.md; this issue is not the trackedNext Step and the definition of done does not list it.
plus the rework commit) rather than one.
gomodguarddeprecation warning in lint output; out ofscope, not acted on.
Model: opus-4-8
Findings (needs-rework):
README.md, Getting Started — the local-run example./bin/pixad --config config.example.yml. This change makes startup reject the placeholdersigning_keyinconfig.example.yml, so that exact documented command now aborts at startup instead of running (it previously ran). The Getting Started section was edited in this PR to add the container paragraph, but the line directly above it still tells a reader to run the example file unchanged, which the new code refuses. The README no longer describes what the binary does, and a newcomer following Getting Started hits an unexplained abort on the first run command. Acceptable: update the local-run example so it does not depend on the now-rejected placeholder — copyconfig.example.yml, set a realsigning_key(or passPIXA_SIGNING_KEY), then run — so the documented command matches the code.PR body length — the description is about 264 words, over the roughly 250-word limit. Acceptable: trim to 250 words or fewer.
Model: opus-4-8
e1044e9037to11c8a96766Both findings addressed.
README.mdGetting Started no longer runsconfig.example.ymlunchanged: the local-run example copies it toconfig.ymland sets a realsigning_keyfirst, matching the new startup rejection. The two other mentions of the file only cite it as a key reference and remain accurate; thedevservertarget usesconfig.dev.yml, so no other stale run of the example existed.Rebased onto current
nextand re-ran the local Docker builder gate before pushing.Model: opus-4-8
Findings (needs-rework):
README.md, Getting Started, the "build and run via Docker" block: the documented steps aremake dockerfollowed bydocker run -p 8080:8080 -e PIXA_SIGNING_KEY="..." pixad:latest.make dockerrunsscript/docker, which tags the image fromscript/projectname— that name ispixa, so the image built ispixa:latest. No Getting Started step createspixad:latest(onlymake docker-versioneddoes), so a reader who follows these steps gets "no such image" from thedocker runline. This PR edited that exact line to add thePIXA_SIGNING_KEYvariable but left the image name that does not match whatmake dockerbuilds. A newcomer following Getting Started hits a failure on the Docker run — the same class of broken Getting Started command the previous round was reworked to fix, in the same block. Acceptable: reference the imagemake dockeractually builds (pixa:latest) in the run command, or change the build step tomake docker-versioned(which tagspixad:latest), so the two lines agree and the documented command runs.Model: opus-4-8
11c8a96766toc9aa48227dFixed. The Getting Started Docker run line now names
pixa:latest, the imagemake dockerbuilds throughscript/projectname, so the build and run steps refer to the same image.Checked the rest of the README's runnable commands (clone, build, the local run, and the Docker build and run) against the Makefile, the
script/entrypoints and the code; the others already match what they call. Ran the documented Docker build and run with a real signing key and confirmed the healthcheck responded, then removed the container and image.Model: opus-4-8
Verified against #110: the definition of done is met — the image ships
config.docker.ymlreadingsigning_keyfromPIXA_SIGNING_KEYwith no allowlist and no placeholder secret, a container withoutPIXA_SIGNING_KEYexits non-zero naming it while a real key serves/.well-known/healthcheck.json, the unchangedconfig.example.ymlmounted over the config path is refused namingsigning_key(failing test committed before the fix),README.mdGetting Started's build, local-run and Docker commands run as written, only the runtime stage of theDockerfilechanged, and the local Docker gate is green.Model: opus-4-8