You wanted three abilities: modify the site, review changes to it, and suggest improvements. This closing chapter is the working method for all three.
NUTRIENT_CATALOG entry in
config.py; everything downstream is key-generic. A
change that fits a seam touches one or two files; needing five is a
signal to re-read.for t in tests/test_m*.py tests/probe_cross_user.py; do
python "$t" || break; done. They need no AWS and no network
and run in seconds. They drive the real routes against
fake boto3 tables (tests/fakes.py) โ a minicluster in
miniature. tests/testkit.py must be imported first in
any new test; it installs the fakes before the app imports.Chapter by chapter, compressed into one table. A "yes" isn't automatically a rejection โ it's where to spend your attention:
| Ask | Because (chapter) |
|---|---|
Does innerHTML or |safe get anything that isn't a source literal? | XSS (Jinja, JS, security) |
| Does any identifier in a URL, query, or form decide whose data is read or written? | Tenant isolation (API, security) |
| Does a new GET change application data? Is a new write route missing its guard decorator or rate limit? | CSRF, auth (HTTP, backend, identity) |
| Does a public page or a log line gain a config value or user content? | Invariants #8, #11 (security) |
New in-process state (cache, counter, thread) โ does it survive the "what if --workers 2?" question, and is the bet commented? | Single-worker design (backend) |
Numbers crossing the DynamoDB edge: Decimal(str(x)) in, float() out? | Decimal discipline (storage) |
| New fetch call: does it handle 401, non-OK, and network failure โ the three-rung ladder? | The error contract (API) |
| New input: validated to canonical form server-side, not just constrained in the HTML? | Validation (HTML, API) |
Hard-coded color instead of a var(--token)? A button that's a styled div? | Theming, a11y (HTML, CSS) |
| Does the diff update the matching stub test โ or need a new one? | The tests are the spec |
Each is small, safe, and touches one new layer. Do them in a branch; the tests tell you if you broke a promise.
--gold in both
theme blocks of base.html and watch it propagate.
Then find one hard-coded color anywhere and tokenize it.privacy.html. No route change needed โ why not?/api/meals payload; you need one element in the
HTML and a few lines in renderDays./api/meals response (e.g. a per-day meal count) in
_meals_payload, render it, and extend the relevant
test. Decimal rules apply.test_m9_status.py asserting
/status shows something it doesn't yet โ then make it
pass. You'll touch a route, a template, and the leak check.NUTRIENT_CATALOG in config.py, and trace
why that one dict entry is enough โ through
resolve_nutrient, the settings page, the form field
name, the AI schema, and the chart. That trace is the
architecture of the app.The strongest improvement proposals here name the trade they're reversing. This codebase declines things on purpose โ GSIs, caching layers, multiple workers, frameworks, a real queue โ and writes down why. "Add Redis so we can run two workers" is only an improvement once ~100 users isn't the scale anymore; "the meals cache from the old tracker" is explicitly warned against in CLAUDE.md. Meanwhile some gaps are real and acknowledged: the ephemeral spool, memory-only rate-limit state across restarts, no CSP header yet. An improvement pitch that says "this trade was right at PoC scale and here's the trigger that changes it" will land; one that pattern-matches "small app is missing big-app machinery" won't.
test_m*.py is an executable
specification of one subsystem.One last pointer, in the spirit of the whole book: this guide is
itself part of the site โ a closed chapter registry and two routes in
app.py (grep for dzidza), templates extending
_dzidza.html, a leak-checked public page like any other,
with a stub test of its own. Reading how the book you just finished is
served makes a fitting final exercise. Dzidza zvakanaka
โ happy learning.