Append Amendment blocks to DEC-003 (getDisplayMedia replaces tabCapture) and DEC-010 (long-lived port replaces alarms keepalive) so downstream phases see the new API contract. Original text intact; amendments are appended, not replacements. Maintains intel/* provenance for the Phase 01 doc cascade.
8.6 KiB
8.6 KiB
Architectural Decisions (synthesized from SPEC)
The SPEC Тз расширение фаза1.md does not formally label itself as ADR-set, but
sections 2 ("Стек"), 7 ("Разрешения в manifest.json"), and 8 ("Важные
ограничения и решения") encode binding technical choices that act as
architectural decisions for Phase 1. Each decision below is reproduced from the
SPEC verbatim where possible and tagged with its origin.
Status legend (synthesized, since SPEC has no formal ADR status field):
Accepted— SPEC §2/§7/§8 prescribed, no contradicting sourcelocked: falseeverywhere — SPEC islocked: falsein classification, so these decisions can still be revised by a future ADR; today they are the authoritative baseline.
DEC-001: Chrome Extension Manifest V3
- Source:
Тз расширение фаза1.md§2 (Стек), §7 (Разрешения) - Status: Accepted
- Locked: false
- Scope: Extension platform / packaging
- Decision: The extension MUST be implemented as a Chrome Extension targeting Manifest V3 (Service Worker background, no persistent background page).
- Rationale (from SPEC): Required for modern Chrome compatibility; implied by
every API used (
chrome.tabCapture,chrome.downloads,chrome.tabs,chrome.alarms). - Confirming source:
README.md§"Технический стек" — "Chrome Extension, Manifest V3".
DEC-002: Service Worker as Background Coordinator
- Source:
Тз расширение фаза1.md§2, §3 (Структура расширения), §8 - Status: Accepted
- Locked: false
- Scope: Background execution model
- Decision: Background logic runs in a Manifest V3 Service Worker
(
background/service-worker.js) that coordinates the video buffer and archive packaging. - Constraint binding: Service Worker is unloaded after ~30 s idle; keepalive
MUST be maintained via
chrome.alarmsfiring every 20 seconds (SPEC §8). - Confirming source:
README.md§"Технический стек".
DEC-003: Tab Video Capture via chrome.tabCapture
- Source:
Тз расширение фаза1.md§2, §4.1, §7 - Status: Accepted
- Locked: false
- Scope: Video acquisition
- Decision: Active-tab video is captured via
chrome.tabCapture.capture(). - Codec/bitrate binding:
video/webm; codecs=vp9at400 000 bps. MediaRecorderchunk cadence: 2000 ms.- Activation constraint:
tabCaptureis tied to the active tab and requires a user gesture on first invocation; on tab switch the capture re-attaches. - Confirming source:
README.md§"Технический стек".
Amendment (Phase 01-stabilize-video-pipeline, 2026-05-15)
- AMENDED-BY: Phase 01 CONTEXT.md D-01..D-05
- Replace
chrome.tabCapture.capture()withnavigator.mediaDevices.getDisplayMedia()called from the offscreen document. - Offscreen document is created with
chrome.offscreen.Reason.DISPLAY_MEDIA(replacesUSER_MEDIA). - Codec/bitrate/timeslice binding unchanged:
video/webm; codecs=vp9@ 400 000 bps, MediaRecorder timeslice 2000 ms. - Trade-off accepted: SPEC §1 "silent operation" is given up — Chrome's permanent "Sharing your screen" indicator is shown while recording. Phase 1 accepts this in exchange for broader capture coverage and elimination of
tabCaptureuser-gesture juggling. - Tab-switch re-attachment clause is REMOVED —
getDisplayMediacaptures a screen/window, not a tab. There is nothing to re-attach. - Manifest permission
tabCaptureis REPLACED withdesktopCapture(the latter is harmless:getDisplayMediais a web standard API and does NOT actually requiredesktopCapture, but we declare it for clarity per CONTEXT.md D-05).
DEC-004: DOM Capture via rrweb
- Source:
Тз расширение фаза1.md§2, §4.2 - Status: Accepted
- Locked: false
- Scope: DOM recording
- Decision: DOM events are captured via the
rrwebnpm library (rrweb.record()), running in the Content Script, with events forwarded to the Service Worker on archive-export request. - Sensitive-data binding: rrweb is configured with
maskInputSelectorto maskinput[type=password]and[data-sensitive="true"]. - Buffer cap binding: 5 000 rrweb events maximum; oldest dropped on overflow (SPEC §8).
- Confirming source:
README.md§"Технический стек", §"Особенности".
DEC-005: Archive Packaging via JSZip
- Source:
Тз расширение фаза1.md§2, §3, §6 - Status: Accepted
- Locked: false
- Scope: Archive assembly
- Decision: ZIP packaging uses the
jszipnpm library bundled aslibs/jszip.min.js(or the Vite-bundled equivalent). - Archive layout binding: see REQ-archive-layout in
requirements.md. - Confirming source:
README.md§"Технический стек".
DEC-006: File Download via chrome.downloads
- Source:
Тз расширение фаза1.md§2, §5, §7 - Status: Accepted
- Locked: false
- Scope: File delivery
- Decision: The assembled ZIP is delivered to the user's "Downloads" folder via
chrome.downloads.download(). No server upload in Phase 1. - Confirming source:
README.md§"Технический стек".
DEC-007: In-Memory Buffers in Service Worker + Content Script
- Source:
Тз расширение фаза1.md§2, §4.1, §4.2, §4.3 - Status: Accepted
- Locked: false
- Scope: Storage strategy
- Decision: All recorded data (video chunks, rrweb events, user-event log) is
held in memory only — video chunks in the Service Worker, rrweb events and
user-event log in the Content Script. No
chrome.storage/ IndexedDB persistence for the rolling buffers in Phase 1. - Confirming source:
README.md§"Технический стек" — "In-memory (Service Worker + Content Script)".
DEC-008: Screenshot via chrome.tabs.captureVisibleTab
- Source:
Тз расширение фаза1.md§4.4, §5 - Status: Accepted
- Locked: false
- Scope: Screenshot capture
- Decision: A single PNG screenshot is captured via
chrome.tabs.captureVisibleTab()at the moment the user clicks "Save archive". The screenshot is bundled asscreenshot.pnginside the ZIP.
DEC-009: WebM Header Retention
- Source:
Тз расширение фаза1.md§4.1, §8 - Status: Accepted
- Locked: false
- Scope: Video container integrity
- Decision: The first chunk emitted by
MediaRecorder(which contains the WebM container header) MUST be retained in the ring buffer indefinitely; only subsequent chunks rotate out by the 30-second TTL rule. - Rationale (from SPEC §8): WebM without its header is not playable.
DEC-010: Service Worker Keepalive via chrome.alarms
- Source:
Тз расширение фаза1.md§8 - Status: Accepted
- Locked: false
- Scope: Service Worker lifecycle
- Decision: To prevent the 30 s idle unload of MV3 Service Workers, a
chrome.alarmsalarm fires every 20 seconds to keep the worker alive.
Amendment (Phase 01-stabilize-video-pipeline, 2026-05-15)
- AMENDED-BY: Phase 01 CONTEXT.md D-17..D-18
- Replace
chrome.alarms-driven 20 s keepalive with a long-livedchrome.runtime.connectport opened from the offscreen document to the Service Worker. The port emits aPINGmessage every 25 s; both directions of traffic reset the SW's 30 s idle timer per Chrome 110+ semantics (developer.chrome.com/blog/longer-esw-lifetimes). - The
alarmspermission is removed frommanifest.json(it is no longer used by Phase 1; Phase 2 / 3 may re-add if needed). - Port lifetime cap (~5 minutes per Chromium-extensions community gist sunnyguan/f94058f66fab89e59e75b1ac1bf1a06e) is mitigated by reconnecting on
onDisconnectand pre-emptively at ~290 s. - See
.planning/phases/01-stabilize-video-pipeline/01-RESEARCH.mdPattern 5 for the canonical implementation.
DEC-011: Manifest Permissions Set
- Source:
Тз расширение фаза1.md§7 - Status: Accepted
- Locked: false
- Scope: Manifest configuration
- Decision:
manifest.jsonrequests exactly:permissions:tabCapture,activeTab,downloads,scripting,storagehost_permissions:<all_urls>
- Note:
tabCapturerequires explicit user gesture on first activation.
DEC-012: Vite + crxjs + TypeScript Build Toolchain
- Source:
README.md§"Технический стек" - Status: Accepted (DOC-level — not asserted by SPEC)
- Locked: false
- Scope: Build tooling
- Decision: The extension is built with Vite + the
crxjsplugin in TypeScript. The SPEC does not prescribe a build tool, so this is a DOC-level decision not contradicted by any higher-precedence source. - Provenance caveat: If a future ADR/SPEC selects a different toolchain, this DEC is auto-overridden.