steid

@jamesgill /

steid/plans/runbook.md
3.6 KBCode·Blame·Raw
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
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)
18
19## Dev setup
20
21```bash
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 # working
29```
30
31`topcoat dev` builds, bundles assets, watches sources, and live-reloads pages that
32include `topcoat::dev::script()`. Press `r` to force a rebuild.
33
34## Configuration
35
36`STEID_`-prefixed env vars via `dotenvy` + `envy`, read into `AppConfig`. Every value
37has a default, so a bare `cargo run` works with no environment at all.
38
39Live now:
40
41```
42STEID_DATABASE_URL=sqlite:steid.db?mode=rwc # default
43STEID_DATA_DIR=./data # default; bare repos, used from M2
44```
45
46The bind address is **not** a `STEID_` variable — Topcoat owns it:
47
48```bash
49HOST=0.0.0.0 PORT=8080 cargo run
50```
51
52That supersedes attempt #2's `STEID_LISTEN_ADDR`.
53
54Arriving with Milestone 1 (#2) — owner bootstrap and registration policy:
55
56```
57STEID_REGISTRATION=personal # personal | invite | open
58STEID_OWNER_EMAIL=admin@localhost.dev
59STEID_OWNER_PASSWORD=changeme
60STEID_OWNER_USERNAME=admin
61```
62
63In `personal` mode the owner account is bootstrapped from `STEID_OWNER_*` on first
64boot. Keep `.env` and `.env.prod` out of git — both are gitignored.
65
66## Repo layout on disk (#2)
67
68Bare repos at `{STEID_DATA_DIR}/{org}/{repo}.git`. Created empty — no initial commit.
69
70## Git transport (Milestone 5)
71
72Smart HTTP, delegated to `git http-backend`, authenticated with personal access tokens
73over HTTP Basic — see [0001]decisions/0001-git-over-http-not-ssh.md. No SSH, no host
74keys, no `authorized_keys`.
75
76```bash
77git clone http://host/owner/repo.git
78```
79
80Fill in the token workflow and the `body_limit` setting once this is built.
81
82## Manual verification checklist (#2)
83
84Attempt #2 verified these by hand each milestone but never wrote down the steps. They
85are the smoke test for Milestones 4–5. The auth rows assumed SSH keys; the shape of
86the check still holds with tokens substituted:
87
88- [ ] Create a repo via the web UI → bare repo appears at
89 `{data_dir}/{org}/{repo}.git`
90- [ ] `git clone` an empty repo → succeeds
91- [ ] `git clone` a repo with history → succeeds
92- [ ] `git clone` a non-existent repo → clean error, not a hang or panic
93- [ ] First push to an empty repo → succeeds
94- [ ] Push to a repo with history → succeeds
95- [ ] Push a repo large enough to exercise the `body_limit` cap → succeeds
96- [ ] Clone with no credentials → rejected, and the prompt is comprehensible
97- [ ] Clone with a valid token → succeeds
98- [ ] Revoke the token → subsequent clone rejected at auth
99- [ ] Clone a private repo as a non-member → rejected
100- [ ] Push as a non-owner member → rejected
101
102Worth automating as an integration test rather than re-running by hand a fourth time.
103
104## `.gitignore`
105
106Applied: `/target`, `/data`, `*.db*`, `.env`, `.env.prod`.
107
108**Do not add `/plans`.** Attempt #2 did, and that is why these docs had to be
109hand-carried between repos.