# Constraints (synthesized from SPEC)

All constraints below are sourced from `Тз расширение фаза1.md` (the SPEC,
precedence 0). The DOC (`README.md`, precedence 1) is a confirming source where
noted; where it diverges, the SPEC takes precedence per the
`ADR > SPEC > PRD > DOC` rule.

Type taxonomy:
- `nfr` — non-functional requirement (performance, memory, latency, security)
- `protocol` — wire/file format or sequence contract
- `schema` — data structure contract
- `api-contract` — external API binding (Chrome extension APIs)

---

## CON-ram-ceiling

- Source: `Тз расширение фаза1.md` §10 (acceptance criterion 9)
- Type: nfr
- Constraint: The extension's RAM footprint MUST NOT exceed **50 MB** while
  running in the background.
- Component-level expected breakdown (SPEC §4, informative, not binding):
  - Video ring buffer: ~1.5–2 MB steady
  - rrweb buffer: ~1–3 MB
  - Event log: ~100–300 KB
  - Total steady-state expected component sum: ~2.6–5.3 MB
- DOC confirming source: `README.md` §"Критерии приёмки Фазы 1" — restates the
  50 MB ceiling identically.
- DOC informational target: `README.md` §"Память" reports an expected
  steady-state of ~5–10 MB. This is a non-binding **estimate**, not a
  contradicting requirement; the binding ceiling remains 50 MB. See
  `INGEST-CONFLICTS.md` for the auto-resolved INFO entry.

---

## CON-archive-export-latency

- Source: `Тз расширение фаза1.md` §10 (acceptance criterion 6)
- Type: nfr
- Constraint: From click to file landing in the Downloads folder MUST be
  **< 5 seconds**.
- DOC confirming source: `README.md` §"Критерии приёмки Фазы 1".

---

## CON-video-window

- Source: `Тз расширение фаза1.md` §4.1
- Type: nfr / protocol
- Constraint: The video ring buffer MUST hold **exactly the most recent 30
  seconds** of footage; older chunks are evicted after each new chunk arrives.
- Exception (DEC-009): the first chunk (WebM header) is exempt from eviction.

---

## CON-rrweb-window

- Source: `Тз расширение фаза1.md` §4.2, §8
- Type: nfr / protocol
- Constraint: rrweb events MUST be retained for **at most 10 minutes** AND **at
  most 5 000 events**, whichever is tighter. Eviction sweep runs every 60 s on
  the time dimension; the 5 000-event cap is enforced on insert (oldest first
  out).

---

## CON-event-log-window

- Source: `Тз расширение фаза1.md` §4.3
- Type: nfr / protocol
- Constraint: The user event log MUST be retained for **at most 10 minutes**.

---

## CON-video-codec

- Source: `Тз расширение фаза1.md` §4.1
- Type: protocol
- Constraint: Video chunks MUST be encoded as `video/webm; codecs=vp9` at a
  target bitrate of `400 000 bps` (~3 MB/min raw). Chunk cadence (MediaRecorder
  timeslice) is `2000 ms`.

---

## CON-webm-header-retention

- Source: `Тз расширение фаза1.md` §4.1, §8
- Type: protocol
- Constraint: The first MediaRecorder chunk (WebM container header) MUST be
  retained in the buffer indefinitely; the assembled `last_30sec.webm` MUST
  remain playable in a browser.

---

## CON-tab-capture-binding

- Source: `Тз расширение фаза1.md` §8
- Type: api-contract
- Constraint: `chrome.tabCapture` operates only on the active tab. On tab
  activation change, the recorder MUST re-attach to the new active tab. First
  invocation requires a user gesture.

### RETIRED (Phase 01-stabilize-video-pipeline, 2026-05-15)

- RETIRED-BY: Phase 01 CONTEXT.md D-01 / D-A2
- Reason: This phase replaces `chrome.tabCapture` with `navigator.mediaDevices.getDisplayMedia()`. The new API is not active-tab-bound; the recorder captures a screen / window selected once via Chrome's native picker and continues across tab switches.
- Replacement: CON-display-capture-binding (below).

---

## CON-service-worker-keepalive

