103 lines
5.8 KiB
Markdown
103 lines
5.8 KiB
Markdown
# Quality gates — the `orphans` provider
|
|
|
|
Gates for `architecture/orphans.md` and the `crabidy-server/src/orphans.rs`
|
|
stub. Each is pass/fail by reading/reasoning or by a named test. Tests live in
|
|
`crabidy-server/src/crabidy_store.rs` (the store methods) and
|
|
`crabidy-server/src/orphans.rs` (the provider), run via
|
|
`devenv shell -- cargo test -p crabidy-server`.
|
|
|
|
## Correctness of the orphan diff
|
|
|
|
- [ ] **G1 — All items enumerated.** `list_orphans` counts every store entry
|
|
that has both a `<name>.cbd-store.toml` sidecar and a readable `<name>` audio
|
|
file. Test: capture two distinct tracks (two store entries), reference
|
|
neither → both listed.
|
|
- [ ] **G2 — Referenced entries excluded.** An entry referenced by a
|
|
`Playable::Store` toml under **any** `ref_root` is not listed. Test: capture
|
|
one track into a `/crabidy` save (which writes a store toml), then
|
|
`list_orphans` with that tree as a ref root → the entry is **not** an orphan;
|
|
delete the save's toml → it **becomes** an orphan.
|
|
- [ ] **G3 — `/fs` references count.** A `Playable::Store` toml under the `/fs`
|
|
root (as `scan --capture` writes) excludes its target. Test: hand-write a
|
|
store toml under an fs ref root → its target is not an orphan.
|
|
- [ ] **G4 — References outside ref roots do not count.** A store toml under a
|
|
directory that is **not** a ref root does not rescue its target from being an
|
|
orphan (documented boundary). Test asserts the target is still listed.
|
|
- [ ] **G5 — Malformed residue is reclaimable.** A sidecar with no audio (or
|
|
audio with no sidecar) is reported as an orphan, never as "referenced". Test:
|
|
drop a lone `x.cbd-store.toml` into the store → listed.
|
|
- [ ] **G6 — Fresh every call.** No persisted orphan list; two consecutive
|
|
`list_orphans` calls straddling a reference change reflect the change
|
|
(covered by G2's two-phase assertion).
|
|
|
|
## Presentation contract (reuse, no new wire)
|
|
|
|
- [ ] **G7 — Child capability flags.** Every `/orphans` child advertises
|
|
`is_queable`, `is_editable`, `is_deletable`, and `is_captured` all `true`, and
|
|
`is_downloadable = false`. The root is `is_queable = true`, `is_creatable =
|
|
false`. Verified by reading `get_lib_node`; test asserts the flags on a listed
|
|
child.
|
|
- [ ] **G8 — Leaf carries exactly one track.** `get_lib_node("/orphans/<seg>")`
|
|
returns a childless, queueable node with one track whose `is_captured` is true
|
|
and whose metadata matches the sidecar. Test asserts `tracks.len() == 1` and
|
|
`children.is_empty()`.
|
|
- [ ] **G9 — Queueing resolves the audio.** Resolving an orphan node (default
|
|
walk) yields one track whose `get_urls_for_track` returns `store_root/<name>`.
|
|
Test drives `resolve_tracks_into("/orphans")` and checks the resolved URL is
|
|
the store path.
|
|
- [ ] **G10 — No proto/TUI/web change.** Confirm by inspection that the feature
|
|
adds no field to any `proto` message and no binding/gesture to `cbd-tui` or
|
|
`cbd-web`: it relies solely on existing `is_editable`/`is_deletable`/
|
|
`is_queable` handling. (If this gate cannot hold, the design in
|
|
`architecture/orphans.md` must be revisited before implementing.)
|
|
|
|
## Rename safety
|
|
|
|
- [ ] **G11 — Renames both files.** `rename_orphan(old, new)` renames the audio
|
|
`<old>`→`<new>` **and** `<old>.cbd-store.toml`→`<new>.cbd-store.toml`; neither
|
|
old name remains on disk. Test.
|
|
- [ ] **G12 — Rename updates the index.** After a rename, the index resolves the
|
|
same content hash / provider ids to the **new** name and no longer to the old
|
|
(so a subsequent capture de-dups against the renamed entry). Test via
|
|
`StoreIndex` lookups or a follow-up capture.
|
|
- [ ] **G13 — Rename validates and refuses collisions.** An empty / separator /
|
|
leading-dot `new` is rejected (`InvalidInput`); a `new` already taken by
|
|
another store audio or sidecar is refused without touching disk. Tests for
|
|
both.
|
|
- [ ] **G14 — Rename is reference-safe by construction.** Only unreferenced
|
|
entries are exposed under `/orphans`, so a rename never invalidates a live
|
|
toml. Verified by reasoning against the diff definition; no test needed beyond
|
|
G2.
|
|
|
|
## Delete safety
|
|
|
|
- [ ] **G15 — Deletes both files.** `delete_orphan(name)` removes the audio and
|
|
the sidecar and drops the entry from the index. Test asserts both files gone
|
|
and `list_orphans` no longer lists it.
|
|
- [ ] **G16 — Idempotent.** Deleting an already-gone entry returns `Ok` (a
|
|
refreshed root), not an error. Test.
|
|
- [ ] **G17 — Delete stays inside the store root.** The name is a validated bare
|
|
file name; delete joins it onto `store_root` and never follows separators or
|
|
`..`. Verified by reasoning (mirrors `Playable::Store` bare-name validation)
|
|
plus a test that a crafted `/orphans/..%2Fx` path is `MalformedPath`, not a
|
|
file operation.
|
|
|
|
## Always-on rules (AGENTS.md)
|
|
|
|
- [ ] **G18 — No panics on input or I/O.** Every error path (missing entry,
|
|
unreadable dir, bad toml, taken rename target, malformed path) is a typed
|
|
`ProviderError`/`StoreError`; no `unwrap`/`expect`/`panic!`/`todo!` remains in
|
|
shipped code. A bad sidecar or track toml during the walk is skipped with a
|
|
warning, never fatal (mirrors `StoreIndex::scan` and `fsdy` listing).
|
|
- [ ] **G19 — Bounded work, no unbounded channels.** The reference walk and
|
|
enumeration use ordinary async fs iteration; if any channel is introduced it
|
|
is bounded. No new external calls (so no timeout/retry surface is added).
|
|
- [ ] **G20 — Public items documented.** Every public item in `orphans.rs` and
|
|
every new public `CrabidyStore`/`fsdy::Client` method has a doc comment
|
|
stating intent and error behavior.
|
|
- [ ] **G21 — Mount is optional and non-fatal.** `/orphans` mounts only when the
|
|
store is present; its absence (no data/state dir) drops the subtree without
|
|
affecting the server, exactly like `/crabidy` and `/fs`. `get_lib_root`
|
|
includes the `orphans` child only when mounted. Verified by reading the
|
|
orchestrator wiring.
|