identity/ (Phase 6, rewritten from the original Node-RED sketch): a
person <-> BLE-identifier registry built directly as a Python service.
Solves multi-phone (multiple identifiers per person), anti-spoofing
(only allowlisted IRK-resolved/fixed-tag entities are ever accepted as
registration candidates, never a raw or randomized MAC), device-less
people (a grandmother without a smartphone gets a no_device registration
plus a hand-operated home/away toggle, reported as "unknown" rather than
a false "away"), and anonymous guests (POST /register/guest, no name
needed). Every person gets an automatic profile picture from their most
recent registration photo. /presence also reports a best-effort room per
person as groundwork for an eventual floor-plan view (not built).
Registration is single-utterance voice ("register me as <name>") or a
touchscreen form; ambiguous/conflicting candidates never auto-commit.
hosts/door-panel/ (Phase 18, new host): structurally kitchen-display's
twin - one Sway workspace, one Chromium kiosk window - defaulting to
identity's weather+clothing/who's-home/groceries-running-low dashboard,
with voice registration as its actual purpose (mic on by default, unlike
every other host's opt-in).
hosts/kitchen-display/: adds opt-in voice satellite and a "Show
registration" screen pointed at identity's register.html, reusing the
same camera-equipped-endpoint registration flow.
pantry-vision/: adds GET /shopping-list (Grocy's own volatile/missing
products, reshaped) for the door panel's "running low" section.
setup-container-host.sh: wires ENABLE_IDENTITY (identity + identity-web,
published like pantry-vision since kiosk browsers call it directly, plus
a persistent SQLite/photos volume unlike pantry-vision's stateless
design) and fixes the HA_URL example to the host's real LAN IP (HA runs
network_mode: host, unreachable by container name - the same situation
Node-RED's own config already documents).
docs/: Phase 6 rewritten, Phase 18 added, hardware/software/guardrail/
open-decision entries throughout project-plan.md and README.md.
components.md gains RuView presence nodes (one per room), fixed BLE tags,
and 2 spare webcams, with the price estimate updated to match.
Nothing here has been run against real hardware, a real HA instance, or
real Private BLE Device entities - TRUSTED_ENTITY_PREFIXES above all
needs checking against a live instance before registration finds
anything. See identity/README.md and hosts/door-panel/README.md for the
itemized verification lists.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6CrKjW3yVptUnjG35HjC1
|
||
|---|---|---|
| .. | ||
| agent | ||
| configs | ||
| live-build/config | ||
| scripts | ||
| README.md | ||
README.md
Sway door panel
Phase 18 of docs/project-plan.md. Builds a Debian 12 live ISO for a wall panel by
the door/wardrobe: weather and what to wear on the way out, who's home, groceries
running low, and — the household's actual registration point — "register me as
<name>" by voice.
Structurally this is ../kitchen-display/'s twin, not a new shape: one Sway
workspace, one Chromium kiosk window, a thin agent that only ever switches which
page is showing. The differences are what it shows by default (identity's
dashboard.html instead of pantry-vision's scan/inventory/recipes) and that its
microphone is expected to actually be used, not an edge-case opt-in.
The actual logic does not live in this directory — ../../identity/ owns
person/presence data and the registration flow; ../../pantry-vision/ owns the
"running low" data. This host is deliberately thin: Sway, one kiosk window, and
door-panel-agent, which only controls which screen is showing — the same split
every other kiosk host in this project already uses.
| Compositor | Sway, one workspace, one Chromium kiosk window |
| Autologin | greetd, straight into /usr/local/bin/kiosk-session |
| Touch input | Native Wayland wl_touch, same assumption as ../touch-panel//../kitchen-display/ |
| Default screen | identity's dashboard.html — weather + clothing suggestion, who's home, groceries running low |
| Registration | identity's register.html — voice ("register me as <name>") or the touchscreen form |
| Voice | wyoming-satellite + openWakeWord — opt-in like every other host's mic, but this device's actual purpose, so the build script defaults it to on |
| Remote control (HA/LLM) | door-panel-agent — Show home / Show registration buttons only |
| Remote control (human) | SSH only — no wayvnc, same scope decision as ../touch-panel/ |
Hardware
No specific unit has been chosen. What's assumed: a touchscreen (native
wl_touch, same caveat as every other touch host in this project) mounted by the
door or wardrobe, with a microphone and speaker for voice registration/Assist
playback. Unlike ../kitchen-display/, no camera is strictly required — the
photo captured during registration (identity's profile-picture feature) is a nice-
to-have audit artifact, not load-bearing, since identity resolution here is BLE/IRK-
based, not camera-based. See docs/project-plan.md §1.16 for the (unverified,
non-specific) hardware line item.
Before you build
Deploy identity/identity-web first (ENABLE_IDENTITY in
hosts/container-host/scripts/setup-container-host.sh) — this image builds and boots
fine without it, but the dashboard will show connection errors until it exists.
pantry-vision is optional (only "Running low" needs it). Then edit the
# CONFIGURATION block at the top of
scripts/build-door-panel-iso.sh:
| Variable | What to put in it |
|---|---|
MQTT_BROKER_HOST |
LAN IP of the container host running Mosquitto |
IDENTITY_WEB_URL / IDENTITY_URL / IDENTITY_TOKEN |
identity's static-serving and API URLs; token must match identity/identity.env's own |
PANTRY_VISION_URL / PANTRY_VISION_TOKEN |
Optional — only "Running low" needs these; must match pantry-vision/pantry-vision.env's own token |
ENABLE_VOICE_SATELLITE |
Defaults to true here (unlike every other host's identical flag) — this device's whole point is voice registration, but it still needs a real mic on the specific unit before flashing it |
KIOSK_USERNAME / IMAGE_HOSTNAME / DOOR_PANEL_NAME |
Per-device identity |
SSH_AUTHORIZED_KEY |
Optional — password auth is disabled and there is no wayvnc |
Build
sudo ./scripts/build-door-panel-iso.sh
Same directory-split convention as every other host: configs/ and agent/ are
human-edited and git-tracked; live-build/config/includes.chroot/ is generated,
gitignored, never hand-edited.
Why one workspace, two kiosk destinations, not three
../touch-panel/ juggles three real apps (Spotify, Home Assistant, a browser) and
needs a persistent touch dock to switch between them. This device only ever shows
one of two pages — the everyday dashboard, or the registration form — and switches
between them rarely (on an MQTT command or a voice trigger), so a dock would be
overhead with nothing to navigate day-to-day. configs/sway/home-kiosk and
configs/sway/identity-kiosk are separate scripts on separate Chromium profiles,
same shape as ../kitchen-display/'s pantry-kiosk/identity-kiosk pair — see that
host's README for why both scripts kill any Chromium instance before launching
(this device also has only one workspace).
Home Assistant entities
door-panel-agent publishes two buttons on connect: Show home, Show
registration — each kills and relaunches the kiosk Chromium window at the
corresponding page. That's the entire MQTT surface. Reading presence/weather/
groceries, or registering a person, is a separate path — Home Assistant/the LLM
calling identity's or pantry-vision's own published APIs directly, not through
this agent. Voice registration in particular never touches this agent at all — see
../../identity/README.md's worked HA intent-script example.
Security boundary
Same shape and reasoning as every other host's agent in this project:
door_panel_agent/mqtt_discovery.py is the entire inbound MQTT control surface of
this machine — LLM tool call → HA service call → MQTT → this agent, no HTTP
listener, no websocket, no exposed Sway IPC socket, no VNC. identity and
pantry-vision are separate, deliberately published services with their own
bearer-token boundaries — see their own READMEs' "A real network listener, unlike
admin-canvas" sections for why that trust model is different on purpose.
Manual verification still outstanding
None of this has been run on hardware. In rough order — on top of everything already
flagged as unverified in ../../identity/README.md (TRUSTED_ENTITY_PREFIXES
above all):
- The ISO builds at all.
- greetd lands in Sway with no login prompt.
- Touch input as native
wl_touch— same open item as every other touch host. door-panel-agentconnects to Mosquitto and the device appears in HA.- Register via the touchscreen form (
Show registration) first, before trying voice — this exercises the whole identity path without needing HA's intent-script wiring set up. Seeidentity/README.md's worked example for that next step. - Voice registration end-to-end: wake word → "register me as
<name>" → a spoken confirmation. This is the number of moving pieces (wyoming-satellite, HA's Assist pipeline, the custom sentence/intent script,identity's/register) that has the most to go wrong and the least individual testing so far. - The dashboard's clothing suggestion (
identity/frontend/dashboard.js'sclothingSuggestion()) is a plain lookup table, untuned against real weather payloads or real household clothing preferences — reasonable starting thresholds, not measured. - Switching between
home-kioskandidentity-kioskactually replaces the window rather than leaving two Chromium instances up — same untested assumption as../kitchen-display/'s identical pair. - Idle-blank timeout (20 minutes,
configs/sway/config) and touch-resume — untested.