docs: add streaming simplification rollout and validation artifacts

This commit is contained in:
2026-03-07 16:30:00 +00:00
parent 580a3619e0
commit 024d81c7ec
5 changed files with 375 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
# Absolute Checklist: Streaming Simplification (WebRTC-only)
## Backend
1. Add/confirm `SIMPLE_STREAMING` environment/config switch (default: true for new deployment profile).
2. In `Backend/routes/streams.ts`, update `POST /streams/request` to:
- keep device role/link validation
- create session with status `requested`
- emit request event directly compatible with WebRTC-only flow
- remove stream-provider payload assumptions from response
3. In `Backend/routes/streams.ts`, update `POST /streams/:id/accept` to:
- validate camera ownership and state
- set status to `streaming`
- set `startedAt`
- emit `stream:started`
- remove or gate all publish/subscribe/media-provider dependency
4. In `Backend/routes/streams.ts`, update `POST /streams/:id/end` to:
- require authorized participant (camera or requester)
- set status to `ended`
- set `endedAt`
- emit `stream:ended`
- stop any active SFU session only if explicitly still active and configured
5. In `Backend/routes/streams.ts`, remove any hard dependency on `mediaProvider.createSession` for live functionality.
6. Gate recording creation in stream end logic behind feature flag (default OFF) or remove endpoint path from phase-1 path.
7. In `Backend/routes/streams.ts`, return minimal deterministic payload for stream start/accept/end responses.
8. In `Backend/db/schema.ts`, mark legacy media fields as deprecated comments only (no schema migration required in phase 1).
9. In `Backend/media/service.ts`, make provider calls no-op for phase-1 streaming runtime or guard them behind non-simplified feature flag.
10. In `Backend/media/providers/mock.ts`, annotate mock provider methods as metadata-only and remove calls from request/accept/end flow.
11. In `Backend/media/sfu/service.ts` and `Backend/media/sfu/noop.ts`, ensure no required startup path is executed for default simplified mode.
12. In `Backend/routes/commands.ts`, document command-table deprecation for stream lifecycle command path; remove active usage if simplified mode is enabled.
## Realtime Gateway
13. In `Backend/realtime/gateway.ts`, remove `stream:frame` event listener and sender path.
14. In `Backend/realtime/gateway.ts`, remove frame-relay participant cache and related validation branch.
15. In `Backend/realtime/gateway.ts`, keep only validated `webrtc:signal` logic for offer/answer/candidate/hangup.
16. In `Backend/realtime/gateway.ts`, simplify signal forwarding so target validation is session ownership + same user context.
17. In `Backend/realtime/gateway.ts`, remove periodic command retry polling for stream commands when in simplified mode.
18. Keep `stream:started` and `stream:ended` emit paths with recipient resolution.
19. Ensure socket middleware still enforces device token auth and role identity checks.
## Web frontend
20. In `WebApp/src/lib/app/controller.js`, collapse stream state to `idle|connecting|active|ended`.
21. Remove fallback image mode, latest-frame state, and frame receiver logic from controller.
22. Ensure client side only uses WebRTC peer connection and `<video>` rendering path.
23. Simplify `ontrack` handling to set remote stream once and ignore duplicate tracks.
24. Add deterministic peer teardown on `stream:ended`, page unload, and navigation changes.
25. In `WebApp/src/routes/camera/+page.svelte`, remove preview-to-frame interval fallback sender.
26. In `WebApp/src/routes/camera/+page.svelte`, ensure camera-side stream path emits offer only and no JPEG payload.
27. In `WebApp/src/routes/camera/+page.svelte`, remove recording branch that depends on frame transport.
28. In `WebApp/src/routes/client/+page.svelte`, remove fallback image DOM branch and related status labels.
## Mobile frontend
29. In `MobileApp/src/app-context.tsx`, remove base64 frame stream state and timer lifecycle for frame relay.
30. In `MobileApp/src/app-context.tsx` and `MobileApp/app/(tabs)/index.tsx`, align stream lifecycle state transitions with web logic.
31. In `MobileApp/app/(tabs)/index.tsx`, remove capture+`stream:frame` emission loop.
32. In `MobileApp/app/(tabs)/index.tsx`, remove any image fallback UI path and render strategy for active stream.
33. In `MobileApp/src/api.ts`, remove calls to publish/subscribe credentials endpoints from simplified runtime flow.
34. Ensure mobile camera cleanup stops local media and closes RTCPeerConnection on end and unmount.
## Cross-cutting API/docs/config
35. In `Backend/docs/openapi.ts`, update documented streaming contract to only include:
- request
- accept
- end
- webrtc signal event behavior
- remove references implying frame fallback as primary path
36. Update any internal docs or README sections describing mock media endpoints as runtime-critical.
37. Add migration notes to avoid breaking integrations (deprecation and rollback behavior).
38. Add explicit log markers for stream request/accept/offer/answer/end events with session id and participant ids.
39. Add compile/build compatibility checks for both apps after removing unused symbols/imports.
40. Add runtime rollback checklist for disabling `SIMPLE_STREAMING` and re-enabling legacy paths.

