docs: fill item 8 in the external-escalation reply

This commit is contained in:
Jakub Zych
2026-10-23 00:10:27 +02:00
parent 894a3d572f
commit e5dd4579a8
2 changed files with 8 additions and 4 deletions

View File

@@ -26,7 +26,7 @@ Reviewed 2026-10-22. The list is `golem15.user` (sm-user-plugin), not cabana adm
| 5 | G7 Users form has no role field | Decline | — | — | declined | n/a |
| 6 | G8 API token guard ignores `tokens_valid_after` | Decline | — | — | declined | n/a |
| 7 | Cookie option on `/login` | Feature | [261022-wah](../quick/261022-wah-opt-in-httponly-session-cookie-on-user-p/) · [todo](../todos/pending/2026-10-22-user-login-opt-in-session-cookie.md) | strnsccy | done (unreleased) | `846087d`, `8bdf2c7` → v0.5.0 |
| 8 | Password-routes 404 switch | Feature | [2026-10-22-user-password-routes-404-switch.md](../todos/pending/2026-10-22-user-password-routes-404-switch.md) | h7yrafgd | open | |
| 8 | Password-routes 404 switch | Feature | [261022-x7a](../quick/261022-x7a-user-plugin-golem15-user-password-public/) · [todo](../todos/pending/2026-10-22-user-password-routes-404-switch.md) | h7yrafgd | done (unreleased) | `3828a65` → v0.5.0 |
| 9 | Lockout keyed on `RemoteAddr` | Fix | [261022-vfz](../quick/261022-vfz-user-plugin-login-throttle-via-surf-clie/) · [todo](../todos/pending/2026-10-22-user-login-lockout-and-same-second-cutoff.md) | sniewiif | done (unreleased) | `b6f8055` → v0.5.0 |
| 10 | Same-second token refusal | Fix | [261022-vfz](../quick/261022-vfz-user-plugin-login-throttle-via-surf-clie/) · [todo](../todos/pending/2026-10-22-user-login-lockout-and-same-second-cutoff.md) | sniewiif | done (unreleased) | `a484d0e` → v0.5.0 |
@@ -48,7 +48,7 @@ Status values: `open` · `done` · `declined`. Shipped: local commit now; replac
/msd-quick --validate User-plugin golem15.user.password.public_routes (default true). When false, do not register POST /login /forgot-password /reset-password so they 404 like unknown paths. Leave /register and the rest. No framework wrap, no custom 404. Base 8bdf2c7. See .planning/todos/pending/2026-10-22-user-password-routes-404-switch.md and .planning/notes/2026-10-22-external-user-plugin-escalations.md
```
Suggested order if you care about risk: G4 (serve blacklist), then G3, G2, 9+10, then the two features. Bugs and item 7 are done locally; item 8 (password-routes 404) is the last of the six. Do not overlap on the same plugin files. Do not send the reply until v0.5.0 is tagged.
Suggested order if you care about risk: G4 (serve blacklist), then G3, G2, 9+10, then the two features. All six are done locally; item 8 (password-routes 404) was the last. Do not overlap on the same plugin files. Do not send the reply until v0.5.0 is tagged.
## Verdicts (kept for the sessions)
@@ -59,7 +59,7 @@ Suggested order if you care about risk: G4 (serve blacklist), then G3, G2, 9+10,
- **G7.** Stock form omission was a 12.1 decision. Stale `organisation_role` is already cleared (`ClearOnChange`, v0.1.8). Apps extend the form.
- **G8.** Personal tokens die via `revoked_at`. `RevokeUserAccess` already sets that on deactivate/ban. Do not teach the API-token guard a JWT cutoff. Password reset killing API tokens would be a separate, explicit revoke.
- **7.** Done locally (`846087d`, `8bdf2c7`). `846087d`: a `/refresh` carried by the `auth.cookie` cookie (`token` by default, no bearer) rewrites it and answers `{}`, whatever `token_cookie` says; bearer and other-cookie refreshes stay body-only; refusals write no cookie. `8bdf2c7`: `golem15.user.jwt.token_cookie` (default off) makes /login, /register (auto sign-in) and /activate-by-code set the HttpOnly `auth.cookie` cookie via `bouncer.LoadCookieConfig` and omit body `token`; off keeps today's bodies. SameSite=Lax, no CSRF; API tokens untouched.
- **8.** Plugin config; no framework wrap. Next: `golem15.user.password.public_routes` (default true). When false, skip registering `/login`, `/forgot-password`, `/reset-password`. `/register` stays (`allow_registration` already gates it).
- **8.** Done locally (`3828a65`). Plugin config; no framework wrap. `golem15.user.password.public_routes` (default true); false leaves `POST /login`, `/forgot-password` and `/reset-password` unregistered, so they get the router's own 404 like any unknown path (a `GET` too, no 405); no custom handler, no `pact`/`surf` change. `/register` stays (`allow_registration` gates it, `golem15.user.turnstile` still guards it), and so do `/activate*`, `/fetch`, `/refresh`, `/logout`, `/change-password` and `/tokens`. Read when the routes are built (a restart applies it); a value other than true or false fails boot.
- **9.** Done locally (`b6f8055`). /login keys the throttle on surf.ClientIP with http.trusted_proxies (the /register expression); RemoteIP stays the RemoteAddr helper; without trusted proxies X-Forwarded-For is ignored.
- **10.** Done locally (`a484d0e`). /reset-password and the admin password set truncate the cutoff to whole seconds like RevokeUserAccess; change-password and bouncer unchanged.
@@ -97,7 +97,7 @@ Ships in SummerCMS v0.5.0 (sm-user-plugin 846087d and 8bdf2c7, tagged with that
Password-routes switch
Agreed, in the user plugin, not as a framework “wrap another plugin’s routes” seam. A config key will stop registering /login, /forgot-password and /reset-password so they 404.
TODO: ships in SummerCMS v0.5.0 — config key <name>.
Ships in SummerCMS v0.5.0 (sm-user-plugin 3828a65, tagged with that wave): set golem15.user.password.public_routes: false (default true; SUMMER_GOLEM15__USER__PASSWORD__PUBLIC_ROUTES=false in the environment) and POST /login, POST /forgot-password and POST /reset-password are not registered, so they answer the same 404 as any unknown path, whatever the method. POST /register stays (allow_registration still decides whether it takes accounts, and golem15.user.turnstile still guards it), as do /activate, /activate-by-code, /fetch, /refresh, /logout, /update, /change-password and /tokens. With the key true or unset nothing changes. The key is read when the routes are built, so a change needs a restart; a value other than true or false stops boot with an error naming the key.
Login lockout keyed on RemoteAddr
Agreed. /login used RemoteAddr; /register already uses the trusted-proxy client address. Behind a reverse proxy five failures locked everyone.

View File

@@ -29,6 +29,10 @@ Leave registered: `/register` (`allow_registration` already refuses at the handl
Base is sm-user-plugin `8bdf2c7` (item 7). Hold push/tag for SummerCMS v0.5.0. After the commit, fill item 8 in `.planning/notes/2026-10-22-external-user-plugin-escalations.md` like the earlier rows (`done (unreleased)`, ships in v0.5.0, name the key). Leave the todo in pending with an Outcome. Do not send the reply; the hold stands until the rest of the v0.5.0 wave (keyboard shortcuts, MCP / 19.7) is tagged.
## Outcome (2026-10-23)
Quick `261022-x7a`. One commit on sm-user-plugin master, `3828a65` (base `8bdf2c7`). `routes.go` reads `golem15.user.password.public_routes` through `publicPasswordRoutes` (unset, empty or true register every route; a bool or the string true or false, any case; anything else fails `Routes` naming the key) and, when false, skips only `POST /login`, `/forgot-password` and `/reset-password`; the turnstile guard stays on `/register`, the default route table is unchanged, and there is no `pact`/`surf`/controller change. `TestPasswordPublicRoutes` (`-short`, route-table recording) and `TestPasswordPublicRoutesAnswer404` (Docker: the dropped routes answer exactly like an unknown path, the rest keep working) cover it. README and `config.yaml` updated. Reply note item 8 filled. Not tagged, not pushed: ships with the v0.5.0 wave.
## Invoke
```