From 1b7f77b298bc9e7249dd6ecb81ce1940908f0947 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Fri, 3 Apr 2026 17:41:39 -0400 Subject: [PATCH] feat(F2): integrate AES-256-CTR encryption into AdaptiveRecorder After FFmpeg finishes writing, _stop_ffmpeg() now reads VIGILAR_ENCRYPTION_KEY and encrypts the MP4 to .vge format via encrypt_file(), updating the returned RecordingSegment to reflect the encrypted file path and size. Co-Authored-By: Claude Sonnet 4.6 --- tests/unit/test_recorder_encryption.py | 10 ++++++++++ vigilar/camera/recorder.py | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/unit/test_recorder_encryption.py diff --git a/tests/unit/test_recorder_encryption.py b/tests/unit/test_recorder_encryption.py new file mode 100644 index 0000000..bcb2dde --- /dev/null +++ b/tests/unit/test_recorder_encryption.py @@ -0,0 +1,10 @@ +"""Test encryption integration flag in recorder.""" + +import os +from vigilar.camera.recorder import AdaptiveRecorder + + +def test_recorder_has_encryption_support(): + """Verify recorder imports encryption module correctly.""" + from vigilar.storage.encryption import encrypt_file + assert callable(encrypt_file) diff --git a/vigilar/camera/recorder.py b/vigilar/camera/recorder.py index ae13dcf..194c556 100644 --- a/vigilar/camera/recorder.py +++ b/vigilar/camera/recorder.py @@ -156,6 +156,27 @@ class AdaptiveRecorder: duration, self._frame_count, file_size, ) + # Encrypt if key is available + encryption_key = os.environ.get("VIGILAR_ENCRYPTION_KEY") + if encryption_key and self._current_path and self._current_path.exists(): + try: + from vigilar.storage.encryption import encrypt_file + vge_path = encrypt_file(str(self._current_path), encryption_key) + segment = RecordingSegment( + file_path=vge_path, + started_at=self._started_at, + ended_at=ended_at, + duration_s=duration, + file_size=Path(vge_path).stat().st_size, + trigger=self._current_trigger, + fps=self._current_fps, + frame_count=self._frame_count, + ) + log.info("Encrypted recording: %s", Path(vge_path).name) + except Exception: + log.exception("Encryption failed for %s, keeping plain MP4", + self._current_path.name) + self._process = None self._current_path = None return segment