steid

@jamesgill /

steid/plans/runbook.md
5.2 KBCode·Blame·Raw
ab7fea9chore: plans setup1mo
1# Runbook
2
3> Attempt #2's only setup instructions lived in a plan file describing an architecture
4> that had already been deleted, so they were actively wrong. Keep this file honest:
5> if a command here doesn't work, fix it or delete it.
6
7## Status
8
d7b99d9docs: record milestone 0 progress and routing findings1mo
9The app boots and serves. Everything marked **(#2)** is carried from the previous
10attempt and has **not** been re-verified against Topcoat — treat it as a sketch.
11
12## Requirements
13
14- **rustc ≥ 1.95** — Topcoat 0.5 requires it, and on an older toolchain `cargo add
15 topcoat` silently resolves to an empty `topcoat v0.0.0` placeholder rather than
16 failing. Verified on 1.97.1.
ca76e1bdocs: fix milestone cross-references after the reorder24d
17- `git` on `PATH` (from Milestone 3 — `git init --bare` creates repos, and from
18 Milestone 4 `git http-backend` serves the protocol)
ab7fea9chore: plans setup1mo
19
20## Dev setup
21
22```bash
d7b99d9docs: record milestone 0 progress and routing findings1mo
23cargo run # serves on http://127.0.0.1:3000
24cargo test
25```
26
27```bash
28cargo install topcoat-cli # dev server: watch, rebuild, asset bundling
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
29topcoat dev # working
ab7fea9chore: plans setup1mo
30```
31
d7b99d9docs: record milestone 0 progress and routing findings1mo
32`topcoat dev` builds, bundles assets, watches sources, and live-reloads pages that
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
33include `topcoat::dev::script()`. Press `r` to force a rebuild.
d7b99d9docs: record milestone 0 progress and routing findings1mo
34
35## Configuration
36
37`STEID_`-prefixed env vars via `dotenvy` + `envy`, read into `AppConfig`. Every value
38has a default, so a bare `cargo run` works with no environment at all.
39
40Live now:
41
42```
43STEID_DATABASE_URL=sqlite:steid.db?mode=rwc # default
88583f2docs: bring tracking docs up to date with milestone 11mo
44STEID_DATA_DIR=./data # default; bare repos, used from M4
45STEID_INSECURE_COOKIES=false # default; see below
d7b99d9docs: record milestone 0 progress and routing findings1mo
46```
47
88583f2docs: bring tracking docs up to date with milestone 11mo
48There is deliberately **no owner password in configuration** — the owner is created
49through the claim flow instead. See
50[0002]decisions/0002-first-run-claim-not-config-bootstrap.md.
51
d7b99d9docs: record milestone 0 progress and routing findings1mo
52The bind address is **not** a `STEID_` variable — Topcoat owns it:
53
54```bash
55HOST=0.0.0.0 PORT=8080 cargo run
56```
ab7fea9chore: plans setup1mo
57
d7b99d9docs: record milestone 0 progress and routing findings1mo
58That supersedes attempt #2's `STEID_LISTEN_ADDR`.
ab7fea9chore: plans setup1mo
59
88583f2docs: bring tracking docs up to date with milestone 11mo
60### `STEID_INSECURE_COOKIES` — development only
ab7fea9chore: plans setup1mo
61
88583f2docs: bring tracking docs up to date with milestone 11mo
62Topcoat's session cookie is `__Host-` prefixed and `Secure`. `Secure` means the browser
63only keeps it over a trustworthy origin, and browsers disagree about whether
64plain-HTTP `localhost` qualifies. Where it doesn't, **the failure is completely
65silent**: the server issues a session and records the row, the browser discards the
66cookie, and every page renders signed out with no error anywhere. This cost an
67afternoon; the symptom looks exactly like broken auth logic.
68
69Setting `STEID_INSECURE_COOKIES=true` swaps in `InsecureCookieTokenStore` — the same
70cookie without `Secure` and without the prefix, named `steid-dev-session` so it can
71never be confused with a hardened one. `HttpOnly` and `SameSite=Lax` are kept. Boot
72prints a warning while it's on.
73
74**Never set this on a deployed instance.** Without `Secure` the session cookie travels
75unencrypted and anyone on the network path can lift it and become that user. Behind
76TLS, leave it unset.
77
78A gitignored `.env` in the repo root sets it for local work. Keep `.env` and
79`.env.prod` out of git — both are gitignored.
80
81## First run
82
83```bash
84cargo run # or: topcoat dev
ab7fea9chore: plans setup1mo
85```
86
88583f2docs: bring tracking docs up to date with milestone 11mo
87An unclaimed instance prints a setup token and redirects every route to `/setup`.
88Paste the token, choose a handle, email, and password, and the owner is created and
89signed in.
90
91The token is **held in memory only**, so every restart mints a new one — including
92each rebuild under `topcoat dev`. Use the most recent one printed. Once claimed, no
93token is minted at all and `/setup` redirects away.
94
95Sign in at `/login` with the **email**, not the handle.
ab7fea9chore: plans setup1mo
96
97## Repo layout on disk (#2)
98
99Bare repos at `{STEID_DATA_DIR}/{org}/{repo}.git`. Created empty — no initial commit.
100
ca76e1bdocs: fix milestone cross-references after the reorder24d
101## Git transport (Milestone 4)
ab7fea9chore: plans setup1mo
102
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
103Smart HTTP, delegated to `git http-backend`, authenticated with personal access tokens
104over HTTP Basic — see [0001]decisions/0001-git-over-http-not-ssh.md. No SSH, no host
105keys, no `authorized_keys`.
ab7fea9chore: plans setup1mo
106
107```bash
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
108git clone http://host/owner/repo.git
ab7fea9chore: plans setup1mo
109```
110
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
111Fill in the token workflow and the `body_limit` setting once this is built.
112
ab7fea9chore: plans setup1mo
113## Manual verification checklist (#2)
114
115Attempt #2 verified these by hand each milestone but never wrote down the steps. They
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
116are the smoke test for Milestones 4–5. The auth rows assumed SSH keys; the shape of
117the check still holds with tokens substituted:
ab7fea9chore: plans setup1mo
118
119- [ ] Create a repo via the web UI → bare repo appears at
120 `{data_dir}/{org}/{repo}.git`
121- [ ] `git clone` an empty repo → succeeds
122- [ ] `git clone` a repo with history → succeeds
123- [ ] `git clone` a non-existent repo → clean error, not a hang or panic
124- [ ] First push to an empty repo → succeeds
125- [ ] Push to a repo with history → succeeds
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
126- [ ] Push a repo large enough to exercise the `body_limit` cap → succeeds
127- [ ] Clone with no credentials → rejected, and the prompt is comprehensible
128- [ ] Clone with a valid token → succeeds
129- [ ] Revoke the token → subsequent clone rejected at auth
ab7fea9chore: plans setup1mo
130- [ ] Clone a private repo as a non-member → rejected
131- [ ] Push as a non-owner member → rejected
132
133Worth automating as an integration test rather than re-running by hand a fourth time.
134
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
135## `.gitignore`
ab7fea9chore: plans setup1mo
136
bd48b4bdocs: serve git over smart HTTP, reorder roadmap portfolio-first1mo
137Applied: `/target`, `/data`, `*.db*`, `.env`, `.env.prod`.
ab7fea9chore: plans setup1mo
138
139**Do not add `/plans`.** Attempt #2 did, and that is why these docs had to be
140hand-carried between repos.