Tracking: 1.0.0 sequencing and critical path #103

Open
opened 2026-08-09 16:10:39 +02:00 by clawbot · 0 comments
Collaborator

Meta-issue, deliberately not on the 1.0.0 milestone so the milestone count stays an honest count of real work units.

Each 1.0.0 issue carries its own coordination note, but there is no single view of the ordering. This is it. The dependencies below are real constraints, not preferences — following a different order mostly means doing work twice.

Branching model (changed 2026-08-10, owner instruction)

Branch and PR per issue, based on next, never main. Each issue PR is squash-merged into next by the manager on a passed review. next is the branch for the next milestone and must be green and mergeable to main at any time without notice; sneak merges next into main when he chooses, via the single milestone PR #105. Feature branches may be red; next and main may not.

Done

  • #54 — golangci-lint v2.12.2 + canonical config. Squash-merged into next 2026-08-10. Three behaviour deltas recorded in its body; eviction-loop cancellation deferred to #102.

Wave 1 — the meta-gate

Until these land, every other issue's "make check green" evidence rests on checks that can pass without having checked:

  • #104 — all linting in Docker via Dockerfile.lint + script/lint. Owner ruling. Supersedes #58, which is closed: with no host lint path left there is no host binary to pin.
  • #101script/cibuild is a bare docker build ., so Docker can serve the RUN make check layers from cache and exit 0 having run nothing. Observed elsewhere in the fleet at 0.262 s, fully CACHED.
  • #59script/test does not follow the conditional-verbose-rerun pattern and has no -cover.
  • #57 — gomodguard_v2; a one-line config change, was gated on #54 and is now unblocked.

Wave 2 — the four release blockers

These block tagging 1.0.0 per REPO_POLICIES.md:

  • #94 trusted-proxy handling → hard prerequisite for #66. Without it a per-IP limiter behind the mandated reverse proxy keys every request to the proxy and locks out all users at once.
  • #91 HSTS / CSP / Permissions-Policy
  • #92 IdleTimeout / ReadHeaderTimeout (slowloris) + request body limits
  • #93 CSRF on the two cookie-authenticated forms

91, 92 and 93 are mutually independent and touch different files (middleware.go, http.go, handlers/templates) — they can run in parallel. 94 must precede 66.

Wave 3 — security, worst first

  • #60q/fit outside the HMAC signature. One signed URL yields 500 unauthorized cache entries and transcodes. Most severe finding in the milestone, and it makes the README's exact-match claim false. Breaking change to the URL signing scheme — any external signer updates in lockstep, so decide early rather than late.
  • #66 (needs 94), #67 blocked networks / SSRF ranges, #62 /v1/e/ validation bypass, #82 EXIF stripping, #68 SVG decision.

Wave 4 — the performance claims

#64 and #65 together — they touch the same code (Service.Get) and target the same blowup; splitting them means two passes over one function. #70 (dead metaCache) is the third leg, and #81 (load test) should run before all three to establish a baseline, otherwise there is no way to show the fixes did anything. README.md:49's 1-5k req/s claim is currently unmeasured.

Wave 5 — correctness cleanup on the newly-landed eviction code

#56 (Stats + never-incremented counters), #69 (CacheTTL never read), #87 (unbounded hostSems, orphaned .meta), #102 (eviction loop not context-cancellable), #72 (swallowed errors), #73 (dead abstractions), #71 (maintenance_mode does nothing), #86 (shutdown/exit code — resolve together with 102, same question about who owns shutdown), #96 (migration path move — do while it is still a pure rename, since policy forbids editing migrations post-1.0).

73 before #39 — removing the dead interfaces first keeps 39's urlparser extraction diff small.

Wave 6 — features, tests, docs

  • Features: #83 before 69's revalidation half; #84 and #88 together (format=auto without Vary: Accept is a correctness bug, not an optimization); #63, #85, #90, #99.
  • Tests: #76, #77, #78, #79, #80. 78's redirect-SSRF test is the highest-value single test in the milestone.
  • Docs: #74, #75 (partly gated on #61 for the config key list), #89 (gated on 94 for trusted-proxy docs), #97, 61 → then #98.

Last

  • #100 — the markdown reflow. It touches README.md and TODO.md and will conflict with anything in flight. Do it when the queue is empty.
  • #17 — uPaaS deployment. Its own body gates it on 1.0 feature completeness, which is why it is off the milestone. It is the step after 1.0.0 closes.

