Skip to content

Rotation thresholds: settings table, GET and catalog:write-gated PATCH - #3047

Merged
jakebromberg merged 3 commits into
mainfrom
feature/issue-2733-rotation-thresholds
Oct 8, 2026
Merged

jakebromberg merged 3 commits into
mainfrom
feature/issue-2733-rotation-thresholds

Conversation

@jakebromberg

@jakebromberg jakebromberg commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Closes #2733

Adds the station-wide rotation thresholds: a single-row rotation_thresholds table (same id boolean + CHECK (id = true) shape as library_watermark), GET /library/rotation/thresholds (catalog: read) and PATCH /library/rotation/thresholds (catalog: write). Wire types are hand-declared field-for-field with the contract (RotationThresholds, UpdateRotationThresholdsRequest); the @wxyc/shared pin is untouched.

Behaviour

  • PATCH is partial at both levels. {} and {"window_days": {}} are 200 no-ops that return the current record; the response is always the whole record after the write.
  • Each day count must be an integer in 1..365. An explicit null at either level and an unknown key at either level are 400s naming the key. Bin keys are matched exactly against ROTATION_BINS (not parseRotationBin), so "h" and " H" are rejected.
  • One atomic UPDATE of only the supplied columns, no read-modify-write. The DB carries only a >= 1 floor so the 365 ceiling can be raised without a migration.
  • /rotation/thresholds is registered above both GET /rotation/:id and PATCH /rotation/:id; the route-order test gains the literal, a PATCH-arm vacuity guard and dispatch assertions, and the two route comments that said "two literals" / "no literal PATCH exists" are reworded.

Migration

0190_rotation-thresholds is a generated CREATE TABLE with the seed (INSERT ... ON CONFLICT DO NOTHING, H/M/L/S = 60, card_stale_days = 30) appended in the same file, following the 0084/0104 precedent. Migration artifacts (sql, snapshot, journal, applied-hashes) are in their own commit. The number is provisional: a sibling PR also adds a migration, so whichever merges second regenerates after rebasing.

This PR carries a migration that auto-deploys to production on merge. Not for auto-merge; after merging, confirm the deploy-auto.yml run succeeded.

Verification

  • typecheck, lint, format:check, test:unit (665 suites), lint:migrations, check:db-mock-sync, check:sql-claim-docs, check:auth-tables-doc, the bulk-update, precondition-guard, cross-cache-flag, legacy-entry-id and LML-caller-classification checks all pass locally.
  • Full integration suite against an isolated Compose project: 169 suites passed, including the new rotation-thresholds.spec.js (defaults, partial update, no-ops, 400 table, re-running the seed leaves an edited row alone).
  • 401/403 are covered by unit tests with the real middleware (integration runs under AUTH_BYPASS).

Size

About 190 added lines of production source including doc comments (roughly 110 of them code); the budget estimate was ~90. Most of the overage is the schema and validator docblocks and the route-order comments.

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

Schema constraint shape report

no new constraints detected in this diff (uniqueIndex, .unique(), SET NOT NULL, CHECK, FK)

…le-row rotation_thresholds table

Adds the station-wide rotation thresholds table (schema and mock double), a validator that is partial at both levels and rejects explicit nulls, unknown keys and day counts outside 1..365, a one-UPDATE service, the two catalog-gated routes registered ahead of the templated rotation routes, and unit and integration coverage.
…ead lint directives and repeated prose, and tighten the route-order and integration tests
@jakebromberg
jakebromberg force-pushed the feature/issue-2733-rotation-thresholds branch from 2b7e0d5 to 8aabdad Compare October 8, 2026 00:20
@jakebromberg
jakebromberg merged commit 641d42e into main Oct 8, 2026
7 checks passed
@jakebromberg
jakebromberg deleted the feature/issue-2733-rotation-thresholds branch October 8, 2026 02:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rotation thresholds: settings table, GET and catalog:write-gated PATCH

1 participant