diff --git a/TODO.md b/TODO.md index 63345477..65e312ef 100644 --- a/TODO.md +++ b/TODO.md @@ -22,7 +22,7 @@ the owner's OS user and can never be granted. Indirection there really is accide ## Themes -**100 open, 31 closed**, across 33 themes. +**106 open, 31 closed**, across 33 themes. | Theme | Open | Closed | | ------------------------------------------------------------------------------------------ | ---- | ------ | @@ -34,18 +34,18 @@ the owner's OS user and can never be granted. Indirection there really is accide | [Chat interface](todo/chat/) | 1 | 0 | | [Code editor](todo/code-editor/) | 1 | 0 | | [Components — the shared UI layer](todo/components/) | 1 | 0 | -| [Documentation conventions — AGENTS.md vs CLAUDE.md](todo/docs-conventions/) | 1 | 0 | +| [Documentation conventions — AGENTS.md vs CLAUDE.md](todo/docs-conventions/) | 2 | 0 | | [File watchers](todo/file-watchers/) | 1 | 0 | -| [Fleet — one command across every server](todo/fleet/) | 5 | 2 | +| [Fleet — one command across every server](todo/fleet/) | 6 | 2 | | [Headscale](todo/headscale/) | 0 | 5 | | [Infra (alpha)](todo/infra/) | 7 | 0 | -| [Known bugs](todo/known-bugs/) | 5 | 4 | +| [Known bugs](todo/known-bugs/) | 6 | 4 | | [Memory — one store instead of per-harness files](todo/memory/) | 1 | 0 | -| [Mobile apps](todo/mobile-apps/) | 4 | 0 | +| [Mobile apps](todo/mobile-apps/) | 5 | 0 | | [Multi-user](todo/multi-user/) | 17 | 5 | | [Notifications](todo/notifications/) | 1 | 0 | -| [Plugin ecosystem — before it opens to third parties (2026-08-18)](todo/plugin-ecosystem/) | 4 | 0 | -| [Plugin infrastructure](todo/plugin-infrastructure/) | 2 | 0 | +| [Plugin ecosystem — before it opens to third parties (2026-08-18)](todo/plugin-ecosystem/) | 5 | 0 | +| [Plugin infrastructure](todo/plugin-infrastructure/) | 3 | 0 | | [Plugin repos — what writing their READMEs turned up](todo/plugin-repos/) | 10 | 9 | | [Plugin system — gaps the email extraction found (2026-08-18)](todo/plugin-system/) | 3 | 0 | | [Prompt library](todo/prompt-library/) | 1 | 0 | @@ -69,13 +69,13 @@ the owner's OS user and can never be granted. Indirection there really is accide ## Newest ten +- `2026-08-27` **AGENTS.md sweep — what is left after the static docs landed** — [docs-conventions/agents-md-remaining](todo/docs-conventions/agents-md-remaining.md) +- `2026-08-27` **The calendar/contacts skill has never been exercised by an actual agent** — [known-bugs/calendar-skill-never-used-by-an-agent](todo/known-bugs/calendar-skill-never-used-by-an-agent.md) +- `2026-08-27` **Setting up a phone for calendar and contacts should be one link inside Officer, not a manual account form** — [mobile-apps/setting-up-a-phone-should-be-a-link-in-the-app](todo/mobile-apps/setting-up-a-phone-should-be-a-link-in-the-app.md) +- `2026-08-27` **Marketplace: browse by tag — filter list, card grid, detail with a back button** — [plugin-ecosystem/marketplace-browse-by-tag](todo/plugin-ecosystem/marketplace-browse-by-tag.md) +- `2026-08-27` **A plugin that has a sidecar proxy loses the request body on its OWN routes** — [plugin-infrastructure/a-plugin-s-own-routes-lose-their-request-body](todo/plugin-infrastructure/a-plugin-s-own-routes-lose-their-request-body.md) - `2026-08-25` **An affordance: a scoped agent warns when a request lands outside its scope** — [affordances/an-affordance-a-scoped-agent-warns-on-the](todo/affordances/an-affordance-a-scoped-agent-warns-on-the.md) - `2026-08-25` **Commit signing is inconsistent across harnesses — Claude names itself, opencode names nothing** — [agent-coordination/commit-signing-is-inconsistent-across-harnesses](todo/agent-coordination/commit-signing-is-inconsistent-across-harnesses.md) - `2026-08-25` **A commander's watcher does not survive a reboot, and nothing says so** — [agent-coordination/a-commander-s-watcher-does-not-survive-a-reboot](todo/agent-coordination/a-commander-s-watcher-does-not-survive-a-reboot.md) - `2026-08-25` **Resurrect Projects/Apps** — [backburner/resurrect-projects-apps](todo/backburner/resurrect-projects-apps.md) - `2026-08-25` **Sweep: AGENTS.md becomes the real instructions everywhere, CLAUDE.md a pointer beside it** — [docs-conventions/sweep-agents-md-primary-claude-md-pointer](todo/docs-conventions/sweep-agents-md-primary-claude-md-pointer.md) -- `2026-08-25` **Refresh mid-turn folds the live tool call — it reads as finished while still running** — [known-bugs/refresh-mid-tool-call-renders-the-turn-folded](todo/known-bugs/refresh-mid-tool-call-renders-the-turn-folded.md) -- `2026-08-25` **The model picker shows `claude-code` instead of the model that is running** — [known-bugs/the-model-picker-shows-the-bare-harness](todo/known-bugs/the-model-picker-shows-the-bare-harness.md) -- `2026-08-25` **Understand how Claude and opencode do memory, then centralize both into one vector database** — [memory/understand-and-centralize-agent-memory-into-a](todo/memory/understand-and-centralize-agent-memory-into-a.md) -- `2026-08-25` **Deep-link a todo notification straight to that item's markdown** — [mobile-apps/deep-link-a-todo-notification-to-its-file](todo/mobile-apps/deep-link-a-todo-notification-to-its-file.md) -- `2026-08-25` **Add a favorites tab/panel to the file browser** — [multi-user/add-a-favorites-tab-panel-to-the-file-browser](todo/multi-user/add-a-favorites-tab-panel-to-the-file-browser.md) diff --git a/todo/fleet/register-ssh-servers-for-terminal-and-agent.md b/todo/fleet/register-ssh-servers-for-terminal-and-agent.md new file mode 100644 index 00000000..963a71b5 --- /dev/null +++ b/todo/fleet/register-ssh-servers-for-terminal-and-agent.md @@ -0,0 +1,54 @@ +--- +id: fleet/register-ssh-servers-for-terminal-and-agent-awareness +title: 'Let a systems admin register SSH-reachable servers, for the terminal and for agent awareness' +theme: fleet +status: open +created: 2026-08-25 +date_source: stated +order: 6 +--- + +**Give a systems admin a way to register SSH-reachable servers.** Wanted 2026-08-25. Two consumers of +one registry: the **terminal** can SSH into a registered machine directly, and **every agent session** +is told which servers exist and how to reach each one, so a mid-conversation request naming a server +("check disk on alpha") doesn't need the agent to guess an address or be taught one by hand — which is +exactly what this session has been doing ad hoc all week. + +**Nothing like this exists today — it is entirely informal.** `docs/servers.md` (written 2026-08-21) is +the closest thing, and it is a hand-maintained markdown file I built by SSHing around and writing down +what I found — not a registry, not admin-editable, not something an agent's preamble reads, and its own +opening line says why access works at all: "no `~/.ssh/config`, no passwords" — every machine is +reachable purely because the owner's key is already trusted there via Tailscale MagicDNS names. There is +no naming layer between "a machine on the tailnet" and "something Officer knows about." + +**This is the mechanism two already-filed items assume exists and don't build:** +`fleet/an-orchestrator-that-acts-on-every-server-at-once` wants to fan out across every server and +needs a machine-readable list to fan out over — today it reads `docs/servers.md` by hand, which is +exactly the gap this closes. `fleet/settings-to-choose-which-server-each-feature` wants to route one +feature (ReClip) to one server by name — the same registry is the thing a dropdown there would be +populated from. Build this once and both get a real backing store instead of a markdown file and a +hard-coded env var respectively. + +**Two things to settle deliberately rather than default into, both real product decisions:** + +- **Metadata only, or credentials too?** Every server this session reached was already trusted via the + owner's existing SSH key — nothing here needed a password or a stored secret. The cheap, low-risk + version of this registry is pure naming: host, tailnet address, login user, a label — an alias table + over trust that already exists. The moment it needs to hold a private key or a password for a NEW + identity, it becomes a secret-store problem (`todo/settings/`'s credential question applies + identically) and should be scoped that way explicitly rather than discovered halfway through building + the UI. +- **Who is "a systems admin" here, permission-wise, and it changes what "the terminal can SSH in" + means.** `terminal` is registered as `kind: 'confined'` + (`permissions/registry.ts:275`) — grantable, but only meaningful for an account with its own Linux + user (`authorize.ts` drops a confined grant otherwise). So if this is meant for an `Admin` role + member rather than only the owner, that account's terminal runs as **their own** OS user, not the + owner's — and the owner's existing "every host already trusts my key" story does NOT extend to them + for free. A granted admin registering a server they cannot yet actually SSH into (their own key isn't + on that box) is the failure mode to design against, not discover afterward. + +**The agent-awareness half is an affordance**, same delivery mechanism as gitea/image-rendering +(`capabilities/affordances/`, loaded per turn, no restart): the registry's contents rendered as a short +block naming each server and how to reach it, so a chat session already knows rather than needing the +owner to paste an address mid-conversation — which is the exact tax this session has been paying +manually every time a fleet question came up.