From 81dc894b2987f1b4f23ee933fadb5efa1d703271 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Sat, 22 Aug 2026 06:08:29 -0400 Subject: [PATCH] docs: add fleet control plane PRD roadmap --- .../FLEET_01_Camera_Identity_Organization.md | 150 +++++++++++++ .../FLEET_02_Scoped_Authorization_Audit.md | 165 +++++++++++++++ docs/prd/FLEET_03_Event_Bus_MQTT_Routes.md | 178 ++++++++++++++++ ...FLEET_04_Fleet_Explorer_Bulk_Operations.md | 157 ++++++++++++++ .../ONVIF_01_Capability_Onboarding_Events.md | 171 +++++++++++++++ docs/prd/ONVIF_02_Metadata_Edge_Recovery.md | 150 +++++++++++++ docs/prd/OPS_01_Backup_Restore.md | 153 ++++++++++++++ docs/prd/OPS_02_Evidence_Cases_Integrity.md | 147 +++++++++++++ .../prd/PRIVACY_01_Masking_Exclusion_Zones.md | 147 +++++++++++++ docs/prd/README.md | 25 +++ docs/prd/STORAGE_01_Multi_Target_Lifecycle.md | 199 ++++++++++++++++++ docs/prd/UXD_04_Maps_Operator_Views.md | 137 ++++++++++++ 12 files changed, 1779 insertions(+) create mode 100644 docs/prd/FLEET_01_Camera_Identity_Organization.md create mode 100644 docs/prd/FLEET_02_Scoped_Authorization_Audit.md create mode 100644 docs/prd/FLEET_03_Event_Bus_MQTT_Routes.md create mode 100644 docs/prd/FLEET_04_Fleet_Explorer_Bulk_Operations.md create mode 100644 docs/prd/ONVIF_01_Capability_Onboarding_Events.md create mode 100644 docs/prd/ONVIF_02_Metadata_Edge_Recovery.md create mode 100644 docs/prd/OPS_01_Backup_Restore.md create mode 100644 docs/prd/OPS_02_Evidence_Cases_Integrity.md create mode 100644 docs/prd/PRIVACY_01_Masking_Exclusion_Zones.md create mode 100644 docs/prd/STORAGE_01_Multi_Target_Lifecycle.md create mode 100644 docs/prd/UXD_04_Maps_Operator_Views.md diff --git a/docs/prd/FLEET_01_Camera_Identity_Organization.md b/docs/prd/FLEET_01_Camera_Identity_Organization.md new file mode 100644 index 00000000..a1f9a58d --- /dev/null +++ b/docs/prd/FLEET_01_Camera_Identity_Organization.md @@ -0,0 +1,150 @@ +# PRD — Camera Identity & Organization + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 1 — foundation +**Scope**: Stable camera identity, physical location hierarchy, normalized tags, +saved smart collections, and the selector language consumed by later fleet PRDs. + +--- + +## 1. Problem + +lightNVR can name and tag streams, which works well for small installations. At +hundreds of cameras, names and IP addresses are mutable, tags become inconsistent, +and flat lists cannot answer ordinary operational questions such as “show every +offline exterior camera in Building C.” + +Authorization, storage, event routing, bulk configuration, and health monitoring +all need to select the same sets of cameras. Implementing a different grouping +model for each feature would create incompatible policy systems. + +## 2. Goals + +- Give every camera an immutable UUID independent of name, address, and hardware + replacement. +- Represent one primary physical location path per camera. +- Preserve many-to-many tags as flexible facets rather than replacing them with + flat groups. +- Add saved static and dynamic collections for reusable fleet queries. +- Define one versioned selector format shared by authorization, event routes, + storage policies, fleet jobs, and operator views. +- Migrate existing installations without changing recording or playback behavior. + +## 3. Non-goals + +- Maps, floor plans, and GIS presentation; covered by UXD 04. +- Bulk editing or configuration templates; covered by Fleet 04. +- Permission enforcement; covered by Fleet 02. +- Multi-NVR federation or multi-tenant cloud management. +- Replacing the existing substream and detection-stream fields with separate + camera entities in v1. + +## 4. Product model + +| Concept | Cardinality | Purpose | Example | +| --- | --- | --- | --- | +| Camera UUID | One per configured camera | Durable identity | `0192...` | +| Display name | One mutable value | Human recognition | `North Lobby` | +| Location | One leaf; inherits ancestors | Physical organization | Campus / Bldg A / Floor 2 | +| Tag | Many per camera | Cross-cutting facets | `outdoor`, `ptz`, `critical` | +| Static collection | Explicit camera membership | Curated group | `Guard Tour A` | +| Smart collection | Saved selector | Dynamic group | `offline AND tag:entrance` | + +The configured stream remains the camera record in v1. Its main, sub, and +detection URLs are profiles of the same logical camera. + +## 5. Requirements + +### 5.1 Stable identity + +- Add a non-null UUID to every camera/stream record. +- Generate UUIDs for existing rows during migration and never derive them from + display name, URL, or IP address. +- Use UUIDs in new APIs, event subjects, policy bindings, and audit records. +- Retain name-based API compatibility during a documented transition period. +- A camera replacement workflow may change serial, MAC, URL, and credentials + while preserving UUID, history, policy membership, and operator layouts. + +### 5.2 Location hierarchy + +- Store an adjacency-list hierarchy with stable node UUID, parent UUID, name, + type, sort order, and optional metadata. +- Suggested types are organization, site, building, floor, and area, but custom + labels are allowed. +- Prevent cycles and destructive deletion of nonempty nodes. +- Moving a subtree updates effective selectors without rewriting every camera. +- Existing cameras migrate under a root `Unassigned` node. + +### 5.3 Normalized tags + +- Normalize tag identity separately from its display label. +- Tags are case-insensitive for uniqueness and preserve display casing. +- Support optional color and description metadata. +- Rename and merge tags without editing each camera record individually. +- Existing tag strings migrate losslessly. + +### 5.4 Collections and selectors + +- Static collections store explicit camera UUID membership. +- Smart collections store a versioned selector AST, not raw SQL. +- v1 selector predicates: camera UUID, location subtree, tag any/all/none, + enabled state, recording mode, vendor/model, ONVIF capability, and health state. +- Boolean `AND`, `OR`, and `NOT` composition is supported with bounded nesting. +- Selector evaluation returns a total count plus a paginated camera result. +- A dry-run/preview endpoint explains why a camera matched. +- Saved collections can be private or shared; access enforcement lands in Fleet + 02, while v1 defaults shared mutation to administrators. + +### 5.5 APIs and migration + +- CRUD APIs for locations, tags, and collections use camera UUIDs. +- Fleet query API supports server-side pagination, sorting, facets, and counts. +- Migration is idempotent and safe to resume after interruption. +- Backup/export formats include stable identities and organization metadata. +- Existing endpoints remain functional until their UUID replacements are adopted + by the web UI. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | UUID schema, migration, UUID-capable camera APIs | +| P1 | Location hierarchy and tag normalization | +| P2 | Selector evaluator and fleet query API | +| P3 | Static/smart collections and organization management UI | + +## 7. Acceptance criteria + +- A migrated installation retains all streams, tags, recordings, and playback. +- Renaming or replacing a camera does not change its UUID or lose history. +- An operator can represent at least five hierarchy levels and move a complete + subtree without editing its cameras. +- A query such as `location:Building-C AND tag:outdoor AND health:offline` + returns correct results and facet counts from a 1,000-camera fixture. +- Authorization, event, storage, and bulk-operation code can consume the same + selector JSON without feature-specific translations. +- Malformed or excessively complex selectors are rejected with actionable errors. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| UUID migration breaks name-based callers | Dual lookup during transition; log deprecated name use | +| Free-form tags remain inconsistent | Central tag dictionary with rename and merge | +| Selector language becomes an unsafe query engine | Typed AST, bounded depth, parameterized SQL only | +| “Camera” and “stream” terminology diverge | Preserve stream internals in v1; document the product-level camera abstraction | + +## 9. Dependencies and successors + +This PRD has no new-feature dependency. It is required by Fleet 02–04, Storage +01, both ONVIF PRDs, and the later operations PRDs. + +## 10. Open questions + +- Whether location node types should remain suggestions or be administrator- + defined vocabulary. +- Whether camera replacement needs history in v1 or only an audited overwrite. +- Whether private smart collections belong in the server database or user-local + preferences for the first implementation. diff --git a/docs/prd/FLEET_02_Scoped_Authorization_Audit.md b/docs/prd/FLEET_02_Scoped_Authorization_Audit.md new file mode 100644 index 00000000..64e73c8f --- /dev/null +++ b/docs/prd/FLEET_02_Scoped_Authorization_Audit.md @@ -0,0 +1,165 @@ +# PRD — Scoped Authorization & Audit + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 2 — access-control foundation +**Scope**: Action-level authorization, resource selectors, scoped API tokens, +consistent endpoint enforcement, and a durable audit trail. SSO is explicitly a +deferred, customer-triggered phase. + +--- + +## 1. Problem + +The current admin/user/viewer roles and allowed-tag filtering provide a useful +baseline, but institutional deployments need to distinguish viewing video from +listening, talking, exporting, operating PTZ, deleting evidence, or changing a +camera. A per-camera checkbox matrix would become unmanageable at hundreds of +cameras and would drift as cameras move or are added. + +The same decision must be enforced consistently by every UI and API endpoint, +and sensitive actions need an auditable record. + +## 2. Goals + +- Authorize explicit actions over dynamic resource scopes. +- Reuse Fleet 01 selectors so permissions follow locations and tags. +- Keep roles understandable: roles bundle actions; grants bind a role to a scope. +- Apply the same authorization rules to sessions and API tokens. +- Default-deny newly introduced privileged actions while preserving sensible + behavior for existing users during migration. +- Audit access-sensitive and state-changing operations. +- Leave a clean integration seam for a future organizational identity provider. + +## 3. Non-goals + +- OIDC, SAML, LDAP, or automatic identity-provider discovery in the initial + implementation. +- Multi-tenant cloud identity federation. +- Per-frame watermarking or DRM. +- Building organization-specific compliance reports before a customer defines + the applicable policy. + +## 4. Authorization model + +`principal/group -> grant -> role(actions) + resource selector + optional schedule` + +Initial actions: + +- `live.view`, `audio.listen`, `audio.talk` +- `recordings.replay`, `recordings.export`, `snapshot.create` +- `ptz.control` +- `evidence.protect`, `recording.delete` +- `camera.configure`, `fleet.execute_job` +- `storage.configure`, `events.configure` +- `users.manage`, `system.admin` + +Roles are named reusable action bundles. A grant binds a user or local group to +a role and a Fleet 01 selector. A schedule may limit a grant by local time and +day. Explicit deny rules are out of scope for v1; absence of an allow is deny. + +## 5. Requirements + +### 5.1 Policy storage and evaluation + +- Persist roles, actions, local groups, grants, schedules, and policy version. +- Compile and cache selectors without caching past policy or camera changes. +- Expose a single server-side authorization function used by all handlers. +- Return `403` without revealing resource metadata when a principal lacks access. +- List endpoints filter unauthorized resources and compute totals after filtering. +- All new actions begin denied except for the built-in administrator role. +- Provide a policy simulation endpoint for administrators: principal + action + + resource returns allow/deny and the matching grant, without executing the action. + +### 5.2 Migration and built-in roles + +- Map existing admins to every action over all cameras. +- Map existing viewers to safe read-only actions within their `allowed_tags`. +- Map existing users to a documented compatibility role within their current + scope; call out any newly restricted destructive action during upgrade. +- Keep built-in roles immutable but cloneable. +- Migrate `allowed_tags` into selector-backed grants and deprecate it only after + all handlers use the new evaluator. + +### 5.3 API tokens + +- Tokens inherit or narrow the issuing principal's grants; they never widen them. +- Token creation requires an explicit expiry, description, and displayed-once + secret. +- Persist only a strong token hash and token identifier. +- Audit creation, use, revocation, expiry, and denied privileged calls. + +### 5.4 Audit trail + +- Record timestamp, request/correlation ID, principal, authentication method, + action, target UUID, outcome, remote address, and safe structured details. +- Required events include login outcomes, policy changes, camera configuration, + PTZ control, audio talk activation, export, protect/unprotect, deletion, + storage policy changes, event route changes, and backup restore. +- Never log passwords, tokens, camera credentials, or raw authorization headers. +- Provide filtered, paginated export with a configurable retention period. +- Audit records are append-only through supported APIs. + +### 5.5 Administration UI + +- Role editor presents action descriptions and warns on destructive bundles. +- Grant editor uses location, tag, collection, or explicit-camera selectors. +- Scope preview shows matched count and a sample before save. +- “Test access as user” uses the simulation endpoint and is itself audited. +- Every denied UI action remains hidden or disabled, but server enforcement is + always authoritative. + +### 5.6 Deferred SSO phase + +OIDC/SSO is **not part of the initial implementation**. It activates when a +committed organizational deployment—such as an SJC-scale customer—requires it +and supplies a real IdP configuration and administrative testing partner. + +When triggered, the phase should add: + +- Authorization Code flow with PKCE, issuer discovery, key rotation, logout, and + configurable local-admin break-glass access. +- IdP group/claim mapping to existing lightNVR roles and grants. +- Just-in-time user provisioning with safe default scope. +- Audit entries that preserve external subject and issuer. + +The core authorization schema must not depend on OIDC, so delaying SSO does not +defer useful access-control work. + +## 6. Phasing + +| Phase | Scope | Trigger | +| --- | --- | --- | +| P0 | Action vocabulary, policy evaluator, endpoint inventory | Immediate | +| P1 | Selector grants, migration, scoped API tokens | After Fleet 01 selector API | +| P2 | Audit log and policy administration UI | After P0/P1 | +| P3 | OIDC/SSO and group mapping | Committed organizational customer only | + +## 7. Acceptance criteria + +- Endpoint tests prove every protected action denies an unauthorized user even + when the HTTP request bypasses the UI. +- A grant for `tag:parking` automatically includes a newly tagged camera and + excludes it when the tag is removed. +- A user may replay but not export recordings when those actions differ. +- A camera-scoped token cannot query or mutate cameras outside its grants. +- Every required sensitive operation produces a redacted audit record with a + correlation ID. +- Upgrading preserves administrator access and produces a migration report. +- No OIDC dependency is required to ship P0–P2. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Missed endpoint creates an authorization gap | Route inventory plus mandatory handler tests and centralized middleware/helper | +| Dynamic selectors create surprising access | Preview, simulation, audit, and visible matching-grant explanation | +| Existing users lose required access | Compatibility mapping and upgrade report | +| SSO work becomes speculative | Gate P3 on a committed customer and actual IdP | + +## 9. Dependencies + +- Fleet 01 for stable camera UUIDs and selectors. +- Fleet 03 should reuse audit correlation IDs and may publish security events, but + durable audit storage must not depend on MQTT delivery. diff --git a/docs/prd/FLEET_03_Event_Bus_MQTT_Routes.md b/docs/prd/FLEET_03_Event_Bus_MQTT_Routes.md new file mode 100644 index 00000000..5eb8a1b8 --- /dev/null +++ b/docs/prd/FLEET_03_Event_Bus_MQTT_Routes.md @@ -0,0 +1,178 @@ +# PRD — Event Bus & MQTT Routes + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 3 — integration foundation +**Scope**: A versioned internal event contract, durable outbox, MQTT destinations, +routing rules, delivery observability, and an operator-facing Events & Routes UI. + +--- + +## 1. Problem + +lightNVR publishes useful detection information to MQTT, but downstream consumers +need stable identity, schemas, delivery guarantees, and events beyond detections. +Adding SMTP, SMS, Telegram, and every future provider to the NVR core would couple +recording reliability to notification integrations and duplicate work better done +by LightNVR Cloud, Home Assistant, Node-RED, or customer systems. + +## 2. Product position + +lightNVR emits facts and reliably routes them. It does not deliver human +notifications itself. + +```text +camera/core event -> normalized event bus -> route rules -> MQTT + -> LightNVR Cloud -> email/SMS/push + -> HA/Node-RED/customer service +``` + +## 3. Goals + +- Define a stable, versioned event envelope with immutable event IDs. +- Publish health, recording, storage, security, ONVIF, and detection events. +- Route events by the Fleet 01 selector plus event-specific predicates. +- Survive broker outages without blocking capture or silently losing queued work. +- Support multiple MQTT destinations with strong TLS and credential handling. +- Expose delivery state, testing, retry, and dead-letter diagnostics. +- Preserve current Home Assistant discovery behavior during migration. + +## 4. Non-goals + +- Native SMTP, SMS, push, Telegram, Slack, or other provider clients. +- A general-purpose scripting runtime inside lightNVR. +- Exactly-once end-to-end delivery; consumers deduplicate using event ID. +- Uploading media to cloud storage in v1. +- Replacing the audit log with MQTT. + +## 5. Event contract + +Use a CloudEvents-inspired JSON envelope: + +```json +{ + "specversion": "1.0", + "id": "01K...", + "type": "io.lightnvr.detection.object.v1", + "source": "urn:lightnvr:installation-uuid", + "subject": "camera/camera-uuid", + "time": "2026-08-22T14:23:18Z", + "datacontenttype": "application/json", + "data": {} +} +``` + +Required invariants: + +- `source + id` is unique and stable across retries. +- Event type includes a schema major version. +- `subject` uses Fleet 01 UUIDs, never mutable names as identity. +- Timestamps are UTC with explicit offset. +- Unknown data fields are ignored by consumers; breaking changes increment type + version. +- Secrets and raw filesystem paths never appear in payloads. + +Initial event families: + +- Detection: motion asserted/cleared, object observed, zone entered. +- Camera: online/offline, authentication failed/recovered, capability changed. +- Stream: degraded/recovered, stale frames, recording started/stopped/gap. +- Storage: pressure, target unavailable/recovered, policy unmet, migration failed. +- System/security: startup/shutdown, update outcome, repeated login failure. +- ONVIF: normalized device events, digital input, relay or tamper state. + +## 6. Requirements + +### 6.1 Internal event bus + +- C API accepts a typed event without performing network I/O on the caller thread. +- Validate required envelope fields and size limits before enqueueing. +- Critical operational events enter a persistent SQLite outbox transactionally + where practical; high-volume observations may use explicit sampling/coalescing. +- Assign severity, sensitivity, default expiry, and media-reference policy per type. +- Prevent an event feedback loop when route-delivery health emits events. + +### 6.2 Routes and filters + +- A route binds enabled event types, Fleet 01 camera selector, event predicates, + schedule, suppression settings, and one destination. +- Detection predicates include label, confidence threshold, and zone. +- Suppression includes debounce, cooldown, grouping window, and maximum rate. +- Preview evaluates a route against stored sample events without publishing. +- Route changes and manual retries are audited through Fleet 02 when available. + +### 6.3 MQTT destinations + +- Support multiple broker profiles with host, port, client ID, TLS mode, CA, + client certificate where applicable, credentials, QoS, and topic template. +- Credentials use the existing secret-storage conventions and are never returned + after save. +- Suggested topic: `lightnvr/v1/events/{type}/{camera_uuid}`; retained state uses + separate state topics and transient events are not retained by default. +- Provide connect test, publish test, current state, last success/error, queue + depth, and reconnect counters. +- MQTT 5 properties may carry content type, expiry, correlation ID, and schema + metadata; remain compatible with MQTT 3.1.1 brokers where feasible. + +### 6.4 Delivery and outbox + +- Persist event envelope, destination, attempt count, next attempt, expiry, and + final state. +- Retry with bounded exponential backoff and jitter. +- Expired or permanently failed deliveries move to a bounded dead-letter view. +- Queue capacity has explicit byte and row limits plus documented shedding order. +- Recording and detection threads never wait for a broker connection. +- Restart resumes eligible queued deliveries without changing event IDs. + +### 6.5 Media references + +- Event payloads may include metadata for a snapshot or logical clip. +- URLs must be authenticated or short-lived and bound to appropriate Fleet 02 + permissions when that PRD lands. +- Optional binary snapshot publishing is a separate opt-in route action with size + limits; it is not embedded as base64 in every event. + +### 6.6 Events & Routes UI + +- Event catalog displays schema, sample payload, sensitivity, and expected rate. +- Destination editor includes validation and safe connection testing. +- Route builder uses camera scope, event type, predicates, schedule, and cooldown. +- Delivery dashboard shows broker state, queue depth, failures, dead letters, and + end-to-end test results. + +## 7. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Envelope, event registry, async in-process bus, compatibility adapter for current detections | +| P1 | SQLite outbox, one MQTT destination, retry/expiry metrics | +| P2 | Multiple destinations, selector routes, suppression rules, UI | +| P3 | Broader health/storage/security/ONVIF event producers and media references | + +## 8. Acceptance criteria + +- Detection, camera-offline, recording-gap, and storage-pressure fixtures validate + against documented schemas. +- A broker outage during 1,000 generated critical events does not block recording; + eligible events deliver after reconnection with unchanged IDs. +- Duplicate delivery is safely recognizable by `source + id`. +- A route scoped to one location never publishes another location's camera event. +- Cooldown prevents an unstable camera from flooding downstream consumers. +- No supported configuration path can add a native email/SMS provider to core; + such delivery remains an external subscriber responsibility. + +## 9. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Event storms exhaust disk | Rate limits, coalescing, expiry, bounded outbox | +| Schema churn breaks cloud consumers | Registry, fixtures, major-versioned types | +| Snapshot URLs leak access | Short-lived authorization-aware references | +| MQTT failure impacts recording | Strict thread isolation and bounded enqueue | + +## 10. Dependencies + +- Fleet 01 for camera UUIDs and selectors. +- Fleet 02 for configuration authorization and audit; P0 may begin before its UI. +- Storage 01 and ONVIF PRDs add producers after this foundation exists. diff --git a/docs/prd/FLEET_04_Fleet_Explorer_Bulk_Operations.md b/docs/prd/FLEET_04_Fleet_Explorer_Bulk_Operations.md new file mode 100644 index 00000000..0ef2b4d7 --- /dev/null +++ b/docs/prd/FLEET_04_Fleet_Explorer_Bulk_Operations.md @@ -0,0 +1,157 @@ +# PRD — Fleet Explorer & Bulk Operations + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 4 — fleet operator experience +**Scope**: A scalable fleet explorer, health queues, configuration templates, +desired-state drift reporting, and durable bulk jobs for hundreds of cameras. + +--- + +## 1. Problem + +Card grids and one-camera-at-a-time forms become operationally expensive around +hundreds of cameras. Operators need to find exceptions, understand fleet health, +and apply a controlled change to all matching cameras—not click through 900 +nearly identical pages or copy settings from a “golden camera.” + +## 2. Goals + +- Keep fleet browsing responsive with at least 1,000 configured cameras. +- Make unhealthy or noncompliant cameras easier to find than healthy ones. +- Support server-side facets, saved views, and organization-tree navigation. +- Replace ad-hoc copy-settings flows with versioned templates and overrides. +- Execute bulk changes as previewable, durable jobs with per-camera results. +- Enforce Fleet 02 permissions on query results and operations. + +## 3. Non-goals + +- Video wall customization or spatial maps; covered by UXD 04. +- Multi-NVR federation. +- Automatic firmware deployment. +- A generic orchestration language or arbitrary shell-command jobs. +- SSO. + +## 4. Primary experience + +The default Fleet page combines: + +- Location tree with total, online, degraded, and offline counts. +- Virtualized/server-paginated table. +- Search and facets. +- Saved personal/shared views. +- Smart operational queues. +- Selection summary and safe bulk action bar. + +Required columns include camera, location, tags, address, vendor/model, stream and +recording status, last frame, current storage policy, template compliance, and +last error. Operators can choose and persist visible columns. + +## 5. Requirements + +### 5.1 Server-side fleet query + +- Page, sort, filter, facet, and aggregate on the server after authorization. +- Search by display name, UUID, IP, MAC, serial, manufacturer, model, tag, and + location path. +- Return aggregate counts for tree nodes and active facets. +- Share the Fleet 01 selector grammar; saved views store selector plus columns and + sort rather than result IDs. +- Use stable cursors or stable sorting so live health changes do not duplicate rows. + +### 5.2 Operational queues + +Ship defined smart collections for: + +- Offline cameras. +- Authentication failures. +- Recording gaps. +- Stale frames or low effective FPS. +- Storage policy unmet. +- Configuration drift. +- Newly discovered/unclaimed devices after ONVIF 01. + +Each queue shows count, oldest unresolved condition, severity, and relevant bulk +remediation. Health state definitions are versioned and explainable. + +### 5.3 Configuration templates + +- A template contains a versioned subset of camera configuration, not secrets by + default. +- Templates may cover recording, retention-policy assignment, detection defaults, + transport, audio, schedules, and selected ONVIF profile choices. +- Bind a template to a Fleet 01 selector with precedence rules. +- Per-camera overrides are explicit, visible, and removable. +- Drift compares desired effective configuration to actual configuration and + distinguishes intentional overrides from errors. +- Updating a template creates a new version and a previewable reconciliation job; + it does not mutate all cameras synchronously inside the save request. + +### 5.4 Bulk jobs + +- A job stores creator, action, selector snapshot, matched count, policy/template + version, creation time, state, progress, and per-camera result. +- Preview shows affected cameras and changes before confirmation. +- Confirmation states whether selection is a fixed UUID snapshot or all cameras + matching at execution; v1 defaults to a fixed snapshot for safety. +- Workers use bounded concurrency and support cancel-before-start, retry-failed, + and export-results. +- Partial failure never reports overall success without a visible breakdown. +- Destructive operations require stronger confirmation and Fleet 02 action. + +### 5.5 Discovery staging + +After ONVIF 01, the Fleet page includes an inbox for discovered devices with +endpoint, IP/MAC, serial, vendor/model, capability summary, duplicate suspicion, +and last-seen time. Operators can batch claim devices, apply a credential profile, +pair media profiles, assign location/tags/template, test, and commit. + +Credentials remain outside templates and job result logs. + +### 5.6 Performance and accessibility + +- Virtualize rendered rows; never create a DOM card for every camera. +- Update only changed health rows through polling deltas or event subscription. +- Preserve keyboard navigation, accessible names, focus, and 44px touch targets. +- Mobile prioritizes operational queues and search; dense bulk administration may + use a responsive table/detail pattern rather than horizontal overflow. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Fleet query API, virtualized table, location tree, facets | +| P1 | Health queues and saved views | +| P2 | Durable bulk-job framework and safe initial actions | +| P3 | Configuration templates, assignments, overrides, drift | +| P4 | ONVIF discovery staging and batch claim integration | + +## 7. Acceptance criteria + +- A 1,000-camera fixture loads its first authorized page and aggregate counts + without returning all camera rows to the browser. +- Filtering by location, tags, health, model, and template compliance composes + correctly and can be saved. +- An action over 900 matched cameras requires one preview and one confirmation, + runs with bounded concurrency, and provides 900 individual outcomes. +- Retrying a partially failed job retries only eligible failures. +- A template change shows exact before/after fields and never overwrites explicit + camera overrides silently. +- Users cannot infer counts or identities outside their Fleet 02 scopes. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Bulk jobs cause a fleet-wide outage | Preview, fixed snapshots, bounded concurrency, canary option, stop threshold | +| Templates hide surprising inheritance | Effective-value explanation and explicit override markers | +| Live health churn destabilizes paging | Stable sort/cursors and delta updates | +| UI becomes an enterprise dashboard maze | Default to exception queues and progressive disclosure | + +## 9. Dependencies + +- Fleet 01 is required for identities, organization, collections, and selectors. +- Fleet 02 is required before privileged bulk actions ship. +- Fleet 03 supplies eventual near-real-time health events. +- ONVIF 01 supplies discovery staging and capability data. diff --git a/docs/prd/ONVIF_01_Capability_Onboarding_Events.md b/docs/prd/ONVIF_01_Capability_Onboarding_Events.md new file mode 100644 index 00000000..8f28cc00 --- /dev/null +++ b/docs/prd/ONVIF_01_Capability_Onboarding_Events.md @@ -0,0 +1,171 @@ +# PRD — ONVIF Capability Onboarding & Events + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 6 — camera interoperability +**Scope**: Capability-driven discovery and onboarding, modern media/profile +selection, reliable device events, diagnostics, and a tested compatibility matrix. + +--- + +## 1. Problem + +lightNVR already has ONVIF discovery, profile enumeration, add/test flows, PTZ, +presets, home position, imaging settings, and motion-oriented event support. The +product and UI still treat ONVIF as a set of optional operations rather than a +device capability contract. + +At fleet scale, operators need to claim many cameras, choose valid main/sub/ +detection profiles, understand what each device actually supports, and diagnose +vendor-specific failures. Event support also needs to discover and normalize more +than a few assumed motion topics. + +## 2. Goals + +- Build and persist a capability matrix for every ONVIF camera. +- Make discovery a staged, repeatable inventory and claim workflow. +- Account for device clock offset and authentication behavior. +- Enumerate and validate modern media profiles, including H.265 and audio where + devices expose them. +- Discover event topics and maintain robust subscriptions. +- Normalize supported device events into Fleet 03 contracts. +- Publish an evidence-backed tested-camera compatibility matrix. + +## 3. Non-goals + +- Claiming ONVIF conformance or certification without passing official tests. +- Supporting deprecated Profile Q anonymous setup behavior. +- Profile M analytics metadata and Profile G recordings; covered by ONVIF 02. +- Implementing every vendor extension. +- Firmware update or vendor device-management portals. + +## 4. Capability model + +For each camera UUID, store a timestamped capability snapshot containing: + +- Device identity: endpoint, manufacturer, model, firmware, serial, hardware ID, + IP and MAC where available. +- Services and versions: Device, Media/Media2, Events, PTZ, Imaging, Analytics, + Recording/Search/Replay, DeviceIO. +- Media: profiles, tokens, stream/snapshot URI support, codec, resolution, FPS, + bitrate, audio source/encoder, and backchannel. +- PTZ and imaging operations already supported by lightNVR. +- Event service mode and discovered topic set. +- Security/authentication and observed clock offset. +- Last probe result, changed fields, raw redacted diagnostic reference. + +Capability changes emit an event and may create configuration drift; they do not +silently rewrite a working stream configuration. + +## 5. Requirements + +### 5.1 Discovery inventory + +- Run bounded WS-Discovery scans on selected interfaces/subnets. +- Deduplicate devices by endpoint plus serial/MAC evidence, not IP alone. +- Persist first seen, last seen, addresses, identity, claim state, and duplicate + suspicion. +- Never auto-claim a discovered device or persist supplied credentials until an + authorized operator confirms. +- Feed the Fleet 04 discovery staging inbox. + +### 5.2 Authentication and time + +- Query device time and calculate clock offset before authenticated calls where + supported. +- Distinguish network, TLS, authentication, time-skew, SOAP-fault, unsupported, + and malformed-response errors. +- Redact credentials and security headers from logs and diagnostics. +- Credential profiles are reusable secret references, not passwords copied into + templates or job records. + +### 5.3 Capability probe + +- Use GetServices/GetCapabilities and service-specific probes rather than vendor + assumptions. +- Cache successful results with manual refresh and bounded periodic refresh. +- Treat partial capability discovery as a usable state with visible warnings. +- Preserve the raw operation name and SOAP fault for diagnostics while presenting + a plain-language operator result. + +### 5.4 Media/profile pairing + +- Enumerate Media and Media2 profiles where supported. +- Present codec, resolution, FPS, bitrate, audio, snapshot, and transport facts. +- Let an operator pair main, sub, and detection uses, preventing accidental use of + the same unsuitable high-resolution profile for every role. +- Test selected URIs before committing configuration. +- Prefer direct camera-reported URIs, then apply explicit address rewriting only + when the camera advertises an unreachable host. +- Support H.264 and H.265 discovery; actual browser playback remains subject to + existing lightNVR transport/codec support. + +### 5.5 Event discovery and subscription + +- Query event properties/topics instead of hard-coding a fixed vendor topic list. +- Create PullPoint subscriptions, renew before expiry, recreate after reboot or + invalid subscription, and back off on repeated failure. +- Normalize initial types: motion state, tamper, digital input, line crossing, + simple analytic alarm, and device fault where semantics are sufficiently known. +- Preserve vendor topic and raw key/value metadata in a bounded diagnostic field. +- Map asserted/cleared state consistently and deduplicate repeated device messages. +- Publish normalized events through Fleet 03; event delivery never runs in the + ONVIF polling/subscription thread. + +### 5.6 Diagnostics and compatibility + +- Generate a redacted per-camera ONVIF report: identity, services, profiles, + capability matrix, clock offset, event topics, selected configuration, last + faults, and software version. +- Maintain response fixtures for tested vendors and regress them in CI. +- Publish a tested-camera matrix distinguishing discovered, streaming, snapshot, + events, PTZ, imaging, audio, and backchannel support. +- “Unknown/not tested” is distinct from “unsupported.” + +### 5.7 Fleet UI integration + +- Discovery staging supports batch credential test, capability probe, profile + pairing, organization, template assignment, and commit. +- Camera detail shows capability badges and diagnostic actions. +- Bulk probe jobs use Fleet 04 bounded concurrency and per-camera results. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Persistent discovery inventory, identity/deduplication, time/auth diagnostics | +| P1 | Capability snapshot and Media/Media2 profile pairing | +| P2 | Event topic discovery, resilient PullPoint manager, normalized events | +| P3 | Fleet staging UI, bulk probes, fixtures, published compatibility matrix | +| P4 | Additional Profile T controls selected from real camera/customer demand | + +## 7. Acceptance criteria + +- Repeated discovery of a DHCP-renumbered camera updates one inventory record. +- A clock-skewed device can be diagnosed without reporting a generic bad-password + error. +- Batch onboarding can claim, organize, profile-pair, test, and commit at least 50 + discovered cameras with individual results. +- Subscription renewal and lightNVR restart recover event delivery without manual + camera reconfiguration. +- A normalized motion/tamper/input event contains stable camera UUID and original + vendor topic diagnostics. +- Compatibility claims are backed by stored fixtures or recorded hardware test + results and never imply ONVIF certification. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Vendor SOAP behavior varies | Capability probing, fixtures, redacted raw faults, compatibility matrix | +| Discovery floods a large subnet | Interface/subnet scope, bounded concurrency, rate limits | +| Subscription loops hammer cameras | Lease-aware renewals and exponential backoff | +| Capability refresh breaks working setup | Snapshot changes are advisory until explicitly reconciled | + +## 9. Dependencies + +- Fleet 01 for stable identity and organization. +- Fleet 03 for normalized event publication. +- Fleet 04 for batch discovery/claim UX; core probes can land first. +- Fleet 02 controls who may discover, claim, configure, and operate cameras. diff --git a/docs/prd/ONVIF_02_Metadata_Edge_Recovery.md b/docs/prd/ONVIF_02_Metadata_Edge_Recovery.md new file mode 100644 index 00000000..2b9d6622 --- /dev/null +++ b/docs/prd/ONVIF_02_Metadata_Edge_Recovery.md @@ -0,0 +1,150 @@ +# PRD — ONVIF Metadata & Edge Recovery + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 7 — advanced interoperability +**Scope**: Profile M analytics metadata ingestion and Profile G edge-recording +search, playback, import, and gap backfill. + +--- + +## 1. Problem + +Many modern cameras can provide structured analytics metadata and retain video on +an SD card during an NVR or network outage. Without these capabilities lightNVR +must duplicate analytics work locally and accepts permanent recording gaps even +when the camera has the missing footage. + +These are advanced features with heavy vendor variation. They should build on a +proven capability registry and event contract rather than being folded into basic +discovery. + +## 2. Goals + +- Ingest supported Profile M metadata with camera-native timestamps and identity. +- Normalize useful objects, classifications, counters, and analytic events. +- Search and play Profile G recordings without first copying every file. +- Detect eligible local gaps and recover matching edge recordings safely. +- Integrate imported recordings with normal timeline, storage policy, provenance, + and audit behavior. +- Degrade explicitly when a camera implements only part of a profile. + +## 3. Non-goals + +- Replacing lightNVR's local detection pipeline. +- Claiming universal Profile M/G support from one tested vendor. +- Making camera SD storage the sole copy of required recordings. +- Automatically importing unlimited edge history. +- Facial recognition or identity matching. + +## 4. Profile M metadata requirements + +### 4.1 Metadata source and time alignment + +- Discover metadata configurations and streams through ONVIF 01 capabilities. +- Pair metadata with the correct camera/media profile. +- Normalize timestamps using measured device clock offset and retain original + device timestamp for diagnostics. +- Reconnect with backoff and detect discontinuities or metadata lag. + +### 4.2 Normalized observations + +When supplied by the device, normalize: + +- Object track identifier and class. +- Bounding box and optional geolocation. +- Confidence, color, vehicle/license attributes, and count values. +- Analytic rule and zone/line identifiers. +- Appearance, update, and disappearance timestamps. + +Unknown vendor extensions remain bounded raw metadata and never become trusted SQL +or arbitrary UI markup. + +### 4.3 Event and recording integration + +- Produce Fleet 03 events with explicit origin `onvif_metadata`. +- Deduplicate an equivalent PullPoint and metadata-stream event when possible while + preserving provenance. +- Allow storage policies to match normalized class, rule, zone, or severity. +- Timeline and recording filters distinguish device metadata from local inference. +- A device observation never silently claims to be locally verified inference. + +## 5. Profile G edge-recovery requirements + +### 5.1 Edge inventory and search + +- Discover Recording, Search, and Replay services and their supported operations. +- Inventory available recording tracks and time bounds without importing media. +- Search by camera and bounded time interval with strict result/page limits. +- Display camera-reported gaps and clock uncertainty. + +### 5.2 Gap detection + +- Define a local recording gap as an expected interval lacking complete playable + local segments, with a configurable grace period. +- Exclude intentional privacy pause, disabled recording, and scheduled-off periods. +- Compare eligible gaps to camera edge availability and create proposed backfill + jobs; automatic execution is opt-in by policy. +- Never infer completeness only from a successful search response. + +### 5.3 Playback and import + +- Permit authorized direct replay from an edge source when supported, clearly + labeled as camera-hosted. +- Backfill runs as a persistent, bounded job outside capture threads. +- Import to a Storage 01 target, verify playable duration/size and optional + checksum, then write recording metadata with source/provenance. +- Preserve the original edge recording identifier and requested/retrieved interval. +- Resolve overlap deterministically; do not create visually duplicated timeline + coverage without explaining source alternatives. +- Interrupted jobs resume or restart safely and never replace the only valid local + segment with a corrupt import. + +### 5.4 Policy and controls + +- Per-camera or selector policy controls edge search, automatic backfill, maximum + age, daily byte budget, bandwidth, schedule, destination target, and minimum gap. +- Emit Fleet 03 proposed/started/completed/partial/failed events. +- Fleet 02 actions distinguish viewing edge video from initiating/importing it. +- Bulk backfill uses Fleet 04 jobs and stop thresholds. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Profile M metadata discovery, parser, timestamp normalization, fixtures | +| P1 | Normalized observations, event/timeline/storage-policy integration | +| P2 | Profile G inventory, bounded search, direct replay | +| P3 | Gap detector and manual backfill jobs | +| P4 | Selector policies and guarded automatic backfill | + +## 7. Acceptance criteria + +- A supported metadata fixture produces stable object tracks and versioned Fleet + 03 events with original and normalized timestamps. +- The UI identifies whether an observation came from local inference or a camera. +- A controlled network outage creates a local gap; when camera footage exists, an + operator can preview and import it into the correct timeline interval. +- Intentional recording-off and privacy intervals do not trigger automatic + backfill proposals. +- Backfill interruption cannot produce a completed DB record pointing to a partial + file. +- Daily transfer limits and target policy are respected across restart. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Device clock drift misaligns metadata/video | Preserve both clocks, periodic offset measurement, visible uncertainty | +| Vendors implement partial profiles | Operation-level capabilities and tested fixtures | +| Edge import saturates camera/network | Schedule, bandwidth/byte budgets, bounded concurrency | +| Overlap creates confusing evidence | Provenance, deterministic preference, alternate-source UI | + +## 9. Dependencies + +- ONVIF 01 capability inventory and diagnostics. +- Fleet 03 event contracts. +- Storage 01 targets and lifecycle jobs before import ships. +- Fleet 04 bulk-job framework for fleet backfill. +- Fleet 02 scoped replay/import permissions and audit. diff --git a/docs/prd/OPS_01_Backup_Restore.md b/docs/prd/OPS_01_Backup_Restore.md new file mode 100644 index 00000000..0f09ac47 --- /dev/null +++ b/docs/prd/OPS_01_Backup_Restore.md @@ -0,0 +1,153 @@ +# PRD — Backup & Restore + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 8a — operational resilience +**Scope**: Complete system-configuration backup, scheduled retention, integrity +verification, restore preflight, and operator-safe recovery. + +--- + +## 1. Problem + +lightNVR can create scheduled SQLite backups and exposes pieces of configuration +export, but an operator does not yet have one supported workflow to answer: +“Can I rebuild this NVR after a failed disk, verify the backup before I need it, +and understand exactly what restore will replace?” + +A database copy alone is insufficient if external configuration, zones, users, +templates, storage policies, organization, or future event routes are omitted. +Conversely, blindly packaging secrets and media creates avoidable security and +capacity risks. + +## 2. Goals + +- Define a versioned, complete system-state backup manifest. +- Create manual and scheduled backups without interrupting recording. +- Verify integrity and compatibility before restore. +- Provide dry-run, explicit replacement scope, and rollback safety. +- Handle credentials deliberately and securely. +- Make backup health observable through Fleet 03 events. + +## 3. Non-goals + +- Backing up all recorded video by default. +- Replacing Storage 01 replication or retention. +- General operating-system imaging. +- Cloud-specific backup providers in core. +- Zero-downtime restore; controlled service interruption is acceptable. + +## 4. Backup artifact + +A backup is a versioned archive containing: + +- Manifest: format version, lightNVR version, installation UUID, timestamps, + included components, checksums, size, encryption metadata, and compatibility. +- Consistent SQLite database snapshot. +- Non-database configuration required for system behavior. +- Optional public assets such as floor plans and user-supplied certificates. +- Optional encrypted secret payload. +- Human-readable summary that contains no secret values. + +Recorded media and generated caches are excluded. Recording metadata may be +included with the database, but restore preflight must report whether referenced +media targets exist. + +## 5. Requirements + +### 5.1 Backup creation + +- Use SQLite's online backup facility or equivalent consistent snapshot. +- Stage the archive outside the active database and publish atomically. +- Calculate a cryptographic checksum for every archive member and the manifest. +- Support manual download, scheduled local creation, and post-success hook/event. +- Configure destination, schedule, count/age retention, and minimum free space. +- Never delete the last verified backup during retention cleanup. +- Failure does not affect recording and remains visible until acknowledged or a + later successful backup. + +### 5.2 Secret handling + +- Default backup excludes reusable secrets and states what must be re-entered. +- Optional secret-inclusive backup requires authenticated reauthorization and + encryption with an operator-supplied passphrase or explicit key facility. +- Never store the backup passphrase in the backup or routine application logs. +- Camera, MQTT, API-token, and future IdP secrets follow one documented policy. +- Restored API token hashes do not reveal plaintext tokens. + +### 5.3 Backup catalog and verification + +- UI lists created time, source version, size, components, encryption state, + verification result, destination, and retention eligibility. +- Verification checks archive readability, member checksums, manifest schema, and + database integrity without mutating the running installation. +- Allow an operator to upload and verify an external backup before restore. +- Periodically reverify retained backups on configurable schedule. + +### 5.4 Restore preflight + +- Parse and verify the entire artifact before stopping services. +- Report source/target versions, migration path, included/excluded components, + missing storage targets, unresolved paths, identity collision, and secrets that + need re-entry. +- Offer restore scopes only where semantically safe: full system is required in + v1; selective restore may be added per component later. +- Require explicit confirmation naming the installation and replacement scope. +- Restore is authorized and audited by Fleet 02. + +### 5.5 Restore execution and rollback + +- Create a local pre-restore safety backup automatically. +- Quiesce state-changing services, restore into staging, run migrations and + integrity checks, then atomically activate. +- If validation or startup fails, return to the pre-restore state and retain error + diagnostics. +- Do not delete media files merely because restored metadata differs. +- Reconcile restored recording metadata and Storage 01 targets as a separate, + previewable post-restore operation. + +### 5.6 Events and diagnostics + +- Emit backup started/succeeded/failed, verification failed, and restore outcome + through Fleet 03 without embedding secret details. +- Health UI shows last successful backup age, last verification, and next schedule. +- Diagnostic bundle includes metadata and errors, not backup payloads. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Manifest format, complete component inventory, manual creation and verify | +| P1 | Catalog, scheduling, retention, health events | +| P2 | Full restore preflight, safety backup, activate/rollback | +| P3 | Encrypted secret payload and optional portable migration helpers | + +## 7. Acceptance criteria + +- A backup from a populated fixture verifies every member and includes all declared + system configuration categories. +- A clean compatible installation can restore the fixture and reproduce cameras, + users, zones, organization, policies, and routes included by the manifest. +- A corrupt member fails verification before any running state changes. +- A simulated post-restore startup failure returns to the pre-restore database and + configuration. +- Secret-excluding archives contain no camera/MQTT passwords or API token values. +- Scheduled retention never removes the only successfully verified artifact. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| “Complete” backup silently omits a new subsystem | Component registry and manifest contract tests | +| Restore bricks the NVR | Full preflight, staging, safety backup, atomic activation/rollback | +| Portable archive leaks credentials | Exclude by default; explicit encrypted secret payload | +| Metadata/media mismatch causes deletion | Read-only reconciliation report; never delete media during restore | + +## 9. Dependencies + +- Each preceding PRD must register its persisted state with the backup component + inventory as it lands. +- Fleet 02 supplies restore authorization/audit. +- Fleet 03 supplies operational events. +- Storage 01 supplies target reconciliation. diff --git a/docs/prd/OPS_02_Evidence_Cases_Integrity.md b/docs/prd/OPS_02_Evidence_Cases_Integrity.md new file mode 100644 index 00000000..5dc4020f --- /dev/null +++ b/docs/prd/OPS_02_Evidence_Cases_Integrity.md @@ -0,0 +1,147 @@ +# PRD — Evidence Cases & Integrity + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 8b — incident preservation +**Scope**: Case-centered recording holds, provenance, auditable access, and +verifiable evidence export. + +--- + +## 1. Problem + +Individual recordings can be protected, but a real investigation is usually +defined by a time interval, cameras or location, incident narrative, and multiple +exports. Protecting files one by one is error-prone, and a downloaded video alone +does not explain its source, time basis, or whether its bytes changed after export. + +## 2. Goals + +- Create an incident/case that groups cameras, time intervals, recordings, notes, + and exports. +- Apply a hold to all existing and newly finalized recordings matching the case. +- Make holds override ordinary retention and pressure cleanup. +- Record provenance and a complete audit history for case-sensitive operations. +- Export evidence with a machine- and human-readable manifest and checksums. +- Keep the core lightweight and avoid pretending to replace full evidence- + management or legal case-management systems. + +## 3. Non-goals + +- Legal conclusions about admissibility or jurisdiction-specific compliance. +- Video redaction/editor tooling in v1. +- Facial identification, transcription, or investigative analytics. +- Digital signatures tied to a public certificate authority in v1. +- Cloud evidence sharing portals. + +## 4. Case model + +A case has stable UUID, title, status, description, created/closed timestamps, +creator, assignees, labels, one or more camera selectors, one or more UTC time +intervals, notes, attachments metadata, associated recording sources, holds, and +export history. + +Statuses are `open`, `closed-held`, and `closed-released`. Closing a case does not +implicitly release its hold. + +## 5. Requirements + +### 5.1 Case creation and matching + +- Create from the Recordings/Timeline selection or from a blank case form. +- Selector uses Fleet 01 camera UUIDs, collections, location subtree, or tags. +- Time intervals are stored in UTC and displayed with the operator's selected zone. +- Preview lists matching recordings, gaps, alternate sources, and estimated bytes. +- A case retains the selector and a materialized membership/provenance record so + later tag/location changes do not erase historical intent. + +### 5.2 Holds + +- On activation, mark all matching existing recordings as held by case UUID. +- Newly finalized recordings whose captured interval overlaps an active case rule + are held transactionally before they become retention candidates. +- A recording can be held by multiple cases and is releasable only when no active + hold remains. +- Storage 01 retention, migration, and pressure cleanup must recognize holds as + stronger than protection or per-recording retention. +- Extending/reducing intervals shows an impact preview; reducing never releases + recordings held by another case. +- Release requires a distinct Fleet 02 permission, reason, confirmation, and audit. + +### 5.3 Integrity and provenance + +- Store source camera UUID, recording UUID, capture interval, source type, original + relative object identity, codec/container facts, byte length, and checksum. +- Calculate checksums asynchronously with visible pending/failed state. +- Imported ONVIF edge recordings include original device/recording identifiers and + import job metadata. +- A mismatch creates a persistent integrity alert; it never silently updates the + expected checksum. + +### 5.4 Evidence export + +- Export a selected case subset without modifying source recordings. +- Package media plus JSON manifest, human-readable summary, checksums, lightNVR + version, installation UUID, export timestamp, requester, source/provenance, and + known timeline gaps. +- Optional clip materialization references original segments and records exact + requested and delivered intervals. +- Re-running an export produces a new export record and manifest, not an overwrite. +- Provide an offline verification command or small portable verifier specification. +- Export authorization and download are audited. + +### 5.5 Access and audit + +- Fleet 02 distinguishes case view, create/edit, hold, release, export, and delete. +- Case visibility is scoped independently but cannot grant access to cameras the + principal otherwise cannot view. +- Audit case creation, selector/time changes, notes, membership changes, checksum + results, holds/releases, exports, and access denial. +- Case deletion is either prohibited after export or implemented as tombstoning; + no supported API erases its audit history. + +### 5.6 UI + +- Case list shows status, owner, interval, camera count, held bytes, integrity + state, and last activity. +- Timeline overlays case intervals and held recordings. +- Case detail explains gaps and alternate edge/local sources. +- Storage dashboard attributes non-deletable capacity to cases. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Case schema, manual recording association, multi-case holds | +| P1 | Selector/time rules and finalization-time automatic hold | +| P2 | Checksums, provenance, integrity monitoring | +| P3 | Evidence export manifest and offline verification | +| P4 | Edge-source provenance integration and optional redaction follow-up | + +## 7. Acceptance criteria + +- A case spanning ten cameras and two intervals holds all overlapping existing and + newly finalized recordings. +- Retention and pressure cleanup cannot remove a held recording. +- Releasing one of two holds leaves the recording held by the other case. +- A byte change after checksum creates a visible integrity failure. +- An offline verifier validates every exported file and reports a deliberately + corrupted file. +- Export manifests identify known gaps and distinguish local from ONVIF edge source. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Holds consume all storage | Capacity impact preview, alerts, explicit administrator policy; never silent deletion | +| “Integrity” is mistaken for legal certification | Precise product language and documented checksum guarantees only | +| Selector changes alter historical membership | Materialized membership plus stored original selector/version | +| Export exposes unauthorized cameras | Intersect case scope with current Fleet 02 access at operation time | + +## 9. Dependencies + +- Fleet 01 identities/selectors and Fleet 02 permissions/audit. +- Storage 01 hold enforcement and location abstraction. +- Fleet 03 operational/integrity events. +- ONVIF 02 provenance for edge imports. diff --git a/docs/prd/PRIVACY_01_Masking_Exclusion_Zones.md b/docs/prd/PRIVACY_01_Masking_Exclusion_Zones.md new file mode 100644 index 00000000..53fba576 --- /dev/null +++ b/docs/prd/PRIVACY_01_Masking_Exclusion_Zones.md @@ -0,0 +1,147 @@ +# PRD — Privacy Masking & Exclusion Zones + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 8d — privacy controls +**Scope**: Permanent privacy masks, camera-side ONVIF preference, explicit +software fallback, and detection exclusion zones distinct from existing privacy +pause and inclusion/detection zones. + +--- + +## 1. Problem + +lightNVR can pause a camera for privacy and can configure detection zones, but +these do not solve two different needs: + +1. Permanently obscure a neighbor's window, keypad, workspace, or public area from + live view, recordings, and snapshots. +2. Ignore a region for motion/analytics while leaving its pixels viewable. + +Software masking can force decode and re-encode, defeating passthrough and raising +CPU usage. Many cameras can apply masks themselves, but capabilities and behavior +vary. Operators need an explicit, testable choice rather than a mask that appears +in one output and leaks through another. + +## 2. Goals + +- Model privacy masks and analytic exclusion zones as separate entities. +- Prefer device-side ONVIF privacy configuration when supported. +- Offer software burn-in only after clear compatibility/performance validation. +- Apply privacy masks consistently to every relevant output. +- Explain when masking changes passthrough, codec, resolution, latency, or CPU use. +- Audit creation, change, disablement, and deletion. + +## 3. Non-goals + +- Automatic face/person/license-plate redaction. +- Editing historical recordings made before a mask existed. +- Claiming a software overlay is a legally certified privacy system. +- Replacing whole-camera privacy pause. +- Treating detection inclusion zones and exclusion zones as interchangeable. + +## 4. Concepts + +| Control | Changes pixels? | Changes analytics? | Typical use | +| --- | --- | --- | --- | +| Privacy pause | Stops capture/processing | Yes | Temporarily disable whole camera | +| Privacy mask | Permanently obscures configured region | May, depending on device pipeline | Neighbor window | +| Detection inclusion zone | No | Analyze only selected region | Driveway | +| Detection exclusion zone | No | Ignore selected region | Moving tree/road | + +## 5. Requirements + +### 5.1 Mask geometry and identity + +- Store stable mask UUID, camera UUID, name, enabled state, source mode, polygon, + coordinate reference, creation/update actor/time, and applied capability state. +- Geometry uses normalized coordinates and is validated for bounds, minimum area, + vertex count, and self-intersection. +- Editing UI uses a current snapshot with explicit age and aspect ratio. +- Transform geometry deliberately when main/sub/detection profiles differ in + aspect ratio; refuse an ambiguous crop rather than guessing silently. + +### 5.2 Device-side masks + +- ONVIF 01 capability probe reports mask/config support at operation level. +- Read existing device masks when supported and distinguish external/unmanaged + masks from lightNVR-managed masks. +- Preview proposed geometry and apply through an authenticated, audited operation. +- Read back configuration and verify persistence after camera reboot where the + device permits. +- Report whether the device applies the mask to main/sub streams, snapshots, + metadata, and edge recordings; unknown is not shown as guaranteed. +- Do not delete or overwrite unmanaged masks without explicit confirmation. + +### 5.3 Software masking + +- Software mode is unavailable until the selected hardware/software pipeline can + sustain the configured stream load in a validation test. +- UI explains that passthrough is disabled and estimates CPU/resource impact. +- Mask is burned before any live output, recording write, snapshot, detector input + when configured, event thumbnail, or downstream restream can observe pixels. +- Fail closed for configured privacy outputs: pipeline failure must not silently + fall back to an unmasked stream. +- Low-resolution proxies and cached thumbnails are invalidated on mask changes. +- Existing historical recordings remain unchanged and the UI states this clearly. + +### 5.4 Exclusion zones + +- Add named normalized polygons independent of privacy masks and inclusion zones. +- A camera may have multiple exclusion zones with schedule and applicable detector + source where supported. +- Generic motion and local object-event generation ignore excluded pixels/objects + according to documented overlap semantics. +- Default overlap rule: suppress only when the tracked object's configured anchor + point lies inside an exclusion zone; future alternatives require explicit UI. +- Exclusion changes emit an audit record but do not imply pixel privacy. + +### 5.5 Verification and visibility + +- Configuration screen provides tested previews for main, sub, detection, snapshot, + and recording paths. +- Camera detail shows `device mask`, `software mask`, `unverified`, or `failed` + state; a generic “privacy enabled” badge is insufficient. +- Fleet 03 emits apply/verify/failure events without mask images or sensitive + geometry by default. +- Fleet 04 can identify mask drift or device reset across selected cameras. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Separate exclusion-zone model and local detection integration | +| P1 | ONVIF device-mask capability/read/apply/read-back for tested cameras | +| P2 | Cross-output verification, fleet drift, reboot persistence tests | +| P3 | Guarded software masking on supported pipelines with fail-closed behavior | + +## 7. Acceptance criteria + +- A configured exclusion zone suppresses eligible local detections while its + pixels remain visible. +- A device-side mask is read back and verified on every camera profile/output the + UI claims it covers. +- Unmanaged device masks survive lightNVR edits unless explicitly selected. +- Software mode cannot be enabled without acknowledging passthrough/resource impact + and passing configured validation. +- No live, recording, snapshot, thumbnail, or restream output marked protected can + fall back to unmasked pixels after a simulated masking-pipeline failure. +- UI clearly states that recordings created before mask activation are unchanged. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Device claims masking but omits an output | Per-output verification and conservative “unknown” state | +| Software masking overloads the NVR | Preflight benchmark, capacity limit, explicit opt-in | +| Aspect-ratio transform leaks an edge | Normalized geometry, preview each profile, refuse ambiguous crop | +| User assumes exclusion means privacy | Separate terminology, icons, APIs, and explanatory copy | + +## 9. Dependencies + +- Fleet 01 camera UUIDs and Fleet 02 configuration permissions/audit. +- ONVIF 01 capability registry for device-side masks. +- Fleet 03 operational failures and Fleet 04 drift reporting. +- Software masking phase requires an explicit performance design and is not a + prerequisite for device-side masking. diff --git a/docs/prd/README.md b/docs/prd/README.md index 7eafa913..f5e03624 100644 --- a/docs/prd/README.md +++ b/docs/prd/README.md @@ -20,4 +20,29 @@ Each PRD is self-contained: problem, goals, requirements, phasing, acceptance, r | --- | --- | | [Recording Retention Policies](PRD_Recording_Retention_Policies.md) | Per-stream retention and deletion policies (implemented — see [the summary](../internal/SUMMARY_Recording_Retention.md) and [the API quick reference](../QUICKREF_Retention_API.md)) | +### Fleet control plane + +These PRDs turn the 2026 competitive audit into independently pursuable work. The +order is intentional: later PRDs reuse the camera identities, selectors, events, +and policy primitives established earlier. + +| Order | PRD | Outcome | Timing | +| --- | --- | --- | --- | +| 1 | [Fleet 01 — Camera Identity & Organization](FLEET_01_Camera_Identity_Organization.md) | Stable camera identity, location hierarchy, tags, and smart collections | Now | +| 2 | [Fleet 02 — Scoped Authorization & Audit](FLEET_02_Scoped_Authorization_Audit.md) | Action-level permissions over reusable fleet scopes | Now; SSO deferred | +| 3 | [Fleet 03 — Event Bus & MQTT Routes](FLEET_03_Event_Bus_MQTT_Routes.md) | Durable provider-neutral events for cloud and automation consumers | Now | +| 4 | [Fleet 04 — Fleet Explorer & Bulk Operations](FLEET_04_Fleet_Explorer_Bulk_Operations.md) | Operate hundreds of cameras through search, queues, templates, and jobs | Next | +| 5 | [Storage 01 — Multi-Target Storage Lifecycle](STORAGE_01_Multi_Target_Lifecycle.md) | Policy-driven placement, migration, retention, and capacity management | Next | +| 6 | [ONVIF 01 — Capability Onboarding & Events](ONVIF_01_Capability_Onboarding_Events.md) | Reliable discovery, profile pairing, capability inventory, and normalized events | Next | +| 7 | [ONVIF 02 — Metadata & Edge Recovery](ONVIF_02_Metadata_Edge_Recovery.md) | Profile M analytics and Profile G recording backfill | Later | +| 8a | [Operations 01 — Backup & Restore](OPS_01_Backup_Restore.md) | Complete, verified, operator-safe system recovery | Later | +| 8b | [Operations 02 — Evidence Cases & Integrity](OPS_02_Evidence_Cases_Integrity.md) | Case holds, chain of custody, and verifiable exports | Later | +| 8c | [UXD 04 — Maps & Operator Views](UXD_04_Maps_Operator_Views.md) | Spatial navigation, shared layouts, and camera sequences | Later | +| 8d | [Privacy 01 — Masking & Exclusion Zones](PRIVACY_01_Masking_Exclusion_Zones.md) | Camera-side privacy masks with explicit software fallback | Later | + +“Now,” “Next,” and “Later” express dependency order, not release promises. SSO is +not a standalone near-term project: it is the final, customer-triggered phase of +Fleet 02. The trigger is a committed organizational deployment with a real IdP +and named administrative counterpart, such as an SJC-scale adoption. + The three UXD PRDs share a primitive — an `` / `useAsyncAction` hook — defined in PRD 01 and consumed by 02 and 03. Land 01 P0 first. diff --git a/docs/prd/STORAGE_01_Multi_Target_Lifecycle.md b/docs/prd/STORAGE_01_Multi_Target_Lifecycle.md new file mode 100644 index 00000000..8a1b50bd --- /dev/null +++ b/docs/prd/STORAGE_01_Multi_Target_Lifecycle.md @@ -0,0 +1,199 @@ +# PRD — Multi-Target Storage Lifecycle + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 5 — storage scale and resilience +**Scope**: Storage targets and pools, selector-driven placement and lifecycle +policies, asynchronous migration, capacity forecasting, and failure behavior. + +--- + +## 1. Problem + +lightNVR already supports per-stream retention, detection-aware retention, +protection, manual tiers, per-recording overrides, and pressure cleanup. Those +policies operate primarily within one global storage path. Larger deployments need +to decide where recordings begin, when they migrate, how long different event +classes remain, and what happens when a target is unavailable or full. + +Simply assigning each camera to one disk cannot express hot-to-warm archival, +spillover, evidence protection, or different retention for high-value events. + +## 2. Goals + +- Separate physical storage configuration from recording lifecycle policy. +- Support multiple local or mounted filesystem targets without blocking capture. +- Select policies using Fleet 01 locations, tags, cameras, and event metadata. +- Automate placement, migration, retention, replication, and pressure priority. +- Make failure and spillover behavior explicit and observable. +- Forecast whether configured capacity can meet desired retention. +- Preserve all existing recordings and retention semantics during migration. + +## 3. Non-goals + +- Bundling vendor-specific S3/cloud SDKs into the C core in v1. +- Distributed erasure coding or implementing a filesystem. +- Treating backup as recording retention; system backup is OPS 01. +- Duplicating continuous video into separate motion files. +- Profile G edge-camera retrieval; ONVIF 02 consumes this policy framework. + +## 4. Product model + +### 4.1 Storage target + +A target represents one writable namespace and reports: + +- Stable UUID, name, type, root path, enabled state. +- Capacity, free bytes, reserved headroom, high/low watermarks. +- Performance class (`hot`, `warm`, `cold`) and optional cost metadata. +- Health, latency, last successful probe, last write, and last error. +- Capabilities such as atomic rename, hard link, and read-only archive. + +v1 target types are local filesystem and administrator-mounted filesystem/NFS. +Future cloud/object targets use an adapter contract rather than changing policy +semantics. + +### 4.2 Storage pool + +A pool is an ordered or weighted set of compatible targets with an allocation +strategy such as most-free, round-robin, or explicit priority. Policies reference +pools when spillover is acceptable and targets when exact placement is required. + +### 4.3 Storage policy + +A versioned policy contains: + +- Fleet 01 camera selector. +- Recording predicates: trigger, object label, zone, severity, and schedule. +- Initial target/pool and fallback behavior. +- Minimum/desired/maximum retention. +- Migration steps after age thresholds. +- Required copy count where supported. +- Pressure-deletion priority and eligibility. +- Protection/hold interaction. + +Precedence is explicit: evidence hold, per-recording override, event-specific +policy, camera-specific policy, selector policy, then system default. + +## 5. Representative policies + +| Use case | Policy | +| --- | --- | +| Ordinary continuous | Hot local pool; desired 14 days; pressure eligible after minimum 7 days | +| Entrance person event | Hot for 48 hours, then warm NAS; retain 90 days | +| Critical area | Keep two copies on distinct targets; alert rather than silently violate minimum retention | +| Protected incident | Hold indefinitely until authorized release; never pressure-delete | +| Low-priority utility view | Local spillover allowed; pressure-delete before all other classes | + +These are examples, not hard-coded product defaults. + +## 6. Requirements + +### 6.1 Recording location schema + +- New recordings store `target_uuid` plus a relative object key; APIs do not rely + on an absolute path as durable identity. +- Existing absolute paths migrate to an automatically created default target. +- Migration is metadata-only until a lifecycle job explicitly moves a file. +- Playback, download, deletion, protection, and thumbnail lookup resolve through + the target abstraction. +- Record policy version and placement reason for explainability. + +### 6.2 Target health and allocation + +- Validate and probe target paths before enablement. +- Monitor capacity, availability, writeability, and optional write latency. +- Each target owns its reserve and pressure watermarks; global pressure remains as + a compatibility default. +- Allocation never chooses an unhealthy target unless policy explicitly allows a + last-resort attempt. +- On failure, follow the policy's named behavior: alternate pool, local emergency + target, pause new recording for affected cameras, or fail and emit an event. +- Emit Fleet 03 events for target and policy state changes. + +### 6.3 Policy assignment and evaluation + +- Policy editor uses Fleet 01 selector preview and recording predicates. +- Detect conflicting assignments before save and display effective precedence. +- Assign policy at recording creation, then retain the applied policy version. +- Object/zone-aware rules may upgrade a logical continuous segment without making + a duplicate recording file. +- Policy simulation takes camera, recording metadata, and time and explains the + chosen placement/lifecycle. + +### 6.4 Lifecycle mover + +- Migration, copy, and verification run asynchronously outside capture threads. +- Jobs persist progress and resume safely after restart. +- Copy to a temporary destination, verify size and configurable checksum, commit + metadata atomically, then remove the old copy only when policy permits. +- Bound concurrency and bandwidth per target and schedule archival windows. +- Playback continues from the old or new verified copy during migration. +- Failed jobs retry with backoff and surface actionable error state. + +### 6.5 Pressure and retention + +- Retain existing age, detection, tier, protection, and per-recording override + behavior through compatibility policies. +- Pressure cleanup evaluates only the affected target/pool and respects minimum + retention, hold, copy-count, and pressure priority. +- If policy cannot be met, retain the recording when safe and emit a persistent + policy-violation condition rather than silently claiming compliance. +- Provide achieved-versus-desired retention by policy and camera. + +### 6.6 Capacity planning + +- Estimate daily byte rate from observed history, not only configured bitrate. +- Forecast days to high watermark and expected achieved retention by target/policy. +- Identify policies whose minimum retention cannot fit current capacity. +- Forecast is advisory and states its sample window and confidence limitations. + +### 6.7 Administration UI + +- Target list shows health, utilization, reserve, watermarks, throughput, and jobs. +- Policy list shows selector, priority, recording predicates, lifecycle, and + compliance state. +- Safe test verifies a target without writing camera data. +- Deleting a nonempty target requires relocation or an explicit, destructive + procedure; disabling it does not orphan metadata. + +## 7. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Target schema/resolver, default-target migration, target health | +| P1 | Selector policies, placement, per-target pressure behavior | +| P2 | Persistent migration/copy jobs, checksums, bandwidth limits | +| P3 | Pools, replication, capacity forecast, policy compliance dashboard | +| P4 | External storage adapter interface, only when a concrete integration is chosen | + +## 8. Acceptance criteria + +- Existing installations upgrade with all recordings playable and one generated + default target. +- Two cameras selected by different policies record to different healthy targets. +- A target outage follows configured fallback without blocking unrelated cameras. +- An interrupted migration resumes without duplicate metadata or loss of the only + verified copy. +- Pressure cleanup cannot delete a protected/held recording or violate required + copy count. +- Continuous video associated with an event gains richer lifecycle treatment + without creating a second full recording. +- A 30-day observed-rate fixture produces target and policy retention forecasts. + +## 9. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Move failure loses the only copy | Copy/verify/atomic metadata commit before source deletion | +| Complex precedence becomes inscrutable | Effective-policy explanation and simulator | +| Slow NAS stalls recorders | Async mover, target health, local emergency policy | +| Files moved outside lightNVR desynchronize DB | Reconciliation tooling and documented managed-root contract | + +## 10. Dependencies + +- Fleet 01 selectors are required for policy scopes. +- Fleet 03 is required for policy and target events before P2 is considered done. +- Fleet 04 provides bulk assignment and compliance queues. +- OPS 02 adds evidence holds that override lifecycle policy. diff --git a/docs/prd/UXD_04_Maps_Operator_Views.md b/docs/prd/UXD_04_Maps_Operator_Views.md new file mode 100644 index 00000000..e9ea9f4c --- /dev/null +++ b/docs/prd/UXD_04_Maps_Operator_Views.md @@ -0,0 +1,137 @@ +# PRD — Maps & Operator Views + +**Status**: Draft +**Created**: 2026-08-22 +**Owner**: TBD +**Priority**: 8c — spatial and role-oriented operation +**Scope**: Floor-plan maps, nested navigation, shared/personal camera layouts, and +operator sequences built on fleet identities and permissions. + +--- + +## 1. Problem + +Names, filters, and tables are efficient for administration but not always for +responding to an incident. Operators reason spatially: which entrance is next to +the alarm, which camera sees the corridor, and what nearby view should be opened. +Different roles also need stable layouts and sequences without reorganizing the +underlying camera inventory. + +## 2. Goals + +- Place cameras and operational entities on uploaded floor/site plans. +- Navigate maps hierarchically from site to building to floor. +- Show live health and event state without rendering hundreds of live videos. +- Let authorized users create personal and shared layouts and camera sequences. +- Keep organization, tags, collections, maps, and views as distinct concepts. +- Respect Fleet 02 visibility at every level and aggregate. + +## 3. Non-goals + +- Full GIS, 3D building modeling, CAD editing, or automatic camera calibration. +- Replacing the Fleet 04 administrative table. +- A dispatch or access-control system. +- Persistently decoding every camera visible on a map. +- Multi-NVR federation in v1. + +## 4. Product model + +- **Map**: image/SVG asset, coordinate space, optional parent map and location node. +- **Map entity**: camera UUID, child-map link, location marker, or supported event + input with position, icon, label, and optional orientation/FOV wedge. +- **Operator view**: ordered tile layout of cameras or collections with playback + preferences and labels. +- **Sequence**: ordered cameras/views plus dwell time and transition behavior. + +Maps describe space. Views describe presentation. Collections describe membership. +Locations describe canonical physical hierarchy. + +## 5. Requirements + +### 5.1 Map administration + +- Upload bounded PNG/JPEG/SVG floor-plan assets with safe content handling. +- Associate a map with a Fleet 01 location and optionally a parent map marker. +- Place cameras through drag/drop; store normalized coordinates independent of + display resolution. +- Configure orientation and approximate FOV wedge manually. +- Warn when a camera is placed on multiple maps but permit it for overview maps. +- Asset replacement preserves entity coordinates when aspect ratio is unchanged + and requires preview/remap otherwise. + +### 5.2 Operator map + +- Display camera health, recording state, active event severity, and selected + detection status through lightweight markers. +- Clicking a permitted camera opens preview/live/detail actions; unauthorized + cameras and counts are not leaked. +- Navigate through child-map markers and breadcrumbs. +- Filter visible entities by tag, state, event type, and saved collection. +- Cluster or aggregate markers at overview scale rather than rendering unreadable + overlap. +- Update state via Fleet 03 deltas or bounded polling. + +### 5.3 Views and sequences + +- Create personal and shared layouts using stable camera UUIDs and saved + collections. +- Store grid size, tile order, labels, and playback transport preference without + changing camera configuration. +- A dynamic collection view fills deterministic slots and explains membership + changes. +- Sequences support ordered items, dwell duration, pause, previous/next, and + optional skip-offline behavior. +- Shared view/sequence mutation requires Fleet 02 permission; viewing is the + intersection of view membership and current camera access. + +### 5.4 Incident navigation + +- Event links can open the relevant map centered on the source camera. +- Map marker exposes adjacent cameras selected by spatial placement, not inferred + solely from similarly named tags. +- Timeline/recordings link preserves camera and event time context. +- Map state never changes evidence or alert acknowledgement implicitly. + +### 5.5 Performance and accessibility + +- Initial map load does not initiate live streams until requested. +- Marker updates are batched; asset caching is versioned. +- Provide list and keyboard alternatives to every map action. +- Use shapes/icons in addition to color for state. +- Touch selection and controls meet 44px target guidance. + +## 6. Phasing + +| Phase | Scope | +| --- | --- | +| P0 | Shared/personal operator views using stable camera UUIDs | +| P1 | Static floor-plan upload, camera placement, health markers | +| P2 | Nested maps, event filters, contextual navigation | +| P3 | Sequences, dynamic collection views, incident deep links | + +## 7. Acceptance criteria + +- A site/building/floor map hierarchy containing 900 cameras remains navigable + without loading 900 video players. +- Moving/renaming a camera preserves its map and view placement by UUID. +- An operator cannot see a marker, aggregate count, preview, or event for a camera + outside their Fleet 02 scope. +- A shared sequence skips an offline camera when configured and preserves order + across restart. +- All map functions have keyboard/list equivalents. + +## 8. Risks and mitigations + +| Risk | Mitigation | +| --- | --- | +| Map becomes a heavy video wall | Markers first; streams only on demand | +| Floor plans expose sensitive layout | Fleet 02 map permissions and safe backup/export handling | +| Dynamic views surprise operators | Stable ordering and membership-change explanation | +| SVG carries active content | Sanitize or rasterize uploads; disallow scripts/external resources | + +## 9. Dependencies + +- Fleet 01 identities, hierarchy, tags, and collections. +- Fleet 02 permission filtering. +- Fleet 03 event/health deltas. +- Fleet 04 query and health-state definitions.