collin/anvil · 12249ca5
docs: trim TODO.md to outstanding work
Collin Richards · 2026-06-10 16:39 UTC · 12249ca50f6643c02c992530842d3d16b9cf2266 · parent 43da2588 · browse files
modifiedTODO.md+8 −84
| ⋯ 3 unchanged lines | |||
| 4 | 4 | - just displays it here — periodically fetched, read-only on the anvil side | |
| 5 | 5 | - [ ] pull requests (gix merge) | |
| 6 | 6 | - [ ] webhooks (mind the SSRF item in `docs/untrusted-mode.md`) | |
| 7 | - | ||
| 8 | - | ## Edit files in the web UI | |
| 9 | - | ||
| 10 | - | Edit a file in the browser and have anvil make a proper commit (author = the | |
| 11 | - | logged-in user, sensible message), written straight onto the branch with gix — | |
| 12 | - | no working tree. The new commit just advances the branch tip, so anyone who | |
| 13 | - | pushed earlier can fast-forward pull it. | |
| 14 | - | ||
| 15 | - | - [x] start minimal: an "Edit" button on the blob page → textarea → commit; | |
| 16 | - | commits build the tree/commit objects via gix and move the ref (reject if the | |
| 17 | - | branch moved under us — no non-fast-forward clobber). `anvil-git/src/edit.rs` | |
| 18 | - | does the CAS commit; `ui.rs` `edit_form`/`edit_submit` wire the page. | |
| 19 | - | - [x] a structured way to add items to `TODO.md` — an "Add task" form that | |
| 20 | - | appends a ticket (`## title`, the richer card style) to the right section per | |
| 21 | - | the todo-md round-trip rules (`todomd::add_task` / `task_sections`), rather | |
| 22 | - | than hand-editing the raw file | |
| 23 | - | - [ ] then richer editing: a real markdown editor with a live render preview | |
| 7 | + | - [ ] richer file editing: a real markdown editor with a live render preview | |
| 24 | 8 | (reuse `render_markdown`) before committing | |
| 25 | - | ||
| 26 | - | ## Image uploads (attachments stored outside git) | |
| 27 | - | ||
| 28 | - | Upload an image in the web editor and link to it from the markdown without the | |
| 29 | - | blob ever entering git history. Stored content-addressed per repo and served | |
| 30 | - | back; the file only carries the URL. | |
| 31 | - | ||
| 32 | - | - [x] store: content-addressed blobs at `data/attachments/{repo_id}/{sha256}`, | |
| 33 | - | deduped per repo; `Attachment` model maps repo_id/hash → content-type, size, | |
| 34 | - | uploader, created-at. Kept out of `repositories/` so it's never a git object. | |
| 35 | - | (`anvil-core`: `attachments`, `storage::attachment_path`, schema shim.) | |
| 36 | - | - [x] serve: `GET /{owner}/{repo}/-/attachments/{hash}`, read-access gated | |
| 37 | - | (private repos stay private), immutable cache + `nosniff` + locked-down CSP. | |
| 38 | - | - [x] upload: `POST /{owner}/{repo}/-/attachments` behind write-access + CSRF | |
| 39 | - | (`X-CSRF-Token` header), magic-byte sniffed to png/jpeg/gif/webp (SVG | |
| 40 | - | rejected), capped by `http.attachment_max_mb`, returns the markdown to splice. | |
| 41 | - | - [x] editor UX: paste or drop an image in the file editor → background upload → | |
| 42 | - | `` inserted at the cursor. | |
| 43 | - | - [x] caps: per-repo attachment quota (`http.attachment_quota_mb`, 0 = | |
| 44 | - | unlimited) — a new upload over the cap is rejected; deduped re-uploads are | |
| 45 | - | always free. (Reject, not evict: evicting would break live Markdown links.) | |
| 46 | - | - [x] carry attachments over git, credential-free: anvil mirrors each upload | |
| 47 | - | into `refs/anvil/attachments` (flat `hash → blob` tree, off the branch | |
| 48 | - | namespace). A default pull never fetches it; opt in with | |
| 49 | - | `git fetch origin '+refs/anvil/attachments:refs/anvil/attachments'` then | |
| 50 | - | `git cat-file -p refs/anvil/attachments:<hash>`. Disk+DB stay canonical; | |
| 51 | - | the ref is a downstream mirror (`anvil-git::attachments_ref`). All uploads | |
| 52 | - | remain web-only. | |
| 53 | - | - [ ] within-repo reclaim: an orphan sweep (delete attachments no committed file | |
| 9 | + | - [ ] attachment reclaim: an orphan sweep (delete attachments no committed file | |
| 54 | 10 | references) and/or a per-attachment delete action — the recourse once a repo | |
| 55 | 11 | hits its quota. Deferred: deletion is destructive and "orphaned" is fuzzy | |
| 56 | - | (tip-only vs any-ref), so it wants its own design pass. | |
| 12 | + | (tip-only vs any-ref), so it wants its own design pass | |
| 57 | 13 | - [ ] remove a repo's attachment + artifact dirs on repo delete — blocked: there | |
| 58 | - | is no repo-delete path yet (only the create-rollback uses it). | |
| 59 | - | ||
| 60 | - | ## Admin: site disk-usage dashboard | |
| 61 | - | ||
| 62 | - | - [x] `/-/admin/usage` (admin-only; 404 for everyone else, nav link for admins): | |
| 63 | - | actual on-disk bytes per user, broken down by content type (repositories / CI | |
| 64 | - | artifacts / attachments) with column + grand totals. `anvil-core::usage` | |
| 65 | - | walks the stores; `storage::dir_size` sums them. | |
| 66 | - | - [ ] maybe: per-repo drill-down, and a cheap cached/periodic variant if the | |
| 67 | - | on-demand disk walk gets slow on large instances. | |
| 68 | - | ||
| 69 | - | ## API tokens (read-only PATs) | |
| 70 | - | ||
| 71 | - | - [x] `ApiToken` model + `anvil-core::api_tokens` (create/list/revoke, SHA-256 | |
| 72 | - | hashed, scoped). CLI `anvild user token create|list|revoke`. | |
| 73 | - | - [x] bearer auth: `CurrentUser` also accepts `Authorization: Bearer <pat>` on | |
| 74 | - | GET/HEAD only — least-privilege read-only (writes need a session CSRF a bearer | |
| 75 | - | lacks). Lets tooling (and Claude) fetch private-repo attachments over HTTP. | |
| 76 | - | See the recipe in `CLAUDE.md`. | |
| 77 | - | - [x] token management on the user settings page (`/-/settings`): create (secret | |
| 78 | - | shown once), list, and revoke — ownership-enforced. | |
| 79 | - | - [ ] maybe later: a `write` scope (would need CSRF-exempt write paths) and | |
| 80 | - | `last_used_at` tracking. | |
| 81 | - | ||
| 82 | - | ## improve todo.md ui style | |
| 83 | - | ||
| 84 | - |  | |
| 85 | - | ||
| 86 | - | ||
| 87 | - | improve this part of the todo md ui. it looks bad. specifically the edit and add task buttons | |
| 88 | - | ||
| 89 | - | ## Ability to reorder tasks in todo.md | |
| 90 | - | ||
| 91 | - | I want to have the ability to reorder the tasks in the todo.md file. | |
| 92 | - | ||
| 93 | - | ||
| 94 | - | This is just a test image to test functionality of a different feature and ignore it for this ticket | |
| 14 | + | is no repo-delete path yet (only the create-rollback uses it) | |
| 15 | + | - [ ] admin usage: per-repo drill-down, and a cheap cached/periodic variant if | |
| 16 | + | the on-demand disk walk gets slow on large instances | |
| 17 | + | - [ ] API tokens: a `write` scope (would need CSRF-exempt write paths) and | |
| 18 | + | `last_used_at` tracking | |