anvilsign in

collin/anvil

BoardRenderedSource

1# Todo
2
3- [ ] pull mirror (maybe): a repo that virtually mirrors a GitHub repo
4 - just displays it here — periodically fetched, read-only on the anvil side
5- [ ] pull requests (gix merge)
6- [ ] webhooks (mind the SSRF item in `docs/untrusted-mode.md`)
7
8## Edit files in the web UI
9
10Edit a file in the browser and have anvil make a proper commit (author = the
11logged-in user, sensible message), written straight onto the branch with gix —
12no working tree. The new commit just advances the branch tip, so anyone who
13pushed 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
24 (reuse `render_markdown`) before committing
25
26## Image uploads (attachments stored outside git)
27
28Upload an image in the web editor and link to it from the markdown without the
29blob ever entering git history. Stored content-addressed per repo and served
30back; 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 `![image](url)` 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
54 references) and/or a per-attachment delete action — the recourse once a repo
55 hits its quota. Deferred: deletion is destructive and "orphaned" is fuzzy
56 (tip-only vs any-ref), so it wants its own design pass.
57- [ ] 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## UI polish (done)
83
84- [x] less vertical padding at the top of the screen (`main` top padding 24→12px)
85- [x] kanban card details: the disclosure toggle restyled to a clean uppercase
86 marker, and the expanded detail text is no longer de-emphasized (full `--fg`,
87 not muted)
88- [x] kanban card images constrained to the card width (`max-width:100%`); they
89 were rendering at natural size on the board while fine on the rendered page
90
91## implement delete task
92
93Implement delete task functionality from the todo.md editor.
94
95## improve todo.md ui style
96
97![image](/collin/anvil/-/attachments/ba1acb93ed73946496a070f018181892fc3ff786a19b92c305ad0623515d41a6)
98
99
100improve this part of the todo md ui. it looks bad. specifically the edit and add task buttons
101
102## Ability to reorder tasks in todo.md
103
104I want to have the ability to reorder the tasks in the todo.md file.
105
106
107This is just a test image to test functionality of a different feature and ignore it for this ticket![image](/collin/anvil/-/attachments/f27ccfc35cee6b280a1df2124b356d81bfebb3a70ae964d582595ed3a1000f3e)