- Source: `Тз расширение фаза1.md` §8
- Type: api-contract
- Constraint: MV3 Service Workers unload after ~30 s of inactivity. The
  extension MUST keep the worker alive via a `chrome.alarms` alarm firing every
  **20 seconds**.

### RETIRED (Phase 01-stabilize-video-pipeline, 2026-05-15)

- RETIRED-BY: Phase 01 CONTEXT.md D-17 / D-A2
- Reason: This phase replaces alarms-driven keepalive with a long-lived `chrome.runtime.connect` port between offscreen and Service Worker. Port-message traffic resets the SW idle timer per Chrome 110+ semantics.
- Replacement: CON-display-capture-binding (binds the port-keepalive expectations alongside the new capture API).

---

## CON-manifest-permissions

- Source: `Тз расширение фаза1.md` §7
- Type: api-contract / schema
- Constraint: `manifest.json` MUST declare exactly:
  ```json
  {
    "permissions": [
      "tabCapture",
      "activeTab",
      "downloads",
      "scripting",
      "storage"
    ],
    "host_permissions": [
      "<all_urls>"
    ]
  }
  ```

---

## CON-sensitive-data-masking

- Source: `Тз расширение фаза1.md` §4.2, §8
- Type: nfr (security / privacy)
- Constraint: Sensitive input fields MUST be masked in both rrweb snapshots and
  the event log. Specifically:
  - `input[type=password]` — value NEVER recorded; element MUST be masked in
    rrweb via `maskInputSelector`.
  - Any element with `data-sensitive="true"` — masked in rrweb via
    `maskInputSelector`.
  - The event logger MUST filter `input` events to drop password field values.

---

## CON-archive-layout

- Source: `Тз расширение фаза1.md` §6
- Type: schema (file layout)
- Constraint: The exported ZIP MUST follow the layout in REQ-archive-layout
  (verbatim, four top-level entries: `video/`, `rrweb/`, `logs/`,
  `screenshot.png`, `meta.json`). Filename pattern:
  `session_report_YYYY-MM-DD_HH-MM-SS.zip`.

---

## CON-meta-json-schema

- Source: `Тз расширение фаза1.md` §6
- Type: schema
- Constraint: `meta.json` MUST conform to the verbatim schema in
  REQ-meta-json-schema. All listed fields are required.

---

## CON-event-log-schema

- Source: `Тз расширение фаза1.md` §4.3
- Type: schema
- Constraint: Each entry in `events.json` MUST conform to:
  ```json
  {
    "timestamp": <epoch_ms>,
    "type": "click | input | navigation | error | network",
    "target": "<css_selector>",
    "value": "<value_or_masked>",
    "url": "<page_url>",
    "meta": {}
  }
  ```

---

## CON-buffer-storage

- Source: `Тз расширение фаза1.md` §2
- Type: nfr
- Constraint: All Phase 1 buffers MUST live in memory only (Service Worker for
  video, Content Script for rrweb + event log). `chrome.storage` is permitted
  but MUST NOT be used to persist the rolling buffers.

---

## CON-display-capture-binding

- Source: Phase 01 CONTEXT.md D-01..D-17, RESEARCH.md Patterns 1 & 5
- Type: api-contract
- Constraint: Video capture uses `navigator.mediaDevices.getDisplayMedia()` invoked once per session from the offscreen document with `chrome.offscreen.Reason.DISPLAY_MEDIA`. The Service Worker is kept alive by a long-lived `chrome.runtime.connect({ name: 'video-keepalive' })` port opened by the offscreen, with traffic in both directions at a minimum cadence of 25 s and pre-emptive reconnect at 290 s.
- Replaces: CON-tab-capture-binding (RETIRED), CON-service-worker-keepalive (RETIRED).
- UX trade-off: Chrome's permanent "Sharing your screen" indicator is shown while recording. SPEC §1 silent-operation property is intentionally relaxed.

---

## CON-no-server-upload

- Source: `Тз расширение фаза1.md` §9
- Type: nfr (scope boundary)
- Constraint: Phase 1 MUST NOT transmit any captured data to a remote server.
  All export is local-only via `chrome.downloads`.
