Camera permission and review fixes (openpanel C3, C4)

C4: a device's `viewers` (superusers by default, or members) covers the
image and video messages its ports publish. Anyone else gets none of their
values on the socket, in the catalogue or a flow's state, 403 for their
history, for the frames they hold (the last 8 included) and for TURN
credentials, no bytes when asking for them, and `bye: forbidden` for a live
view. A device credential stays bounded by its dashboards. The device page
sets it in its Camera section, and a tile the viewer may not see says
"No access to this camera" and asks the camera for nothing.

C3:
- A volatile upload is held to MAX_FRAME_BYTES (4 MiB, 413 above it, read
  without extra copies), and so is a frame on a device's socket.
- A frame the engine holds in memory is written to the ring directory
  before a local worker is handed it, so load_artifact finds it.
- A socket the bus dropped events for catches up with a snapshot, demand
  included, and a device's credential is checked again per frame, cached by
  the flow store revision and its nonce, so a lost event never keeps an
  unpaired device's frames coming.
- A report is at most 64 KB once its named config_schemas are put in place.
- A device away for 60 s has its true bool messages set to false.
- Refused frames are logged by fixed keys, a frame is named after its
  message, `fluksio serve` waits 5 s for open connections, a tile with a
  stream URL creates no demand, the 8-name cap keeps the newest names.
- Every container's log rotates (json-file, 3 x 10 MB).
This commit is contained in:
Melvin Strobl
2026-10-17 09:20:04 +02:00
parent 6a98dcd23f
commit 72c1d73e96
36 changed files with 1268 additions and 152 deletions
+13
View File
@@ -2,12 +2,21 @@
# published host ports, hot reload and the mail/browser test helpers.
# Never used in production — the Makefile only layers it for `make dev*`.
# Every container's log rotates: json-file, at most 3 files of 10 MB each.
# Docker's default keeps one file that grows until the host's disk is full.
x-logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "3"
services:
# Local Traefik. Services stay reachable both on their published ports and
# on http://api.localhost / http://app.localhost via the routers in
# compose.yml. Dashboard at http://localhost:8090.
proxy:
logging: *logging
# A patch tag, so a host holding an older cached 3.6 pulls this one. 3.6.25
# knows --accesslog.fields.queryparameters, which older 3.6 refuses.
image: traefik:3.6.25
@@ -61,6 +70,7 @@ services:
# them, and 1883 in particular tends to be taken by the real broker on a
# machine that runs this alongside anything else.
mosquitto:
logging: *logging
image: eclipse-mosquitto:2
restart: "no"
# The config the image ships for exactly this: listener on 1883, anonymous
@@ -68,6 +78,7 @@ services:
command: mosquitto -c /mosquitto-no-auth.conf
influxdb:
logging: *logging
image: influxdb:2.7
restart: "no"
# Dev credentials, and no volume: the container comes up initialised and a
@@ -151,6 +162,7 @@ services:
API_DOCS_ENABLED: "true"
mailcatcher:
logging: *logging
image: schickling/mailcatcher
ports:
- "1080:1080"
@@ -162,6 +174,7 @@ services:
restart: "no"
playwright:
logging: *logging
build:
context: ..
dockerfile: frontend/Dockerfile.playwright
+9
View File
@@ -1,5 +1,14 @@
# Every container's log rotates: json-file, at most 3 files of 10 MB each.
# Docker's default keeps one file that grows until the host's disk is full.
x-logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "3"
services:
traefik:
logging: *logging
# A patch tag, so a host holding an older cached 3.6 pulls this one. 3.6.25
# knows --accesslog.fields.queryparameters, which older 3.6 refuses.
image: traefik:3.6.25
+16
View File
@@ -6,11 +6,20 @@
# Paths are relative to this directory, which compose uses as the project
# directory (build contexts therefore point at `..`, the repo root).
# Every container's log rotates: json-file, at most 3 files of 10 MB each.
# Docker's default keeps one file that grows until the host's disk is full.
x-logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "3"
services:
# Umami's database, and nothing else's. The engine keeps its own state in
# SQLite on the flow-data volume, which is why this is behind a profile now.
db:
logging: *logging
image: postgres:18
container_name: fluksio-db
restart: always
@@ -36,6 +45,7 @@ services:
- POSTGRES_DB=${POSTGRES_DB:-app}
redis:
logging: *logging
image: redis:8.2-alpine
container_name: fluksio-redis
restart: always
@@ -57,6 +67,7 @@ services:
- app-redis-data:/data
adminer:
logging: *logging
image: adminer
container_name: fluksio-adminer
restart: always
@@ -73,6 +84,7 @@ services:
- ADMINER_DESIGN=pepa-linha-dark
backend:
logging: *logging
image: '${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}'
container_name: fluksio-api
restart: always
@@ -177,6 +189,7 @@ services:
# Static documentation site (zensical), served at docs.${DOMAIN}. Content and
# config live in ../docs/ and ../zensical.toml; `make docs-serve` previews it.
docs:
logging: *logging
container_name: fluksio-docs
restart: always
security_opt:
@@ -211,6 +224,7 @@ services:
# authority: on a machine that runs anything besides this stack, that is a
# deliberate operator decision. `make up` opts in; the dev stacks do not.
autoheal:
logging: *logging
image: willfarrell/autoheal:latest
container_name: fluksio-autoheal
profiles: ["autoheal"]
@@ -236,6 +250,7 @@ services:
# goes in through a config file rather than the command line, which `ps`
# shows. See DEPLOY.md for ports, DNS and certificates.
coturn:
logging: *logging
image: coturn/coturn:4.6.3
container_name: fluksio-coturn
profiles: ["turn"]
@@ -282,6 +297,7 @@ services:
# `analytics` profile, so a plain `make up` never starts it; bring it up with
# `make umami`, which also provisions its database.
umami:
logging: *logging
container_name: fluksio-umami
# Pinned by digest so a bump is a deliberate step: this is an internet-facing
# third-party dashboard, not a library.