All checks were successful
check / check (push) Successful in 4s
closes #49 Records the P0 manual test pass in `TODO.md` per its Workflow section (checked-off results into Completed Steps; cache size management and eviction promoted to Next Step). `TODO.md` is the only changed file — no production code changes, as the issue requires. ## Test setup `pixad` built from `main` at `6573b9d` via `make build`, run on port 18099 with a throwaway local config (temp state dir, known `signing_key`, `allowlist_hosts` including `s3.sneak.cloud`), driven with curl using explicit cookie replay (session cookies are `Secure`/`HttpOnly`/`SameSite=Strict`). ## Results — all six checks PASS 1. **Login form**: GET `/` → HTTP 200, `Pixa - Login` page with `name="key"` password form. 2. **Wrong key error**: POST `/` with `key=wrong-key` → HTTP 200 login page containing "Invalid signing key". 3. **Generator form**: POST `/` with the correct signing key → HTTP 303 to `/` with `Set-Cookie: pixa_session=...; HttpOnly; Secure; SameSite=Strict`; GET `/` with that cookie → `Pixa - URL Generator` with the `/generate` form and logout link. 4. **Encrypted URL serves image**: POST `/generate` (ttl=3600) produced a `/v1/e/<token>/img.jpeg` URL → HTTP 200, `Content-Type: image/jpeg`, 800x600 baseline JPEG, 61706 bytes. 5. **Expired URL → 410**: a ttl=1 URL fetched after 3 s → HTTP 410 Gone with `{"error":"URL has expired","status":410,...}`. 6. **Logout**: GET `/logout` → HTTP 303 to `/` with `Set-Cookie: pixa_session=; Max-Age=0`; subsequent GET `/` → login form again. Additionally, all nine checks in `scripts/manual-test.sh` passed against the same server instance. ## Verification `make check` green on the branch head (all tests, golangci-lint 0 issues, fmt-check clean) — the first fully green `make check` on a `main`-derived branch under the current linter, confirming the #47/#48 fix on merged `main`. Note for review: the test execution was performed this session; the adversarial re-review (independently re-running the six flows) is still pending and should happen before merge. Co-authored-by: sneak <sneak@sneak.berlin> Reviewed-on: #50 Co-authored-by: clawbot <clawbot@noreply.example.org> Co-committed-by: clawbot <clawbot@noreply.example.org>
4.4 KiB
4.4 KiB
Workflow
- branch (from
main) - do the work in Next Step
- move Next Step to the top of Completed Steps
- move the top item of Future Steps into Next Step
- commit (
TODO.mdchanges in the same commit as the work) - merge to
mainif the branch is not protected, otherwise open a PR - push
Status
pre-1.0. No git tags exist. Recent work extracted the internal/magic,
internal/allowlist, internal/httpfetcher, and internal/signature
packages. The gosec findings from the 2026-07-06 survey are resolved:
the last two open findings (G124, session cookie attributes in
internal/session) are fixed as of this change, so make check is green
on main.
Next Step
P0: implement cache size management and eviction so the disk cannot fill up
Completed Steps
- 2026-08-07 manual test pass of the auth and encrypted URL flows
against a locally built and running
pixad(built frommainat6573b9d, port 18099, local throwaway config); all six checks passed, plus all nine tests inscripts/manual-test.sh(closes #49):- visit
/and see the login form: HTTP 200,Pixa - Loginpage withname="key"password form - wrong key shows an error: POST
/withkey=wrong-keyreturned HTTP 200 login page containing "Invalid signing key" - correct signing key shows the generator form: POST
/returned HTTP 303 to/withSet-Cookie: pixa_session=...; HttpOnly; Secure; SameSite=Strict; GET/with that cookie renderedPixa - URL Generatorwith the/generateform and logout link - a generated encrypted URL serves the image: POST
/generate(ttl=3600) produced a/v1/e/<token>/img.jpegURL that returned HTTP 200,Content-Type: image/jpeg, an 800x600 baseline JPEG of 61706 bytes - an expired URL (short TTL) returns 410: a ttl=1 URL fetched
after 3 s returned HTTP 410 Gone with
{"error":"URL has expired","status":410,...} - logout redirects back to login: GET
/logoutreturned HTTP 303 to/withSet-Cookie: pixa_session=; Max-Age=0; subsequent GET/rendered the login form again
- visit
- 2026-08-07 fix the two remaining gosec findings (G124 in
internal/session): session cookies now always carry
Secure/HttpOnly/SameSite=Strict on both the set and clear paths;
make checkgreen (closes #47) - 2026-07-07 Adopted scripts-to-rule-them-all:
script/entrypoints, Makefile shims, README Entrypoints section - 2026-04-07 extract magic byte detection into internal/magic (#42)
- 2026-03-25 extract allowlist package from internal/imgcache (#41)
- 2026-03-25 move schema_migrations table creation into 000.sql (#36)
- 2026-03-20 enforce and document exact-match-only signature verification (#40)
- 2026-03-20 bound imageprocessor.Process input read to prevent unbounded memory use (#37); consolidate appname into an internal/globals constant (#34)
- 2026-03-18 parse version prefix from migration filenames (#33)
- 2026-03-15 QA audit fixes for 1.0/MVP readiness (#25)
- 2026-03-02 split Dockerfile with pre-built golangci-lint stage for faster CI (#23)
- 2026-02-25 repo policy compliance: CI workflow, hash-pinned images, golangci-lint and gosec fixes of that date (#14); arm64 Docker build fix (#16)
- 2026-01-08 WebP and AVIF encoding support via govips (both former P0 image processing items, now done)
Future Steps
- P0: validate configuration on startup, fail fast on bad config
- P1: implement blocked networks configuration to extend SSRF protection
- P1: rate limit global concurrent upstream fetches to prevent resource exhaustion
- P1: strip EXIF and other metadata from processed images (privacy)
- P2: security
- referer blacklist
- per-IP rate limiting
- per-origin rate limiting
- P2: HTTP response handling
- Last-Modified headers
- Vary header for content negotiation
- X-Request-ID propagation
- P2: auto format selection (format=auto based on Accept header)
- P2: configuration
- add all configuration options from README
- environment variable overrides
- YAML config file support
- P2: operational
- optional Sentry error reporting
- comprehensive request logging
- Prometheus performance metrics
- integration tests for the image proxy flow
- load tests to verify the 1k to 5k req/s target
- P2: documentation
- configuration options
- API endpoints
- deployment guide
- example nginx or caddy reverse proxy config