openaliro/architecture
asxeem/openaliro
openaliro
Architecture
Every subsystem on one page, in reading order: entry points (nothing imports them) first, then the machinery they drive. Each heading links to the full per-module reference.
Fly through the whole surface
Every file the docs cover, in one 3D graph — orbit it, filter it, click a node for what it does.
Open the 3D viewflowchart LR gvn0["woz_aliro"] gvn1["woz_aliro_stack"] gvn2["woz_port"] gvn3["woz_uwb/aliro"] gvn4["woz_uwb/facade"] gvn0 --> gvn2 gvn0 --> gvn3 gvn0 --> gvn4
flowchart LR
subgraph gvc0["woz_aliro"]
aliro_advtag
aliro_apdu
aliro_ble
aliro_crypto
aliro_hash
aliro_lab
aliro_lat
aliro_prim
aliro_prim_psa
aliro_prov
aliro_ranging
aliro_reader
aliro_rssi_gate
aliro_stepup
aliro_stepup_parse
end
subgraph gvc1["woz_aliro_stack"]
access_document
advertising_core
aliro_stack
ble_message
ble_timeout
nfc_auth
nfc_select
nfc_step_up
session
tlv
end
subgraph gvc2["woz_port"]
woz_log
woz_port
end
subgraph gvc3["woz_uwb/aliro"]
aliro_uwb_adapter
aliro_uwb_session
cherry
cherry_ccc
end
subgraph gvc4["woz_uwb/facade"]
woz_uwb_facade
end
aliro_stepup --> aliro_crypto
aliro_advtag --> aliro_prim
aliro_crypto --> aliro_prim
aliro_crypto --> aliro_hash
aliro_lat --> aliro_lab
aliro_lat --> woz_log
aliro_lat --> woz_port
aliro_prim_psa --> aliro_prim
aliro_ranging --> aliro_ble
aliro_ranging --> aliro_crypto
aliro_ranging --> aliro_lab
aliro_ranging --> aliro_lat
aliro_ranging --> woz_log
aliro_ranging --> aliro_uwb_adapter
aliro_ranging --> aliro_uwb_session
aliro_ranging --> cherry
aliro_ranging --> cherry_ccc
aliro_ranging --> woz_uwb_facade
aliro_reader --> aliro_ble
aliro_reader --> aliro_crypto
aliro_reader --> aliro_lab
aliro_reader --> aliro_lat
aliro_reader --> aliro_prim
aliro_reader --> aliro_prov
aliro_reader --> aliro_rssi_gate
aliro_reader --> aliro_stepup
aliro_reader --> aliro_apdu
aliro_reader --> aliro_ranging
aliro_reader --> woz_log
aliro_reader --> woz_port
aliro_stepup --> aliro_crypto
aliro_stepup --> aliro_hash
aliro_stepup_parse --> aliro_stepup
aliro_stack --> advertising_core
ble_message --> tlv
ble_timeout --> ble_message
nfc_auth --> tlv
nfc_select --> tlv
nfc_step_up --> tlv
session --> access_document
session --> ble_messageModules
woz_aliromodules/woz_aliro27 modules⌄
aliro_ranging.cUWB ranging bring-up and lifecycle for the Aliro reader: initializes the reader's UWB adapter and Cherry CCC context once, then arms, feeds, and tears down per-connection ranging sessions driven by the M1-M4 setup exchanged over the peer's L2CAP channel. Maintains process-wide singletons for the Cherry context and adapter (set up once via aliro_ranging_init) and for the single active ranging session (the DW3000 supports only one session at a time), tracking its owning secure channel for send/receive framing.aliro_reader.cAliro reader engine: drives the Access Protocol (AUTH0/AUTH1/EXCHANGE) handshake over BLE, manages reader identity and credential trust provisioning in NVS, and arms UWB ranging once a session is authenticated. Maintains a fixed-size table of per-connection sessions tracking transaction phase and secure-channel state, and exposes start/attach entry points for both standalone and Matter-attached BLE transports, plus provisioning and diagnostic APIs used by Matter commissioning and the bench console.aliro_lat.cWalk-up latency trace: first-hit phase timestamps + the consolidated budget line.aliro_crypto.cAliro cryptographic primitives: key derivation (KDF/HKDF), key-block splitting, AES-GCM secure channels, and wire message framing built on a pluggable crypto backend (aliro_prim_*). Implements the Aliro key-derivation chain (ECDH shared secret -> z -> 160-byte key block -> split session keys / URSK / BLE ranging keys), per-direction AES-256-GCM secure channels with monotonic message counters, and the seal/open framing used to carry engine plaintext over the wire.aliro_stepup.cAliro step-up phase codec + verifier: derives the StepUpSK SessionData keys, builds the mdoc DeviceRequest and its ENVELOPE/GET RESPONSE APDUs, seals/opens SessionData over the aliro_secchan AES-256-GCM channel, and runs the six-step Access Document verification of spec 7.4. The ES256 primitive is injected (verify ctx) so this unit carries no elliptic-curve dependency.aliro_advtag.cAliro BLE advertisement Dynamic Tag derivation (Aliro 1.0 section 11.3.1), shared by the BLE transport (live advertising) and the host KAT suite (spec section 20 worked examples).aliro_stepup_parse.cDeviceResponse structural decoder for the Aliro step-up phase: a minimal, bounds-checked, depth-limited CBOR reader (definite-length core-deterministic only) plus the Table 8-22/7-1/7-2 field walk. No crypto and no allocation; every parsed field is a slice of the caller's buffer. This is the wire-facing attack surface and is fuzzed on its own (tests/host/fuzz/fuzz_stepup.c).aliro_apdu.cAliro APDU TLV codec: builds command payloads (AUTH0, AUTH1, AuthData, EXCHANGE) and parses response APDUs, plus BLE envelope framing/unframing and ISO7816 APDU wrap/status-word stripping. Provides a minimal BER-TLV writer (aliro_tlv_w_init/put/finish) used to assemble command payloads, and TLV/APDU parsing helpers used to extract fields from device responses.aliro_approach.cNo module docstring. First commit: "approach: predict time-of-arrival, open the bolt at arrival".aliro_hash.cSelf-contained SHA-256, HMAC-SHA256, HKDF, and ANSI-X9.63 KDF implementation for the ESP32-IDF Aliro crypto port, with no external crypto library dependency.aliro_prim_psa.cAliro crypto primitive backend implemented on Arm PSA Crypto: random generation, AES-256-GCM encrypt/decrypt, and NIST P-256 key generation, ECDH, and ECDSA sign/verify. Provides the aliro_prim_* / aliro_* primitive functions consumed by the higher-level Aliro KDF and secure-channel code in aliro_crypto.c; callers must call aliro_prim_init before using any other function in this file.aliro_prov.cAliro reader provisioning state: default dev identity, and serialization/deserialization of the reader identity plus trusted-credential store to/from a self-describing binary blob. Also implements the trust-store membership check and add-with-dedup operations used to decide whether a presented credential public key is trusted.aliro_rssi_gate.cBLE-RSSI ranging power gate implementation: EWMA smoothing in Q4 fixed point, open/close hysteresis with a sustained-below close hold, and an optional rise-rate fast open so a fast approach is not penalized by the smoothing lag. Pure logic — no radio, clock, or logging dependencies — so the host suite can drive it with synthetic approach traces.aliro_ble.hAliro BLE-UWB reader transport: GATT service definition, advertised feature flags, and transport callbacks connecting the BLE peripheral role to the Aliro protocol handler in aliro_reader. Callers configure the transport via aliro_ble_prepare (which builds the READ characteristic payload without touching NimBLE), then register the GATT service returned by aliro_ble_service_def with the host's combined service table.aliro_crypto.hAliro crypto public API: key derivation, AES-GCM secure channels, and wire message seal/open framing shared by the reader and device sides of an Aliro session.aliro_lab.hAliro Lab trace: structured "[ALAB]" lines at transaction phase boundaries, parsed by tools/aliro_lab.py into a scored walk-up report. Ships in every Aliro build (CONFIG_WOZ_ALIRO_LAB defaults y, like the sibling uwbdiag trace) but is OFF at boot and toggled at runtime by thelab on/lab offconsole command, so any firmware profiles on demand with no reflash. Set CONFIG_WOZ_ALIRO_LAB=n to strip it from a hardened production image.aliro_lat.hNo module docstring. First commit: "Cut ESP32 walk-up unlock latency: instrument, unblock, and precompute".aliro_ranging.hAliro M1-M4 ranging-setup interface: negotiates UWB ranging parameters with the device and produces the BLE ranging-control secure channel used to carry the M1-M4 exchange.aliro_prim.haliro_prov.hPersistent reader provisioning storage: identity and credential trust anchors saved to and loaded from NVS. Declares aliro_prov_store for committing an identity/trust pair to NVS, and struct aliro_trust_store, the set of trusted credential public keys against which a presented credential is authenticated.aliro_reader.haliro_rssi_gate.hBLE-RSSI ranging power gate: decides when the phone is close enough that arming UWB ranging is worth the radio's RX power. Pure sample-in/state-out logic (EWMA smoothing, open/close hysteresis with a close hold-off, optional rise-rate fast open for fast approaches) so it host-tests without a radio; the reader feeds it connection RSSI samples and defers Reader-Status-AP-Completed until it opens.aliro_stepup.hAliro step-up (Access Document) phase: builds the mdoc DeviceRequest, unwraps and decrypts the SessionData DeviceResponse, decodes the CBOR document per spec 7.2/8.4.2, and runs the six-step Access Document verification of spec 7.4. Reference-completeness codec + verifier; the verdict is logged and stored, never gates the unlock (the provisioned trust store remains the sole gate).aliro_apdu.hAPDU framing and parsing for the Aliro Access Protocol: builds outbound command APDUs via a TLV writer and parses the AUTH0/AUTH1 response APDUs exchanged during the reader-device handshake.aliro_hash.hStreaming SHA-256 (FIPS 180-4) implementation used by the Aliro crypto layer. Declares struct aliro_sha256, the incremental hash context used across init/update/finish calls.aliro_advtag.hAliro BLE advertisement Dynamic Tag derivation (Aliro 1.0 section 11.3.1): the 7-byte GroupResolvingKey-resolvable tag the phone recomputes to identify a reader of interest.aliro_approach.hNo module docstring. First commit: "approach: predict time-of-arrival, open the bolt at arrival".
woz_aliro_stackmodules/woz_aliro_stack/src18 modules⌄
session.cppble_message.cble_timeout.cnfc_auth.cnfc_select.cnfc_step_up.cadvertising_core.caliro_stack.cppClean-room implementation of the Nordic Aliro public API used by this app. Protocol constants and wire formats come from Aliro Specification 1.0. No implementation detail from the proprietary archive is used here.access_document.ctlv.caccess_document.hble_message.hAliro 1.0 Bluetooth LE message framing (section 11.7).ble_timeout.hAliro 1.0 Bluetooth LE responseTimeout rules (section 11.9).nfc_auth.hAliro 1.0 expedited authentication APDU codecs.nfc_select.hnfc_step_up.hAliro 1.0 / ISO 18013-5 NFC step-up message and APDU codecs.tlv.hMinimal strict BER/DER-TLV reader for Aliro APDU payloads.advertising_core.hClean-room Aliro BLE advertising primitives. Kept as portable C so the byte-order rules can be tested on the host using the specification's published known-answer vectors.
woz_portmodules/woz_port/include2 modules⌄
woz_uwb/aliromodules/woz_uwb/src/aliro16 modules⌄
aliro_uwb_msg.csetup/notification message codec.aliro_uwb_session.cper-session lifecycle and state machine.aliro_uwb_adapter.creader-context lifecycle.aliro_uwb_msg_builder.cbig-endian TLV message builder.aliro_uwb_msg_parser.cTLV attribute parser and big-endian reads.aliro_uwb_msg.hmessage framing accessors, dispatch and builders.aliro_uwb_msg_builder.hbig-endian TLV message builder.aliro_uwb_msg_parser.hTLV attribute iteration and big-endian reads.aliro_uwb_msg_spec.hUWB ranging-service framing constants.aliro_uwb_adapter.hreader-device public interface.aliro_uwb_session.hper-session public interface.cherry.hCherry core (context + device-capabilities) interface.cherry_ccc.hCCC/Aliro-session interface (seam the adapter drives).aliro_uwb_internal.hprivate context types and shared helpers.cherry_session.hgeneric base-session interface.cherry_common.hdiagnostics config struct and report forward decl.
woz_uwb/facademodules/woz_uwb/src/facade11 modules⌄
woz_uwb_facade.cUWB facade: binds the CCC credential-based STS engine to the DW3000 radio, exposes Aliro DS-TWR responder start/stop and range query, and manages platform dependencies (HFCLK boost, SPI init, callbacks).flight_recorder.cNo module docstring. First commit: "flight-recorder: record/replay real UWB walk-ups".woz_alloc.hMemory allocation and timing facade: qmalloc, qcalloc, qfree wrap the platform heap; qrtc_get_us returns monotonic microseconds since boot.woz_util.hNo module docstring. First commit: "port: replace the Zephyr compat shims with a neutral woz_port.h contract".woz_uwb_facade.hPublic header for UWB facade: exposes Aliro DS-TWR responder lifecycle and range query; the CCC engine is bound and unbound via internal ursk and stop calls.flight_recorder.hNo module docstring. First commit: "flight-recorder: record/replay real UWB walk-ups".woz_bytes.hNo module docstring. First commit: "port: replace the Zephyr compat shims with a neutral woz_port.h contract".woz_diag.hDIAGK(): gate for verbose UWB bring-up diagnostics.trace.hStructured [WOZ_TRACE] emit helpers, gated on CONFIG_WOZ_E2E_TRACE.woz_logfmt.cPRETTY-gated high-res timestamp + compact colored log line.woz_logquiet.cPRETTY-gated runtime muting of benign upstream error spam. The stock Matter/BLE stack logs several non-fatal conditions at LOG_ERR/LOG_WRN (red/yellow): mDNS advertiser "incorrect state" churn, "Long dispatch time" perf notes, unsupported-attribute reads, the "No valid legacy adv to stop" BLE double-stop, and the empty-slot "Failed to get Access Document at index: 0" the access layer emits on first contact. All are expected on this bare DK bring-up and every one is proven benign by the healthy unlock that follows. A compile-time level cut can't remove just these: each noisy source shares its CONFIG_*_LOG_LEVEL with a source whose INFO lines drive the demo narrative (access_document shares CONFIG_DOOR_LOCK_APP_LOG_LEVEL with access_manager's "ACCESS GRANTED"/ranging lines; bt_adv shares CONFIG_BT_HCI_CORE_LOG_LEVEL), and a threshold below ERR still lets ERR through. So mute per-source at runtime. Reversible: compiled only under CONFIG_WOZ_PRETTY_SHELL (PRETTY=1). Drop PRETTY and every one of these lines returns for raw diagnosis. Needs CONFIG_LOG_RUNTIME_FILTERING=y (set in ports/nrf5340dk/overlays/woz-pretty.conf).
integrationintegration/homeassistant1 module⌄
portsports/esp3222 modules⌄
app_main.cppMatter application main: door lock endpoint setup, Matter lifecycle event handling, and (when CONFIG_ENABLE_ALIRO_BLE_UWB is set) startup/coexistence wiring for the Aliro BLE+UWB reader alongside the Matter BLE commissioning transport. Owns the Aliro reader background task (started once on commissioning-complete or at boot if already commissioned) and the Matter attribute/identify/device-event callbacks required by esp-matter's node/cluster framework.app_driver.cppBoard driver glue for the ESP32 Matter port: button input, WS2812 lock-status LED, and the Matter attribute-update hook wired into the app's driver layer.app_shell.cppESP32-IDF console shell for the Aliro Matter door lock app: registers status, range, aliro, lock/unlock, codes, factoryreset, and clear commands and runs the REPL.aliro_reader_delegate.cppAliroReaderDelegate: implements the Aliro reader-provisioning and BLE-UWB portions of the Matter DoorLock::Delegate interface, backing the controller-facing GetAliro*/SetAliroReaderConfig commands and persisting the provisioned reader identity via aliro_reader_provision_identity. Bridges Matter cluster commands to the underlying aliro_reader NVS-backed identity/trust store and to the BLE advertising layer (refreshed when the group resolving key changes).door_lock_callbacks.cppMatter DoorLock cluster plugin callbacks: wires the ESP32 port's BoltLockManager into the Matter DoorLock cluster's lock/unlock commands, user and credential storage, schedule storage, cluster init, and auto-relock notification hooks.door_lock_manager.cppBoltLockManager: Matter door lock cluster backing store for the ESP32 port. Implements the DoorLock cluster's user, credential, and weekday/yearday/holiday schedule get/set callbacks over fixed-size in-memory tables mirrored to NVM (ESP32Config blobs), plus lock/unlock actuation and PIN validation. Cluster indices are one-indexed by Matter and decremented internally before bounds-checking against this platform's fixed capacity limits.lock_led.cLock-state indicator LED: maps lock state (and Aliro activity) to an RGB colour for the single status pixel. Locked always extinguishes the indicator; unlocked shows blue during active UWB/Aliro engagement and a different colour otherwise, per lock_led_color.app_shell.cESP32-IDF console shell for the standalone Aliro UWB responder bench app: registers status, range, aliro-start/stop, provisioning, trust, and clear commands and runs the linenoise-based REPL.main.cWoz UWB ranging engine on ESP32-S3 (ESP-IDF) — minimal bring-up app. Binds a canned URSK and starts the CCC DS-TWR responder on the DW3000, then polls for a range. With no iPhone/initiator present this proves the SPI + DW3000 + CCC init path comes up on ESP32-S3; a live range needs a peer that drives the DS-TWR exchange (an Aliro Wallet, or a second board as initiator). The demo responder lifecycle + interactive console live in app_shell.c.dw3000_hw.cESP-IDF GPIO/IRQ backend for the DW3000 decadriver — implements dw3000_hw.h. Replaces the Zephyr deps/dw3000/platform/dw3000_hw.c (not compiled here). IRQ mirrors the Zephyr design: the GPIO ISR wakes a dedicated high-priority task (pinned to core 1) that calls dwt_isr() while the IRQ line stays high — dwt_isr does SPI, so it cannot run in true ISR context. Also provides the cycle-counter diag symbols that dwt_uwb_driver/dw3000/dw3000_device.c references (Xtensa CCOUNT via esp_cpu_get_cycle_count).dw3000_spi.cESP-IDF SPI backend for the DW3000 decadriver — implements dw3000_spi.h. Replaces the Zephyr deps/dw3000/platform/dw3000_spi.c (not compiled here). CS is a plain GPIO (spics_io_num = -1), matching the Zephyr cs-gpios model, so the wakeup path can hold CS low ~500us. Each DW3000 command is one CS-low full-duplex transfer: header + body assembled in a DMA-capable, word-aligned bounce buffer; on reads the body slice of the RX buffer is copied back.app_priv.happ_shell.haliro_reader_delegate.hDeclares AliroReaderDelegate, the Aliro (Apple Home Key) reader-provisioning and BLE-UWB half of the Matter DoorLock cluster delegate, bridging controller commands to the on-device reader identity, trust store, and BLE advertising state.door_lock_manager.hDoor lock manager for the Matter DoorLock cluster: owns bolt lock state plus the users, credentials, and weekday/yearday/holiday schedules backing the cluster's server attributes. Declares BoltLockManager (accessed via the BoltLockMgr() singleton) and the LockInitParams::LockParam/ParamBuilder types used to configure it from zap-derived capacity attributes at init time.lock_led.hLock status LED color mapping: derives the RGB color for the lock indicator from the current locked and Aliro-ranging state.app_shell.hboard_pins.hDW3000 (DWM3000EVB) wiring per ESP32 target, SPI2/FSPI. Source of truth for the wiring table in docs/esp32-bringup.md. Change to match how the DWM3000EVB is soldered to your board.aliro_ble.cNimBLE-backed BLE transport for the Aliro reader: GAP advertising, the Aliro GATT service, and an L2CAP connection-oriented channel (CoC) used to carry Aliro protocol messages. Supports two bring-up modes: a standalone NimBLE host (aliro_ble_start) and attachment to a host already owned and synced by another stack such as esp-matter (aliro_ble_prepare + aliro_ble_start_attached). Tracks CoC channels per connection handle in a fixed-size table and exposes send/receive plus reader-status notification helpers to the rest of the Aliro reader.aliro_prov_nvs.cNVS-backed persistence for Aliro reader provisioning: loads and stores the serialized reader identity and trust store built by aliro_prov.c. Lazily initializes NVS on first use; safe to call alongside aliro_ble's own nvs_flash_init.aliro_stepup_worker.cNo module docstring. First commit: "esp32: add the Aliro step-up (Access Document) phase".woz_wrap_stubs.cMinimal ESP-IDF port of the essential RX-callback shim. The Nordic build routes DW3000 RX events through uwb_rxdiag.c's __wrap_dwt_setcallbacks -> shim_rxok, which (after the blob's own prepoll_rx_rearm arms the SP3 POLL window) calls ccc_shim_rx_try_prepoll to decrypt+warm the NEXT block's STS. That bootstrap warm is what flips g_warm_valid true so the POLL window ever gets armed and Response_0 sent. This port omits uwb_rxdiag.c wholesale (its heartbeat needs Zephyr k_work, which the compat layer does not provide), so without this shim dwt_setcallbacks installs prepoll_rx_rearm directly, ccc_shim_rx_try_prepoll is never reached, g_warm_valid stays false, and the responder receives Pre-POLLs but never replies. Re-create only the essential chain here (no k_work, no diagnostics). Also keeps the dwt_configurestsmode pass-through the essential RX path needs.
releaserelease2 modules⌄
flash.shflash.sh — program the openaliro ESP32-S3 Matter lock (single merged image at offset 0x0) with esptool. See FLASH.md for wiring and first run. Usage: bash flash.sh [PORT] e.g. bash flash.sh /dev/ttyACM0flash.shflash.sh — program the openaliro nRF5340 DK firmware (both cores) over the DK's on-board J-Link, using nrfutil. See FLASH.md for setup and first run. Usage: bash flash.sh [JLINK_SERIAL_NUMBER]
scriptsscripts9 modules⌄
bootstrap.shbootstrap.sh — build a self-contained west workspace, PRISTINE from upstream. Fetches everything the build needs from public GitHub into ./workspace (git-ignored), then applies our integration patches on top. It never reads from any other local checkout — a clean upstream fetch every time. Fetches (all public): - Nordic add-on ncs-door-lock-and-access-control @ the pin below - NCS v3.3.0 + Zephyr + every module (via the add-on's own west manifest) Prereq (once per machine): nRF Connect SDK v3.3.0 toolchain nrfutil sdk-manager toolchain install --ncs-version v3.3.0 Usage: scripts/bootstrap.sh # workspace in ./workspace ALIRO_WS=/big/disk/ws scripts/bootstrap.sh # put the multi-GB workspace elsewherebuild.shbuild.sh {build|rebuild|flash|flash-erase|build-flash} — build the Aliro NFC+UWB image from the self-contained ./workspace. Run scripts/bootstrap.sh first. Layers our modules + ISC dw3000 onto the fetched add-on via out-of-tree overlays. Output → ./build (git-ignored). Incremental by default — a full from-scratch (pristine) build runs only when it has to: first build, changed build flags (UWB chip / self-test / config), or when you ask for one. A preflight first checks the workspace is bootstrapped. scripts/build.sh build # incremental where safe (fast) scripts/build.sh rebuild # force a clean pristine build PRISTINE=1 scripts/build.sh build # same as rebuild UWB_SELFTEST=1 scripts/build.sh build # one-shot boot self-test, no iPhone (diagnostic) PRETTY=1 scripts/build.sh build # curated/clean console (reversible; default verbose) ALIRO_SOURCE=1 scripts/build.sh build # clean-room source stack (discovery slice) UWB_CHIP=dw3720 scripts/build.sh build # select the plugged-in UWB chip (default: dw3000)docs-publish.shdocs-publish.sh — snapshot the rendered site/ onto the local gh-pages branch. The site is a build artifact and never lives on main; what gets published is a snapshot branch that holds site/'s contents at its root. This script only moves the LOCAL gh-pages ref — pushing it (git push origin gh-pages) stays a human step on purpose. Run it throughmake docs-publish, which rebuilds the site first so a stale or partial tree can never be snapshotted. Guards, in order: - site/index.html and site/.nojekyll must exist (the build completed); - docs/ must be clean: if the rebuild just changed the committed pages, they must be committed first, so every snapshot corresponds to a commit; - an existing gh-pages branch is reused only when it is one of our snapshots ("docs site …") — a real branch by that name is never eaten; - the snapshot must actually contain index.html and .nojekyll; - each snapshot chains to the previous one, so the push fast-forwards. Nothing here checks out a branch or touches the working tree: the snapshot is built through a throwaway index, so it is safe to run from any worktree, with any branch checked out, dirty or not.docs.shdocs.sh — build the documentation site into site/. Two generators write into the same output directory, in this order: 1. the subsystem tree + guides + search shell -> site/*.html 2. doxygen (docs/Doxyfile) -> site/api/ then a link pass rewrites cross-document links so the published site has no dead ends, and the freshness gate confirms the committed docs/ tree matches the source. Run it throughmake docs. Nothing here needs the NCS toolchain or hardware.flash_html.pyRender a release FLASH.md into a self-contained FLASH.html.test-runner.shPretty umbrella runner for every host-side suite: one banner, live per-check rows, a per-suite summary table, and suite timings. The suites themselves are unchanged — this only orchestrates and renders their existing output: firmware (C host) tests/host/run.sh the KAT suite + the lab python suite shared core (C host) ports/esp32/test/run.sh reader/stepup/crypto/... stages web twin scripts/twin-suite.sh constant-drift gate + WASM selftest Default: suites run in parallel, output replayed in order when done. SERIAL=1 streams them live, one at a time. SUITES="firmware shared" scopes. Exit is nonzero if any suite fails. Colour off when not a TTY or NO_COLOR.twin-suite.shThe web-twin suite for the umbrella runner (make check): the constant-drift gate (always) plus the WASM twin's node self-test against the committed web-twin/twin.js (when node is present). No rebuild here — regenerating twin.js needs a pinned emsdk and is CI's byte-diff staleness gate; this only proves the committed firmware artifact still passes its scenario.twin-wasm.shBuild the web twin's firmware: modules/woz_uwb + the tests/host shim compiled to WASM (Emscripten), driven by web-twin/twin_glue.c. Output is a single self-contained web-twin/twin.js (MODULARIZE + SINGLE_FILE: the .wasm rides embedded, so the page keeps working from file:// and the site copy stays a flat file pair). The compile is path-prefix-mapped for reproducibility: the same emsdk version must produce a byte-identical twin.js on any machine, which is what lets CI rebuild and diff it as a staleness gate.ws-seed.shws-seed.sh — give this git worktree its own NCS workspace, cheaply. Frequent branch-bouncing over a single shared workspace is a trap: the tree holds one patch state at a time (last bootstrap wins), so a build from the wrong worktree silently compiles another branch's patches. This seeds a per-worktree workspace at the default path ($TREE/workspace) so build.sh picks it up with no env var, and each worktree stays self-contained. Cheap because it uses an APFS copy-on-write clone (cp -c): the clone shares every block with the primary and costs ~0 extra disk until a patched file diverges. Cleanup is automatic — the workspace lives inside the worktree, so deleting the worktree deletes it (seemake ws-clean).
toolstools18 modules⌄
aliro_gait.pyAliro Gait: carry-motion features from Aliro Lab walk-up captures.aliro_lab.pyAliro Lab: score a captured reader serial log.aliro.luaNo module docstring. First commit: "Add Wireshark dissector for the clear-text Aliro BLE plane".docs_3d.pyRender the whole code surface as a flyable 3D graph: site/graph3d.html.docs_api.pyFill the reference pages the page generator leaves bare.docs_cmds.pyRender runnable command blocks as one copy chip per command.docs_flash.pyPublish the browser flasher: site/flash/ = the web-flasher/ page + firmware.docs_github.pyPoint the rendered site back at its GitHub repository.docs_graph.pyMake the architecture page's dependency graph legible.docs_links.pyRepair cross-document links in the rendered site, then assert none are left broken.docs_media.pyAdd the repo's imagery to the rendered site: demo screenshots and a share card.docs_nav.pyGive the rendered site one curated reading order.docs_start.pyGive the rendered site a real "Get started" landing.docs_theme.pyRetheme the rendered site: warm paper surfaces, serif display headings.docs_title.pyTitle the generated pages after the repository, not after the checkout directory.docs_twin.pyFold the interactive walk-up digital twin into the rendered site.flight_recorder.pyflight_recorder.py — carry a recorded UWB walk-up off the device and turn it into replayable / fuzzable artifacts.power_profile.pyPower profile: turn a gated-walk-up serial log (+ optional power capture) into the mA / unlock-latency / approach numbers of the RSSI-gate study.
web-twinweb-twin2 modules⌄
check_constants.pyNo module docstring. First commit: "web: add the walk-up digital twin as an interactive page".twin_glue.cWASM entry points: the twin page's firmware harness. Compiled (emcc) with the untouched modules/woz_uwb sources plus the same tests/host shim the host suite links, so the page runs the real responder: every block is a genuinely CCM*-encrypted Pre-POLL/POLL/Response/Final/ Final_Data exchange decoded by the firmware's own RX state machine, and the page reads its decisions through the same facade seam the lock uses. The peer (iPhone) side comes from tests/host/twin_frames.c — shared with test_twin.c, so the page and the suite drive the responder identically. The JS above supplies only the world: target distance, noise, spoof timing, and the pacing of the five per-block legs (PREPOLL/POLL/TXDONE/FINAL/FINAL_DATA) so a visitor can single-step a live DS-TWR round. Distance is injected the way physics does it: the initiator-side DS-TWR intervals ride in the Final_Data as round1 = reply1 + 2*tof and reply2 = round2 - 2*tof, which makes the firmware's own (round1*round2 - reply1*reply2)/sum recover exactly tof ticks (1 tick ~ 15.65 ps, ~4.692 mm — ccc_shim_rx.c final_data_decode). A Ghost-Peak spoof is a negative-tof block through the same full path.
woz_aliro_ecpmodules/woz_aliro_ecp/src1 module⌄
woz_uwb/cccmodules/woz_uwb/src/ccc17 modules⌄
ccc_shim_rx.cresponder-RX CCC STS substitution (ld --wrap=dwt_rxenable) programming the CCC STS on each RX-arm; target only.cherry_ccc_shim.ccherry_ccc_* seam (Aliro responder) implemented over the lock-native FiRa MAC; maps each call onto woz_uwb_facade.ccc_shim_wrap.cper-frame STS interception (ld --wrap=dwt_configurestsiv) substituting CCC STS for the FiRa MAC; target only.ccc_session.cAliro/CCC ranging seam implementation. See ccc_session.h.ccc_sts.cDW3000 STS register load for the CCC ranging path.ccc_mac.cUWB MAC: hopping sequence, SP0 frame codec, ranging schedule.ccc_shim.cCCC STS substitution core (implementation).ccc_crypto_mbedtls.cAES-ECB block via mbedTLS, backing the CCC key schedule on SoCs without a PSA provider (e.g. ESP32-S3).ccc_crypto_psa.cOn-target AES-ECB block (PSA/CC312) backing the CCC key schedule.ccc_kdf.cUWB key schedule + SP0 Pre-POLL frame codec.aliro_round_config.hone knob for the CCC ranging round's responder count.ccc_kdf.hUWB ranging key schedule + SP0 frame crypto (CONFIG_WOZ_ALIRO). Turns the 32-byte URSK into the per-ranging-cycle keys the DW3000 STS engine and the SP0 frames consume, over a single AES block-encrypt primitive.ccc_mac.hCCC UWB MAC layer: ranging-round scheduling, SP0 frame codec, DS-TWR.ccc_shim.hmap a per-frame STS index to the (dURSK, STS-V) pair the DW3000 STS engine loads.aliro_kdf.hUWB Ranging Secret Key (URSK) length.ccc_session.hAliro/CCC ranging seam: map an Aliro session's URSK + M1-M4 setup to ccc_ran_params.ccc_sts.hload a CCC ranging PPDU's STS key + IV into the DW3000 STS engine.
woz_uwb/drivermodules/woz_uwb/src/driver7 modules⌄
uwb_rxdiag.cDiagnostic RX/TX event tallies + ranging heartbeat.uwb_isr.cDW3000 interrupt-callback registration (implementation).uwb_min.cDW3110 bring-up driver (implementation).uwb_selftest.cKconfig-gated one-shot UWB init self-test (no iPhone).uwb_min.hMinimal DW3110 (DWM3000EVB) hardware bring-up driver.uwb_rxdiag.hRead-side accessors for the RX event tallies + log stream.uwb_isr.hDW3000 interrupt-callback registration (public surface).