metaedit

0003. Treat UpdateItem as a full overwrite with a fixed write whitelist

Context

POST /Items/{itemId} is the only metadata write path in the Jellyfin API. Its implementation assigns every field unconditionally, for example item.Name = request.Name, item.Genres = request.Genres, item.ProviderIds = request.ProviderIds. It is not a JSON Merge Patch: a field omitted from the body is written as null or empty.

Some fields also have surprising side effects. Tags written to a MusicAlbum are unioned onto and subtracted from every child track. Setting LockData on a folder cascades recursively to all children. ArtistItems/AlbumArtists are the write source for the internal Artists/AlbumArtists arrays, so an incomplete list drops artist links.

Decision

Define a single explicit WRITABLE_FIELDS whitelist and always send a body that contains every key in it. The body is built from a fresh read of the item, with accepted changes layered on top; every rejected key carries its current value verbatim.

Invariant, asserted in the domain layer and in a contract test:

set(payload) == set(WRITABLE_FIELDS)

ArtistItems, AlbumArtists and Album are excluded from the whitelist for v1.

Consequences

Alternatives rejected