Files
platform/todo
pastilhasandClaude Opus 5 a15fadbddc 27 tests on the file standing between a member and a shell
authorize.ts had none, and its own header is what says why that mattered: every deny path in the platform
ends there, and the failure mode of a permissive default is not a bug report, it is someone else's session.

It had none for a structural reason rather than an oversight. Every path needed two database calls, and the
only file here that mocks officerdb leaks its stub into whatever runs after it — so the obvious approach
would have traded one untested file for a flaky suite.

So the decisions are split from the fetching. resolveEffectivePermissions, decideApiRequest and
decideWsProvider are pure functions of their arguments; the async wrappers keep the role cache, the
fail-closed catches and the shape callers use. No behaviour change, and the live gate still answers 401 on
file-browser, users and tasks.

REAL registry keys throughout, deliberately: a suite built on invented permissions keeps passing after a
rename, which is the failure an authorization table can least afford. If a key here disappears this file
goes red.

Pinned beyond the happy paths — the owner carries no grants to consult; core is write unconditionally; a
confined grant is dropped without a Linux user and all three drop together; execution and admin grants in
the table are ignored even though no CHECK stops the row existing; an unknown key is ignored without
disturbing what is legitimately held; self-service is exact in method AND path; a socket needs no level; an
unauthenticated caller is refused every door.

Two gaps are stated in the file rather than left to be found: ownerOnly has no declaring permission yet, so
testing it would test the fixtures; and the grant cache's contract is a claim about call sites, not logic.

Found while writing them: readOnlyWrites paths are relative to the permission's api prefix, and getting that
wrong fails as "no permission covers this path" rather than as a level error — a misleading message for a
misleading path, now commented at the test that hit it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 04:42:56 +00:00
..

todo/ — the format

One item per file. A file is a card. That is the whole idea, and everything below follows from it.

It replaced a single 1,050-line TODO.md on 2026-08-21, which had reached 72 open items across 28 sections and was read mostly on a phone. The split was mechanical — no prose was rewritten.

Layout

todo/
├── README.md          # this file
├── <theme>/
│   ├── _index.md      # the theme itself: display name, and any prose that belongs to the whole group
│   └── <item>.md      # one item

The theme is the directory. _index.md carries the theme's display heading, so a theme is self-describing and nothing has to hold a slug→name map. TODO.md at the repository root is the generated index over all of it — bun run todo:index.

An item

---
id: fleet/an-orchestrator-that-acts-on-every-server-at
title: 'An orchestrator that acts on every server at once'
theme: fleet
status: open
created: 2026-08-21
date_source: stated
order: 1
---

**An orchestrator that acts on every server at once** — pull and update every platform, restart a
process everywhere, report which host is behind…
  • id — <theme>/<slug>, and it is the filename. Stable: rename the title freely, leave the id alone. Anything pointing at an item points at this.
  • status — open or done today. The board will want more (doing, blocked); adding one is a new value here, not a new file or a new directory.
  • created — the date the item was raised. date_source says how much to trust it: stated (the prose named a date — true), section (inherited from its old section heading — close), assumed (unknown, floored at 2026-08-20, the day before the split — a bounded "before today" rather than an invented day).
  • order — position within the theme, preserved from the original list. What a board reorders.
  • priority (optional) — urgent when the owner says so, absent otherwise. There is no scale of five: an item is either something he named as urgent or it is not, and a scale would only invite everything to drift upward. Urgent items are listed first in the generated index.
  • due (optional) — a date the owner named. Only ever written because he said one; never inferred from tone or from how the item is worded.
  • The body is prose, and it is the point. These entries carry the reasoning, what was verified versus assumed, and what was already tried. An item stripped to a title loses the thing that made this list worth keeping.

Two-way sync — the contract for the Kanban board

A board that reads this tree and writes back to it is a wanted feature (todo/prompt-library/… see todo/tooling/). What it may rely on:

  • A card is a file. Creating a card creates a file; moving a card between columns rewrites one frontmatter field; deleting a card deletes a file. Every board action is a small, reviewable git diff.
  • id is the identity, not the title and not the line number. Renaming or rewording never orphans a card.
  • Frontmatter is the machine's half, the body is the human's half. A board may rewrite frontmatter freely. It must not reformat a body it did not change — the prose is hand-written and a normalising pass would produce a diff nobody can read.
  • TODO.md is generated output. A board must never write to it; it regenerates from the tree.
  • Git is the sync log. No lock file and no sidecar state: the file on disk is the truth, and two writers are resolved the way every other conflict in this repository is.