Code review of the Artist/ownership refactor surfaced three gaps:
- SyncUser updated User.Name on every login but never the linked
Artist row, so renames never reached track credits - defeating the
point of centralizing names in Artist.
- YouTubeTrackProvisioner looked up artists by ExternalId only when a
browseId was known, so it could never reuse the ExternalId-less
rows the migration backfilled from legacy Artist strings, creating
duplicate Artist rows for the same person. It now adopts the
backfilled row (assigning it the browseId) when one matches by
normalized name.
- AddArtistsAndTrackOwnership deduped legacy YouTube artist strings
case-sensitively before hashing them into a case-insensitive unique
index, and never guarded against local tracks with no UserHasTrack
row - either would abort the migration on real data. Backfill now
dedupes via DISTINCT ON over the normalized name and drops orphaned
local tracks before the ownership check constraint is added.
One file per use case under the feature folder (Tracks/PlayLists/Users),
dropping the Commands/Queries/Handlers sub-folders and their namespaces.
Each file now holds the record and its handler in namespace
Musify.Application.<Feature>; external usings updated accordingly.
Build: 0 warnings, 0 errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ardalis Result<T> carried incoherent success sub-statuses and a clunky
generic converter; ErrorOr models success-or-errors cleanly.
- Application: all commands/queries/handlers now return ErrorOr<T>
(non-generic Result -> ErrorOr<Success>); errors via Error.NotFound/
Conflict/Validation/Unauthorized/Failure; success via value or new Success()
- Drop ResultExtensions.As<>(): error propagation is now just return .Errors
- Rewrite HTTP mapping (ErrorOrHttpExtensions) off Error.Type; success maps
to 200 (value) or 204 (Success); Created still built in the endpoints
- Endpoints/gateway middleware: !IsSuccess -> IsError
- Swap Ardalis.Result package for ErrorOr 2.1.1 (remove unused ref from Worker)
Build: 0 warnings, 0 errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Move all .NET (6 projects, solution, Directory.*.props, nuget.config)
into backend/ so the monorepo root can host non-.NET projects later
- Remove throwaway test artifacts: player.html, pl.json
- Trim dead Flutter rules from .gitignore
Build from backend/Musify.slnx: 0 warnings, 0 errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>