Commit Graph
13 Commits
Author SHA1 Message Date
clawbot aaf1bbbd4e Add the four settings the README documented but pixa lacked (closes #61)
access_control_allow_origin, upstream_fetch_timeout,
upstream_max_response_size and downstream_timeout were in the README
but unknown to pixa, so a config that followed it aborted startup. Each
is now a setting with its PIXA_ variable, defaulting to the value that
was fixed in the code: *, 30s, 50 MiB and 60s. Durations are positive Go
duration strings; the size is a positive whole number of bytes; the
origin is * or one scheme and host. An invalid value aborts startup
naming the key and value. downstream_timeout replaces HTTPWriteTimeout
for the server's write timeout and the per-request timeout.

Model: opus-5-5
2026-09-29 06:11:44 +00:00
clawbot 52b64c9197 Test four README settings pixa does not have yet (closes #61)
Failing tests for access_control_allow_origin, upstream_fetch_timeout,
upstream_max_response_size and downstream_timeout: their defaults,
valid values from the file and the environment, invalid values aborting
startup naming the key or variable and the value, the CORS middleware
answering with the configured origin, and the server's write timeout
coming from downstream_timeout. They do not compile until the settings
exist.

Model: opus-5-5
2026-09-29 06:11:06 +00:00
clawbot e410146fb6 Rate limit login attempts per client address (closes #66)
check / check (push) Successful in 12s
POST / had no limit, so the signing key could be guessed at no cost. It
is now limited to 5 attempts per minute per client by a new RateLimit
middleware on github.com/go-chi/httprate; an attempt over the limit gets
429 with Retry-After. It counts by the address the ClientIP middleware
resolved through trusted_proxies (an IPv4-mapped address as its IPv4
address, IPv6 by its /64) and runs after the body-size and CSRF checks,
so every attempt that reaches the key comparison is counted. README says
that with the default trusted_proxies a client with a private address
can choose its counted address, and how to close that.

Model: opus-5-5
2026-09-29 01:03:37 +02:00
clawbot 10eab440e7 Resolve real client IP behind trusted proxies (closes #94)
check / check (push) Successful in 2m31s
RFC1918 ranges are the default trusted proxy set on an omitted key; an explicit list replaces the default; an explicit empty list trusts no one; unparseable values abort startup; forwarded headers honored only from trusted peers. Independent review passed: #127 (comment)

model: claude-opus-4-8 (implementation and review); merged by claude-fable-5
2026-09-22 10:25:41 +02:00
clawbot b4e5300feb feat: add HSTS, CSP, and Permissions-Policy security headers (closes #91)
check / check (push) Failing after 0s
SecurityHeaders() now also sets Strict-Transport-Security (one year, includeSubDomains), a Content-Security-Policy (default-src self, frame-ancestors none) and a Permissions-Policy denying the browser features pixa does not use. X-Frame-Options stays as the legacy fallback.

What a reader would trip over: HSTS is sent on every response even though pixa listens on plain HTTP behind a TLS-terminating proxy; browsers ignore the header over plaintext, and this avoids trusting a forwarded-proto header. The clipboard feature is left unlisted so the copy button on the generator page keeps working.

Disclosure: script-src and style-src carry unsafe-inline because the generator template has inline onclick handlers and the bundled Tailwind script injects a style element at runtime; removing it needs template changes and is tracked separately.

Model: opus-4-8 (implementation, review); fable-5-1 (landing message)
2026-09-21 20:43:13 +02:00
clawbot 04b5db6fbf next -> main (1.0.0 milestone) (#105)
check / check (push) Successful in 5s
Accumulating milestone branch. One squashed commit per closed issue; `next` is kept green and mergeable to `main` at any time without notice.

Landed so far:

- `chore: update golangci-lint to v2.12.2 with canonical config` (#54) — canonical v2-schema `.golangci.yml`, pins bumped in `Dockerfile` and `script/bootstrap`, tree at `0 issues.`. Three behaviour deltas are recorded in that PR's body: `Cache.StoreVariant` takes a context, `MetadataStorage.Store` no longer leaks temp files on failure, and the `signing_key` too-short error text gained a `value too short:` prefix.

Sequencing for the milestone is tracked in #103.

Reviewed-on: #105
Co-authored-by: clawbot <clawbot@noreply.example.org>
2026-09-21 09:31:54 +02:00
sneak 9bfae69ccf Fix logging: add response_bytes to middleware, cache_key to handler
- Middleware now tracks and logs bytes written via response_bytes
- Handler logs cache_key for cache hit debugging
- Changed "served encrypted image" to "image served" (only URL is encrypted)
2026-01-08 13:05:10 -08:00
sneak 2e349a8b83 Implement security headers middleware
Adds X-Content-Type-Options, X-Frame-Options, Referrer-Policy,
and X-XSS-Protection headers to all responses.
2026-01-08 10:02:17 -08:00
sneak 5de7a26735 Add failing tests for security headers middleware
Tests for X-Content-Type-Options, X-Frame-Options, Referrer-Policy,
X-XSS-Protection headers on responses.
2026-01-08 10:01:36 -08:00
sneak 29adb6ee47 Rename unused parameters to _ to satisfy linter 2026-01-08 02:27:45 -08:00
sneak 3f6328766c Rename MiddlewareParams to Params to avoid stuttering 2026-01-08 02:25:42 -08:00
sneak 115f92660d Define CORSMaxAgeSeconds constant 2026-01-08 02:21:30 -08:00
sneak 516853626d Add basic webserver skeleton with healthcheck 2026-01-08 02:20:23 -08:00