From 2173173becfb7783991c9395e782ae9c99057290 Mon Sep 17 00:00:00 2001 From: retoor Date: Tue, 6 Oct 2026 03:12:09 +0200 Subject: [PATCH] Lessons L-15 to L-19: route docs, form errors, tokens, tests, venv stamp --- DEVELOPMENT_FLOW.md | 100 ++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/DEVELOPMENT_FLOW.md b/DEVELOPMENT_FLOW.md index e768e58..53af238 100644 --- a/DEVELOPMENT_FLOW.md +++ b/DEVELOPMENT_FLOW.md @@ -426,3 +426,103 @@ Standing instruction from retoor, recorded as a clear rule: - Research grounds the choice (example: invite tokens use hash-only storage, single use and expiry per current security practice), it never replaces verification against the repo's own code and tests. + +### L-2026-10-05-15: Every new route needs a docs_api registry entry + +| Field | Value | +|--------------|-------| +| date | 2026-10-05 | +| agent | muse-spark | +| status | proposed | +| dpp_template | no | +| dpp_reason | proposed; Grok folds into template docs section | + +The suite enforces documentation coverage: +`test_every_product_route_is_documented` fails when any product route +is missing from the `docs_api` registry, and +`test_documented_auth_matches_reality` calls every registered probe +path as anon, member and admin and asserts the declared auth holds. + +Adding a route therefore means adding its registry entry in the same +change: method, path, auth level, fields, sample, plus a safe probe +path and body. Admin probes conventionally target an `unknown` id +(404 for admins proves the route exists past the guard); public +probes must answer anon with anything but 401 or 403. + +### L-2026-10-05-16: New public POST forms need a validation_handler branch + +| Field | Value | +|--------------|-------| +| date | 2026-10-05 | +| agent | muse-spark | +| status | proposed | +| dpp_template | no | +| dpp_reason | proposed; Grok folds into template forms section | + +`RequestValidationError` on an HTML form post only re-renders the +form for paths the `validation_handler` in `main.py` knows +(`/auth/login`, `/join`, `/invite/...`). Any other path bounces the +user to the referer with no error shown. + +Every new public POST form needs its own branch that echoes the +submitted values (never passwords) back into its template with the +friendly messages, or the form silently eats validation errors. + +### L-2026-10-05-17: Token features store hash only, single use, silent invalid + +| Field | Value | +|--------------|-------| +| date | 2026-10-05 | +| agent | muse-spark | +| status | proposed | +| dpp_template | no | +| dpp_reason | proposed; Grok folds into template auth section | + +The member-invite pattern is the template for future token features +(password reset, email change, one-time links): + +- Token from `secrets` with at least 128 bits; store SHA-256 only so + a database read never yields a usable token. +- Single use (`used_at`) plus expiry (`expires_at`, setting-backed). +- One live token per subject; issuing revokes the previous. +- Unknown, used, revoked and expired tokens answer identically, so + links cannot be probed for state. +- Bind the token to its subject where one exists (invite email). + +### L-2026-10-05-18: Shared-DB API tests must not assert closed sets + +| Field | Value | +|--------------|-------| +| date | 2026-10-05 | +| agent | muse-spark | +| status | proposed | +| dpp_template | no | +| dpp_reason | proposed; Grok folds into template test section | + +API tests share one server database per session. A test that asserts +an exact set of rows (observed: `/people` usernames equal to the two +seeds) breaks the moment any other test legitimately adds rows +through the product's own flows. + +Assert intent instead: seeds present, ordering held, every row +well-formed (username pattern, required fields). Closed-set +assertions are only valid for tables no test ever extends. + +### L-2026-10-05-19: Version bumps must not rebuild the venv + +| Field | Value | +|--------------|-------| +| date | 2026-10-05 | +| agent | muse-spark | +| status | proposed | +| dpp_template | no | +| dpp_reason | proposed; Grok folds into template make section | + +The Makefile venv stamp depends on `pyproject.toml`, so a +version-only bump makes the next `make` target rebuild the whole +virtualenv (observed: rebuild failed on a box whose system python +has no `venv` module, blocking unrelated targets). + +Workaround: `touch .venv/.stamp` when only the version changed. +Durable fix for the template: key the stamp on dependency inputs, +not on the version field. diff --git a/pyproject.toml b/pyproject.toml index e0d361e..32ed4d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "molodetz" -version = "1.0.18" +version = "1.0.19" description = "Molodetz, a calm community blog roll." readme = "README.md" requires-python = ">=3.12"