steid

@jamesgill /

steid/plans/current.md
4.1 KBCode·Blame·Raw
1# Current
2
3> Keep this file short. One active step, one ordered backlog. Completed work moves to
4> [progress.md]progress.md. If this file starts reading like a changelog, it has
5> drifted — that's exactly what went wrong last time.
6
7## Active: Milestone 0 — Skeleton
8
9**Goal:** a Topcoat app that boots, serves one page, reads config from env, and opens
10a SQLite pool. No domain logic yet. The point is to learn Topcoat's shape before
11committing the architecture to it.
12
13### Steps
14
15- [x] Add `topcoat` 0.5 + `tokio` to `Cargo.toml`
16- [x] Get the getting-started hello-world page rendering
17- [x] Work out how routing wants the source tree laid out — see
18 [routing findings]#routing-findings below
19- [x] Config from env via `envy` (`STEID_*`) — see [runbook.md]runbook.md
20- [x] SQLite pool registered as app context; page reads it via `app_context::<T>(cx)`
21- [ ] Install `topcoat-cli` and confirm `topcoat dev` watch/reload works
22- [ ] Decide the layering question in [architecture.md]architecture.md#open-question-topcoats-data-access-vs-clean-architecture
23 — this is the one genuinely open design question and it blocks Milestone 1
24
25### Done when
26
27`cargo run` serves a page that renders a value read from SQLite, with config supplied
28by env. **Met** — renders the SQLite version, and `STEID_DATABASE_URL` redirects it to
29a different file.
30
31### Routing findings
32
33- **Topcoat 0.5 requires rustc ≥ 1.95.** On an older toolchain `cargo add topcoat`
34 silently resolves to an empty `topcoat v0.0.0` placeholder instead of failing. Local
35 stable is now 1.97.1. Worth a `rust-toolchain.toml` if this ever builds on another
36 machine.
37- `Router::builder().discover()` collects `#[page]`-annotated items **at link time**,
38 so pages can live in any module. Layering is our choice, not the framework's — the
39 home page sits in `infrastructure/web.rs` per `architecture.md`.
40- `module_router!` is Topcoat's recommended alternative, deriving each URL from the
41 module tree rather than a path string. **Deferred to Milestone 1.** Steid's URL space
42 is parameterised at the root (`/{owner}`, `/{owner}/{repo}`, `/{owner}/keys`), which
43 means `path_param!` declarations inside route modules; worth designing once there are
44 real routes rather than guessing now.
45- Path and query params are read from `Cx` via `path_param!` / `#[query_params]`, not
46 injected as handler arguments. Parses are memoized per request.
47- Layouts wrap by path prefix and nest outermost-first, and a layout can catch a page's
48 `NotFoundError` to render a branded 404 — that replaces attempt #2's `not_found.html`.
49- `HOST` / `PORT` configure the bind address, so `STEID_LISTEN_ADDR` from attempt #2 is
50 gone. `runbook.md` reflects this.
51
52## Backlog
53
54Ordered. Pull from the top.
55
561. **Milestone 1 — Identity.** Domain model (User, Org, Membership, Actor, Role),
57 value objects (Email, PasswordHash), typed IDs, repository ports, Argon2 hashing,
58 registration policy, session cookies. Reference implementation exists and was
59 solid — port the domain layer, rewrite the web layer.
602. **Milestone 2 — Repo model.** `Repository` entity, `Visibility`, `create_repo` use
61 case, bare repo on disk at `{data_dir}/{org}/{repo}.git`. Watch the
62 DB-plus-filesystem atomicity problem — see
63 [architecture.md]architecture.md#db-plus-filesystem-writes.
643. **Milestone 3 — Git over SSH.** `GitProtocolServer` port, `GitBinary` adapter,
65 embedded russh. Channel-splitting is fiddly; the notes in
66 [progress.md]progress.md#ssh-channel-bridging are hard-won.
674. **Milestone 4 — SSH key auth + authz.**
68
69## Open questions
70
71- **Topcoat is nine days old** (v0.5.0, first release 2026-07-22, breaking changes
72 expected). Pin the exact version and expect to chase it. Budget time for churn that
73 isn't feature work.
74- Does Topcoat's asset/CSS pipeline coexist with an embedded russh server in one
75 binary, or does the CLI's watch-and-rebuild model push SSH into a separate process?
76 Unresolved — affects the embedded-SSH approach and single-binary deploy.
77- Topcoat ships Tailwind without Node. That reopens the design system from attempt #1
78 that was dropped purely to avoid an npm build step — see [ui.md]ui.md.