View File

@@ -0,0 +1,73 @@
# Execution Prompt: Streaming Simplification
You are implementing `STREAMING_SIMPLIFICATION` in `/home/matiss/Documents/Final Year Project`.
## Objective
Deliver a WebRTC-only streaming architecture for this codebase by implementing the four artifacts:
1. `docs/STREAMING_SIMPLIFICATION_IMPLEMENTATION_PLAN.md`
2. `docs/STREAMING_SIMPLIFICATION_ABSOLUTE_CHECKLIST.md`
3. `docs/STREAMING_SIMPLIFICATION_VALIDATION_MATRIX.md`
4. This execution prompt.
## Governing constraints
- Preserve device token auth and role checks.
- Keep request/accept/end endpoints and WebRTC signaling functional.
- Remove socket JPEG frame fallback from runtime path.
- Keep rollback-capable behavior using `SIMPLE_STREAMING` where possible.
- Do not reintroduce any media-path dependency on mock provider endpoints.
## Execution sequence (strict)
1. Implement all backend stream endpoint and session-state simplifications first.
2. Simplify realtime gateway signaling path second.
3. Update web frontend streaming controller and pages.
4. Update mobile frontend streaming behavior.
5. Update docs, config notes, and OpenAPI/event description.
6. Run validation matrix gating; do not mark complete until all required evidence rows are filled.
## Completion gates
### Gate A — Backend
- `Backend/routes/streams.ts` follows simplified lifecycle only.
- `Backend/realtime/gateway.ts` contains no frame-relay path in active flow.
- Unauthorized access checks remain strict and verifiable.
### Gate B — Frontends
- Web and Mobile each have one stream state machine and one active rendering strategy.
- No scheduled frame-relay sender/receiver code remains in runtime path.
- End-of-stream cleanup is deterministic and symmetric.
### Gate C — Delivery readiness
- OpenAPI/docs updated for simplified contract.
- Feature flag/rollback documented.
- Validation matrix entries populated from observed evidence.
## Evidence rules
For every checklist line in `docs/STREAMING_SIMPLIFICATION_ABSOLUTE_CHECKLIST.md`:
1. Fill corresponding row in `docs/STREAMING_SIMPLIFICATION_VALIDATION_MATRIX.md` from pending -> done.
2. Populate columns:
- **Code Evidence**: file path + symbols/line references
- **Test Evidence**: command output or test report artifact names
- **Runtime Evidence**: screenshot/video/log excerpt references and scenario details
3. Keep one evidence item per row if possible; if blocked, include blocker and retry plan.
## Required validation commands (when execution resumes)
- Backend: validate API/types/contracts compile/build and lint status.
- Gateway: static check that `stream:frame` handlers are absent in effective runtime mode.
- Frontend: build check for both web and mobile after removing unused imports/state.
- Runtime smoke checks:
- client request -> camera accept -> stream start -> stream end
- unauthorized request rejection
- cleanup path after end and reconnect
## Final report format
Return a final report with:
1. Completed tasks grouped by file.
2. Validation matrix fully updated.
3. Any deviations from this spec and why.
4. Exact first and second risk identified after rollout.
Do not introduce additional assumptions not covered in the checklist without updating the checklist and matrix.

View File

