fix(install): arch guard + CSI device access (P5-2, P5-5)

- 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Xmn8KZWqiQUguEMRtn6rW
This commit is contained in:
유창욱 2026-07-17 09:38:18 +09:00
parent 7a86545367
commit 36b1f94571
3 changed files with 22 additions and 3 deletions

View file

@ -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

View file

@ -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

View file

@ -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.