TODO.md had reached 1050 lines and 72 open items across 28 sections, read mostly on a phone. It is now a directory: todo/<theme>/<item>.md, one card per file, with frontmatter carrying id, status, created date and order, and the prose body copied across verbatim. TODO.md becomes a generated index (bun run todo:index). Dates: where an item's prose stated one it is used; otherwise its old section's; otherwise 2026-08-20, floored at the day before the split rather than invented. date_source records which. Shaped for a two-way Kanban board, filed as todo/tooling — a card is a file, id is the identity, frontmatter is the machine's half and the body is the owner's. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
853 B
853 B
id, title, theme, status, created, date_source, order
| id | title | theme | status | created | date_source | order |
|---|---|---|---|---|---|---|
| multi-user/a-second-super-admin-was-storable-and-made | A second Super Admin was storable, and made the owner nondeterministic | multi-user | done | 2026-08-11 | stated | 9 |
A second Super Admin was storable, and made the owner nondeterministic. Fixed 2026-08-11.
ck_users_owner_is_super_admin pins user 1's role but a row-level CHECK cannot see other rows, and
updateUserRoleHandler happily promoted anyone — while getOwnerUser() was
WHERE role='Super Admin' LIMIT 1 with no ORDER BY. Two holders would have made "who owns this
server" a question the query plan answered, and that answer feeds the agent sidecar's identity,
vault access and origin scoping. Both write paths now refuse the role, the list endpoint offers
assignableRoles without it, and getOwnerUser() orders by id.