the catalogue was the only way a remote plugin could arrive, so "build one and give it to a friend" had no route. the first real case is a plugin that must never be listed: fofos/fofos-admin is one website's admin panel, useful to exactly one person. MUCH smaller than the todo assumed. fetchPlugin already cloned, validated the URL, refused to overwrite an existing directory, checked for a manifest and removed a failed clone. exactly one line tied it to the marketplace — where the string came from. so this is a source parameter threaded through, and a route. THE NAME COMES FROM THE REPOSITORY, because appName is the DIRECTORY name and is never declared in a manifest — the id cannot disagree with where the code sits. that decision is inherited here rather than remade: the repo name becomes the directory, the route segment, the table prefix and the sidecar suffix. so it is checked against ^[a-z0-9]+(-[a-z0-9]+)*$ BEFORE anything is cloned; a half-clone under an unusable name reads as a broken plugin rather than an absent one. the URL is validated identically whether it came from the catalogue or from a person, because the catalogue is not a trust boundary — it is just where a string came from, and the same string reaches the same argv. what differs is who may ask: this route is owner-only, and the owner is choosing what code runs rather than choosing from a list somebody curated. validation is not review, and nothing here reads what it cloned. caught by testing: the source reached installPlugin and stopped there — the fetchPlugin call still had the old two arguments, so a URL install fell back to the catalogue and failed with "no catalogue entry". the guard tests are what surfaced it, because the error named the wrong cause. verified end to end against fofos-admin — cloned, schema applied, mounted, dock pinned — then purged, since officer-dev is not that website's machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
6.3 KiB
TODO — the index
Deferred work. The items live in todo/, one file each, grouped by theme; this file is the map
over them and is GENERATED — run bun run todo:index after any change rather than editing it here.
Format and the two-way-sync contract: todo/README.md. Browse and edit it at /todos in the app.
Context, corrected 2026-08-07. This list used to open by saying Officer was "collapsing from multi-tenant / open-source-ready to a single-user platform", and told you to treat multi-tenant indirection as accidental complexity. That direction was reversed. The permission model shipped on 2026-08-07 to serve a real goal — deploy to the company server, onboard people, give each one their own Gitea account through the platform. Per-user scoping is now a requirement, and the items that proposed deleting it have been removed rather than left to mislead the next reader.
What did NOT reverse: execution permissions (terminal, chat, tasks, files, desktop, browser) run as
the owner's OS user and can never be granted. Indirection there really is accidental complexity.
Urgent
- due 2026-08-22 — Settings to choose which server each feature uses — fleet/settings-to-choose-which-server-each-feature
- An affordance: a scoped agent warns when a request lands outside its scope — affordances/an-affordance-a-scoped-agent-warns-on-the
- A commander's watcher does not survive a reboot, and nothing says so — agent-coordination/a-commander-s-watcher-does-not-survive-a-reboot
Themes
106 open, 33 closed, across 34 themes.
Records — no items, kept for the reasoning
- Affordances (2026-08-19)
- Inputs outside forms (2026-08-19) — swept, fixed, closed
- Release-binary dependencies (2026-08-19)
Newest ten
2026-08-27Turn an ordinary chat into a commander or a bot, carrying its context along — agent-coordination/turn-a-chat-into-a-commander-or-a-bot2026-08-27The calendar API cannot express repeating events, reminders, invitees or a cancelled occurrence — calendar/the-json-api-cannot-express-recurrence-alarms2026-08-27AGENTS.md sweep — what is left after the static docs landed — docs-conventions/agents-md-remaining2026-08-27The calendar/contacts skill has never been exercised by an actual agent — known-bugs/calendar-skill-never-used-by-an-agent2026-08-27Setting 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-app2026-08-27Marketplace: browse by tag — filter list, card grid, detail with a back button — plugin-ecosystem/marketplace-browse-by-tag2026-08-25An affordance: a scoped agent warns when a request lands outside its scope — affordances/an-affordance-a-scoped-agent-warns-on-the2026-08-25Commit signing is inconsistent across harnesses — Claude names itself, opencode names nothing — agent-coordination/commit-signing-is-inconsistent-across-harnesses2026-08-25A commander's watcher does not survive a reboot, and nothing says so — agent-coordination/a-commander-s-watcher-does-not-survive-a-reboot2026-08-25Resurrect Projects/Apps — backburner/resurrect-projects-apps