@@ -0,0 +1,138 @@
# Implementation Plan: Streaming Simplification (WebRTC-only)
## 0) Goal and scope
### Goal
Simplify the current streaming architecture to a single production-pragmatic implementation path:
- Control plane via REST + socket signaling
- Media plane via WebRTC only
- No JPEG frame fallback relay
- Preserve security and device-role authorization
### Scope in/out
- In scope:
- Stream request/accept/end lifecycle
- Device role and ownership checks
- WebRTC signaling and connection setup/teardown
- Frontend Web + Mobile stream runtime paths
- API/docs updates for simplified contract
- Out of scope:
- Multi-party broadcast or conferencing
- SFU/ingest pipeline replacement in this phase
- Media provider feature parity with mock provider URLs
- Full recording workflow and upload/finalization
## 1) Current-state constraints to keep
- Devices use bearer tokens and role-based socket/session authentication.
- Stream request is initiated by a `client` device targeting a linked `camera`.
- Current schema/event names exist and are used across components.
- Backend and frontends already support `stream:requested`, `stream:started`, `stream:ended`, and `webrtc:signal`.
## 2) Explicit requirements
1. Runtime complexity reduction:
- Keep one media transport: WebRTC.
- Remove socket JPEG fallback flow from runtime.
2. Reliability and safety:
- Keep strict owner/role checks for all stream/session endpoints.
- Ensure deterministic teardown when stream ends.
3. Maintainability:
- Remove dead or non-critical branches.
- Minimize special-case flags and dual state machines.
4. Backward compatibility strategy:
- Prefer a feature flag `SIMPLE_STREAMING` for controlled rollout.
## 3) Assumptions
- Existing database schema can remain (deprecating fields is acceptable for now).
- Camera and client are expected to be online for primary WebRTC path; if not reachable, stream request/accept will fail gracefully.
- `stream:frame` is not required for core user value in phase 1.
- Recording features can be delayed or gated without blocking stream acceptance.
- Existing command dispatch infrastructure can be simplified or replaced by direct request/session events without redesigning auth.
## 4) Non-goals and excluded behaviors
- No immediate migration to true production-grade media server or SFU.
- No auto-retry queue for offline command delivery.
- No new codec/transcoding pipeline.
## 5) Target architecture
### Backend
- Stream endpoints: request -> accept -> end.
- Session state transitions:
- `requested` -> `streaming` -> `ended`
- Commands table may be retained only for audit/logging or removed later.
- Gateway relays:
- `webrtc:signal` only for media negotiation.
- `stream:started` and `stream:ended` for lifecycle updates.
### Frontend (Web + Mobile)
- Shared runtime model:
- `idle` -> `connecting` -> `active` -> `ended`
- On camera accept: start WebRTC offer.
- On client started event: start WebRTC answer/handling.
- On ended: stop peer connections, clear state.
- No frame image fallback state/UI.
## 6) Phased implementation strategy
### Phase 1: Contract freeze and safety gate (Day 0)
1. Lock simplified state contract and event matrix.
2. Add/validate `SIMPLE_STREAMING` flag and default behavior.
3. Add migration notes for legacy paths.
### Phase 2: Backend control-plane simplification (Day 1)
1. Refactor stream request/accept/end handlers to only manage session lifecycle and signaling.
2. Remove/disable stream-provider-specific runtime side effects from these handlers.
3. Ensure response payloads are minimal and stable.
### Phase 3: Gateway simplification (Day 1)
1. Remove `stream:frame` event handler and related relay state.
2. Keep only validated WebRTC signaling and lifecycle event emitters.
3. Remove command retry loop if not required by flag.
### Phase 4: Web frontend simplification (Day 2)
1. Simplify stream controller into single mode.
2. Remove image fallback flow and related timers/state.
3. Keep single video render path and deterministic cleanup.
### Phase 5: Mobile frontend simplification (Day 2)
1. Remove periodic frame capture/relay code and image fallback rendering.
2. Keep camera capture + WebRTC publish path.
3. Align end/cleanup behavior with web.
### Phase 6: API/doc/ops cleanup (Day 3)
1. Update OpenAPI/event docs and internal docs.
2. Deprecate references to frame-based streaming and mock endpoints in code comments.
3. Add rollout and rollback runbook.
### Phase 7: Validation and rollout (Day 4)
1. Manual runtime smoke tests for request/accept/offer/answer/end.
2. Validate unauthorized access rejection for all endpoints.
3. Rollout in flag-off/flag-on modes and monitor.
## 7) Sequence and dependency reasoning
- Backend simplification must land before frontend simplification to avoid client calling removed paths.
- Gateway simplification is independent after stream endpoints are stable but should be merged before frontend hardening.
- Frontend changes rely on a stable event contract (`webrtc:signal`, `stream:started`, `stream:ended`).
- Docs/validation are final tasks once behavior stabilizes.
## 8) Failure handling and risk controls
1. **Rollback strategy:** feature flag switch routes behavior back to existing legacy logic.
2. **Forward progress gate:** stream accept/start should not require any media provider credential.
3. **Safety gate:** reject unknown/non-matching event payloads in gateway before forwarding.
4. **Error handling:** explicit peer connection cleanup on timeout/error and session end.
5. **Observability:** structured logs for request/accept/offer/answer/hangup/end with stream session ids.
## 9) Acceptance criteria
1. `client` -> request -> camera `accept` -> live WebRTC stream works on web and mobile.
2. No `stream:frame` event is used in runtime media path.
3. Stream teardown always emits `stream:ended`, clears peer connections, and stops capture.
4. Unauthorized role/device combinations are rejected with explicit errors.
5. OpenAPI and internal docs only advertise simplified contract by default.
6. Feature flag allows toggling between simplified and legacy behavior for quick rollback.

