Persistent camera registry: the enrolled-camera record (identity, connection, feeds, storage destinations, detection config, retention policy) keyed by camera-discovery's CameraId, with credentials sealed at rest via infrastructure-secrets. Discovery stays pure; this crate owns persistence.
| Tier | operations |
| Role | unclassified (baselined) |
| Path | crates/operations/camera-registry |
| Edition | 2021 |
| Targets | operations_camera_registry, store_integration |
| Public items | 55 across 1 module |
| Tests | 23 |
What it is for
Persistent camera registry — the enrolled-camera record.
operations-camera-discovery stays pure (identity + probing, no DB). This crate owns the durable Camera record: connection, feeds, storage destinations, detection config, and retention policy, keyed by the discovery CameraId. Camera credentials are sealed at rest via infrastructure_secrets — the plaintext password never lives in the struct and is never serialized (see CameraView, the API projection that omits it).
The sqlx persistence layer + migrations land behind the postgres feature in the next unit; everything here is pure and unit-tested.
Capabilities
crate root
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub const MAX_NAME_LEN: usize |
fn slugify_name(raw : & str) -> String |
fn draft_from_discovery(discovered : & DiscoveredCamera) -> Result <Camera, RegistryError> |
AddrMode
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum AddrMode |
AddrMode :: fn as_db(& self) -> & 'static str |
AddrMode :: fn from_db(s : & str) -> Option <Self> |
Addressing
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct Addressing |
Camera
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct Camera |
Camera :: fn new(id : CameraId, name : impl Into <String>) -> Result <Self, RegistryError> |
Camera :: fn id(& self) -> CameraId |
Camera :: fn live_feed(& self) -> Option <& Feed> |
Camera :: fn record_feed(& self) -> Option <& Feed> |
Camera :: fn detect_feed(& self) -> Option <& Feed> |
Camera :: fn view(& self) -> CameraView |
CameraFunction
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum CameraFunction |
CameraStatus
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum CameraStatus |
CameraStatus :: fn as_db(& self) -> & 'static str |
CameraStatus :: fn from_db(s : & str) -> Option <Self> |
CameraView
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct CameraView |
Capabilities
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct Capabilities |
Capabilities :: fn default() -> Self |
Credentials
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct Credentials |
Credentials :: fn seal(cipher : & SecretCipher, username : impl Into <String>, password_plaintext : & str,) -> Result <Self, SecretError> |
Credentials :: fn from_sealed(username : impl Into <String>, password : Sealed) -> Self |
Credentials :: fn sealed(& self) -> & Sealed |
Credentials :: fn password(& self, cipher : & SecretCipher) -> Result <Zeroizing <String>, SecretError> |
DetectionConfig
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct DetectionConfig |
DetectionConfig :: fn default() -> Self |
Feed
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct Feed |
FeedRole
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum FeedRole |
LowDiskBehavior
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum LowDiskBehavior |
ObjectClass
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum ObjectClass |
RegistryError
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum RegistryError |
RetentionPolicy
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct RetentionPolicy |
RetentionPolicy :: fn default() -> Self |
StorageDest
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub struct StorageDest |
StorageRole
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum StorageRole |
StorageWhen
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum StorageWhen |
Transport
Persistent camera registry — the enrolled-camera record.
| Item |
|---|
pub enum Transport |
Transport :: fn as_db(& self) -> & 'static str |
Transport :: fn from_db(s : & str) -> Option <Self> |
store (other)
Postgres persistence for the camera registry (behind the postgres feature).
| Item |
|---|
async fn list_archived(pool : & PgPool) -> Result <Vec <ArchivedCamera>, StoreError> |
ArchivedCamera
Postgres persistence for the camera registry (behind the postgres feature).
| Item |
|---|
pub struct ArchivedCamera |
CameraRow
Postgres persistence for the camera registry (behind the postgres feature).
| Item |
|---|
CameraRow :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result |
StoreError
Postgres persistence for the camera registry (behind the postgres feature).
| Item |
|---|
async fn ensure_schema(pool : & PgPool) -> Result <(), StoreError> |
pub enum StoreError |
StoreError :: fn is_duplicate_name(& self) -> bool |
async fn create(pool : & PgPool, cam : & Camera) -> Result <(), StoreError> |
async fn get(pool : & PgPool, id : CameraId) -> Result <Option <Camera>, StoreError> |
async fn get_by_name(pool : & PgPool, name : & str) -> Result <Option <Camera>, StoreError> |
async fn list(pool : & PgPool) -> Result <Vec <Camera>, StoreError> |
async fn update(pool : & PgPool, cam : & Camera) -> Result <bool, StoreError> |
async fn archive(pool : & PgPool, id : CameraId) -> Result <bool, StoreError> |
async fn restore(pool : & PgPool, id : CameraId) -> Result <bool, StoreError> |
async fn purge(pool : & PgPool, id : CameraId) -> Result <bool, StoreError> |
How to use it
No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.
Module structure
operations_camera_registry
store
Public surface
`crate root`
| Item | What it is |
|---|---|
pub enum RegistryError | Registry-level errors (credential errors surface SecretError separately). |
pub const MAX_NAME_LEN: usize | Longest accepted camera name |
fn slugify_name(raw : & str) -> String | Validate a camera name against every downstream consumer that resolves through it (Gate 4 BLOCK 4) |
pub enum Transport | Stream transport a feed uses. |
pub enum FeedRole | What a given feed is used for |
pub struct Feed | One stream endpoint of a camera, with its assigned role. |
pub enum StorageRole | Role of a storage destination. |
pub enum StorageWhen | When a destination receives footage. |
pub struct StorageDest | One storage destination for a camera's footage |
pub enum LowDiskBehavior | What the recorder does when a storage destination runs low on space. |
pub struct RetentionPolicy | Per-camera retention policy |
RetentionPolicy :: fn default() -> Self | — |
pub enum CameraFunction | ZoneMinder-style capture function. |
pub enum ObjectClass | Object classes the detector filters for. |
pub struct DetectionConfig | Detection / motion configuration (forge-nvr Rust detector) |
DetectionConfig :: fn default() -> Self | — |
pub enum AddrMode | How the camera is addressed on the network. |
pub struct Addressing | Connection addressing: DHCP vs static, with current/last-known host + port. |
pub struct Capabilities | What an operator has enabled on this camera |
Capabilities :: fn default() -> Self | — |
pub enum CameraStatus | Last-known reachability. |
Transport :: fn as_db(& self) -> & 'static str | Stable DB/string form. |
Transport :: fn from_db(s : & str) -> Option <Self> | — |
AddrMode :: fn as_db(& self) -> & 'static str | — |
AddrMode :: fn from_db(s : & str) -> Option <Self> | — |
CameraStatus :: fn as_db(& self) -> & 'static str | — |
CameraStatus :: fn from_db(s : & str) -> Option <Self> | — |
pub struct Credentials | Camera access credentials |
Credentials :: fn seal(cipher : & SecretCipher, username : impl Into <String>, password_plaintext : & str,) -> Result <Self, SecretError> | Seal a plaintext password under cipher. |
Credentials :: fn from_sealed(username : impl Into <String>, password : Sealed) -> Self | Rehydrate from a persisted sealed value (from the DB). |
Credentials :: fn sealed(& self) -> & Sealed | The sealed password, for persistence to a BYTEA column. |
Credentials :: fn password(& self, cipher : & SecretCipher) -> Result <Zeroizing <String>, SecretError> | Decrypt the password (zeroized on drop) |
pub struct Camera | The durable camera record. |
Camera :: fn new(id : CameraId, name : impl Into <String>) -> Result <Self, RegistryError> | Create a validated record |
Camera :: fn id(& self) -> CameraId | The stable enrollment identity (never changes; not the IP/MAC). |
Camera :: fn live_feed(& self) -> Option <& Feed> | The feed assigned the live role (falls back to the first feed). |
Camera :: fn record_feed(& self) -> Option <& Feed> | The feed assigned the record role. |
Camera :: fn detect_feed(& self) -> Option <& Feed> | The feed the detector runs on. |
Camera :: fn view(& self) -> CameraView | Project to the API-safe view (omits the sealed password entirely). |
pub struct CameraView | API-safe projection of a Camera |
fn draft_from_discovery(discovered : & DiscoveredCamera) -> Result <Camera, RegistryError> | Build a draft registry record from a discovery result — maps the stable id, current IP (as static addressing — the operator can switch to DHCP), the probed streams as Live feeds, and the vendor/model as the label |
`store`
| Item | What it is |
|---|---|
async fn ensure_schema(pool : & PgPool) -> Result <(), StoreError> | Apply the registry's migrations, in order, on every call |
pub enum StoreError | Persistence errors. |
StoreError :: fn is_duplicate_name(& self) -> bool | Does this error mean "another LIVE camera already uses that name"? The cameras_name_live_uniq partial index is what enforces the rule, so the violation arrives as a Postgres 23505 |
CameraRow :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result | — |
pub struct ArchivedCamera | An archived row, for the trash listing only |
async fn create(pool : & PgPool, cam : & Camera) -> Result <(), StoreError> | Insert a new camera |
async fn get(pool : & PgPool, id : CameraId) -> Result <Option <Camera>, StoreError> | Fetch a live camera by id |
async fn get_by_name(pool : & PgPool, name : & str) -> Result <Option <Camera>, StoreError> | Fetch a live camera by name — the handle the relay addresses a camera by. |
async fn list(pool : & PgPool) -> Result <Vec <Camera>, StoreError> | List all live cameras (name order) |
async fn list_archived(pool : & PgPool) -> Result <Vec <ArchivedCamera>, StoreError> | List archived cameras, most recently archived first (the trash view). |
async fn update(pool : & PgPool, cam : & Camera) -> Result <bool, StoreError> | Update an existing live camera |
async fn archive(pool : & PgPool, id : CameraId) -> Result <bool, StoreError> | Soft-archive a live camera |
async fn restore(pool : & PgPool, id : CameraId) -> Result <bool, StoreError> | Un-archive a camera |
async fn purge(pool : & PgPool, id : CameraId) -> Result <bool, StoreError> | Irreversibly delete an archived camera |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
ensure_schema | store::ensure_schema |
Boundary
Reaches into infrastructure.
Shares tier operations with 40 other crates: operations-approval-workflow, operations-assessments, operations-block-imaging, operations-boot-media, operations-browser-agent-worker, operations-camera-discovery, operations-camera-liveview, operations-compliance, … (40 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | operations |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/operations/camera-registry |
| Vocabulary in force (lexicon) | current |
Tier flow. Which tiers this crate's own edges cross.
flowchart LR n_operations["operations"] --> n_infrastructure["infrastructure"]
Dependencies
Runtime, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `infrastructure-secrets` | infrastructure | no | always |
| `operations-camera-discovery` | operations | no | always |
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
chrono | ^0.4 | serde | yes | always |
serde | ^1 | derive | no | always |
sqlx | ^0.8 | runtime-tokio, postgres, chrono, uuid, json | yes | always |
thiserror | ^2 | — | no | always |
uuid | ^1 | v4, v7, serde, js | no | always |
zeroize | ^1 | — | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
serde_json | ^1 | — | no | always |
tokio | ^1 | full, macros, rt-multi-thread | no | always |
Build. None.
Depended on by. 1 workspace crate.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR n_application_cameras["application-cameras"] -->|uses| SELF SELF["operations-camera-registry"] SELF -->|runtime| n_infrastructure_secrets["infrastructure-secrets"] SELF -->|runtime| n_operations_camera_discovery["operations-camera-discovery"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
| Feature | Enables | On by default |
|---|---|---|
default | — | yes |
postgres | dep:sqlx, dep:chrono | no |
flowchart LR n_default["default"] n_postgres["postgres"] --> n_dep_sqlx["dep:sqlx"] n_postgres["postgres"] --> n_dep_chrono["dep:chrono"]
Targets
| Kind | Name | Source |
|---|---|---|
| lib | operations_camera_registry | `src/lib.rs` |
| test | store_integration | `tests/store_integration.rs` |
Error model
| Error type | Named by |
|---|---|
RegistryError | draft_from_discovery |
StoreError | archive, create, ensure_schema, get, get_by_name, list, … (10 total) |
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | yes |
| async runtime | none detected |
| database access | yes |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
1 workspace crate depends on this one: application-cameras.
Verification
| Kind | Count |
|---|---|
| Unit tests | 18 |
| Integration tests | 5 |
| Examples | 0 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
crate root | 22 | 0 | 0 |
store | 12 | 0 | 2 |
What the tests establish, by name:
archive_restore_purge_lifecycle—tests/store_integration.rscapabilities_round_trip_and_survive_archive—tests/store_integration.rscrud_round_trip_with_sealed_credentials—tests/store_integration.rsensure_schema_is_idempotent_on_a_bare_database—tests/store_integration.rslive_names_are_unique_but_archived_names_are_reusable—tests/store_integration.rscapabilities_decode_from_pre_migration_rows—src/lib.rscapabilities_default_is_capture_on_download_off—src/lib.rscapabilities_round_trip_through_json—src/lib.rscredentials_seal_and_unseal—src/lib.rsdraft_falls_back_to_ip_when_model_absent—src/lib.rsdraft_from_discovery_maps_identity_ip_and_streams—src/lib.rsfeed_role_accessors—src/lib.rsnew_accepts_conventional_device_names—src/lib.rsnew_defaults_are_sane—src/lib.rsnew_rejects_an_overlong_name—src/lib.rsnew_rejects_empty_name—src/lib.rsnew_rejects_names_that_break_downstream_consumers—src/lib.rsview_carries_capabilities—src/lib.rsview_omits_password_but_keeps_username—src/lib.rsview_round_trips_through_json—src/lib.rsbad_enum_column_is_reported—src/store.rsrow_into_camera_reconstructs_sealed_credentials—src/store.rsrow_with_no_credentials_maps_to_none—src/store.rs
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 46 | 55 |
Public modules with a //! block | 1 | 1 |
pie showData
title Public items with rustdoc
"Documented" : 46
"No rustdoc detected" : 9
Metrics
| Metric | Value |
|---|---|
| Rust source files | 2 |
| Source lines | 1308 |
| Code lines | 1025 |
| Public API items | 55 |
| Public modules | 1 |
| Tests | 23 |
| Examples | 0 |
| Cargo features | 2 |
| Direct runtime dependencies | 8 |
| Workspace reverse dependencies | 1 |
pie showData
title Public API by kind
"constant" : 1
"enum" : 11
"function" : 12
"method" : 21
"struct" : 10
pie showData
title Rust source composition
"Code" : 1025
"Blank or comment" : 283
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.