-- The latest still frame from each camera, held by the server itself. -- -- Camera snapshots already worked, through the same presigned-URL path face -- images use: the agent asks for a URL, PUTs the JPEG to object storage, and -- the server presigns a short-lived link when somebody looks. That is the right -- design for face images - one per visit, unbounded, and they must never touch -- a shop PC's disk or the server's. -- -- It is the wrong design for the ONE case where a deployment has no object -- storage at all. Head office then reports "This system is not storing images" -- for every camera, forever, on a screen whose whole point is to SHOW the -- camera. A self-hosted customer who does not want an S3 bucket, and every -- local install, got a wall of empty tiles. -- -- What makes this safe to put in the database, when face images are not: -- -- * ONE ROW PER CAMERA. The primary key is the camera, so a snapshot -- replaces its predecessor. An estate's storage is (cameras x ~100 KB) -- and does not grow with time or with footfall. Face images grow with -- every visitor who ever walks in, which is why they stay in a bucket. -- * It is a picture of a shop floor, not a face crop attached to an -- identity. It carries no template and is not tied to a person. -- * ON DELETE CASCADE from the camera. Removing a camera removes its -- picture, with no second place to remember to clean up. -- -- When object storage IS configured nothing changes: the bucket path stays -- primary and this table is not written. BEGIN; CREATE TABLE IF NOT EXISTS camera_snapshots ( camera_id uuid PRIMARY KEY REFERENCES site_cameras(id) ON DELETE CASCADE, -- Denormalised deliberately, like every other table here: a cross-tenant -- read should require a wrong WHERE clause rather than a forgotten join. client_id uuid NOT NULL REFERENCES clients(id) ON DELETE CASCADE, site_id uuid NOT NULL REFERENCES sites(id) ON DELETE CASCADE, image bytea NOT NULL, bytes integer NOT NULL, captured_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS camera_snapshots_client_idx ON camera_snapshots (client_id); COMMIT;