crabidy/plan/fs-provider.md

57 lines
3.2 KiB
Markdown

# Plan: fs-provider
Ordered tasks; each names its verification (tests in `fsdy/src/lib.rs`
and/or gates in `quality/fs-provider.md`). Stubs, tests, and workspace
wiring exist; all 13 fsdy tests fail on `todo!()` at plan time.
- [x] **T1 — `TrackFile::parse` + `playable()` validation.** TOML parse
into the schema structs; `playable()` enforces exactly-one, http(s)
scheme, absolute link, no `/fs` link. Verifies:
`parse_accepts_a_full_track_file`, `parse_defaults_optional_metadata`,
`parse_rejects_wrong_playable_cardinality`,
`parse_rejects_invalid_playables`; gate "link chains impossible".
- [x] **T2 — `TrackFile::to_track`.** Single conversion site; link rewrites
the path, file/url keep it; album/duration mapped. Verifies:
`to_track_rewrites_the_path_only_for_links`; gate "single
file-to-Track conversion".
- [x] **T3 — path scheme: `is_track_path` + `disk_path`.** Suffix+prefix
check; decode-validate-join with `.`/`..`/empty/separator rejection in
one helper. Verifies: `track_paths_need_the_suffix_and_the_provider_prefix`,
`client_paths_cannot_escape_the_root`; gate "one validation place".
- [x] **T4 — `init` + `settings`.** Parse `Settings`, default root
`dirs::audio_dir()`, `Config` error when neither; nonexistent root
accepted; write-back serialization. Verifies:
`settings_round_trip_through_the_config_write_back`,
`init_accepts_a_root_that_does_not_exist_yet`.
- [x] **T5 — `read_track_file` + `get_metadata_for_track` +
`get_urls_for_track`.** tokio::fs read, parse, playable dispatch
(relative file joined onto the track file's dir; link →
`MalformedPath` warn). Verifies: `urls_resolve_per_playable_kind`,
`metadata_of_a_link_track_carries_the_target_path`; gates "plain
paths/URLs only", "no file contents in logs".
- [x] **T6 — `list_dir` + `get_lib_node` + `get_lib_root`.** Sorted
case-insensitive listing; skip symlinks/hidden/non-UTF-8/foreign/
broken (warn with file name); encoded child paths; parent links.
Verifies: `listing_sorts_and_skips_foreign_hidden_and_broken_entries`,
`listing_a_missing_directory_is_an_error_not_a_panic`,
`nodes_link_back_to_their_parent`,
`resolving_a_tree_streams_chunks_in_listing_order`; gates "symlinks
skipped", "listing order = resolve order", "tokio::fs only".
- [x] **T7 — orchestrator wiring.** `fs_client: Option<Arc<fsdy::Client>>`
in `ProviderOrchestrator`; non-fatal init from `fsdy.toml` with
write-back; `/fs` arms in every trait method; root child only when
present; `crabidy-server/Cargo.toml` gains `fsdy`. Verifies: gates
under "Orchestrator wiring"; workspace build.
- [x] **T8 — full verification.** All fsdy tests + whole workspace suite
green; clippy/fmt/taplo/markdownlint clean; walk the remaining gates
and tick them; no `todo!()` left.
- [x] **T9 — live smoke test.** Build a real tree under a temp root
(nested dirs, a relative-file track, a url track, a `/tidal` link
track), run the server pointing at it, list `/fs` over the provider
layer, and resolve a directory — remove any temporary probe
afterwards. Verifies: end-to-end behavior of D2/D4 outside unit
scope.
- [x] **T10 — docs.** `plan/summary.md` section incl. deviations;
reconcile `architecture/fs-provider.md` if the implementation
diverged.