docs(01-01): cite D-05 in must_haves per coverage gate .planning/phases/01-stabilize-video-pipeline/01-01-PLAN.md
This commit is contained in:
@@ -18,12 +18,14 @@ requirements_addressed:
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "`src/offscreen/recorder.ts` exists and exports the symbols Plan 02 tests against: addChunk, trimAged, getBuffer, resetBuffer, assertCodecSupported, VIDEO_BUFFER_DURATION_MS"
|
||||
- "`src/offscreen/recorder.ts` exists at the canonical source path as a real TypeScript module — strict type-check, source maps, IDE support (D-06)"
|
||||
- "`src/offscreen/recorder.ts` exports the symbols Plan 02 tests against: addChunk, trimAged, getBuffer, resetBuffer, assertCodecSupported, VIDEO_BUFFER_DURATION_MS"
|
||||
- "Running `npx vitest run tests/offscreen/ring-buffer.test.ts tests/offscreen/codec-check.test.ts` exits 0 with all tests green"
|
||||
- "Buffer holds at most: 1 header chunk + every chunk with arrival timestamp newer than now-30_000ms"
|
||||
- "Codec strictly bound to `video/webm;codecs=vp9` at 400 000 bps with `MediaRecorder.isTypeSupported` gate; no fallback chain (D-20)"
|
||||
- "`MediaRecorder.start(2000)` is called on session start (timeslice = 2000 ms per SPEC §4.1)"
|
||||
- "On `MediaStreamTrack.onended`, the buffer is cleared and a `RECORDING_ERROR` of `'user-stopped-sharing'` is emitted to SW"
|
||||
- "Capture is `navigator.mediaDevices.getDisplayMedia()` invoked from inside the offscreen document (D-01); SW-side `chrome.tabCapture.getMediaStreamId` is removed in Plan 05"
|
||||
- "Single continuous `MediaRecorder` runs for the whole session with `mediaRecorder.start(2000)` so chunks land on cluster boundaries per SPEC §4.1 (D-09)"
|
||||
- "One-time source picker fires on session start (operator picks screen/window once); on `MediaStreamTrack.onended` the buffer is cleared and a `RECORDING_ERROR` of `'user-stopped-sharing'` is emitted to SW so the popup can re-prompt next interaction (D-03)"
|
||||
- "Restart-segments fallback (D-13) is pre-staged as a commented-out skeleton at the bottom of recorder.ts so Plan 07's fallback path doesn't require a re-plan"
|
||||
- "`src/offscreen/index.html` exists at the source path and references `./recorder.ts`"
|
||||
- "`src/shared/logger.ts` has an `OffscreenLogger` class with `[OS:...]` prefix"
|
||||
@@ -72,8 +74,10 @@ handshake — that is Plan 04. To keep this plan inside its context budget, the
|
||||
port-side code in `recorder.ts` is left as a small import-time placeholder
|
||||
that Plan 04 fills in. The Plan-02 port + handshake tests therefore remain
|
||||
RED until Plan 04 lands, which is the intended choreography per the
|
||||
wave-1 dependency graph (Plans 03 and 04 run in parallel; Plan 02 wrote both
|
||||
sets of RED tests in advance).
|
||||
sequential wave structure (Plan 03 lands in wave 2; Plan 04 follows in wave
|
||||
3 and refactors the bootstrap section of the same file). Plan 02 wrote both
|
||||
sets of RED tests in advance so Plan 03 and Plan 04 each have a discrete
|
||||
RED→GREEN cycle to flip.
|
||||
|
||||
Purpose: REQ-video-ring-buffer's load-bearing logic lives here. The ring
|
||||
buffer is a pure function — exactly the TDD sweet spot. The remaining
|
||||
@@ -155,7 +159,7 @@ export interface VideoChunk {
|
||||
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|-------------|-----------------|
|
||||
| T-1-01 | Tampering — codec downgrade | `MediaRecorder` constructor | mitigate | `assertCodecSupported()` calls `MediaRecorder.isTypeSupported('video/webm;codecs=vp9')` BEFORE constructing the recorder; if it returns false, throws an Error and emits `RECORDING_ERROR` to SW. No vp8 / h264 / default fallback chain. The strict mode covers `MediaRecorder` itself being absent (the codec-check test mocks both cases). Grep gate: `grep -v '^#' src/offscreen/recorder.ts \| grep -cE 'codecs=(vp8\|h264)'` returns 0 (no fallback codec strings in the module). |
|
||||
| T-1-03 | Information Disclosure — captured stream contains other apps' content | `getDisplayMedia` stream | accept | This is the documented residual risk per CONTEXT.md D-04. The Chrome "Sharing your screen" indicator is the user-facing signal; the operator chose to share. No code-level mitigation is possible (the API is supposed to capture the screen). Documented as accepted risk in 01-RESEARCH.md §"Security Domain". |
|
||||
| T-1-03 | Information Disclosure — captured stream contains other apps' content | `getDisplayMedia` stream | accept | This is the documented residual risk per CONTEXT.md D-04 — the operator opted into the "Sharing your screen" indicator as the cost of the broader capture coverage. The Chrome "Sharing your screen" indicator is the user-facing signal; the operator chose to share. No code-level mitigation is possible (the API is supposed to capture the screen). Documented as accepted risk in 01-RESEARCH.md §"Security Domain". |
|
||||
| T-1-NEW-03-01 | DoS — unbounded buffer growth on a stuck timestamp | `addChunk` + `trimAged` | mitigate | The trim function uses arrival timestamp; if a clock anomaly produces a negative or stuck `now`, the buffer is bounded above by SPEC §10 #9 (50 MB RAM ceiling) anyway. Defensive belt: the recorder also exposes `getBuffer().length` to SW so a healthchecker can observe growth. No active rate-limit needed for Phase 1. |
|
||||
</threat_model>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user