Skip to content

feat: security-harden the RPi camera plugin and reorganize into delivery/streaming/observability#14

Merged
simonvanlierde merged 164 commits into
mainfrom
dev
Jul 2, 2026
Merged

feat: security-harden the RPi camera plugin and reorganize into delivery/streaming/observability#14
simonvanlierde merged 164 commits into
mainfrom
dev

Conversation

@simonvanlierde

@simonvanlierde simonvanlierde commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Production security-hardening pass plus a feature-first reorganization.
166 files; the bulk is defensive work backed by tests, plus a no-behavior-change module reshuffle. Details in CHANGELOG.md under v0.4.0.

Highlights

Security

  • Auth/sessions: enforced lifetimes, ASVS-aligned cookies, same-origin write checks, structured auth/CSRF/session logging
  • Browser: per-request CSP nonces, restricted CORS + private-network access, blocked TRACE, limited static file types
  • Relay/pairing: startup + boundary credential validation, command allowlist, bounded inputs, rate limits; auth required for pairing/preview/metrics; fail closed for prod loopback pairing
  • Transport: HTTPS enforced for S3 and OTLP
  • Config/secrets: reject DEBUG=true in prod; reveal local API key on demand instead of embedding in HTML
  • Supply chain: security CI workflow, digest-pinned images, loopback-default listeners

Refactor

  • image_sinks/uploaddelivery, mediacamera/streaming, systemobservability

Fixes

  • Post-hardening correctness/reliability: open-redirect and token-redaction fixes, 403-not-500 on bad API keys, credential-file crash guards, worker desync/loop-death fixes, UTC-aware timestamps, Compose dma_heap mapping

Testing

Suite green after follow-up fixes; net LOC down from dead-code and duplicate-test cleanup.

simonvanlierde and others added 30 commits April 22, 2026 23:52
Co-authored-by: Copilot <copilot@github.com>
…time

Type ImageProperties.capture_time as AwareDatetime so naive values are
rejected, and convert to UTC in serialize_datetime_with_z so non-UTC
offsets emit a real 'Z' timestamp instead of a bare offset.
Address code-review findings on the test suite:

- backend/test_client: fix zero-arg build_device_assertion stub that
  passed only via the caught TypeError, not the intended ValueError
- camera/test_manager: relocate check_stream_duration tests into their
  class and assert the logged message in test_logs_runtime_error
- streaming/test_preview_pipeline: yield distinct encoder instances so
  the restart assertion verifies a fresh encoder at the new bitrate
- integration/test_setup: assert the probe fetches the normalized URL
- pairing/test_flow: drop dead get_responses payload
- workers/test_preview_sleeper: correct stale autouse-fixture comment
- backend/test_contract_adapters: assert required EXIF tags, not truthiness
- streaming/test_stream: drop always-skipping non-YouTube-modes test

Also sanitize the DELETE /streams/youtube 500 via client_error_detail
so internal RuntimeError text no longer leaks to clients, matching the
captures/hls error paths; test flipped to assert the message is hidden.
Weaker subset of test_active_stream_returns_contract_view in
tests/unit/backend/test_contract_adapters.py.
…duplicates

test_single_key_string now feeds a bare string so it covers the JSON-decode comma-split fallback instead of duplicating test_valid_json_array. Remove two pure model_validate_json(model_dump_json()) round-trips that only exercised Pydantic serialization; validator coverage lives in the reject_* tests.
get_state() is a one-line getter; asserting it returns self.state tests nothing. Keep the reset_state coverage.
- Drop Dockerfile.mediamtx; the pinned mediamtx-ffmpeg image already ships
  busybox wget for the healthcheck, so use it directly in compose and remove
  the now-dead paths-filter entry from the security workflow.
- Move renovate.json and codecov.yml under .github/ to declutter the root.
- Trim renovate.json: drop the default-on pep621 block and the pinDigests
  keys already implied by config:best-practices.
Resolve conflicts in favor of dev (feature-first hardening branch): PR #9's
pairing rework and dev's overlap the same files, dev is the superset. Adopt
main's renovate action bumps (checkout df4cb1c, setup-uv v8.2.0) across all
workflows and the pyjwt 2.13.0 / pydantic-settings 2.14.2 security bumps.

Drop -X ours collateral: dead __all__ in pairing service.py and duplicate
_parse_list_env in settings.py.
@simonvanlierde simonvanlierde changed the title Dev feat: security-harden the RPi camera plugin and reorganize into delivery/streaming/observability Jul 1, 2026
Comment thread app/core/middleware.py Fixed
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Comment thread app/camera/services/backend.py Fixed
Comment thread app/observability/tracing.py Fixed
Comment thread app/observability/tracing.py Fixed
Comment thread app/observability/logging.py Fixed
Comment thread tests/integration/test_error_handling.py Fixed
Comment thread tests/unit/core/test_middleware.py Fixed
Comment thread tests/unit/relay/test_service.py Fixed
Comment thread app/core/settings.py Fixed
Comment thread app/core/settings.py Dismissed
- middleware: salt+HMAC rate-limit bucket keys (CodeQL weak-hash on sensitive data)
- backend: drop redundant bare ... after property docstring
- tracing: replace bare ... protocol bodies with docstrings
Comment thread app/observability/logging.py Dismissed
Comment thread tests/integration/test_error_handling.py Dismissed
Comment thread tests/unit/core/test_middleware.py Dismissed
Comment thread tests/unit/relay/test_service.py Dismissed
Comment thread app/core/settings.py Dismissed
@simonvanlierde simonvanlierde merged commit 04e77ee into main Jul 2, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants