feat: initial Signage 0.1.0
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# 0004: A channel group is one clock; an audience channel is one rendering of it
|
||||
|
||||
- Status: Accepted
|
||||
- Date: 2026-08-27
|
||||
- Related: [0002](0002-content-provider-contract.md), [0005](0005-authoritative-playback.md)
|
||||
|
||||
## Context
|
||||
|
||||
A church wants the lobby screens, the sanctuary side screens, and the online stream overlay to be on
|
||||
the same slide at the same moment — but the online audience should see "watching from home" wording
|
||||
where the room sees "welcome in". That is one program with two renderings, not two programs.
|
||||
|
||||
It also wants the nursery hallway to run a completely different loop. That *is* two programs.
|
||||
|
||||
## Decision
|
||||
|
||||
**A channel group owns exactly one authoritative timeline clock.** It has one active timeline, one
|
||||
current slot, one start instant, one deadline, one pause state, one blackout state, and one pending
|
||||
activation. Everything a group's channels do, they do together.
|
||||
|
||||
**A channel is an audience within a group.** Each has a `key` (`default`, `in-person`, `online`, …),
|
||||
and exactly one channel per group is the default. Channels differ in exactly one way: which variant of
|
||||
a resolved selection they render.
|
||||
|
||||
- Signage resolves **one logical selection per slot occurrence**, for the whole group.
|
||||
- The provider is asked once, with every audience key the group has.
|
||||
- Each channel renders the variant matching its key, or the default variant if the provider offered
|
||||
none.
|
||||
|
||||
A truly independent clock requires another channel group. There is no per-channel pause, no
|
||||
per-channel skip, and no per-channel timeline — and no route that could express one.
|
||||
|
||||
**One default channel is created automatically**, and no other. `in-person` and `online` are examples
|
||||
in a document, not rows in a migration: a church that never needs a second audience never sees one.
|
||||
|
||||
**A viewer never chooses its channel.** A display registers with its persistent viewer identity and
|
||||
joins the default channel of the default group; an administrator moves it from the management
|
||||
dashboard. A public display that could pick its own channel would let anyone who reaches the page
|
||||
select what a screen shows.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Two viewers that connected minutes apart render the same slot with the same deadline, because both
|
||||
read the same persisted absolute instants rather than counting from when they arrived.
|
||||
- Adding an audience is additive: the provider starts returning a second variant, and the default
|
||||
channel is unaffected.
|
||||
- A provider that returns no variant for `online` is not a failure and produces no warning. Returning
|
||||
the default is the contract.
|
||||
- "Pause the lobby but not the sanctuary" is impossible by construction, and correctly so — those are
|
||||
two groups.
|
||||
|
||||
## Alternatives
|
||||
|
||||
- **One clock per channel, synchronized by convention.** Rejected: two clocks drift, and no amount of
|
||||
correction makes two televisions in one room agree.
|
||||
- **Per-channel timelines with a shared cursor.** Rejected: the cursor is only meaningful against one
|
||||
pattern; two patterns of different length make "the same slot" undefined.
|
||||
- **Let the display pick its audience from a query parameter.** Rejected: it is an unauthenticated
|
||||
content selector on a screen in a public hallway.
|
||||
- **Create `in-person` and `online` channels on install.** Rejected: it presumes a broadcast ministry
|
||||
every church does not have, and an unused channel is a thing an operator has to understand and
|
||||
ignore forever.
|
||||
Reference in New Issue
Block a user