| 1 | # đŸ¤– AGENTS.md: todo-ocaml |
| 2 | |
| 3 | The one rule: **the page works without JavaScript, and JavaScript only |
| 4 | makes it nicer.** Every action is a plain form POST that answers 303. The |
| 5 | script in `static/app.js` posts the same forms with `X-Fragment: todoapp` |
| 6 | and swaps in the HTML the server renders; it never holds state of its own. |
| 7 | |
| 8 | ## Tenancy |
| 9 | |
| 10 | - **One instance for the whole app** (`todo-ocaml.bfj.oncarlos.com`), one |
| 11 | SQLite file. |
| 12 | - **Each visitor's list is kept separately by an anonymous cookie** |
| 13 | (`todomvc_list`, 128 random bits from `getrandom(2)`, `HttpOnly; |
| 14 | SameSite=Lax; Path=/`, plus `Secure` over https). An unknown or garbled |
| 15 | cookie gets a fresh, empty list. Every query that reads or writes a todo |
| 16 | is scoped by that list id; an id outside the caller's list is a 404. |
| 17 | - **No sign-in.** Losing the cookie loses the list. That's accepted. |
| 18 | - **Trust class C.** Todo titles are stored as plain text in SQLite, not |
| 19 | encrypted. That's a deliberate choice for a demo app holding nothing |
| 20 | sensitive. |
| 21 | |
| 22 | ## Working here |
| 23 | |
| 24 | - Work only in `apps/ocaml/`. `BRIEF.md` and `CONTRACT.md` at the repo root |
| 25 | are binding. |
| 26 | - Build with `make build` (x86, local) and `make build-arm64` (shipped, |
| 27 | inside the emulated arm64 root). Both use opam roots under `.cache/`. |
| 28 | - `make test` runs the unit and handler tests. Run the shared suite with |
| 29 | `scripts/test-app.sh` before every deploy. |
| 30 | - Migrations only add. Never drop or rewrite data. |
| 31 | - Bind `127.0.0.1` only. Scratch goes in `mktemp -d -p "$TMPDIR"`. |
| 32 | |