ratings: an unrated season or episode does not inherit its series' score #240

Closed
opened 2026-10-09 17:40:29 +02:00 by Claude · 1 comment
Collaborator

Upstream stores, on an item with no rating of its own, the score of the nearest rated parent: BaseItem.OfficialRatingForComparison walks DisplayParent (episode → season → series), and OnMetadataChanged writes InheritedParentalRatingValue/SubValue from it on create, update, refresh and item-update.

The port scores the row's own rating only:

  • crates/ephyra-db/src/scan/row.rs — official_rating() only, and it overwrites the stored score, so a rescan of an episode drops the score upstream gave it, and an item with a CustomRating is scored by its official one.
  • crates/ephyra-db/src/items/writes.rs — the row's own custom-or-official rating.
  • crates/ephyra-http item update (branch v12.2-gaps, d1119a89) recomputes children it writes by walking the display-parent chain, which is the only place that does.

A NULL score passes the max-rating filter (as upstream's does), so an episode of an over-limit series is visible to a capped account once the port has rewritten its row, unless block-unrated covers the type. This is authorization: review required.

It also blocks the in-place upgrade (see that issue): upstream's MigrateRatingLevels nulls inherited scores and relies on the next save to refill them.

Port the inheritance where the port writes a score (scan and item writes), with the custom rating taking precedence as upstream's does, and test it against rows the reference wrote: reference/snapshots/enriched has 60 unrated rows carrying inherited 14/0 and 17/1.

Upstream stores, on an item with no rating of its own, the score of the nearest rated parent: `BaseItem.OfficialRatingForComparison` walks `DisplayParent` (episode → season → series), and `OnMetadataChanged` writes `InheritedParentalRatingValue`/`SubValue` from it on create, update, refresh and item-update. The port scores the row's own rating only: - `crates/ephyra-db/src/scan/row.rs` — `official_rating()` only, and it overwrites the stored score, so a rescan of an episode drops the score upstream gave it, and an item with a `CustomRating` is scored by its official one. - `crates/ephyra-db/src/items/writes.rs` — the row's own custom-or-official rating. - `crates/ephyra-http` item update (branch `v12.2-gaps`, `d1119a89`) recomputes children it writes by walking the display-parent chain, which is the only place that does. A NULL score passes the max-rating filter (as upstream's does), so an episode of an over-limit series is visible to a capped account once the port has rewritten its row, unless block-unrated covers the type. This is authorization: review required. It also blocks the in-place upgrade (see that issue): upstream's `MigrateRatingLevels` nulls inherited scores and relies on the next save to refill them. Port the inheritance where the port writes a score (scan and item writes), with the custom rating taking precedence as upstream's does, and test it against rows the reference wrote: `reference/snapshots/enriched` has 60 unrated rows carrying inherited 14/0 and 17/1.
Author
Collaborator

Landed in 2bcfedcb and 4b58af21: one derivation of upstream's GetParentalRatingScore (custom rating along the display-parent chain first, then official) used by the scan write, the item edit and the edit propagation; a write that moves a row's rating or score rescores its display-descendants in the same transaction; Database::recompute_inherited_scores recomputes every row to what a save would write. One independent review round; its two findings (the refill skipping rated rows, a parent's later rating not reaching unchanged children) are fixed with tests that fail without them. <mpaa> in an nfo is now read (40ae7be2); <customrating> is #244.

Landed in 2bcfedcb and 4b58af21: one derivation of upstream's `GetParentalRatingScore` (custom rating along the display-parent chain first, then official) used by the scan write, the item edit and the edit propagation; a write that moves a row's rating or score rescores its display-descendants in the same transaction; `Database::recompute_inherited_scores` recomputes every row to what a save would write. One independent review round; its two findings (the refill skipping rated rows, a parent's later rating not reaching unchanged children) are fixed with tests that fail without them. `<mpaa>` in an nfo is now read (40ae7be2); `<customrating>` is #244.
Sign in to join this conversation.
No description provided.