274 lines
15 KiB
Markdown
274 lines
15 KiB
Markdown
# NODEDC MISSION CORE
|
|
|
|
NODEDC MISSION CORE is the vendor-neutral control, observation, mission-planning,
|
|
recording, and integration platform for NODEDC autonomous systems. This
|
|
repository is the canonical early-stage monorepo: it contains the Mission Core
|
|
Control Station, the current local control plane, shared contracts as they are
|
|
extracted, and device plugins.
|
|
|
|
The first proven hardware vertical is the XGRIDS/LixelKity K1 plugin. On firmware
|
|
3.0.2 the host provisions the scanner onto an existing LAN without LixelGO,
|
|
connects to its MQTT broker, persists each raw frame before preview work, decodes
|
|
point cloud and pose, and renders the real cloud plus trajectory through an
|
|
embedded self-hosted Rerun Web Viewer. Native MQTT persistence uses bounded
|
|
group commit (at most 0.5 seconds, 4 MiB or 32 messages), and camera archives
|
|
commit complete fMP4 segments before their index rows. These are explicit
|
|
crash-RPO bounds, not a zero-loss or disk-replication claim. The former
|
|
Foxglove bridge remains only as a legacy regression module.
|
|
|
|
The backend vendor implementation is physically isolated below
|
|
`src/k1link/device_plugins/xgrids_k1/`; its reviewed manifest and compatibility
|
|
profile remain below `plugins/xgrids-k1/`. Mission Core host code discovers
|
|
archive sources, recovery hooks and recording exporters only through the plugin
|
|
runtime contribution. The verified wire protocol and raw evidence format are
|
|
unchanged.
|
|
|
|
Plugin SDK v0alpha2 now provides executable, vendor-neutral identity, session,
|
|
operation, runtime-action, stream, evidence and compatibility contracts. Every
|
|
backend action crosses immutable SDK `RuntimeActionInvocation` and
|
|
`RuntimeActionResult` validation in the actual dispatcher hot path. The meanings
|
|
remain a local experimental vocabulary rather than a mutation of NODE.DC
|
|
Platform Ontology. The device process is still transitional and in process: it
|
|
uses an explicitly injected K1 normalizer to produce transport-neutral local
|
|
consumer views; portable SDK stream envelopes, process isolation, durable
|
|
operations, multi-device routing and the remote Edge split remain later gates.
|
|
|
|
The current runtime cannot read K1 firmware automatically. It keeps the exact
|
|
profile inactive until the operator explicitly attests firmware `3.0.2` and
|
|
direct-LAN topology; state records that basis as `operator-attested`, not as
|
|
device-derived evidence.
|
|
|
|
The repository now contains one narrowly gated state-changing command:
|
|
`ble wifi-configure`. It accepts only the reviewed firmware-3 provisioning
|
|
profile and requires explicit `--confirm-write`; the Wi-Fi password is collected
|
|
through a hidden local macOS dialog. MQTT capture and decoding are read-only.
|
|
Nothing changes router settings, firmware or global Python packages.
|
|
|
|
## Verified XGRIDS K1 stand
|
|
|
|
- one XGRIDS/LixelKity K1;
|
|
- one Apple Silicon MacBook running macOS;
|
|
- one ordinary TP-Link Deco/mesh network used by other devices;
|
|
- the proven baseline used no LixelGO, phone, Linux host, dedicated AP,
|
|
OpenWrt, or vendor SDK.
|
|
|
|
An owner-controlled iPhone with LixelGO is now available for a separate,
|
|
evidence-only observation stage. It does not invalidate the no-phone baseline
|
|
and is not a runtime dependency. The decision and gated runbook are
|
|
[`ADR 0005`](docs/adr/0005-owner-controlled-lixelgo-iphone-observation.md) and
|
|
[`docs/08_LIXELGO_IPHONE_OBSERVATION.md`](docs/08_LIXELGO_IPHONE_OBSERVATION.md).
|
|
The Mac capture environment is isolated under
|
|
`plugins/xgrids-k1/lab/iphone-capture/` and does not require full Xcode.
|
|
|
|
The ordinary router is sufficient for the first gates. We first observe the
|
|
existing LAN without changing it. A Guest/IoT SSID is optional and may be
|
|
counterproductive if Deco isolates clients; Mac and K1 must ultimately be able
|
|
to reach each other.
|
|
|
|
## What is actually being proved
|
|
|
|
The project has three independent gates:
|
|
|
|
1. K1 is operational and can record a project autonomously.
|
|
2. Mac can discover and inspect the K1 BLE/GATT surface safely.
|
|
3. Without LixelGO, K1 can be associated with Wi-Fi and a proprietary data
|
|
session can be opened.
|
|
|
|
All three gates are now proven on the tested unit. The spatial stream is plain
|
|
MQTT 3.1.1 on TCP 1883. Firmware-3 `lio_pcl` is protobuf wrapped in a raw LZ4
|
|
block, and `lio_pose` is an uncompressed protobuf. Owner-operated LixelGO capture
|
|
also proved separate left/right RTSP/H.264 camera previews on TCP 8554. This is a
|
|
compressed preview contract, not proof of full-resolution raw camera access.
|
|
|
|
## Local environment
|
|
|
|
The project uses Python 3.12 in a repository-local `.venv` managed by `uv`.
|
|
This does not install Python packages globally and does not modify neighboring
|
|
repositories.
|
|
|
|
```bash
|
|
cd /Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE
|
|
uv sync --frozen --group dev
|
|
uv run k1link doctor
|
|
uv run pytest
|
|
```
|
|
|
|
## Mission Core Control Station and visualization adapters
|
|
|
|
The browser application is the universal Mission Core Control Station rather than
|
|
a K1-specific Foxglove launcher. Its fixed shell contains six architectural
|
|
sections — Center, Fleet, Observation, Missions, Data and System — while the K1
|
|
BLE/Wi-Fi/live workflow remains isolated as the first real device adapter. Its
|
|
React provisioning, acquisition/replay and diagnostic blocks live beside the
|
|
plugin manifest under `plugins/xgrids-k1/frontend`; the generic application
|
|
mounts them through one reviewed composition import.
|
|
|
|
Install, type-check, build and serve the complete local application from the
|
|
repository root:
|
|
|
|
```bash
|
|
uv sync --frozen --group dev
|
|
cd apps/control-station
|
|
npm ci
|
|
npm run test:unit
|
|
npm run typecheck
|
|
npm run build
|
|
cd ../..
|
|
uv run k1link serve
|
|
```
|
|
|
|
Open `http://127.0.0.1:8000`. The static application, REST/WebSocket control
|
|
plane and credential endpoint bind to loopback only. The current K1 adapter
|
|
still provides real CoreBluetooth discovery, one operator-triggered reviewed
|
|
BLE Wi-Fi provisioning write, read-only MQTT live capture, native `.k1mqtt` and
|
|
reviewed-TSV replay, raw-first evidence storage and measured preview metrics.
|
|
Physical K1 scanning is still started and stopped by the verified double-click;
|
|
the connector publishes no modeling command. The observed LixelGO action mapping
|
|
remains descriptive and write-disabled.
|
|
|
|
This locked bootstrap is repeatable in the current workspace, not yet a
|
|
standalone release install. The frontend consumes sibling `file:` packages from
|
|
`NODEDC_DESIGN_GUIDELINE`; `package-lock.json` does not pin that checkout's Git
|
|
revision or content hash. Publishing/vendoring those packages or enforcing an
|
|
immutable donor revision remains a packaging and CI prerequisite.
|
|
|
|
The Observation spatial workspace embeds the open-source Rerun Web Viewer
|
|
inside the Mission Core shell. It can open a compatible RRD over same-origin
|
|
HTTP or a Rerun gRPC/proxy source such as
|
|
`rerun+http://127.0.0.1:9876/proxy`; no external hosted viewer UI is used.
|
|
Dynamic point-cloud/camera composition and the live source contract are fixed in
|
|
[`ADR 0006`](docs/adr/0006-vendor-neutral-observation-sources-and-live-only-timeline.md).
|
|
The durable session catalog, recorded `session_time` scrubber and versioned
|
|
workspace-layout profile are fixed in
|
|
[`ADR 0008`](docs/adr/0008-durable-observation-sessions-and-workspace-layout.md).
|
|
|
|
The first K1 live session or adapter file-replay (`.k1mqtt`/reviewed TSV) in a
|
|
`k1link serve` process creates one local Rerun `RecordingStream`, starts its
|
|
gRPC/proxy server on TCP 9876 and publishes the resulting URL through
|
|
control-plane state. Later live/file-replay sessions reset their session-local
|
|
scene and metrics and reuse that process-wide stream. Saved observation sessions
|
|
do not reuse this listener: they open a private digest-bound RRD generation over
|
|
same-origin HTTP through Rerun's native incremental receiver. Unless an operator
|
|
has entered a manual source, the React application assigns the applicable source
|
|
to the embedded viewer. The complete live runtime path is K1 MQTT → raw-first
|
|
evidence capture → bounded latest-wins preview queue → explicitly injected K1
|
|
protobuf/LZ4 normalizer → transport-neutral decoded local views → Rerun
|
|
`Points3D`, `Transform3D` and `LineStrips3D` → embedded Web Viewer. Rerun does
|
|
not inspect K1 topics or raw payloads. These local decoded views are not yet the
|
|
portable Plugin SDK wire envelopes.
|
|
|
|
The default Rerun blueprint shows a 12-second sliding accumulation of real point
|
|
frames. Product controls are connected for point size, intensity/height/distance
|
|
or available RGB coloring, Turbo/Viridis/Plasma/grayscale/custom palettes,
|
|
point and trajectory visibility, and the scene grid. The first disk action saves
|
|
and restores the versioned spatial layout without mutating sensor evidence.
|
|
Saved native point/pose sessions are materialized losslessly into private,
|
|
digest-bound RRD recordings and can be played, paused and scrubbed on a
|
|
zero-based `session_time` timeline. No synthetic point cloud, trajectory,
|
|
camera frame or latency value is generated.
|
|
|
|
A powered-device checkpoint passed 80 real MQTT messages through the current
|
|
Rerun runtime: 38 point-cloud frames, 42 pose frames, 2,775 points in the last
|
|
cloud and zero decode errors. The later RTSP camera preview is available through
|
|
the generic floating observation windows and new acquisitions archive its fMP4
|
|
segments independently of browser delivery. Historical sessions recorded before
|
|
that archive contract contain no video. Rerun `capture_time` and the camera
|
|
index use Mac receive/arrival timestamps, not proven K1 sensor timestamps or a
|
|
photon-to-screen measurement.
|
|
|
|
The old Foxglove implementation is retained only in
|
|
`src/k1link/device_plugins/xgrids_k1/viewer/foxglove_bridge.py` and its regression tests. The current
|
|
live/replay runtime does not start it or use TCP 8765. The
|
|
[live viewer runbook](docs/06_K1_LIVE_VIEWER.md) records the active Rerun path and
|
|
its timing/security boundaries; the frontend contract is documented in
|
|
[`apps/control-station/README.md`](apps/control-station/README.md).
|
|
The host storage layout, recovery rules, replay API and operator path are in
|
|
[`docs/09_OBSERVATION_SESSIONS.md`](docs/09_OBSERVATION_SESSIONS.md).
|
|
|
|
The FastAPI application and credential endpoint bind to loopback, but the Rerun
|
|
gRPC server currently binds TCP 9876 on all network interfaces even though its
|
|
reported source URL contains `127.0.0.1`. It has no connector-level
|
|
authentication or TLS. Use it only on a trusted laboratory LAN, do not expose
|
|
9876 to the public Internet or a cellular WAN, and add an authenticated secure
|
|
proxy before any remote deployment. Stopping acquisition keeps the local scene
|
|
server and its URL available for the next session. Stop `k1link serve` to close
|
|
the listener and release its retained memory.
|
|
|
|
`doctor` is intentionally non-invasive. It checks the local Python environment
|
|
and reports external tools; it does not request Bluetooth permission, scan the
|
|
LAN, touch the K1, alter Homebrew, or change capture permissions.
|
|
|
|
The implemented laboratory commands include:
|
|
|
|
```bash
|
|
uv run k1link ble scan --duration 30 --out sessions/<id>/captures/ble.json
|
|
uv run k1link ble gatt-dump --device <corebluetooth-uuid> \
|
|
--out sessions/<id>/captures/gatt.json
|
|
uv run k1link ble wifi-configure --device <corebluetooth-uuid> \
|
|
--profile xgrids-k1-fw3-wifi-v1 --write-mode with_response \
|
|
--confirm-write --out sessions/<id>/captures/wifi.sensitive.json
|
|
uv run k1link net snapshot --out sessions/<id>/captures/network.json
|
|
uv run k1link net mqtt-capture --host <confirmed-private-k1-ip> \
|
|
--confirm-owned-device --duration 180 \
|
|
--out sessions/<id>/captures/mqtt-run
|
|
uv run k1link analyze mqtt-streams \
|
|
--capture sessions/<id>/captures/mqtt-run/mqtt.raw.k1mqtt \
|
|
--out sessions/<id>/analysis/mqtt-streams.summary.json
|
|
```
|
|
|
|
On macOS the BLE scan is active CoreBluetooth discovery, but it does not connect
|
|
to or modify devices. `gatt-dump` connects and performs service discovery only.
|
|
`mqtt-capture` accepts only a literal RFC1918 target, uses a fixed report-topic
|
|
allowlist, never publishes and never reconnects. It writes a length-framed raw
|
|
file, JSONL metadata and an integrity summary with mode `0600`.
|
|
|
|
Session output is sensitive and ignored by Git. It can contain device identity,
|
|
trajectory, mapped interiors and local addressing even when no credentials are
|
|
present.
|
|
|
|
## Documentation
|
|
|
|
- [Technical audit](docs/00_TECHNICAL_AUDIT.md)
|
|
- [Implementation gates](docs/01_IMPLEMENTATION_PLAN.md)
|
|
- [First lab runbook](docs/02_FIRST_LAB_RUNBOOK.md)
|
|
- [Artifact and secret policy](docs/03_ARTIFACT_POLICY.md)
|
|
- [Reviewed BLE Wi-Fi profile](docs/04_K1_WIFI_PROVISIONING_PROFILE.md)
|
|
- [Verified MQTT stream profile](docs/05_K1_MQTT_STREAM_PROFILE.md)
|
|
- [Live console and embedded Rerun runbook](docs/06_K1_LIVE_VIEWER.md)
|
|
- [Mission Core monorepo and plugin boundary](docs/07_MISSION_CORE_MONOREPO.md)
|
|
- [Owner-controlled LixelGO/iPhone observation](docs/08_LIXELGO_IPHONE_OBSERVATION.md)
|
|
- [Observation sessions, playback and workspace layout](docs/09_OBSERVATION_SESSIONS.md)
|
|
- [Monorepo architecture decision](docs/adr/0002-mission-core-monorepo.md)
|
|
- [Device plugin UI and runtime boundary](docs/adr/0003-device-plugin-ui-and-runtime-boundary.md)
|
|
- [Plugin SDK v0alpha2 and experimental device lifecycle](docs/adr/0004-plugin-sdk-v0alpha2-and-experimental-device-lifecycle.md)
|
|
- [Owner-controlled LixelGO observation decision](docs/adr/0005-owner-controlled-lixelgo-iphone-observation.md)
|
|
- [Vendor-neutral live observation sources](docs/adr/0006-vendor-neutral-observation-sources-and-live-only-timeline.md)
|
|
- [K1 camera preview copy-remux gateway](docs/adr/0007-k1-camera-preview-copy-remux-gateway.md)
|
|
- [Durable observation sessions and workspace layout](docs/adr/0008-durable-observation-sessions-and-workspace-layout.md)
|
|
- [Redacted live lab report](docs/lab/001_K1_LIVE_MQTT_20260715.redacted.md)
|
|
- [Session manifest schema](schemas/session-manifest.schema.json)
|
|
- [Reference input provenance](docs/reference/README.md)
|
|
|
|
The two supplied source documents are retained unchanged under
|
|
`docs/reference/`. Corrections and decisions are recorded separately so their
|
|
provenance remains clear.
|
|
|
|
## Safety boundary
|
|
|
|
Allowed initial work is non-mutating discovery, standard device-information reads,
|
|
controlled notification listening, autonomous button operation, targeted
|
|
capture of traffic to or from the confirmed K1 address, and offline analysis of
|
|
owned artifacts.
|
|
|
|
The reviewed provisioning write requires its named profile and explicit operator
|
|
confirmation. Application command publishing remains disabled: physical
|
|
double-click is the verified start/stop mechanism. Any future MQTT publisher,
|
|
router configuration change or new BLE write requires its own evidence and
|
|
reviewed step. Random writes, fuzzing, brute force, firmware operations,
|
|
destructive file access and credential guessing remain out of scope.
|
|
|
|
Real captures, projects, router metadata, serials, credentials, maps, images,
|
|
and logs under `.runtime/`, canonical evidence roots and legacy `sessions/` are
|
|
ignored by normal Git. Redacted manifests and SHA-256 inventories are committed;
|
|
encrypted/replicated artifact storage remains a deployment decision.
|