Commit Graph
13 Commits
Author SHA1 Message Date
ekklesiaandClaude Opus 5.5 f1b7d67aa5 fix(display): define the display-server messages once, in src/shared
CI / lint (pull_request) Successful in 13s
CI / typecheck (pull_request) Successful in 15s
CI / test (pull_request) Successful in 21s
CI / build (pull_request) Successful in 18s
CI / integration (pull_request) Successful in 3m32s
The display controller and the viewer routes each described the
heartbeat their own way and disagreed about one thing: the display sent
null for "nothing to report", and the route accepted only a missing
field. Every heartbeat from a screen showing a native image was refused
with a 400. The roster therefore marked working screens Offline 90 s
after they opened, and never recorded offlineReady or cachedAssetCount.

src/shared/display-protocol.ts now defines every message between a
display and the server:
- viewer session request and response;
- heartbeat request and response;
- channel state;
- the realtime display payload.

Both halves import it. Its rules: a nullable field accepts null
explicitly, an absent field means "not reported", and an unknown field
is ignored, so a newer display is never refused by an older server.

- The routes parse with the shared parsers, and a refusal names the
  field with Signage's sanitized code.
- The server's channel state extends the wire type, so a field the
  display relies on cannot drift without a compile error.
- The display builds its heartbeat as the shared type, and reads its
  registration with the shared parser instead of casting it.
- Test stubs that described server responses more loosely than the
  server sends them (no viewerName, no stale, partial media) now match
  the real responses and are typed as the protocol.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 21:25:21 -05:00
ekklesiaandClaude Opus 5.5 458043280a test(display): run the real display controller against the real viewer routes
Every display test answered the controller with a hand-written stub, and
every viewer test called the service with a hand-written object, so
neither side was ever tested against the other. In production every
heartbeat was refused with a 400.

This suite answers the real controller's requests with the real viewer
route handlers over the in-memory store. The routes gain an optional
store factory for that; production still uses the module database.

Fails today: POST /viewers/:viewerId/heartbeat -> 400
SIGNAGE_INVALID_REQUEST, because the display sends
reportedContributionId: null and the route accepts only a missing field.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 21:25:21 -05:00
ekklesiaandClaude Opus 5.5 3073baeb8b ci: build, test, and run Signage inside a pinned Ekklesia on every change
CI / lint (pull_request) Successful in 12s
CI / typecheck (pull_request) Successful in 15s
CI / test (pull_request) Successful in 19s
CI / build (pull_request) Successful in 18s
CI / integration (pull_request) Successful in 3m34s
Signage had no CI. Its tests passed while three defects shipped that
appear only inside Ekklesia, in a real browser. Every job now assembles
Signage into a pinned platform commit, as an instance does, and
installs that workspace with --frozen-lockfile:
- lint, typecheck, test: Signage's own checks;
- build: the platform's gates against exactly this module set (boundary
  rules, module manifest, migrations), then the build;
- integration: the deployment image from the platform's Dockerfile,
  then the platform's split-topology smoke. It pairs a kiosk display,
  restarts it on the same profile, and runs the scenarios in
  ci/display-scenarios.

The supporting files:
- ci/platform.env pins one platform commit. ci/assemble.sh fetches the
  platform's main and refuses a pinned commit that is not on it, so CI
  only runs reviewed platform code.
- ci/pnpm-lock.yaml is the assembled workspace's lockfile, regenerated
  with ci/update-lock.sh.

Same trust rules as the platform: actions pinned by SHA,
persist-credentials false, no secrets, no pull_request_target.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 19:11:53 -05:00
ekklesia 1bf89a3942 feat: align Signage with platform display and design 2026-09-30 18:21:42 -05:00
ekklesia af0f0adadc test: align signage release expectations 2026-09-29 20:50:02 -05:00
ekklesia 36c1a72363 feat: make display setup actionable 2026-09-29 20:49:51 -05:00
ekklesia 7999582460 fix: preserve valid timeline slot positions 2026-09-29 20:49:39 -05:00
ekklesia 218e05e71e chore: release signage 0.1.1 2026-09-29 19:33:56 -05:00
ekklesia afac1bf8e7 chore: release signage 0.1.1 2026-09-29 19:27:03 -05:00
ekklesia aa8cb1c96f fix: complete display and channel group management 2026-09-29 18:15:26 -05:00
ekklesia 5760059ee3 fix: make timeline activation durable and visible 2026-09-29 18:15:08 -05:00
ekklesia 92bef4c7aa feat: initial Signage 0.1.0 2026-08-28 16:41:54 -05:00
ekklesia 20756f11af first commit 2026-08-27 17:05:45 -05:00