But both URL schemes expire. A signed URL carries exp, and pixa returns 410/401 once it passes; an encrypted URL carries a TTL (the manual test pass recorded in TODO.md confirms a ttl=1 URL returns 410 Gone after 3 s).
So for any URL with a TTL shorter than a year — i.e. all of them — we instruct every intermediary cache and browser to keep serving the content for a year after we would refuse to serve it ourselves. Expiration becomes advisory the moment a CDN or corporate proxy is in front of pixa, which defeats the stated purpose of putting expiry in the signature ("to prevent replay attacks", README.md:69-70).
immutable compounds it: conforming clients will not revalidate even on a forced reload.
Definition of done
max-age is clamped to the remaining lifetime of the URL (exp - now for signed URLs, remaining TTL for encrypted URLs), never exceeding it.
Decide and document whether immutable is still appropriate; it is defensible for content-addressed variants within the URL's own lifetime, but state the reasoning in the PR.
A URL with no expiry (allowlisted host, unsigned) may keep the long max-age — confirm that path still does.
Failing tests first: a request through a signed URL expiring in 60 s must not emit a max-age greater than 60; same for a short-TTL encrypted URL.
make check green.
Verified against `main` at `61f42e6`.
Both image paths set a one-year immutable cache header unconditionally:
- `internal/handlers/image.go:126`
- `internal/handlers/imageenc.go:76`
```go
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
```
But both URL schemes expire. A signed URL carries `exp`, and pixa returns 410/401 once it passes; an encrypted URL carries a TTL (the manual test pass recorded in `TODO.md` confirms a `ttl=1` URL returns 410 Gone after 3 s).
So for any URL with a TTL shorter than a year — i.e. all of them — we instruct every intermediary cache and browser to keep serving the content for a year after we would refuse to serve it ourselves. Expiration becomes advisory the moment a CDN or corporate proxy is in front of pixa, which defeats the stated purpose of putting expiry in the signature ("to prevent replay attacks", `README.md:69-70`).
`immutable` compounds it: conforming clients will not revalidate even on a forced reload.
## Definition of done
1. `max-age` is clamped to the remaining lifetime of the URL (`exp - now` for signed URLs, remaining TTL for encrypted URLs), never exceeding it.
2. Decide and document whether `immutable` is still appropriate; it is defensible for content-addressed variants within the URL's own lifetime, but state the reasoning in the PR.
3. A URL with no expiry (allowlisted host, unsigned) may keep the long max-age — confirm that path still does.
4. Failing tests first: a request through a signed URL expiring in 60 s must not emit a `max-age` greater than 60; same for a short-TTL encrypted URL.
5. `make check` green.
clawbot
added this to the 1.0.0 milestone 2026-08-09 03:43:32 +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.
Verified against
mainat61f42e6.Both image paths set a one-year immutable cache header unconditionally:
internal/handlers/image.go:126internal/handlers/imageenc.go:76But both URL schemes expire. A signed URL carries
exp, and pixa returns 410/401 once it passes; an encrypted URL carries a TTL (the manual test pass recorded inTODO.mdconfirms attl=1URL returns 410 Gone after 3 s).So for any URL with a TTL shorter than a year — i.e. all of them — we instruct every intermediary cache and browser to keep serving the content for a year after we would refuse to serve it ourselves. Expiration becomes advisory the moment a CDN or corporate proxy is in front of pixa, which defeats the stated purpose of putting expiry in the signature ("to prevent replay attacks",
README.md:69-70).immutablecompounds it: conforming clients will not revalidate even on a forced reload.Definition of done
max-ageis clamped to the remaining lifetime of the URL (exp - nowfor signed URLs, remaining TTL for encrypted URLs), never exceeding it.immutableis still appropriate; it is defensible for content-addressed variants within the URL's own lifetime, but state the reasoning in the PR.max-agegreater than 60; same for a short-TTL encrypted URL.make checkgreen.