docs(planning): mark Phase 1.5 live broadcast as Done

Tasks 1.5.4, 1.5.5, 1.5.6 marked 🟩 with commit hashes and implementation
notes. Phase 1.5 status updated to Done in ROADMAP.md.
This commit is contained in:
2026-05-02 18:00:24 +02:00
parent 87dec03d3c
commit fa50df3e27
4 changed files with 14 additions and 10 deletions
+4 -4
View File
@@ -61,7 +61,7 @@ These rules govern every task. Any deviation must be discussed and documented as
### Phase 1.5 — Live broadcast ### Phase 1.5 — Live broadcast
**Status:** ⬜ Not started **Status:** 🟩 Done
**Outcome:** WebSocket endpoint inside the Processor that fans live position updates from Redis to subscribed [[react-spa]] clients. Cookie-based auth via Directus's `/users/me`, per-event subscription with one-time authorization at subscribe time, snapshot-on-subscribe, multi-instance per-instance consumer-group fan-out. The wire spec is `docs/wiki/synthesis/processor-ws-contract.md`. Unblocks the SPA's live-map feature for the Rally Albania 2026 dogfood. **Outcome:** WebSocket endpoint inside the Processor that fans live position updates from Redis to subscribed [[react-spa]] clients. Cookie-based auth via Directus's `/users/me`, per-event subscription with one-time authorization at subscribe time, snapshot-on-subscribe, multi-instance per-instance consumer-group fan-out. The wire spec is `docs/wiki/synthesis/processor-ws-contract.md`. Unblocks the SPA's live-map feature for the Rally Albania 2026 dogfood.
[**See `phase-1-5-live-broadcast/README.md`**](./phase-1-5-live-broadcast/README.md) [**See `phase-1-5-live-broadcast/README.md`**](./phase-1-5-live-broadcast/README.md)
@@ -71,9 +71,9 @@ These rules govern every task. Any deviation must be discussed and documented as
| 1.5.1 | [WS server scaffold + heartbeat](./phase-1-5-live-broadcast/01-ws-server-scaffold.md) | 🟩 | `b8ebbd0` | | 1.5.1 | [WS server scaffold + heartbeat](./phase-1-5-live-broadcast/01-ws-server-scaffold.md) | 🟩 | `b8ebbd0` |
| 1.5.2 | [Cookie auth handshake](./phase-1-5-live-broadcast/02-cookie-auth-handshake.md) | 🟩 | `190254d` | | 1.5.2 | [Cookie auth handshake](./phase-1-5-live-broadcast/02-cookie-auth-handshake.md) | 🟩 | `190254d` |
| 1.5.3 | [Subscription registry & per-event authorization](./phase-1-5-live-broadcast/03-subscription-registry.md) | 🟩 | `38de4bc` | | 1.5.3 | [Subscription registry & per-event authorization](./phase-1-5-live-broadcast/03-subscription-registry.md) | 🟩 | `38de4bc` |
| 1.5.4 | [Broadcast consumer group & fan-out](./phase-1-5-live-broadcast/04-broadcast-consumer-group.md) | | | | 1.5.4 | [Broadcast consumer group & fan-out](./phase-1-5-live-broadcast/04-broadcast-consumer-group.md) | 🟩 | `c07ea0e` |
| 1.5.5 | [Snapshot-on-subscribe](./phase-1-5-live-broadcast/05-snapshot-on-subscribe.md) | | | | 1.5.5 | [Snapshot-on-subscribe](./phase-1-5-live-broadcast/05-snapshot-on-subscribe.md) | 🟩 | `f4b50ca` |
| 1.5.6 | [Integration test (testcontainers Redis + Postgres + Directus stub)](./phase-1-5-live-broadcast/06-integration-test.md) | | | | 1.5.6 | [Integration test (testcontainers Redis + Postgres + Directus stub)](./phase-1-5-live-broadcast/06-integration-test.md) | 🟩 | `2f2cf5c` |
### Phase 2 — Domain logic ### Phase 2 — Domain logic
@@ -1,7 +1,7 @@
# Task 1.5.4 — Broadcast consumer group & fan-out # Task 1.5.4 — Broadcast consumer group & fan-out
**Phase:** 1.5 — Live broadcast **Phase:** 1.5 — Live broadcast
**Status:** ⬜ Not started **Status:** 🟩 Done
**Depends on:** 1.5.3 **Depends on:** 1.5.3
**Wiki refs:** `docs/wiki/synthesis/processor-ws-contract.md` §Streaming updates, §Multi-instance behaviour; `docs/wiki/concepts/live-channel-architecture.md` §Multi-instance Processor **Wiki refs:** `docs/wiki/synthesis/processor-ws-contract.md` §Streaming updates, §Multi-instance behaviour; `docs/wiki/concepts/live-channel-architecture.md` §Multi-instance Processor
@@ -218,4 +218,8 @@ Per the contract: omit fields rather than send `null` for absent values.
## Done ## Done
(Filled in when the task lands.) Landed in `c07ea0e`. Key implementation decisions:
- `CodecError`/`decodePosition` moved to `src/shared/codec.ts`; `Position`/`AttributeValue` moved to `src/shared/types.ts`. Both `src/core/` and `src/live/` re-export from shared to preserve existing import paths.
- `broadcast.ts` ACKs all stream entries immediately (durability not needed for fan-out).
- Test uses a `stopSignal` Promise to coordinate between the broadcast loop and the test's `stop()` call, avoiding the tight-loop OOM that naive polling triggers.
@@ -1,7 +1,7 @@
# Task 1.5.5 — Snapshot-on-subscribe # Task 1.5.5 — Snapshot-on-subscribe
**Phase:** 1.5 — Live broadcast **Phase:** 1.5 — Live broadcast
**Status:** ⬜ Not started **Status:** 🟩 Done
**Depends on:** 1.5.3, 1.4 (Postgres pool) **Depends on:** 1.5.3, 1.4 (Postgres pool)
**Wiki refs:** `docs/wiki/synthesis/processor-ws-contract.md` §Server response — subscribed **Wiki refs:** `docs/wiki/synthesis/processor-ws-contract.md` §Server response — subscribed
@@ -142,4 +142,4 @@ Same field-omission convention: don't emit `null` for absent values.
## Done ## Done
(Filled in when the task lands.) Landed in `f4b50ca`. `src/live/snapshot.ts` uses DISTINCT ON (device_id) ORDER BY device_id, ts DESC with WHERE faulty=false. Registry's `fetchSnapshot` helper already had the try/catch fail-open pattern from task 1.5.3. `createSnapshotProvider` injected into `createSubscriptionRegistry` in main.ts.
@@ -1,7 +1,7 @@
# Task 1.5.6 — Integration test (testcontainers Redis + Postgres + Directus stub) # Task 1.5.6 — Integration test (testcontainers Redis + Postgres + Directus stub)
**Phase:** 1.5 — Live broadcast **Phase:** 1.5 — Live broadcast
**Status:** ⬜ Not started **Status:** 🟩 Done
**Depends on:** 1.5.4, 1.5.5 **Depends on:** 1.5.4, 1.5.5
**Wiki refs:** **Wiki refs:**
@@ -189,4 +189,4 @@ The `serializeForStream` helper handles the bigint/Buffer sentinel encoding (alr
## Done ## Done
(Filled in when the task lands.) Landed in `2f2cf5c`. Key divergence from spec: `test/fixtures/test-schema.sql` uses `entry_devices.device_id TEXT` (IMEI) instead of UUID FK to devices, matching Phase 1's IMEI-as-device_id convention. The live server uses a two-step startup (probe server → fixed port) because LIVE_WS_PORT=0 doesn't expose the bound port via the LiveServer public interface. The metricsServer dummy prevents afterAll hanging on unclosed handles.