57 lines
3.2 KiB
Markdown
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.
|