Data layer
Source of truth:
docs/research/platform-and-architecture/marine-data-layer/and the marine-data-layer ADRs.
Overview
The data layer sits between raw NMEA sentences from hardware and the application tier. It has four responsibilities:
- Ingest — parse NMEA 2000 and NMEA 0183 frames from USB/serial dongles into a typed internal message format.
- Bus — fan out messages to registered subscribers with capability checks.
- Sync — replicate a subset of the bus to Supabase Realtime so cloud services and the web UI stay current.
- Security boundary — enforce mTLS between every process and the bus, including in-vessel over LAN.
NMEA ingest
The on-boat agent reads frames from a CAN/serial dongle and emits typed
BusMessage structs. No SignalK adapter, no external dependencies — the
platform speaks its own internal bus format directly.
NMEA 2000 (CAN) ──► Go ingest agent ──► BusMessage ──► Bus
NMEA 0183 (serial) ──► Go ingest agent ──► ↑
BLE and WiFi gateway devices arrive via the same agent after a hardware translation step.
Plugin sandbox (ADR-002)
Plugins run in WASM with capability-scoped imports. The host hands each plugin only the handles it declared at install time:
read_path— subscribe to specific bus paths (e.g.navigation/position)write_path— publish to specific bus pathsnetwork_get— outbound HTTP to declared hostnames only
A plugin physically cannot open arbitrary sockets, read host filesystem paths, or inspect bus paths it did not declare. This is enforced at the WASM module level, not by configuration.
mTLS posture (ADR-003)
Every connection to the bus — local or remote — presents a client certificate
issued by the on-boat PKI (apps/svc-pki). This includes:
- Cloud services polling the sync bridge
- Web UI sessions over the local LAN
- Plugin workers inside the OS
The hardware CAN bus is plaintext (hardware-defined — unfixable in software). Everything above it is encrypted and authenticated.
Supabase sync bridge
A lightweight bridge process subscribes to a whitelist of bus paths and upserts rows into Supabase tables via the service-role key. The cloud web UI reads these tables via SSR. Realtime subscriptions (kanban, instrument panels) use the Supabase Realtime channel directly from the browser.
Bus ──► sync-bridge ──► Supabase Postgres ──► SSR pages
└──► Realtime ──► browser
Further reading
docs/research/platform-and-architecture/marine-data-layer/design-2026.mddocs/research/platform-and-architecture/marine-data-layer/adrs/— ten ADRs- Architecture overview