Cloud cameras are now a distinct type ('cloud') managed entirely by
sync. Bidirectional: cameras added in vendor cloud appear automatically,
removed cameras get deleted. Cloud cameras and their entities are
read-only in admin UI — no manual editing.
- Camera type CHECK widened to include 'cloud'
- New columns: cloud_account_id, cloud_vendor_camera_id,
cloud_stream_url, cloud_stream_type
- Repo: upsertCloudCamera, deleteCloudCamerasNotIn,
listCloudCamerasByAccount
- Sync replaces import: full reconciliation per account
- Hik-Connect: fetch HLS preview URLs via previewURLs endpoint
- Tuya: fetch stream URLs during sync (not just on demand)
- Kiosk API: GET /api/kiosk/cameras/:id/stream returns fresh
relay URL from vendor (session-based URLs expire)
- Cloud cameras show read-only detail page with cloud badge
- Coolify compose: postgres 18 as default, BF_DB=postgres,
server depends_on postgres healthy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cloud camera platform integrations with provider interface pattern:
Framework (cloud-cameras/types.ts):
- CloudCameraProvider interface: testCredentials, listCameras,
getStreamUrl, credentialFields
- CloudAccount model + vendor registry
- Multiple accounts per vendor per tenant supported
- All auth on server — kiosk only gets streaming URLs
Vendors:
- Hik-Connect: token auth, device list via OpenAPI, local RTSP
(cloud P2P relay requires native SDK — not supported yet)
- Dahua: HTTP Basic/Digest against device ISAPI, channel enumeration,
RTSP URL construction per channel
- Tuya: OAuth2 + HMAC-SHA256, device list + stream allocation via
IoT Cloud API, RTSP/HLS URL from allocate endpoint
- Uniview: HTTP Basic against LightAPI, channel enumeration via
/LAPI/V1.0/Channels, RTSP per channel
- TP-Link: no cloud API, direct RTSP + TCP port probe for testing
DB: cloud_accounts table (SQLite migration) for storing encrypted
credentials per vendor per tenant.
Admin UI for account management TODO — provider framework + DB ready.