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>
106 lines
4.4 KiB
Markdown
106 lines
4.4 KiB
Markdown
# 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.md` changes in the same commit as the work)
|
|
* merge to `main` if 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 from `main` at
|
|
`6573b9d`, port 18099, local throwaway config); all six checks
|
|
passed, plus all nine tests in `scripts/manual-test.sh` (closes #49):
|
|
- [x] visit `/` and see the login form: HTTP 200, `Pixa - Login`
|
|
page with `name="key"` password form
|
|
- [x] wrong key shows an error: POST `/` with `key=wrong-key`
|
|
returned HTTP 200 login page containing "Invalid signing key"
|
|
- [x] correct signing key shows the generator form: POST `/`
|
|
returned HTTP 303 to `/` with
|
|
`Set-Cookie: pixa_session=...; HttpOnly; Secure; SameSite=Strict`;
|
|
GET `/` with that cookie rendered `Pixa - URL Generator` with the
|
|
`/generate` form and logout link
|
|
- [x] a generated encrypted URL serves the image: POST `/generate`
|
|
(ttl=3600) produced a `/v1/e/<token>/img.jpeg` URL that returned
|
|
HTTP 200, `Content-Type: image/jpeg`, an 800x600 baseline JPEG of
|
|
61706 bytes
|
|
- [x] 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,...}`
|
|
- [x] logout redirects back to login: GET `/logout` returned HTTP
|
|
303 to `/` with `Set-Cookie: pixa_session=; Max-Age=0`;
|
|
subsequent GET `/` rendered the login form again
|
|
- 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 check` green (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
|