docs(go): write AGENTS.md with the one rule and tenancy declaration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev b389a0fef862e8ecc8b76154a739a11427603176 parent daea4d5
1 file changed, +39 −0
  • apps/go/AGENTS.md +39 −0
diff --git a/apps/go/AGENTS.md b/apps/go/AGENTS.md
new file mode 100644
index 0000000..e942adc
--- /dev/null
+++ b/apps/go/AGENTS.md
@@ -0,0 +1,39 @@
+# 🤖 AGENTS.md: todo-go
+
+The CARLOS bakeoff's TodoMVC, in Go. Live at
+`https://todo-go.bfj.oncarlos.com` (Carloku app `todo-go`, account `bfj`).
+
+## The one rule
+
+**Every page works as plain HTML forms first.** The server renders the
+whole app, and every change is a form POST answered with a 303. The
+JavaScript in `web/static/app.js` only sends those same POSTs in the
+background and swaps in the HTML the server sends back. If a feature
+can't be done with JavaScript off, it is done differently, not skipped.
+
+`BRIEF.md` and `CONTRACT.md` at the repo root are binding; this file
+adds what is specific to the Go build.
+
+## Tenancy declaration
+
+| Question | Answer |
+|---|---|
+| What is one instance? | The whole app. One process, one SQLite file, one unix socket |
+| How do people reach it? | Anonymously. A visitor's first request sets a random cookie (256 bits), and that cookie is their list. No sign-in, no accounts |
+| Where is each list kept? | In the one SQLite file, each row keyed by the SHA-256 of the visitor's cookie. The app never stores the cookie itself, so a copy of the database can't be used to open anyone's list |
+| Trust class | **C**, chosen 2026-10-23: todo titles are stored as plain text, readable by the server and by anyone holding the database or its replicas. A todo list for a public demo doesn't justify server-blind encryption |
+| Benefits claimed | Hibernation (the instance sleeps when idle and starts in milliseconds), replication of the one file by the platform |
+| Costs accepted | A list lives as long as its cookie: clear cookies and the list is gone, and there is no way to move a list between browsers. Every list shares one file, so there is no per-visitor export or erasure beyond "delete by cookie hash" |
+
+## Rules
+
+- One static binary, `CGO_ENABLED=0`. SQLite through `modernc.org/sqlite`.
+- Migrations in `internal/todo/store.go` only ever add. Never edit or
+ remove a shipped migration; append a new one.
+- Every query that touches a todo names the caller's list. An id that
+ isn't in the caller's list is a 404.
+- Titles are rendered by `html/template`, never as raw HTML.
+- JavaScript is one small ES module with no build step. Keep it under
+ 300 lines.
+- Servers bind `127.0.0.1` only. Don't change `GOCACHE`; `make
+ build-arm64 COLD=1` passes `-a` instead.