docs: finalize Phase 4 schedule copy in the contract

This commit is contained in:
NeilClack
2026-09-29 10:50:18 -05:00
parent fcb5db458b
commit be303dcd9c
+34 -8
View File
@@ -339,16 +339,25 @@ populate `email` and `blocks` exactly as before. Old Kiosks ignore the new
fields; new Kiosks may read either endpoint. This endpoint does **not** emit an fields; new Kiosks may read either endpoint. This endpoint does **not** emit an
ETag and does **not** return 304. ETag and does **not** return 304.
### (e) Portal-internal endpoints (names & purpose only) ### (e) Portal-internal endpoints (not Kiosk-facing)
Finalized in Phases 3 and 4. They are **not** Kiosk-facing. These are session-authenticated Portal actions; they are **not** part of the
Kiosk API and are not served by `/api/v2/...`.
- `POST /api/v2/...` / server actions for Schedule CRUD (create/update/delete - Schedule CRUD — implemented in Phase 3 as SvelteKit form actions on
Block, set `type`, assign Proclamations) — Phase 3. `(protected)/(user)/schedule` (`?/setType`, `?/createBlock`, `?/updateBlock`,
- `POST .../copy` to copy a Schedule between License Keys on the same account — `?/deleteBlock`), backed by `$lib/server/schedule.ts`.
Phase 4. - **Copy** — implemented in Phase 4 as the `?/copy` action plus
`copySchedule()` in `$lib/server/schedule.ts`. Copies one License Key's
Exact paths and payloads are deferred; they will be recorded here when added. Schedule to one or more other License Keys **by value, in a single database
transaction** (all targets succeed or none). The target `type` becomes the
source's; Block rows get fresh IDs; each block's `dynamicAudio` and ordered
Proclamation references are preserved. The source and every target must
belong to the caller's account; a target equal to the source, an empty
target list, or a source without a schedule are rejected. The resulting
schedule is run through the shared validator before commit. Because Block IDs
are part of the serialized payload, every target's content-derived
`version`/ETag changes, so its Kiosk refetches.
--- ---
@@ -544,6 +553,17 @@ later phase.
off, the engine plays local selections but the cache keeps updating. The off, the engine plays local selections but the cache keeps updating. The
older `proclamation.schedule_active` flag is retained in config but is not older `proclamation.schedule_active` flag is retained in config but is not
consulted by the Phase 3 engine. consulted by the Phase 3 engine.
20. **Copy semantics.** Copies are **independent, by value** snapshots: no link
is kept to the source, and editing the source later does not affect targets
(and vice versa). A copy replaces any existing target Schedule in full
(type and blocks) and requires explicit confirmation in the UI when a target
already has one. No "copy to all" shortcut and no scheduled/linked copies
(per the Phase 4 brief). The copied schedule is validated before commit; a
source schedule that fails validation is rejected rather than copied.
21. **Copy and Kiosk code.** Verified against the Phase 3 Kiosk engine/fixture
tests that a copied payload (new Block IDs, same type/times/audio/refs) is
parsed and evaluated identically to any other; **no Kiosk changes were
required**.
--- ---
@@ -561,3 +581,9 @@ later phase.
browser-fallback timezone note; the Kiosk adds the conditional client, browser-fallback timezone note; the Kiosk adds the conditional client,
atomic cache, schedule engine, and a System Settings On/Off toggle. Open atomic cache, schedule engine, and a System Settings On/Off toggle. Open
items 2, 5, 7, 8, 9, 11, 15, and 16 are updated to reflect the changes. items 2, 5, 7, 8, 9, 11, 15, and 16 are updated to reflect the changes.
- 2026-09-29 — Phase 4. Schedule copy is implemented as a Portal-internal
action (`?/copy`) backed by a single-transaction service that copies by
value with fresh Block IDs (so target ETags change), preserving `dynamicAudio`
and Proclamation order, scoped to the caller's account, and validated before
commit. Endpoint (e) is finalized; open items 20 and 21 record the copy
semantics and the Kiosk no-change verification.