screentinker/server
ScreenTinker 400a438fff revert: drop zone-binding, keep whole-playlist grants + size-guidance card (#73)
Investigation found zone placement is a DEVICE property (device.layout_id), not a playlist
property: a normal playlist has no derivable layout (zone_id is NULL unless set in the
device-assignment flow), so a playlist-scoped zone grant can't reach the normal flow. The
right model: placement belongs to the device (same playlist can be full-screen on one screen,
a zone on another); the agency just gets whole-playlist grants + size-guidance.

Removed the zone-grant machinery (security-adjacent dead surface is a liability, not dormant
convenience): api_token_target_zones (schema + a DROP migration for the dev DB where the
short-lived CREATE ran), resolveGrantedZone, grantableZoneIds, buildZoneGrantRows, the
create/PUT zone validation, GET /api/playlists/:id/zones, getPlaylistZones, the settings
zone-picker + its i18n, and the zone-grant bite-test.

KEPT (model-agnostic, good): the reactive per-playlist size-guidance card - GET
/api/agency/playlists/:playlistId/layout (router.param-confined) now reports the zones the
playlist actually feeds (where/what-size content lands), or full-screen when it has no layout.
Whole-playlist grants = today's working model. 147 suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:52:11 -05:00
..
config feat(api): agency-token security primitive - off-ladder scope + agencyGate (#73) 2026-06-13 21:30:38 -05:00
db revert: drop zone-binding, keep whole-playlist grants + size-guidance card (#73) 2026-06-14 15:52:11 -05:00
lib revert: drop zone-binding, keep whole-playlist grants + size-guidance card (#73) 2026-06-14 15:52:11 -05:00
middleware feat(api): per-agency-token auto-publish (#73) 2026-06-14 13:48:17 -05:00
player feat(scheduling): per-item schedule blocks (#74 dayparting, #75 auto-expire) 2026-06-11 15:46:41 -05:00
routes revert: drop zone-binding, keep whole-playlist grants + size-guidance card (#73) 2026-06-14 15:52:11 -05:00
scripts feat(scheduling): per-item schedule blocks (#74 dayparting, #75 auto-expire) 2026-06-11 15:46:41 -05:00
services feat(api): batched email digest for agency uploads (#73) 2026-06-14 13:59:37 -05:00
test revert: drop zone-binding, keep whole-playlist grants + size-guidance card (#73) 2026-06-14 15:52:11 -05:00
ws feat(scheduling): per-item schedule blocks (#74 dayparting, #75 auto-expire) 2026-06-11 15:46:41 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js chore(version): single-source VERSION, env-configurable data paths, bump tooling 2026-06-10 12:56:03 -05:00
package-lock.json chore(server): TOTP schema + otplib dep (#100) 2026-06-13 20:48:55 -05:00
package.json chore(server): TOTP schema + otplib dep (#100) 2026-06-13 20:48:55 -05:00
server.js feat(api): batched email digest for agency uploads (#73) 2026-06-14 13:59:37 -05:00
version.js chore(version): single-source VERSION, env-configurable data paths, bump tooling 2026-06-10 12:56:03 -05:00