File tags: store + API + chips in the details pane + filter (#530, 3/4) #540
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Cordy/Cairn#540
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Third slice of #530. Tags per file, entered as chips in the details pane's overview panel (per the OpenCloud reference), listable and filterable in browse/search.
Needs: a tag store (statestore pattern, survives redeploys per #153),
GET/PUTAPI per path plus a tag-filter query, chips UI in #538's overview panel, and tag propagation on rename/move/copy — Cairn keys by path, not stable file IDs, so tags must be re-keyed exactly like the activity feed (#539); trash/restore and delete need defined semantics (tags die with the file? survive restore?).Scope guard: instance-local flat tags, no hierarchies, no per-tag permissions. Backend TDD; i18n ×4.
Design note (build follows on approval-by-silence — flag anything off):
path → [tags]in.cairn-state/tags.json; flat instance-local tags, lowercase-normalized, per-file cap 20, simple charset rule (letters, digits, dash, space). No hierarchies, no per-tag permissions (the issue's scope guard).GET/PUT /api/v1/tags?path=(whole-list PUT, matching the settings idiom) andGET /api/v1/tags/find?tag=returning the caller's matching paths for the filter;resolveOwned-class handling, owner-only in v1.tag:foosyntax) rather than a new control.Shipped in v0.6.222 (PR #620, tag on
e7d7cd1), live on both dogfoods.Built per the design note:
internal/tags: path → tags beside recents/favorites (tags.json). Normalization: lowercase, trimmed, single-spaced, letters/digits/dash/space, ≤40 chars — mirrored in the UI aspure:tag-normso the input rejects instantly what the server would reject. Caps: 20 tags/item, 5000 tagged items per instance.GET/PUT /api/v1/tags?path=,GET /api/v1/tags/find?tag=. Every path passes a Stat through the caller's scoped store — including each find result, so tag search never leaks paths the caller couldn't browse.menuGates(...).mutate; hidden on read-only items that have no tags. Typingtag:fooin the search box lists everything with that tag. i18n ×4.Deliberate v1 edges — flag if they bite: