From 36b1f9457112c496c372b1f45dc4476db2f67897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EC=B0=BD=EC=9A=B1?= Date: Fri, 17 Jul 2026 09:38:18 +0900 Subject: [PATCH] fix(install): arch guard + CSI device access (P5-2, P5-5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - P5-2 [H] build_offline_bundle.sh native branch hard-fails when uname -m != TARGET_ARCH (an x86 build was producing an aarch64-named tarball of x86_64 wheels). - P5-5 [H] systemd unit adds DeviceAllow char-media + /dev/dma_heap for the CSI camera — picamera2/libcamera on Pi 5 needs them or the unit denies its own camera. OFF-HW: verify on Pi. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_019Xmn8KZWqiQUguEMRtn6rW --- deploy/bundle/build_offline_bundle.sh | 9 +++++++++ deploy/systemd/move-detect-edge.service | 10 +++++++++- docs/delivery-audit.md | 6 ++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/deploy/bundle/build_offline_bundle.sh b/deploy/bundle/build_offline_bundle.sh index 948230a..d3a5117 100755 --- a/deploy/bundle/build_offline_bundle.sh +++ b/deploy/bundle/build_offline_bundle.sh @@ -59,6 +59,15 @@ else echo " or use --cross to pin aarch64/$PYABI wheels explicitly." >&2 exit 1 fi + # Guard the ARCH too: a native build on an x86_64 workstation would download x86_64 wheels + # while the tarball is still named/declared aarch64 (line 27/86/92) — a bundle that installs + # then fails to import on the Pi. numpy/opencv/onnxruntime are per-arch, so this is fatal. + HOST_ARCH="$(uname -m)" + if [ "$HOST_ARCH" != "$TARGET_ARCH" ]; then + echo "ERROR: native build host arch is $HOST_ARCH but TARGET_ARCH is $TARGET_ARCH." >&2 + echo " Build natively ON an $TARGET_ARCH host (a Pi 5 / arm64 CI), or use --cross." >&2 + exit 1 + fi python3 -m pip download -d "$WHEELHOUSE" "${RUNTIME_PKGS[@]}" fi diff --git a/deploy/systemd/move-detect-edge.service b/deploy/systemd/move-detect-edge.service index c4e8333..0a15019 100644 --- a/deploy/systemd/move-detect-edge.service +++ b/deploy/systemd/move-detect-edge.service @@ -42,9 +42,17 @@ RestartSec=5 StateDirectory=move-detect StateDirectoryMode=0750 -# Camera + accelerator device access (USB UVC = /dev/video*, Hailo = /dev/hailo0). +# Camera + accelerator device access. Once ANY DeviceAllow= is present, systemd denies every +# unlisted device node, so the CSI camera needs its nodes explicitly: +# char-video4linux USB UVC (/dev/video*) AND the CSI capture nodes +# char-media picamera2/libcamera opens /dev/media* to configure the CSI pipeline (Pi 5) +# /dev/dma_heap/* libcamera allocates capture buffers from the dma-heap on Pi 5 +# Without char-media + dma_heap a Hailo Pi with a CSI camera is denied its own camera by this +# unit's policy. (OFF-HW: verify on the Pi — `journalctl` shows a libcamera EPERM/open failure.) DeviceAllow=/dev/hailo0 rw DeviceAllow=char-video4linux rw +DeviceAllow=char-media rw +DeviceAllow=/dev/dma_heap/ rw # Conservative hardening (loosen if it blocks device access on your image). NoNewPrivileges=true diff --git a/docs/delivery-audit.md b/docs/delivery-audit.md index d222712..1c3fe3e 100644 --- a/docs/delivery-audit.md +++ b/docs/delivery-audit.md @@ -184,17 +184,19 @@ misconfig/degradation fail LOUD. verbatim even when the bundle carries no working backend. **Fix:** mirror the [6/8] probe. DONE — [5/6] probes HEF+hailo_platform / onnx+onnxruntime, reconciles POSE_BACKEND in the installed env, hard-fails if neither. test_deploy_artifacts.py locks the gate. -- [ ] **P5-2 [H]** `deploy/bundle/build_offline_bundle.sh:55` — a native build on x86 produces +- [x] **P5-2 [H]** `deploy/bundle/build_offline_bundle.sh:55` — a native build on x86 produces an aarch64-named tarball full of x86_64 wheels. **Fix:** assert `uname -m == TARGET_ARCH`. + DONE — native branch now hard-fails when uname -m != TARGET_ARCH. - [ ] **P5-3 [M]** `deploy/bundle/build_offline_bundle.sh:65` — the air-gapped bundle never carries the Hailo HEF, so offline Hailo install is impossible. **Fix:** stage the HEF (via `fetch_hailo_hef --arch`) into the bundle. - [ ] **P5-4 [M]** `deploy/bundle/build_offline_bundle.sh:28` — pip deps unpinned, no digests, MANIFEST has no hashes, bundle unsigned; spec requires SHA256/GPG + SBOM. **Fix:** pin + hash + manifest digests. -- [ ] **P5-5 [H]** `deploy/systemd/move-detect-edge.service:46` `OFF-HW` — `DeviceAllow` omits +- [x] **P5-5 [H]** `deploy/systemd/move-detect-edge.service:46` `OFF-HW` — `DeviceAllow` omits `/dev/media*` and `/dev/dma_heap`; picamera2/libcamera on Pi 5 needs them, so the CSI camera is denied by the unit's own policy. **Fix:** add the device classes; verify on hardware. + DONE — added `char-media` + `/dev/dma_heap/`. OFF-HW: confirm on the Pi with the CSI camera. - [ ] **P5-6 [L]** `cloud/deploy/build_cafe24_package.sh` — dev cache dirs (`.impeccable/`, `.ruff_cache/`) can ship inside the web-served package. **Fix:** exclude.