Standing constraints

  • Issue PRs are based on next and squash-merged into next by the manager. main is protected and only ever receives the milestone PR, which sneak merges.
  • Default merge style is squash, so every PR body becomes a permanent commit message — inaccurate PR bodies are a review finding, not a formatting nit.
  • Every PR gates on make check via make targets / script/ entrypoints only. All linting runs in Docker via script/lint (issue 104).
  • Never modify an existing test without explicit owner approval. New tests need no approval.
  • Never modify .golangci.yml without asking — it is canonical and hash-verified (021cc83f…46bcb).
Meta-issue, deliberately **not** on the `1.0.0` milestone so the milestone count stays an honest count of real work units. Each 1.0.0 issue carries its own coordination note, but there is no single view of the ordering. This is it. The dependencies below are real constraints, not preferences — following a different order mostly means doing work twice. ## Branching model (changed 2026-08-10, owner instruction) Branch and PR per issue, **based on `next`, never `main`**. Each issue PR is squash-merged into `next` by the manager on a passed review. `next` is the branch for the next milestone and must be green and mergeable to `main` at any time without notice; `sneak` merges `next` into `main` when he chooses, via the single milestone PR https://git.eeqj.de/sneak/pixa/pulls/105. Feature branches may be red; `next` and `main` may not. ## Done - **https://git.eeqj.de/sneak/pixa/pulls/54** — golangci-lint v2.12.2 + canonical config. Squash-merged into `next` 2026-08-10. Three behaviour deltas recorded in its body; eviction-loop cancellation deferred to https://git.eeqj.de/sneak/pixa/issues/102. ## Wave 1 — the meta-gate Until these land, every other issue's "`make check` green" evidence rests on checks that can pass without having checked: - **https://git.eeqj.de/sneak/pixa/issues/104** — all linting in Docker via `Dockerfile.lint` + `script/lint`. Owner ruling. **Supersedes https://git.eeqj.de/sneak/pixa/issues/58**, which is closed: with no host lint path left there is no host binary to pin. - **https://git.eeqj.de/sneak/pixa/issues/101** — `script/cibuild` is a bare `docker build .`, so Docker can serve the `RUN make check` layers from cache and exit 0 having run nothing. Observed elsewhere in the fleet at 0.262 s, fully `CACHED`. - **https://git.eeqj.de/sneak/pixa/issues/59** — `script/test` does not follow the conditional-verbose-rerun pattern and has no `-cover`. - **https://git.eeqj.de/sneak/pixa/issues/57** — gomodguard_v2; a one-line config change, was gated on #54 and is now unblocked. ## Wave 2 — the four release blockers These block tagging 1.0.0 per `REPO_POLICIES.md`: - **https://git.eeqj.de/sneak/pixa/issues/94** trusted-proxy handling → **hard prerequisite for https://git.eeqj.de/sneak/pixa/issues/66**. Without it a per-IP limiter behind the mandated reverse proxy keys every request to the proxy and locks out all users at once. - **https://git.eeqj.de/sneak/pixa/issues/91** HSTS / CSP / Permissions-Policy - **https://git.eeqj.de/sneak/pixa/issues/92** `IdleTimeout` / `ReadHeaderTimeout` (slowloris) + request body limits - **https://git.eeqj.de/sneak/pixa/issues/93** CSRF on the two cookie-authenticated forms 91, 92 and 93 are mutually independent and touch different files (`middleware.go`, `http.go`, handlers/templates) — they can run in parallel. 94 must precede 66. ## Wave 3 — security, worst first - **https://git.eeqj.de/sneak/pixa/issues/60** — `q`/`fit` outside the HMAC signature. One signed URL yields 500 unauthorized cache entries and transcodes. Most severe finding in the milestone, and it makes the README's exact-match claim false. **Breaking change to the URL signing scheme** — any external signer updates in lockstep, so decide early rather than late. - **https://git.eeqj.de/sneak/pixa/issues/66** (needs 94), **https://git.eeqj.de/sneak/pixa/issues/67** blocked networks / SSRF ranges, **https://git.eeqj.de/sneak/pixa/issues/62** `/v1/e/` validation bypass, **https://git.eeqj.de/sneak/pixa/issues/82** EXIF stripping, **https://git.eeqj.de/sneak/pixa/issues/68** SVG decision. ## Wave 4 — the performance claims **https://git.eeqj.de/sneak/pixa/issues/64 and https://git.eeqj.de/sneak/pixa/issues/65 together** — they touch the same code (`Service.Get`) and target the same blowup; splitting them means two passes over one function. **https://git.eeqj.de/sneak/pixa/issues/70** (dead `metaCache`) is the third leg, and **https://git.eeqj.de/sneak/pixa/issues/81** (load test) should run *before* all three to establish a baseline, otherwise there is no way to show the fixes did anything. `README.md:49`'s 1-5k req/s claim is currently unmeasured. ## Wave 5 — correctness cleanup on the newly-landed eviction code **https://git.eeqj.de/sneak/pixa/issues/56** (Stats + never-incremented counters), **https://git.eeqj.de/sneak/pixa/issues/69** (`CacheTTL` never read), **https://git.eeqj.de/sneak/pixa/issues/87** (unbounded `hostSems`, orphaned `.meta`), **https://git.eeqj.de/sneak/pixa/issues/102** (eviction loop not context-cancellable), **https://git.eeqj.de/sneak/pixa/issues/72** (swallowed errors), **https://git.eeqj.de/sneak/pixa/issues/73** (dead abstractions), **https://git.eeqj.de/sneak/pixa/issues/71** (`maintenance_mode` does nothing), **https://git.eeqj.de/sneak/pixa/issues/86** (shutdown/exit code — resolve together with 102, same question about who owns shutdown), **https://git.eeqj.de/sneak/pixa/issues/96** (migration path move — do while it is still a pure rename, since policy forbids editing migrations post-1.0). **73 before https://git.eeqj.de/sneak/pixa/issues/39** — removing the dead interfaces first keeps 39's `urlparser` extraction diff small. ## Wave 6 — features, tests, docs - Features: **https://git.eeqj.de/sneak/pixa/issues/83** before 69's revalidation half; **https://git.eeqj.de/sneak/pixa/issues/84** and **https://git.eeqj.de/sneak/pixa/issues/88** together (`format=auto` without `Vary: Accept` is a correctness bug, not an optimization); **https://git.eeqj.de/sneak/pixa/issues/63**, **https://git.eeqj.de/sneak/pixa/issues/85**, **https://git.eeqj.de/sneak/pixa/issues/90**, **https://git.eeqj.de/sneak/pixa/issues/99**. - Tests: **https://git.eeqj.de/sneak/pixa/issues/76**, **https://git.eeqj.de/sneak/pixa/issues/77**, **https://git.eeqj.de/sneak/pixa/issues/78**, **https://git.eeqj.de/sneak/pixa/issues/79**, **https://git.eeqj.de/sneak/pixa/issues/80**. 78's redirect-SSRF test is the highest-value single test in the milestone. - Docs: **https://git.eeqj.de/sneak/pixa/issues/74**, **https://git.eeqj.de/sneak/pixa/issues/75** (partly gated on https://git.eeqj.de/sneak/pixa/issues/61 for the config key list), **https://git.eeqj.de/sneak/pixa/issues/89** (gated on 94 for trusted-proxy docs), **https://git.eeqj.de/sneak/pixa/issues/97**, 61 → then **https://git.eeqj.de/sneak/pixa/issues/98**. ## Last - **https://git.eeqj.de/sneak/pixa/issues/100** — the markdown reflow. It touches `README.md` and `TODO.md` and will conflict with anything in flight. Do it when the queue is empty. - **https://git.eeqj.de/sneak/pixa/issues/17** — uPaaS deployment. Its own body gates it on 1.0 feature completeness, which is why it is off the milestone. It is the step *after* 1.0.0 closes. ## Standing constraints - Issue PRs are based on `next` and squash-merged into `next` by the manager. `main` is protected and only ever receives the milestone PR, which `sneak` merges. - Default merge style is **squash**, so every PR body becomes a permanent commit message — inaccurate PR bodies are a review finding, not a formatting nit. - Every PR gates on `make check` via make targets / `script/` entrypoints only. All linting runs in Docker via `script/lint` (issue 104). - Never modify an existing test without explicit owner approval. New tests need no approval. - Never modify `.golangci.yml` without asking — it is canonical and hash-verified (`021cc83f…46bcb`).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#103