A root or policy change must re-derive the verdicts it invalidates #241

Closed
opened 2026-08-25 10:30:19 +01:00 by naps62-yolo · 1 comment
Owner

crates/arr-api/src/relocate.rs:4-5 claims a move leaves things so that "the
root's policy (§5.1) applies to a library the files are actually in". Nothing
makes that true.

movies::update (crates/arr-api/src/movies.rs:478) and the series equivalent
(series.rs:630) call reclassify only if overrides_changed. The effective
policy comes from the root, so moving a movie from a main root to a kids
root leaves every stored verdict on its release deck computed under the old
policy until the next sweep — and §9.3's deck and the daemon's manual-grab gate
both read that stored column. That is the failure reclassify.rs's own module
doc exists to prevent.

#236 widens it: PUT /api/roots/{id} writes policy_id
(roots.rs:186-199) with no reclassify at all, so one settings edit can
silently invalidate the verdicts of an entire library.

The root_id half predates this milestone; the doc comment asserting otherwise
is new, and the policy_id half is now a first-class operator action.

Scope: a root change on a title, and a policy change on a root, both re-derive
the verdicts of everything affected. If that is too expensive to do inline for
a whole library, say so in §5.1 and make the sweep the contract instead — but
then the doc comment has to stop claiming it happens.

`crates/arr-api/src/relocate.rs:4-5` claims a move leaves things so that "the root's policy (§5.1) applies to a library the files are actually in". Nothing makes that true. `movies::update` (`crates/arr-api/src/movies.rs:478`) and the series equivalent (`series.rs:630`) call `reclassify` only `if overrides_changed`. The effective policy comes from the root, so moving a movie from a `main` root to a `kids` root leaves every stored verdict on its release deck computed under the old policy until the next sweep — and §9.3's deck and the daemon's manual-grab gate both read that stored column. That is the failure `reclassify.rs`'s own module doc exists to prevent. #236 widens it: `PUT /api/roots/{id}` writes `policy_id` (`roots.rs:186-199`) with no reclassify at all, so one settings edit can silently invalidate the verdicts of an entire library. The `root_id` half predates this milestone; the doc comment asserting otherwise is new, and the `policy_id` half is now a first-class operator action. Scope: a root change on a title, and a policy change on a root, both re-derive the verdicts of everything affected. If that is too expensive to do inline for a whole library, say so in §5.1 and make the sweep the contract instead — but then the doc comment has to stop claiming it happens.
naps62-yolo added this to the Feedback pass 2 milestone 2026-08-25 10:30:19 +01:00
naps62-yolo added the area/apidifficulty/hardtype/bug labels 2026-08-25 10:30:19 +01:00
Author
Owner

Out of scope here, found while fixing this: PUT /api/policies/{policy_id} (policies.rs update) rewrites a policy's rules with no reclassify at all. That is the third action that invalidates stored verdicts — same failure as the two this issue covers, one level up. reclassify::root now exists, so the fix is small: for each root using the edited policy, re-derive. Needs its own issue.

Out of scope here, found while fixing this: `PUT /api/policies/{policy_id}` (`policies.rs` `update`) rewrites a policy's rules with no reclassify at all. That is the third action that invalidates stored verdicts — same failure as the two this issue covers, one level up. `reclassify::root` now exists, so the fix is small: for each root using the edited policy, re-derive. Needs its own issue.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: yolo/arr#241