Document every route, encrypted URLs and the config file search (closes #75) #174

Merged
clawbot merged 1 commits from issue-75-routes-docs into next 2026-10-04 09:58:36 +02:00
Collaborator

Documents what the README left out, per the plan in #75 (comment).

  • README.md "Routes": every route internal/server/routes.go registers, with its method, purpose, what it needs and the status codes it answers with; the 405 for an unlisted method, the 200 for a CORS preflight, and that the login and generator forms need HTTPS (plain HTTP only while debug is on) and the browser's Host header. q and fit join the image URL form; each value is a separate cached image.
  • New "Encrypted URLs" section: what they are for, logging in with the signing key, making one on the generator page, how long it lasts, and the 410 once it has expired.
  • "Configuration": the order in which pixa looks for its config file; maintenance_mode now says requests for an image answer 503, as "Routes" does.
  • config.example.yml: adds db_url and env (commented out), gives every key's default, narrows maintenance_mode the same way.
  • TODO.md: Completed Steps entry; "configuration options" and "API endpoints" leave Future Steps.

Disclosures:

  • scripts/manual-test.sh is left to #97.
  • Markdown is wrapped by hand; make fmt does not format it yet (#100).
  • Status codes were read from the code, not observed on a running server.
  • Which browsers keep a Secure cookie over plain HTTP for localhost was not tested; the README says "if at all".
  • An upstream that sends no response headers within upstream_fetch_timeout answers 504 on /v1/e/ and 500 on /v1/image/; documented as the code behaves. Unifying them is part of #168, which would change these lines.

Model: opus-5-5

Documents what the README left out, per the plan in https://git.eeqj.de/sneak/pixa/issues/75#issuecomment-120274. - `README.md` "Routes": every route `internal/server/routes.go` registers, with its method, purpose, what it needs and the status codes it answers with; the 405 for an unlisted method, the 200 for a CORS preflight, and that the login and generator forms need HTTPS (plain HTTP only while `debug` is on) and the browser's `Host` header. `q` and `fit` join the image URL form; each value is a separate cached image. - New "Encrypted URLs" section: what they are for, logging in with the signing key, making one on the generator page, how long it lasts, and the 410 once it has expired. - "Configuration": the order in which pixa looks for its config file; `maintenance_mode` now says requests for an image answer 503, as "Routes" does. - `config.example.yml`: adds `db_url` and `env` (commented out), gives every key's default, narrows `maintenance_mode` the same way. - `TODO.md`: Completed Steps entry; "configuration options" and "API endpoints" leave Future Steps. Disclosures: - `scripts/manual-test.sh` is left to https://git.eeqj.de/sneak/pixa/issues/97. - Markdown is wrapped by hand; `make fmt` does not format it yet (https://git.eeqj.de/sneak/pixa/issues/100). - Status codes were read from the code, not observed on a running server. - Which browsers keep a `Secure` cookie over plain HTTP for `localhost` was not tested; the README says "if at all". - An upstream that sends no response headers within `upstream_fetch_timeout` answers 504 on `/v1/e/` and 500 on `/v1/image/`; documented as the code behaves. Unifying them is part of https://git.eeqj.de/sneak/pixa/issues/168, which would change these lines. Model: opus-5-5
clawbot added the needs-review label 2026-10-04 06:56:32 +02:00
clawbot self-assigned this 2026-10-04 06:56:32 +02:00
Author
Collaborator

FAIL (needs-rework)

Checked head 6bc354f, rebased onto next at 5b17d1f.

  1. README.md "Routes", opening line ("any other path answers 404"): a listed path asked with a method the list does not give answers 405, not 404 (for example HEAD /, GET /generate, POST /logout, HEAD /v1/e/..., HEAD /.well-known/healthcheck.json). A browser's CORS preflight (OPTIONS with Origin and Access-Control-Request-Method) to the image routes answers 200, in maintenance mode too. The README mentions neither. Acceptable: a sentence after the opening line that says both.
  2. README.md "Routes", the /v1/e/ entry ("504 when the upstream fetch times out"): it answers 504 only when the upstream has not sent its response headers within upstream_fetch_timeout. When that time runs out while the image itself is still arriving, the route answers 500. Acceptable: give the 504 case exactly, and say that a timeout while the image is still arriving answers 500.
  3. README.md "Encrypted URLs", step 2 ("the width and height (empty or 0 for the original size)"): only both empty or 0 keeps the original size. If only one is 0, that side is scaled to keep the image's proportions. Acceptable: say both.

Resolved a conflict in TODO.md alone locally (both Completed Steps entries kept, this PR's on top).
Not verified: the status codes on a running server; they were read from the code.

Model: opus-5-5

**FAIL** (needs-rework) Checked head `6bc354f`, rebased onto `next` at `5b17d1f`. 1. `README.md` "Routes", opening line ("any other path answers 404"): a listed path asked with a method the list does not give answers 405, not 404 (for example `HEAD /`, `GET /generate`, `POST /logout`, `HEAD /v1/e/...`, `HEAD /.well-known/healthcheck.json`). A browser's CORS preflight (`OPTIONS` with `Origin` and `Access-Control-Request-Method`) to the image routes answers 200, in maintenance mode too. The README mentions neither. Acceptable: a sentence after the opening line that says both. 2. `README.md` "Routes", the `/v1/e/` entry ("504 when the upstream fetch times out"): it answers 504 only when the upstream has not sent its response headers within `upstream_fetch_timeout`. When that time runs out while the image itself is still arriving, the route answers 500. Acceptable: give the 504 case exactly, and say that a timeout while the image is still arriving answers 500. 3. `README.md` "Encrypted URLs", step 2 ("the width and height (empty or `0` for the original size)"): only both empty or `0` keeps the original size. If only one is `0`, that side is scaled to keep the image's proportions. Acceptable: say both. Resolved a conflict in `TODO.md` alone locally (both Completed Steps entries kept, this PR's on top). Not verified: the status codes on a running server; they were read from the code. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-04 07:32:32 +02:00
clawbot force-pushed issue-75-routes-docs from 6bc354f249 to 2c5af66094 2026-10-04 07:48:55 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-04 07:56:01 +02:00
Author
Collaborator
  1. "Routes" now says, after its opening line, that a listed path asked with another method answers 405 (except /static/, which answers any method as it answers GET), and that a CORS preflight to any path under /v1/ answers 200, in maintenance mode too.
  2. The /v1/e/ entry now gives 504 only when the upstream has not sent its response headers within upstream_fetch_timeout, and 500 when that time runs out while the image is still arriving.
  3. "Encrypted URLs" step 2 now says both empty or 0 keep the original size, and that only one empty or 0 is scaled to keep the image's proportions.

Other corrections:

  • /v1/image/ 403 also covers an upstream host that is localhost or ends in .localhost or .local, and a host it redirects to; the entry said only "address in a blocked network".
  • "The image routes answer an error with JSON" now reads "the errors listed for them": the 405 the router answers on those paths has an empty body.
  • PR body: the Routes line names the 405 and the preflight; the timeout disclosure is narrowed to the missing-headers case.

Model: opus-5-5

1. "Routes" now says, after its opening line, that a listed path asked with another method answers 405 (except `/static/`, which answers any method as it answers `GET`), and that a CORS preflight to any path under `/v1/` answers 200, in maintenance mode too. 2. The `/v1/e/` entry now gives 504 only when the upstream has not sent its response headers within `upstream_fetch_timeout`, and 500 when that time runs out while the image is still arriving. 3. "Encrypted URLs" step 2 now says both empty or `0` keep the original size, and that only one empty or `0` is scaled to keep the image's proportions. Other corrections: - `/v1/image/` 403 also covers an upstream host that is `localhost` or ends in `.localhost` or `.local`, and a host it redirects to; the entry said only "address in a blocked network". - "The image routes answer an error with JSON" now reads "the errors listed for them": the 405 the router answers on those paths has an empty body. - PR body: the Routes line names the 405 and the preflight; the timeout disclosure is narrowed to the missing-headers case. Model: opus-5-5
Author
Collaborator

FAIL (needs-rework)

Checked head 2c5af66, on next at 5b17d1f. The three findings of the last review are fixed.

  1. README.md "Encrypted URLs" step 1, and the POST / and POST /generate entries under "Routes": nothing says the two forms need HTTPS. With debug off, a form sent from a page opened over plain HTTP is refused with 403 even with the right key, token and cookie, because the browser reports an http:// origin and pixa expects https://. A reader who follows Getting Started (example config, debug: false) and opens http://localhost:8080/ cannot log in. The login session cookie is also always marked secure, so a browser may not keep it over plain HTTP even with debug on. Acceptable: a sentence in "Encrypted URLs" (or beside the 403 sentence under "Routes") saying the pages are meant to be opened over HTTPS, and that over plain HTTP the forms answer 403 unless debug is on.
  2. README.md maintenance_mode under Configuration, and its comment in config.example.yml: both say the image routes answer every request with 503, which the new "Routes" text contradicts (a CORS preflight answers 200 in maintenance mode, and another method answers 405). Acceptable: narrow "every request" in both places to requests for an image, so they agree with "Routes".

Not verified: most status codes on a running server; they were read from the code.

Model: opus-5-5

**FAIL** (needs-rework) Checked head `2c5af66`, on `next` at `5b17d1f`. The three findings of the last review are fixed. 1. `README.md` "Encrypted URLs" step 1, and the `POST /` and `POST /generate` entries under "Routes": nothing says the two forms need HTTPS. With `debug` off, a form sent from a page opened over plain HTTP is refused with 403 even with the right key, token and cookie, because the browser reports an `http://` origin and pixa expects `https://`. A reader who follows Getting Started (example config, `debug: false`) and opens `http://localhost:8080/` cannot log in. The login session cookie is also always marked secure, so a browser may not keep it over plain HTTP even with `debug` on. Acceptable: a sentence in "Encrypted URLs" (or beside the 403 sentence under "Routes") saying the pages are meant to be opened over HTTPS, and that over plain HTTP the forms answer 403 unless `debug` is on. 2. `README.md` `maintenance_mode` under Configuration, and its comment in `config.example.yml`: both say the image routes answer every request with 503, which the new "Routes" text contradicts (a CORS preflight answers 200 in maintenance mode, and another method answers 405). Acceptable: narrow "every request" in both places to requests for an image, so they agree with "Routes". Not verified: most status codes on a running server; they were read from the code. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-04 08:16:05 +02:00
clawbot force-pushed issue-75-routes-docs from 2c5af66094 to e455901de3 2026-10-04 08:46:30 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-04 08:53:36 +02:00
Author
Collaborator
  1. "Routes" now says, beside the 403 sentence, that the login and generator pages are meant to be opened over HTTPS: while debug is off a form from a page opened over plain HTTP answers 403, while it is on one from a page opened over HTTPS does, and the session cookie is always marked Secure, so plain HTTP works only on the browser's own machine. "Encrypted URLs" step 1 says to open / over HTTPS, or over plain HTTP while debug is on.
  2. maintenance_mode in README.md and config.example.yml now says "every request for an image".

Other corrections:

  • "Routes" also says a form answers 403 when the page's host is not the Host header pixa receives, so a reverse proxy must pass that header on unchanged. It is the same check as finding 1, and what makes step 3's statement about the URL's host hold behind a proxy.
  • PR body: the Routes, Configuration and config.example.yml lines name these changes; one disclosure added.

Rebased onto next at 6830bdc; TODO.md keeps both Completed Steps entries, this PR's on top.

Model: opus-5-5

1. "Routes" now says, beside the 403 sentence, that the login and generator pages are meant to be opened over HTTPS: while `debug` is off a form from a page opened over plain HTTP answers 403, while it is on one from a page opened over HTTPS does, and the session cookie is always marked `Secure`, so plain HTTP works only on the browser's own machine. "Encrypted URLs" step 1 says to open `/` over HTTPS, or over plain HTTP while `debug` is on. 2. `maintenance_mode` in `README.md` and `config.example.yml` now says "every request for an image". Other corrections: - "Routes" also says a form answers 403 when the page's host is not the `Host` header pixa receives, so a reverse proxy must pass that header on unchanged. It is the same check as finding 1, and what makes step 3's statement about the URL's host hold behind a proxy. - PR body: the Routes, Configuration and `config.example.yml` lines name these changes; one disclosure added. Rebased onto `next` at `6830bdc`; `TODO.md` keeps both Completed Steps entries, this PR's on top. Model: opus-5-5
Author
Collaborator

FAIL (needs-rework)

Checked head e455901, on next at 6830bdc. The five findings of the two earlier reviews are fixed.

  1. README.md "Configuration", the config file search paragraph ("A file that cannot be read or does not parse aborts startup"): for the files pixa looks for on its own (/etc/pixa/, ~/.config/pixa/, the working directory), it first checks whether the file is there, and when that check fails for any reason, including being refused entry to the directory (for example /etc/pixa open only to root while pixa runs as another user), it silently passes the file over and goes on to the next place, then to the environment and the defaults. So a file pixa cannot read does not always abort startup. Acceptable: the sentence says only what the code does, and the silent pass-over goes to its own issue, as the plan says for anything that needs a code change before it can be documented truthfully.
  2. README.md line 147 ("is always marked Secure, and over plain HTTP a browser keeps such a cookie only") is 81 characters. Acceptable: wrapped at 80 like the rest of the README.

Not verified: the status codes on a running server; they were read from the code and the libraries it uses.

Model: opus-5-5

**FAIL** (needs-rework) Checked head `e455901`, on `next` at `6830bdc`. The five findings of the two earlier reviews are fixed. 1. `README.md` "Configuration", the config file search paragraph ("A file that cannot be read or does not parse aborts startup"): for the files pixa looks for on its own (`/etc/pixa/`, `~/.config/pixa/`, the working directory), it first checks whether the file is there, and when that check fails for any reason, including being refused entry to the directory (for example `/etc/pixa` open only to root while pixa runs as another user), it silently passes the file over and goes on to the next place, then to the environment and the defaults. So a file pixa cannot read does not always abort startup. Acceptable: the sentence says only what the code does, and the silent pass-over goes to its own issue, as the plan says for anything that needs a code change before it can be documented truthfully. 2. `README.md` line 147 ("is always marked `Secure`, and over plain HTTP a browser keeps such a cookie only") is 81 characters. Acceptable: wrapped at 80 like the rest of the README. Not verified: the status codes on a running server; they were read from the code and the libraries it uses. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-04 09:11:34 +02:00
clawbot added 1 commit 2026-10-04 09:34:18 +02:00
README.md "Routes" lists every route pixa registers with its method,
purpose, what it needs and the status codes it answers with, read from
the handlers, says q and fit are part of what is cached, and says the
login and generator forms need HTTPS unless debug is on. A new
"Encrypted URLs" section covers logging in with the signing key, making
a URL on the generator page, how long it lasts, and the 410 once it has
expired. "Configuration" gives the order in which pixa looks for its
config file. config.example.yml now lists db_url and env and gives every
key's default. scripts/manual-test.sh is left to #97.

Model: opus-5-5
clawbot force-pushed issue-75-routes-docs from e455901de3 to 1789fd4584 2026-10-04 09:34:18 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-04 09:34:27 +02:00
Author
Collaborator
  1. The config file search paragraph in README.md now says only what the code does: a named file (--config or PIXA_CONFIG_PATH) aborts startup when it is missing, cannot be read or does not parse; of the files pixa looks for on its own, one it finds but cannot read or parse aborts startup, and one it cannot find, for any reason, is passed over without a message, even when it is there in a directory pixa may not enter. "the first of these that exists" now reads "that pixa finds". The code is unchanged; #176 will correct the paragraph when it lands.
  2. Line 147 and the rest of its paragraph are rewrapped at 80; no other line this PR adds is over 80 except the image URL form in its code block, which cannot be wrapped.

Model: opus-5-5

1. The config file search paragraph in `README.md` now says only what the code does: a named file (`--config` or `PIXA_CONFIG_PATH`) aborts startup when it is missing, cannot be read or does not parse; of the files pixa looks for on its own, one it finds but cannot read or parse aborts startup, and one it cannot find, for any reason, is passed over without a message, even when it is there in a directory pixa may not enter. "the first of these that exists" now reads "that pixa finds". The code is unchanged; https://git.eeqj.de/sneak/pixa/issues/176 will correct the paragraph when it lands. 2. Line 147 and the rest of its paragraph are rewrapped at 80; no other line this PR adds is over 80 except the image URL form in its code block, which cannot be wrapped. Model: opus-5-5
Author
Collaborator

PASS at head 1789fd4, rebased onto next at 1616e91.

Not verified: the status codes and the browser cookie behaviour on a running server; they were read from the code and the libraries it uses.

Model: opus-5-5

**PASS** at head `1789fd4`, rebased onto `next` at `1616e91`. Not verified: the status codes and the browser cookie behaviour on a running server; they were read from the code and the libraries it uses. Model: opus-5-5
clawbot merged commit 363774c058 into next 2026-10-04 09:58:36 +02:00
clawbot deleted branch issue-75-routes-docs 2026-10-04 09:58:37 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#174