# XGRIDS / LixelKity K1 plugin This directory is the package boundary for the first Mission Core device plugin. It now owns the canonical v1alpha2 manifest [`plugin.manifest.json`](plugin.manifest.json). The statically linked frontend contribution lives in [`frontend/`](frontend/) beside the manifest and profiles; its provisioning, acquisition/replay, diagnostics and metrics are separate plugin-owned components. The verified backend implementation is physically isolated in `src/k1link/device_plugins/xgrids_k1/`. The v1alpha2 catalog can describe one or more independently profiled models. This manifest currently exposes only `xgrids.lixelkity-k1`, and the transitional runtime still owns one active model/session at a time. Concurrent model/session routing remains a later supervisor milestone. The plugin owns: - the exact firmware/topology compatibility profiles under [`profiles/`](profiles/), with strict evidence flags and a fail-closed loader; - BLE discovery hints and K1 GATT metadata; - the reviewed firmware-3 Wi-Fi provisioning profile; - K1 LAN status and private-address validation; - subscribe-only data MQTT transport plus a separately bounded canonical application-control transport; - native `.k1mqtt` capture; - firmware-scoped protobuf/LZ4 and legacy codecs; - normalization of K1 point cloud and pose, plus raw-only preservation of the still-undecoded status and heartbeat channels; - exact-profile left/right RTSP producer selection, H.264 copy-remux preview and the handoff of acquisition-owned init/fMP4/index evidence to the host archive; - K1-specific operator instructions and compatibility tests. - the scoped React `device.connection` contribution and its BLE/Wi-Fi and acquisition pipeline UI. - the interactive canonical application-control session: one socket owner, separate workspace/project/START/STOP UI checkpoints, live status gates, single-action physical permits and no automatic retry. The plugin does not own: - Mission Core navigation, fleet, missions, users, roles, or audit; - the generic spatial scene or Rerun Web Viewer; - the host observation catalog, RRD preparation/cache, recorded-camera player, workspace layout, platform storage, remote transport, or other devices. The `k1link` distribution and CLI names remain compatibility names. All device-specific implementation behind them is plugin-owned, and every change must preserve replay and real-device acceptance. Mission Core imports this plugin only from `apps/control-station/src/composition/devicePlugins.ts`. The generic shell never branches on this plugin ID or reads `k1_ip`, BLE candidates, MQTT topics, or other vendor state. The frontend contribution imports the host only through `@mission-core/plugin-sdk`; its CSS is scoped below `.xgrids-k1-plugin`. Backend startup loads the reviewed factory declared by `backendEntrypoint`, then cross-checks the runtime-owned plugin ID, version, supported host API and exact action set against this manifest. The runtime must complete the versioned control-plane handshake and report `ready` before any action is admitted. Actions enter through the host dispatcher and the transitional facade `src/k1link/device_plugins/xgrids_k1/facade.py`. The old flat routes live in the plugin's legacy router; both paths now cross the same runtime transport and delegate to the proven `XgridsK1CompatibilityService` methods. Synchronous capture/runtime operations run outside the FastAPI event loop. Model switching calls the plugin deactivation hook. It is rejected while the canonical K1 control socket is open, so navigation can never become an implicit device STOP. Operator-manual acquisition uses semantic `acquisition.stop` in `capture-only` mode; replay and pre-v1alpha2 sessions retain the legacy `stream.stop` shim. BLE, MQTT, codec, archive discovery and RRD export modules now live under the plugin package after replay parity and physical K1 regression. The current transport remains in-process and its health is lifecycle-only; process isolation, crash/restart containment and signed deployment remain later supervisor gates. The compatibility profile is descriptive and cannot itself authorize a vendor write. The current runtime cannot inspect K1 firmware: it keeps the profile inactive until the operator explicitly attests firmware `3.0.2` and direct-LAN topology, and records that basis as `operator-attested` rather than device-derived evidence. Validate the current exact-match profile without device I/O with: ```bash uv run python plugins/xgrids-k1/profile_loader.py ``` Plugin v0.5.0 installs that reviewed transport behind explicit plugin actions. Opening control performs only the connection-owned operations 1–6. Workspace entry releases operation 7; saving the project and preparing local reception releases operations 8–10; a separate START click carries the project name and then waits for bound `SCANNING + project + init_ready` before operations 13–14. STOP is separately permitted, never retried, and keeps the same socket until K1 reports unbound READY and the operator confirms a steady green indicator. The admin CLI still provisions the fixed Keychain item through Apple's hidden prompt without accepting the private value as an argument. No physical command is emitted merely by loading the plugin, opening the page, navigating, polling state or running repository tests. Full v0.5.0 physical acceptance remains an operator-run gate. The optional owner-controlled iPhone/LixelGO observation tool lives under [`lab/iphone-capture/`](lab/iphone-capture/). It pins `pymobiledevice3` in a separate `uv` environment, writes only ignored evidence sessions, and remains a lab subprocess rather than a plugin/runtime dependency. The first capture is gated by ADR 0004 and ADR 0005.