steid

@jamesgill /

steid/plans/runbook.md
3.8 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.
17- `git` on `PATH` (from Milestone 3 — the protocol server shells out to it)
ab7fea9chore: plans setup1mo
18
19## Dev setup
20
21```bash
d7b99d9docs: record milestone 0 progress and routing findings1mo
22cargo run # serves on http://127.0.0.1:3000
23cargo test
24```
25
26```bash
27cargo install topcoat-cli # dev server: watch, rebuild, asset bundling
28topcoat dev # not yet tried on this project
ab7fea9chore: plans setup1mo
29```
30
d7b99d9docs: record milestone 0 progress and routing findings1mo
31`topcoat dev` builds, bundles assets, watches sources, and live-reloads pages that
32include `topcoat::dev::script()`. How that interacts with an embedded SSH server is
33unresolved — see [current.md]current.md#open-questions.
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
44STEID_DATA_DIR=./data # default; bare repos, used from M2
45```
46
47The bind address is **not** a `STEID_` variable — Topcoat owns it:
48
49```bash
50HOST=0.0.0.0 PORT=8080 cargo run
51```
ab7fea9chore: plans setup1mo
52
d7b99d9docs: record milestone 0 progress and routing findings1mo
53That supersedes attempt #2's `STEID_LISTEN_ADDR`.
ab7fea9chore: plans setup1mo
54
d7b99d9docs: record milestone 0 progress and routing findings1mo
55Arriving with Milestone 1 (#2) — owner bootstrap and registration policy:
ab7fea9chore: plans setup1mo
56
57```
58STEID_REGISTRATION=personal # personal | invite | open
59STEID_OWNER_EMAIL=admin@localhost.dev
60STEID_OWNER_PASSWORD=changeme
61STEID_OWNER_USERNAME=admin
62```
63
64In `personal` mode the owner account is bootstrapped from `STEID_OWNER_*` on first
d7b99d9docs: record milestone 0 progress and routing findings1mo
65boot. Keep `.env` and `.env.prod` out of git — both are gitignored.
ab7fea9chore: plans setup1mo
66
67## Repo layout on disk (#2)
68
69Bare repos at `{STEID_DATA_DIR}/{org}/{repo}.git`. Created empty — no initial commit.
70
71## SSH (#2)
72
73The SSH server is embedded (russh), not OpenSSH — there is no `authorized_keys`
74configuration and no forced command. Users register public keys through the web UI at
75`/{owner}/keys`, and the server matches incoming keys by SHA256 fingerprint.
76
77Host key generation and persistence was never written down. Sort it out during
78Milestone 3 and document it here — a host key regenerated on each boot means every
79client gets a changed-host-key warning.
80
81```bash
82git clone git@host:owner/repo
83```
84
85## Manual verification checklist (#2)
86
87Attempt #2 verified these by hand each milestone but never wrote down the steps. They
88are the smoke test for Milestones 2–4:
89
90- [ ] Create a repo via the web UI → bare repo appears at
91 `{data_dir}/{org}/{repo}.git`
92- [ ] `git clone` an empty repo → succeeds
93- [ ] `git clone` a repo with history → succeeds
94- [ ] `git clone` a non-existent repo → clean error, not a hang or panic
95- [ ] First push to an empty repo → succeeds
96- [ ] Push to a repo with history → succeeds
97- [ ] Clone with an unregistered key → `Permission denied`, exit 128
98- [ ] Register key via `/{owner}/keys` → clone and push both succeed
99- [ ] Revoke key via web UI → subsequent clone rejected at auth
100- [ ] Clone a private repo as a non-member → rejected
101- [ ] Push as a non-owner member → rejected
102
103Worth automating as an integration test rather than re-running by hand a fourth time.
104
105## Suggested `.gitignore` additions
106
107Not applied yet — no code to ignore. When the app lands:
108
109```
110/data
111*.db
112*.db-shm
113*.db-wal
114.env.prod
115```
116
117**Do not add `/plans`.** Attempt #2 did, and that is why these docs had to be
118hand-carried between repos.