Skip to main content

max / mountaineer

Consolidate todos: fold sysop/docs/todo.md into docs/todo.md Monorepo gets one todo. Per-subcommand implementation phases from sysop become the new 'Per-subcommand implementation' subsection under '## sysop CLI'. Deferred subcommands and tooling-deferred items move alongside. The 'Deferred (decided but not v1)' subsection is retitled 'sysop id deferred' since that's what it's about. Resolved bullets pruned: language is Rust (visible in the workspace), role->tool source-of-truth is data/roles.toml. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-18 03:25 UTC
Commit: ac50b7f000c35d6fbbd85a1c1791d905f6424e94
Parent: 7e8a0cf
2 files changed, +67 insertions, -80 deletions
M docs/todo.md +67 -3
@@ -170,8 +170,6 @@ Builds 11–16 (ISO-boots-and-installs era — full session details in `../build
170 170 - [x] **v1 scope: SSH only** — age and Nebula CA bindings deferred
171 171 - [x] **Signing-as-a-service is v1 design requirement** — operations split: *use* (sign/decrypt/derive — works on all backends including hardware) vs *extract* (read bytes — best-effort, fails on hardware-backed scopes). v1 must model this even though it only ships software-backed scopes
172 172 - [x] **SSH-specific shape decided**: `sysop id agent <scope>` returns ssh-agent socket, backends plug behind it (`file://`, `agent://`, `yubikey://` v2). Consumers set `SSH_AUTH_SOCK`. `sysop id sign` for non-ssh-agent cases. `sysop id export` is extract verb (always succeeds on `file://` in v1)
173 - - [ ] Language confirmed (likely Rust given ratatui)
174 - - [ ] Repo layout / source-of-truth for role→tool mapping (principle 15)
175 173 - [ ] Final subcommand list spec'd (sketch: `sysop id list/show/new/import/rotate/authorize/revoke/agent/sign/export`, `sysop id host show/rotate`)
176 174 - [ ] Reconcile route-assumed subcommands when sysop section opens
177 175 - [ ] STACK.md: dedicated `sysop` section (currently buried in ifupdown-ng paragraph)
@@ -186,7 +184,73 @@ Builds 11–16 (ISO-boots-and-installs era — full session details in `../build
186 184 - [ ] Hardware key bootstrap: how does `sysop id import --yubikey` work — discover-and-claim, or operator-supplied handle?
187 185 - [ ] Cross-host scope sync (two laptops): operator's problem (rsync/git) but needs defended recommendation in docs
188 186
189 - ### Deferred (decided but not v1)
187 + ### Per-subcommand implementation
188 +
189 + Status: MVP slice complete. `sysop info`, `sysop motd`, `sysop services`, `sysop storage`, `sysop wifi`, `sysop net` all run on host via mock-or-real backend auto-detection. Yambar producers ready for `svc`, `zfs`, `net`. `sysop wifi` is the first interactive subcommand (masked password input). Active: TBD — natural next is `sysop id` (large) or overlay/installer work in `../build/`.
190 +
191 + **sysop-tui primitives**
192 +
193 + - [ ] Re-verify on a real Mountaineer system (foot terminal, Iosevka, flatwhite-configured 24-bit color). Host-side macOS eyeball passed; values may still need tuning once foot/helix/zellij/yambar ship the matching theme
194 + - [ ] `Footer` right-align option (deferred until a subcommand needs a left status segment)
195 + - [ ] Help overlay primitive (`?` action classifies; no overlay renderer yet)
196 +
197 + **sysop info**
198 +
199 + - [ ] Version field on the detail screen (requires per-tool version queries — shell out to `<tool> --version`, parse, cache; defer until subprocess plumbing is settled)
200 + - [ ] Runtime override: layer `/etc/mountaineer/roles.toml` on top of the compiled-in defaults (principle 2 — operator can see/edit). Currently only `include_str!` source
201 + - [ ] Server vs Sysadmin profile filter — graphical-layer roles should be hidden in `--server` mode
202 +
203 + **sysop motd**
204 +
205 + - [ ] `/etc/profile.d/sysop-motd.sh` glue script — calls `sysop motd print` on login. Lives in `../build/apkovl-src/`
206 + - [ ] Tip set worth revisiting once more `sysop` verbs exist — currently 6, drawn from AESTHETICS
207 + - [ ] Decide whether `sysop motd print` should respect a "first-login-of-the-day" suppression to avoid tip spam in tmux-heavy sessions
208 +
209 + **sysop services**
210 +
211 + - [ ] Detail view per service: dependencies, log path, time-in-state. Needs `s6-svstat` shell-out
212 + - [ ] Enable / disable / restart verbs. Requires real s6-rc; can't be meaningfully mocked, gate on live-system testing
213 + - [ ] Reflect transient state from `s6-rc-update` runs (currently only Up/Down are derived from `s6-rc -a list` + `-d list`)
214 + - [ ] Backend mismatch indicator — if mock is active on what looks like a Mountaineer system, surface that as a fault
215 +
216 + **sysop storage**
217 +
218 + - [ ] Detail view: vdev tree, error counters (read/write/cksum), scrub progress. Needs `zpool status -P <name>` parsing
219 + - [ ] Dataset view: `zfs list` — separate verb (`sysop storage datasets`?) or filtered detail screen
220 + - [ ] Snapshot management — read-only first (list), write later
221 + - [ ] Scrub trigger verb. Same caveat as services enable/disable — gate on live system
222 +
223 + **sysop wifi**
224 +
225 + - [ ] Pre-scan: `iwctl station wlan0 scan` + brief wait before `get-networks`, so the cache is fresh on first invocation
226 + - [ ] `r` to rescan from the list view (calls iwctl scan, waits, refreshes)
227 + - [ ] Auto-detect interface name (currently hardcoded `wlan0`); `iwctl device list` is the source
228 + - [ ] Enterprise (8021x) flow — out of scope for MVP, currently a no-op on Enter; needs identity + cert/PEAP plumbing
229 + - [ ] iwctl `get-networks` text parsing is fragile; verify on a real Mountaineer install and adjust. D-Bus interface is the upgrade path if the text format proves too noisy
230 + - [ ] Disconnect verb (`sysop wifi disconnect`)
231 + - [ ] Promote the password input to a `sysop-tui` primitive once a second consumer exists (probably `sysop id` for passphrase entry)
232 +
233 + **sysop net**
234 +
235 + - [ ] SSID enrichment for wireless: read `/var/lib/iwd/` or `iwctl station <iface> show` to populate `ssid` on the real backend (mock already returns it)
236 + - [ ] Default route / gateway display (`ip -json route show default` parsing)
237 + - [ ] Resolver liveness check — show whether unbound is reachable on 127.0.0.1:53 (would also feed a future `sysop info resolver` detail screen)
238 + - [ ] Yambar `net` segment should reflect the active default-route interface, not just wired-first. Currently wired-first heuristic
239 + - [ ] Detail view: per-interface MAC, MTU, link speed (ethtool for wired)
240 +
241 + ### Deferred subcommands (post-MVP)
242 +
243 + - [ ] `sysop logs <service>` — lnav front
244 + - [ ] `sysop upgrade`, `sysop wg`, `sysop notifications mute`, `sysop podman-s6`
245 +
246 + ### sysop tooling deferred (post-MVP)
247 +
248 + - [ ] Tab completion (bash/zsh/nushell)
249 + - [ ] Man pages (mdoc; generated from clap?)
250 + - [ ] CI / reproducible builds story
251 + - [ ] Release artifact shape (static-linked musl binary in Alpine apk)
252 +
253 + ### `sysop id` deferred (decided but not v1)
190 254
191 255 - [ ] **Age slot in scopes** + per-host age recipient. Mesh route assumes age-encrypted bundles addressed to per-host recipients; v1-compatible variant needed (operator-decrypted-locally or scp over existing ssh path)
192 256 - [ ] **Nebula CA slot in scopes**. v1: mesh CA management is its own thing under `~/.config/mountaineer/nebula-ca/`, age-encrypted independently. Reunified when scope model is mature
@@ -1,77 +0,0 @@
1 - # sysop — todo
2 -
3 - Component of the Mountaineer monorepo. Cargo workspace; binary + primitives crate.
4 -
5 - Status: Pre-v0. MVP slice complete: `sysop info`, `sysop motd`, `sysop services`, `sysop storage`, `sysop wifi`, `sysop net` all run on host with mock-or-real backend auto-detection. Yambar producers ready for `svc`, `zfs`, `net`. First interactive subcommand (`wifi`) lands a masked password input. Active: TBD — natural next is `sysop id` (large) or pause sysop for overlay/installer work.
6 -
7 - ## Phase 1 — sysop-tui primitives (open items)
8 -
9 - - [ ] Re-verify on a real Mountaineer system (foot terminal, Iosevka, flatwhite-configured 24-bit color). Host-side macOS eyeball passed; the values may still need tuning once foot/helix/zellij/yambar ship the matching theme
10 - - [ ] `Footer` right-align option (deferred until a subcommand needs a left status segment)
11 - - [ ] Help overlay primitive (`?` action classifies; no overlay renderer yet)
12 -
13 - ## Phase 2 — `sysop info` (open items)
14 -
15 - - [ ] Version field on the detail screen (requires per-tool version queries — shell out to `<tool> --version`, parse, cache; defer until subprocess plumbing is settled)
16 - - [ ] Runtime override: layer `/etc/mountaineer/roles.toml` on top of the compiled-in defaults (principle 2 — operator can see/edit). Currently only `include_str!` source
17 - - [ ] Server vs Sysadmin profile filter — graphical-layer roles should be hidden in `--server` mode
18 -
19 - ## Phase 3 — `sysop motd` (open items)
20 -
21 - - [ ] `/etc/profile.d/sysop-motd.sh` glue script — calls `sysop motd print` on login. Lives in `../build/apkovl-src/`
22 - - [ ] Tip set worth revisiting once more `sysop` verbs exist — currently 6, drawn from AESTHETICS
23 - - [ ] Decide whether `sysop motd print` should respect a "first-login-of-the-day" suppression to avoid tip spam in tmux-heavy sessions
24 -
25 - ## Phase 4 — `sysop services` (open items)
26 -
27 - - [ ] Detail view per service: dependencies, log path, time-in-state. Needs `s6-svstat` shell-out
28 - - [ ] Enable / disable / restart verbs. Requires real s6-rc; can't be meaningfully mocked, gate on live-system testing
29 - - [ ] Reflect transient state from `s6-rc-update` runs (currently only Up/Down are derived from `s6-rc -a list` + `-d list`)
30 - - [ ] Backend mismatch indicator — if mock is active on what looks like a Mountaineer system, surface that as a fault
31 -
32 - ## Phase 6 — `sysop wifi` (open items)
33 -
34 - - [ ] Pre-scan: `iwctl station wlan0 scan` + brief wait before `get-networks`, so the cache is fresh on first invocation
35 - - [ ] `r` to rescan from the list view (calls iwctl scan, waits, refreshes)
36 - - [ ] Auto-detect interface name (currently hardcoded `wlan0`); `iwctl device list` is the source
37 - - [ ] Enterprise (8021x) flow — out of scope for MVP, currently a no-op on Enter; needs identity + cert/PEAP plumbing
38 - - [ ] iwctl `get-networks` text parsing is fragile; verify on a real Mountaineer install and adjust. D-Bus interface is the upgrade path if the text format proves too noisy
39 - - [ ] Disconnect verb (`sysop wifi disconnect`)
40 - - [ ] Promote the password input to a `sysop-tui` primitive once a second consumer exists (probably `sysop id` for passphrase entry)
41 -
42 - ## Phase 5 — `sysop storage` (open items)
43 -
44 - - [ ] Detail view: vdev tree, error counters (read/write/cksum), scrub progress. Needs `zpool status -P <name>` parsing
45 - - [ ] Dataset view: `zfs list` — separate verb (`sysop storage datasets`?) or filtered detail screen
46 - - [ ] Snapshot management — read-only first (list), write later
47 - - [ ] Scrub trigger verb. Same caveat as services enable/disable — gate on live system
48 -
49 - ## Phase 7 — `sysop net` (open items)
50 -
51 - - [ ] SSID enrichment for wireless: read `/var/lib/iwd/` or `iwctl station <iface> show` to populate `ssid` on the real backend (mock already returns it)
52 - - [ ] Default route / gateway display (`ip -json route show default` parsing)
53 - - [ ] Resolver liveness check — show whether unbound is reachable on 127.0.0.1:53 (would also feed a future `sysop info resolver` detail screen)
54 - - [ ] Yambar `net` segment should reflect the active default-route interface, not just wired-first. Currently wired-first heuristic
55 - - [ ] Detail view: per-interface MAC, MTU, link speed (ethtool for wired)
56 -
57 - ## Deferred (post-MVP scaffolding)
58 -
59 - - [ ] `sysop logs <service>` — lnav front
60 - - [ ] `sysop id` — identity subsystem (full design in `../../docs/todo.md`)
61 - - [ ] `sysop upgrade`, `sysop wg`, `sysop notifications mute`, `sysop podman-s6`
62 - - [ ] Tab completion (bash/zsh/nushell)
63 - - [ ] Man pages (mdoc; generated from clap?)
64 - - [ ] CI / reproducible builds story
65 - - [ ] Release artifact shape (static-linked musl binary in Alpine apk)
66 -
67 - ## Key Paths
68 -
69 - - `Cargo.toml` — workspace root
70 - - `crates/sysop/` — CLI binary
71 - - `crates/sysop-tui/` — shared TUI primitives (flatwhite, footer chrome, selection, reserved keys)
72 - - `../../docs/AESTHETICS.md` — committed aesthetic/UX picks the TUI must honor
73 - - `../../docs/MANIFESTO.md` — principles 1, 2, 14, 15 are the load-bearing ones for this component
74 - - `../../docs/STACK.md` — role→tool mappings consumed by `sysop info`
75 - - `../../docs/todo.md` — wider Mountaineer state and the `sysop id` design
76 - - `../../build/` — apkovl-src, installer, mkimg profiles (where overlay configs that consume `sysop` producers will live)
77 - - `/Users/max/Code/CONTRIBUTING.md` — cross-cutting rules