View File

@@ -0,0 +1,45 @@
# Streaming Simplification Rollout And Rollback
## Rollout intent
`SIMPLE_STREAMING` enables the new WebRTC-only control path:
- direct `stream:requested` fan-out to the camera
- no media-provider session requirement for request/accept/end
- no `stream:frame` relay in the backend gateway
- web client uses only WebRTC offer/answer/candidate signaling
## Migration notes
1. Native mobile is not yet on the WebRTC path.
2. `MobileApp/package.json` does not include a native WebRTC dependency such as `react-native-webrtc`.
3. `MobileApp/README.md` documents that the mobile app still relies on legacy `stream:frame` relay.
4. Because of this, `SIMPLE_STREAMING` defaults to `false`.
5. Web and backend are prepared for the simplified path now.
## Safe enablement sequence
1. Deploy backend and web changes with `SIMPLE_STREAMING=false`.
2. Validate legacy mobile behavior still works.
3. Validate web camera/client behavior with `SIMPLE_STREAMING=true` in a controlled environment.
4. Add native mobile WebRTC support before changing the default flag value.
## Runtime checks when enabling
1. Request a stream from a web client to a web camera.
2. Confirm the camera receives `stream:requested`.
3. Confirm `stream:started` is emitted after accept.
4. Confirm WebRTC offer/answer/candidate exchange succeeds.
5. Confirm `stream:ended` tears down both sides cleanly.
6. Confirm no `stream:frame` messages appear in gateway logs.
## Rollback checklist
1. Set `SIMPLE_STREAMING=false`.
2. Restart backend instances.
3. Verify `/streams/request` creates `start_stream` commands again.
4. Verify mobile frame-relay streaming resumes.
5. Re-run web and mobile smoke checks on the legacy path.
## Known blocker
Native mobile parity is blocked until a supported RN WebRTC stack is added and wired into `MobileApp/src/app-context.tsx`.

View File

