steid

@jamesgill /

steid/CLAUDE.md
4.3 KBCode·Blame·Raw
1# Steid
2
3A personal-first gitforge in Rust. Hosts git repos, writing, and projects for one
4developer or an organisation. **Portfolio-first, not a Gitea clone** — the profile page
5is the product and repos are one kind of thing on it. Use that to break ties.
6
7## Read first
8
9`plans/` is the source of truth and is tracked in git. Read it at the start of a
10session rather than inferring intent from the code.
11
12| File | Holds |
13|---|---|
14| `plans/ROADMAP.md` | vision, stack, the single milestone ladder |
15| `plans/current.md` | the active milestone only — steps, watch-fors, backlog |
16| `plans/progress.md` | what shipped, and the decisions worth not rediscovering |
17| `plans/architecture.md` | layer rules and conventions |
18| `plans/runbook.md` | how to run it, config, manual verification |
19| `plans/decisions/` | ADRs; `TEMPLATE.md` defines the format |
20
21## Keep the docs current
22
23**Before reporting work complete, update `plans/`.** This is part of finishing the
24work, not a follow-up chore — the project has been restarted three times and the
25previous attempts lost their reasoning at exactly these handover points.
26
27- `current.md` — tick off finished steps; move completed work out to `progress.md`.
28 If it starts reading like a changelog, it has drifted.
29- `progress.md` — record decisions and gotchas that aren't obvious from the code. The
30 test is: would the next session waste an hour rediscovering this?
31- `ROADMAP.md` — only when a milestone's status actually changes.
32- `decisions/` — a new ADR when a choice would be expensive to reverse or constrains
33 future work. Write it when the decision is made; reconstructed rationale is fiction.
34
35Also update `current.md` when a *new* problem is found — an unfinished item, a
36shortcut taken, a hole opened. Carry those forward explicitly at milestone rollover
37rather than letting them vanish.
38
39Skip all of this for typos, formatting, and dependency bumps.
40
41## Working style
42
43- **Commit directly to `main`.** No feature branches — solo repo. Cleanliness comes
44 from small, self-contained commits that each compile, not from branching.
45- Small steps. Build up slowly; prefer a working increment over a big drop.
46- Explain *why* in commit messages, not just what.
47
48## Conventions
49
50Full detail in `plans/architecture.md`. The short version:
51
52- **Layers:** `domain` (no knowledge of HTTP/SQL/git/Topcoat) → `application` (use
53 cases and ports) → `infrastructure` (adapters, web). Dependencies point inward.
54- **Every use case takes an `Actor`** and enforces authorization before any side
55 effect — one place, reachable from a page, an `/api` route, or a future transport.
56- **Typed IDs**, never raw `String` for entity references.
57- **`new()` validates, `from_trusted()` doesn't.** Storage adapters use
58 `from_trusted`; re-validating stored rows makes a tightened rule unreadable.
59- **`from_str` returns `Result`, never `Option`.** A silently-defaulted enum surfaces
60 later as the wrong permissions.
61- **Every repository port gets two implementations** — in-memory (what makes use cases
62 testable without a database) and SQLite.
63- Request helpers are **functions taking `cx`**, not middleware or extractors. A page
64 that forgets to call one gets nothing; a route added without middleware silently
65 gets someone else's data.
66- Safe Rust only. No `unsafe`.
67
68## Before saying it's done
69
70```bash
71cargo test
72cargo clippy --all-targets # expect zero warnings
73cargo fmt
74```
75
76Report counts accurately — don't state a test number without running it.
77
78Verify behaviour rather than asserting it. A passing unit test is not evidence that a
79page works; the session-cookie bug passed every test and failed silently in the
80browser. Say plainly what was checked and what wasn't.
81
82## Gotchas
83
84- **Topcoat 0.5 needs rustc ≥ 1.95.** On older toolchains `cargo add topcoat` silently
85 resolves to an empty `topcoat v0.0.0` placeholder instead of failing.
86- **Topcoat is very new** (first release 2026-07-22) and expects breaking changes.
87 Check its docs on GitHub rather than assuming an API.
88- **`STEID_INSECURE_COOKIES=true`** is set in a gitignored `.env` for local dev,
89 because a `Secure` cookie is dropped silently over plain-HTTP localhost. Never
90 deploy it.
91- **The setup token is in memory only**, so every restart — including each `topcoat
92 dev` rebuild — mints a new one.
93- Don't leave background servers running; the user drives the app.