diff --git a/TODO.md b/TODO.md index 8f67cde0..e9aec6c2 100644 --- a/TODO.md +++ b/TODO.md @@ -32,7 +32,7 @@ Deferred work. Context: Officer is collapsing from multi-tenant / open-source-re on the real 18k-mail DB. Search box placeholder hints at operators. - [x] **`OR`** (done 2026-07-24, `85d38fb`). Query splits on top-level uppercase `OR` into branches; each branch is a self-contained condition (`id IN (FTS subquery)` + its SQL filters) and - branches are OR'd — so OR works across full-text *and* structured filters. Verified on the 18k + branches are OR'd — so OR works across full-text _and_ structured filters. Verified on the 18k DB (`from:github OR from:deepgram` = 90+7 = 97 exactly). - [ ] **Remaining:** parenthesised grouping (nesting `(a OR b) c`), `in:sent/inbox/spam/trash` (folder scope), and relative dates (`newer_than:7d`). Grouping needs a recursive parser. @@ -61,10 +61,9 @@ Deferred work. Context: Officer is collapsing from multi-tenant / open-source-re - [ ] **Sender/domain management view.** Left panel: controls to group mail **by sender** or **by domain** (room for more grouping axes later). From a group, run bulk actions on that sender/domain: **unsubscribe + mark irrelevant**, **delete all mail** from it, **block/ignore - future incoming**, etc. Think "inbox cleanup / triage" — operate on a whole sender at once. - - Needs: aggregate query (count/size per sender + per domain), a block/ignore list the - sync/IDLE path honors on incoming, an unsubscribe action (List-Unsubscribe header / link), - and bulk delete over a sender/domain. + future incoming**, etc. Think "inbox cleanup / triage" — operate on a whole sender at once. - Needs: aggregate query (count/size per sender + per domain), a block/ignore list the + sync/IDLE path honors on incoming, an unsubscribe action (List-Unsubscribe header / link), + and bulk delete over a sender/domain. - [ ] **Chat view.** The existing AI email-assistant flow — likely stays roughly as-is, just lives as one of the tabs (main view). - Open question: tabs vs. some other view switcher; which view is default. @@ -99,6 +98,25 @@ it exists in the reference app, so none of it was in scope for parity. Transmission is the third door to it. Worth a think about whether they should know about each other at all. +## Headscale + +Gaps against headscale's own API, found while reading the app on 2026-08-05. None is urgent; the +first is the only one you would otherwise SSH in to do. + +- [ ] **ACL policy is not wired at all.** `/api/v1/policy` (GET/PUT) has no sidecar route and no + screen. Editing the policy means SSHing to the host, which is the one thing this app exists to + avoid. Wants a text editor with the server's own validation error surfaced on save, not a + form — the policy is HuJSON and headscale is the authority on whether it parses. + +- [ ] **A node cannot be moved between users.** `/api/v1/node/{id}/user` is missing, so a node can be + renamed, tagged, route-approved and expired, but not re-owned. + +- [ ] **Users are create/delete/list only.** No rename (`/api/v1/user/{id}/rename/{newName}`). + +- [ ] **Nothing refreshes.** No query in `useHeadscaleData.ts` polls, so a node going offline (or + coming back) only appears on a manual reload. A modest `refetchInterval` on the nodes list is + probably the whole fix. + ## Known bugs - [ ] **`bootstrap.ts` runs `npm install -g` for Pi on every boot.** `findPiPackageDir` checks stale