@@ -0,0 +1,44 @@
# Validation Matrix: Streaming Simplification (WebRTC-only)
| Row ID | Checklist Item | Status | Code Evidence | Test Evidence | Runtime Evidence |
|---|---|---|---|---|---|
| B1 | Add/confirm `SIMPLE_STREAMING` environment/config switch | done | `Backend/media/config.ts:28,44-50` (`parseFeatureFlag`, `simpleStreamingEnabled`, `streamRecordingEnabled`) | `bun test` -> `tests/media-config.test.ts` passed (3 cases) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B2 | Update stream request endpoint with simplified flow and role/link checks | done | `Backend/routes/streams.ts:168-184` (`createStreamRequestedPayload`, simplified `/streams/request` response) | `bun test` -> `tests/streaming-simple.test.ts` passed (`builds deterministic requested and started payloads`) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B3 | Update stream accept endpoint to set `streaming` and emit started | done | `Backend/routes/streams.ts:344-356` (`createStreamStartedPayload`, simplified accept response) | `bun test` -> `tests/streaming-simple.test.ts` passed (`builds deterministic requested and started payloads`) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B4 | Update stream end endpoint with proper status, end timestamp, lifecycle emit | done | `Backend/routes/streams.ts:660-721` (`status: nextStatus`, `createStreamEndedPayload`, simplified end response) | `bun test` -> `tests/streaming-simple.test.ts` passed (`normalizes ended payload and strips provider fields from API response`) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B5 | Remove media provider dependency in accept logic | done | `Backend/media/service.ts:17-24` (`mediaProviderRuntimeEnabled`, `createLiveMediaSession`), `Backend/routes/streams.ts:320-334` (accept uses wrapper result) | `bun test` -> `tests/media-config.test.ts`, `tests/streaming-simple.test.ts` both passed | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B6 | Gate/remove recording creation path in stream end logic | done | `Backend/media/config.ts:45,50`, `Backend/routes/streams.ts:681-683` (`streamRecordingEnabled`) | `bun test` passed all 17 tests in `Backend/tests/*` | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B7 | Return minimal deterministic stream payloads | done | `Backend/streaming/simple.ts:35-73` (`createStream*Payload`, `toSimpleStreamSessionResponse`), `Backend/routes/streams.ts:184,356,721` | `bun test` -> `tests/streaming-simple.test.ts` passed (3 cases) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B8 | Document deprecated media fields in schema | done | `Backend/db/schema.ts:68-69` (legacy provider field comments) | `bun test` passed all 17 tests in `Backend/tests/*` | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B9 | Guard media service calls behind non-simplified mode | done | `Backend/media/service.ts:17-24` (`mediaProviderRuntimeEnabled`, `createLiveMediaSession`) | `bun test` -> `tests/media-config.test.ts` passed (3 cases) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B10 | Annotate mock provider as metadata-only in phase-1 path | done | `Backend/media/providers/mock.ts:40-41` (runtime compatibility comment), `Backend/routes/streams.ts:320-334` (runtime no longer requires provider session in simplified mode) | `bun test` passed all 17 tests in `Backend/tests/*` | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B11 | Ensure SFU service not required in simplified mode | done | `Backend/media/sfu/service.ts:1,6-8` (`simpleStreamingEnabled` short-circuit) | `bun test` passed all 17 tests in `Backend/tests/*` | `bunx tsc --noEmit` exited 0 in `Backend/` |
| B12 | Deprecate command-table stream lifecycle usage under simplified mode | done | `Backend/routes/commands.ts:53`, `Backend/routes/streams.ts:168-184`, `Backend/realtime/gateway.ts:110-116` | `bun test` passed all 17 tests in `Backend/tests/*` | `bunx tsc --noEmit` exited 0 in `Backend/` |
| R13 | Remove `stream:frame` event listener/sender from gateway | done | `Backend/realtime/gateway.ts:323-349` (`webrtc:signal` only in streaming path) | `bun test` passed all 17 tests in `Backend/tests/*` | `rg -n "stream:frame" Backend/realtime/gateway.ts` returned no matches; `bunx tsc --noEmit` exited 0 |
| R14 | Remove frame-relay participant cache and validation branches | done | `Backend/realtime/gateway.ts:240-349` (no `verifiedRelayTargets`, no frame validation branch) | `bun test` passed all 17 tests in `Backend/tests/*` | `rg -n "stream:frame" Backend/realtime/gateway.ts` returned no matches; `bunx tsc --noEmit` exited 0 |
| R15 | Keep only `webrtc:signal` relay logic for streaming | done | `Backend/realtime/gateway.ts:323-349` (`socket.on('webrtc:signal'...)`) | `bun test` -> `tests/streaming-simple.test.ts` passed (`only relays WebRTC signals between stream participants`) | `rg -n "stream:frame" Backend/realtime/gateway.ts` returned no matches; `bunx tsc --noEmit` exited 0 |
| R16 | Simplify signal validation to ownership + session checks | done | `Backend/realtime/gateway.ts:330-343` (`streamSessions` lookup + `canRelayWebrtcSignal`), `Backend/streaming/simple.ts:20-33` | `bun test` -> `tests/streaming-simple.test.ts` passed (`only relays WebRTC signals between stream participants`) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| R17 | Remove command retry polling for stream command queue when flag is enabled | done | `Backend/realtime/gateway.ts:110-116,155-161` (`start_stream` dispatch/retry disabled under `SIMPLE_STREAMING`) | `bun test` passed all 17 tests in `Backend/tests/*` | `bunx tsc --noEmit` exited 0 in `Backend/` |
| R18 | Preserve `stream:started` and `stream:ended` event emission | done | `Backend/routes/streams.ts:344-353,685-714`, `Backend/realtime/gateway.ts:36-49` (`sendRealtimeToDevice`) | `bun test` -> `tests/streaming-simple.test.ts` passed (`builds deterministic requested and started payloads`, `normalizes ended payload`) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| R19 | Keep strict socket auth and room handling for devices | done | `Backend/realtime/gateway.ts:176-235` (token auth, role match, room join) | `bun test` -> `tests/device-token.test.ts` passed (2 cases) | `bunx tsc --noEmit` exited 0 in `Backend/` |
| W20 | Simplify web stream state machine | done | `WebApp/src/lib/app/controller.js:144-152,950-975`, `WebApp/src/lib/app/store.js:43-44` | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `npm run build` in `WebApp/` passed |
| W21 | Remove web fallback image mode and frame state | done | `WebApp/src/lib/app/store.js:43-44`, `WebApp/src/lib/app/controller.js:144-152`, `WebApp/src/routes/client/+page.svelte:183-189` | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `rg -n "stream:frame|clientFallbackFrame|getPublishCreds|getSubscribeCreds|frameRelay" WebApp/src` returned no matches; `npm run build` passed |
| W22 | Enforce video-only rendering path on client | done | `WebApp/src/routes/client/+page.svelte:183-189`, `WebApp/src/lib/app/controller.js:723,950-968` | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `npm run build` in `WebApp/` passed |
| W23 | Simplify `ontrack` handling | done | `WebApp/src/lib/app/controller.js:711-723` (`connection.ontrack`) | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `npm run build` in `WebApp/` passed |
| W24 | Add deterministic teardown path on end/unmount/navigation | done | `WebApp/src/lib/app/controller.js:596-614,975-992,1125-1132` (`teardownPeerConnection`, `stream:ended`, cleanup) | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `npm run build` in `WebApp/` passed |
| W25 | Remove frame capture/sender fallback on web camera page | done | `WebApp/src/lib/app/controller.js:869-882,908-928` (camera request handling now only starts preview/accept/offer), `WebApp/src/routes/camera/+page.svelte` remains preview-only | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `rg -n "stream:frame|clientFallbackFrame|getPublishCreds|getSubscribeCreds|frameRelay" WebApp/src` returned no matches; `npm run build` passed |
| W26 | Ensure camera only sends WebRTC offer path | done | `WebApp/src/lib/app/controller.js:738-749,869-882,908-928` (`startOfferToClient`, `handleCameraStreamRequest`) | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `npm run build` in `WebApp/` passed |
| W27 | Remove recording hooks tied to fallback transport | done | `WebApp/src/lib/app/controller.js:869-882,975-992` (recording kept, fallback transport removed), no frame relay refs remain in `WebApp/src` | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `rg -n "stream:frame|clientFallbackFrame|getPublishCreds|getSubscribeCreds|frameRelay" WebApp/src` returned no matches; `npm run build` passed |
| W28 | Remove client-side image fallback UI branches | done | `WebApp/src/routes/client/+page.svelte:183-189`, `WebApp/src/lib/app/store.js:43-44` | `npm run check` in `WebApp/` passed (`svelte-check found 0 errors and 0 warnings`) | `npm run build` in `WebApp/` passed |
| M29 | Remove mobile frame relay state and timer lifecycle | blocked | `MobileApp/src/app-context.tsx:86-87,175-213`, `MobileApp/README.md:75-79` show native mobile still depends on frame relay; `MobileApp/package.json` has no `react-native-webrtc` dependency | `npm run lint` in `MobileApp/` passed | `rg -n "react-native-webrtc" MobileApp/package.json` returned no matches; native WebRTC stack still absent |
| M30 | Align mobile state transitions with web logic | blocked | `MobileApp/src/app-context.tsx:105-113,349-381`, `MobileApp/src/state.ts:92-93`, `MobileApp/README.md:75-79` | `npm run lint` in `MobileApp/` passed | `npx tsc --noEmit` exited 0 in `MobileApp/`; implementation remains blocked by missing native WebRTC runtime |
| M31 | Remove mobile JPEG relay loop | blocked | `MobileApp/src/app-context.tsx:183-213,312-319`, `MobileApp/README.md:75-79` | `npm run lint` in `MobileApp/` passed | `rg -n "react-native-webrtc" MobileApp/package.json` returned no matches; removing the JPEG loop would break the only current mobile stream path |
| M32 | Remove mobile image fallback rendering path | blocked | `MobileApp/app/(tabs)/index.tsx:150-151,284`, `MobileApp/src/state.ts:92-93` | `npm run lint` in `MobileApp/` passed | `npx tsc --noEmit` exited 0 in `MobileApp/`; image fallback remains required until native WebRTC view/render support exists |
| M33 | Remove publish/subscribe credential calls from streaming runtime | blocked | `MobileApp/src/app-context.tsx:312,361`, `MobileApp/src/api.ts:84-85` | `npm run lint` in `MobileApp/` passed | `npx tsc --noEmit` exited 0 in `MobileApp/`; credential calls remain because mobile still follows the legacy relay path |
| M34 | Ensure mobile peer cleanup on end/unmount | blocked | `MobileApp/src/app-context.tsx:375-412` has no RTCPeerConnection lifecycle to clean up; `MobileApp/README.md:79` documents missing RN WebRTC stack | `npm run lint` in `MobileApp/` passed | `rg -n "react-native-webrtc" MobileApp/package.json` returned no matches; unblock by adding supported native WebRTC dependency and peer lifecycle code |
| C35 | Update OpenAPI streaming contract | done | `Backend/docs/openapi.ts:740,786,832`; legacy credential/playback stream paths removed from OpenAPI | `bunx tsc --noEmit` exited 0 in `Backend/` | `rg -n "publish-credentials|subscribe-credentials|playback-token" Backend/docs/openapi.ts` returned no matches |
| C36 | Update docs/comments to remove fallback as primary path | done | `Backend/README.md:133,147,191`, `MobileApp/README.md:75-79`, `Backend/public/backend-architecture.html:499-500`, `Backend/db/schema.ts:68-69` | `npm run check` in `WebApp/` passed; `bunx tsc --noEmit` in `Backend/` passed | `rg -n "stream:frame|frame relay|SIMPLE_STREAMING" Backend/README.md MobileApp/README.md Backend/public/backend-architecture.html docs/STREAMING_SIMPLIFICATION_ROLLOUT_AND_ROLLBACK.md` confirmed updated docs |
| C37 | Add migration and deprecation guidance | done | `docs/STREAMING_SIMPLIFICATION_ROLLOUT_AND_ROLLBACK.md:11-19`, `Backend/README.md:147-149` | `bunx tsc --noEmit` exited 0 in `Backend/` | `rg -n "Migration notes|Safe enablement sequence" docs/STREAMING_SIMPLIFICATION_ROLLOUT_AND_ROLLBACK.md` returned matches at lines 11 and 19 |
| C38 | Add structured stream lifecycle logging | done | `Backend/routes/streams.ts:171,230,359,719`, `Backend/realtime/gateway.ts:348` | `bun test` passed all 17 tests in `Backend/tests/*` | `bunx tsc --noEmit` exited 0 in `Backend/`; log markers present for request/accept/end/signal events |
| C39 | Add compile/build checks after cleanup | done | Validation spans `Backend/`, `WebApp/`, and `MobileApp/` | `bun test` passed (17/17), `npm run check` passed, `npm run lint` passed | `bunx tsc --noEmit` in `Backend/` exited 0, `npm run build` in `WebApp/` passed, `npx tsc --noEmit` in `MobileApp/` exited 0 |
| C40 | Add rollback runbook for flag behavior | done | `docs/STREAMING_SIMPLIFICATION_ROLLOUT_AND_ROLLBACK.md:35-43` | `bunx tsc --noEmit` exited 0 in `Backend/` | `rg -n "Rollback checklist|Known blocker" docs/STREAMING_SIMPLIFICATION_ROLLOUT_AND_ROLLBACK.md` returned matches at lines 35 and 43 |