Files
NODEDC_MISSION_CORE/docs/audits/2026-09-07-k1-plugin-boundary-r1.md
T

8.4 KiB

K1 plugin boundary R1 — implementation

Scope: the first independently verifiable increment of the approved plugin refactor. This report does not declare the whole architecture migration or the physical Bridge incident resolved.

Result

The shared sensor workspace no longer imports K1, selects K1-specific controls, or owns K1 control-operation deadlines. K1 detail, live settings, live renderer and Bridge enrollment are under plugins/xgrids-k1/frontend/src/sensors. Control Station receives their optional contributions from the installed DeviceUiPlugin registry; Node composes the same integration explicitly. Both hosts resolve @mission-core/sensor-sdk to the same portable host surface. Missing and ambiguous renderers fail closed; absence does not substitute the camera detail controls for an unsupported device. Existing camera behavior is retained through the host's default camera detail.

Four functions were mechanically extracted from facade.py into connection_attempt.py. Their ASTs match the pre-change working-tree copy exactly, including runtime/target/parent/lease/host-epoch proof checks. The facade is now 35,549 lines; this is a first responsibility boundary, not a claim that the remaining service is small or process-isolated.

Node now exports the existing connection attempt, snapshot revision, runtime start time and current permitted enrollment actions. The compact projection does not forward diagnostics, timeline payloads or exception text. After an invocation error the driver may read the exact journaled operation once; it never resends the physical command. Explicit host admission rejection is distinguished from an unknown post-dispatch outcome. Secrets are removed from input references even on pre-dispatch rejection; this does not claim secure erasure of immutable language/runtime copies.

The enrollment observer distinguishes delivery completion from network and control completion. It sends one POST, resolves lost responses by the same operation ID, follows the exact owned bootstrap, ignores older snapshots, stops observing across a runtime replacement, and stops client observation on window closure without cancelling/replaying physical commands. Read-only observation has a bounded budget beyond the existing delivery deadline; it does not extend command admission. Polling in the open window keeps host availability and backend authority visible. A changed runtime/discovery/mode invalidates the selected device and credential draft.

Validation

  • All 629 cases in the existing acquisition lifecycle suite passed after the extraction, including the existing recovery and physical-authority checks.
  • The final Python read-model, Node bridge and Fleet enrollment set passed: 22 cases, covering projection privacy, exact operation correlation, no-resubmit behavior, secret lifetime and pre-dispatch rejection.
  • The full frontend unit suite passed: 784 tests. After the final observer and presentation changes, 41 focused enrollment/boundary/architecture tests passed, including two additional cases for current authority and delayed results during an observed board outage.
  • The architecture test passed. Control Station and Node TypeScript checks and production builds passed. Jobs were run without a second backend or Docker startup. The Node dependency install used the local npm cache with scripts disabled. Full frontend tests emitted existing sandbox HMR/listener warnings; the unit tests do not establish browser or hardware acceptance.
  • Ruff and git diff --check passed. The four extracted functions retain equal ASTs after formatting. Existing dirty working-tree changes were preserved.

The canonical LaunchAgent was restarted only after /api/state showed idle capture/control and no accepted/running operation. The configured persistent data directory remained outside the checkout. The replacement serves 127.0.0.1:8000, reports liveness alive, runtime snapshot-runtime-fefcc6209249e845738886a72813e13c, and idle source state. No Mission Core backend was found listening on 8765.

Limits and next acceptance gate

No physical K1 command or new capture was issued in this increment. Browser hardware acceptance remains pending the owner's required cache clearing; the available browser tools do not expose that operation. A new tab or reload was not counted as a cleared-cache test. The Node UI is built locally, but this increment was not installed on the Ubuntu mini-PC.

The BLE packet format, provisioning dispatch/polling behavior, acquisition command order, camera producer and Rerun profile settings were not modified. In particular, this work does not prove resolution of the earlier ATT failure or the separately identified early network-status polling risk.

Backend optional installation, dependency separation, isolated macOS runtime, portable media IPC, archive-codec separation and full Node reboot acceptance remain subsequent stages. Multiple simultaneous device sessions and a multi-provider enrollment picker are not supplied by this increment.

Before the next deeper lifecycle extraction, accept one cleared-cache UI Bridge connection and its exact operation stages on the prepared Mac; keep network/control unknown states honest and compare recovery against the prior Ops scenarios. Ubuntu Bridge requires its own physical acceptance before any claim of platform parity. LAB/recorded/live Rerun profiles remain separate acceptance dimensions.

References: architecture audit, Ops inventory, changed source hashes.

The implementation and open hardware checks were added to Ops card #3, “Mission Core. Lixel K1 / XGRIDS Integration”, as 12 titled R1 blocks. The 17 existing blocks and historical card status were preserved.

Owner's fresh Chrome test after R1

The owner reported clearing Chrome's cache, scanning, selecting K1 and submitting the network form. The canonical service journal records discovery completing in 12.395 seconds and the network attempt running from 2026-09-06 21:16:38.081 UTC to 21:16:49.307 UTC (11.226 seconds). It failed at gatt-write, after one dispatched 99-byte write-with-response, with BleakGATTProtocolError, ATT 4 (INVALID_PDU). Advertised characteristic properties were read/write; the reported command capacity was 253 bytes. The write was not confirmed. Neither post-write status polling nor MQTT bootstrap was reached. This failure does not implicate the separate early status-poll termination risk, camera path or Rerun profiles.

The selected FW 3.0.2 profile classifies this reply as k1-wifi-network-not-found, based on the previously reviewed firmware callback. This attempt itself did not obtain live DeviceInfo and cannot establish the actual firmware or exact cause of network invisibility. The submitted network name is deliberately not retained in the server journal. The exact SSID was requested from the owner; no password was requested or retained. No spelling error or radio incompatibility is assumed.

Source review confirmed that the form captures the password before clearing React state, and the station path passes it to the existing frame encoder. The existing LAB form trims SSID edges; whether that affects this attempt is unknown. No provisioning behavior was changed on this evidence. The focused Wi-Fi provisioning and firmware failure suites passed (43 tests); hardware acceptance remains failed/pending diagnosis.

Sanitized operation events, UTC and monotonic observation timestamps, owner test notes and an artifact hash are retained outside Git in the ignored .runtime/k1-connect-incident-20260906/fresh-2116/ directory. The agent issued only local state/liveness reads, with no new device command or service restart. Core 8000 remained alive. A fresh Ops card read timed out; this addendum has not yet been copied to Ops.

Subsequent successful connection and refusal guidance

The owner subsequently confirmed a mistyped network name and a successful connection after correcting it. Core independently reports network applied and DeviceInfo/control ready in 8.298 seconds on 2026-09-07. The previous failure is explained for this incident; its historical outcome is not rewritten. The UI now names Wi-Fi failure prominently and asks to check the network name and password. See the bounded correction and evidence. This accepts that connection attempt, not stream, reboot, Ubuntu or fresh-cache visual acceptance of the subsequent wording change.