98 lines
5.2 KiB
Markdown
98 lines
5.2 KiB
Markdown
# 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 MQTT transport and report-topic allowlist;
|
||
- 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 dormant application-control facade boundary: explicit shadow arm/disarm,
|
||
a 15–300 second Keychain-backed in-memory authority lease, and redacted state.
|
||
|
||
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. An active acquisition uses
|
||
semantic `acquisition.stop` in `capture-only` mode; replay and pre-v1alpha2
|
||
sessions retain the legacy `stream.stop` shim. Neither path claims that the
|
||
physical K1 stopped without separate operator evidence. 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.4.0 does not widen device authority. Its application-control
|
||
coordinator has no request-emission method, no live MQTT sink and no UI control;
|
||
`vendor_writes_enabled` remains false. A separate uninstalled acceptance-only
|
||
transport now implements exact subscriptions, QoS2 completion, response
|
||
barriers and no-retry poisoning. The admin CLI can provision the fixed Keychain
|
||
item through Apple's hidden prompt without accepting the value as an argument.
|
||
Neither path is imported by the facade; Keychain provisioning and a controlled
|
||
physical START/STOP acceptance are still required.
|
||
|
||
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.
|