Connector runtime
The two-way connector runtime behind every data source — inbound ingest modes, how data reaches tables and the live picture, and the outbound actions that let a governed write or command go back out.
Scrydon's connector runtime is one service that runs every data source's inbound acquisition (poll, push, stream, and a MAVLink telemetry link) and, where an organization has opted in, a source's declared outbound actions back toward the same provider or vehicle. It composes existing kernels — the poll scheduler, stream supervision, the push runtime, the durable ingest buffer, and (for MAVLink) a held UDP link — and adds nothing on top of them that duplicates what they already do.
This page is the map for two audiences: an operator deciding what to enable and how to read what happened, and an extension author deciding which ingest mode and which declared actions a data source should carry. For the field-level authoring reference, see Ingest modes and Data Sources.
Inbound: how data reaches a table
Every data source declares exactly one ingest.mode. Four of them run continuously on the connector runtime:
| Mode | What drives the fetch | Transport |
|---|---|---|
poll | the runtime's scheduler, on the source's intervalSec, or on Sync now | HTTP request/response |
push | the provider delivers to a per-installation endpoint | an authenticated, queued HTTP delivery |
stream (websocket) | a governed socket the runtime holds open | a long-lived WebSocket subscription |
stream (udp, protocol: 'mavlink') | a MAVLink link to one radio or vehicle | UDP, MAVLink v2 telemetry, signed or unsigned |
manual, on-demand and query sources are not continuous. A person triggers a manual upload or an on-demand fetch: the runtime parses and maps that one run and returns its rows, and the platform commits them. A query source does not run on the connector runtime at all; it reads a remote database through its governed connection and owns no managed table.
A MAVLink link is a stream source with transport: 'udp'. The runtime binds one UDP socket, sends outward to the peer to open the return path through NAT, and decodes HEARTBEAT, SYS_STATUS, SYSTEM_TIME and GLOBAL_POSITION_INT into a vehicle telemetry table — receive only, unless the source also declares an outbound action (below) and the link is signed: an unsigned link never sends a command. A link is signed (signing: 'signed-required') with the connection's linkKey credential, or left unsigned-allowed; a replayed or unsigned frame on a signed link is refused and never becomes a row. See A MAVLink link over UDP for the full manifest and the operator's private-network declaration it depends on.
Live positions and the committed record
The rows the table and the ontology read are committed about once a minute per source (STREAM_COMMIT_INTERVAL_MS), or sooner when a batch fills one commit. That commit is the record: it is what a governed read of the table sees and what an operator's "last sync" reflects. Before it, a WebSocket stream appends its frames to the durable ingest buffer within 250 ms of arrival (STREAM_BATCH_FLUSH_MS), so a crash between commits loses as little as possible. A MAVLink link keeps no such journal: what a link could not commit is lost with it, and its health window says so.
A source that also declares trackProjection sends positions to a governed ontology correlated_tracks stream — this is how a vehicle or AIS position reaches Horizon's map. Each commit sends its rows' positions. Between commits, a best-effort live tick at the same 250 ms cadence sends the newest position per entity, after the organization's data policy has scanned it; a tick is never written to the table and never counts as a sync. A row with no position is skipped, never failed. A row that carries its own markings is never projected: a track stream cannot enforce per-reader markings, so a marked row stays in the table, visible only to readers who hold its markings. See Data Sources for the trackProjection field reference.
Source health
A source reports one status a person reads — Healthy, Failed, Paused or Running — plus mode-specific detail: a stream's stream_disconnected / stream_silent / stream_set_aside, a poll's last_error and consecutive_failures, a push source's delivery warnings. The health check and digest daily alerts both read this same state; nothing bypasses it.
Markings, clearance and loss prevention on the way in
Every table a source writes has a markings column (an array of marking slugs) that every governed read filters on. The platform adds it when the table does not declare it, and a table that declares it must declare it as an array; a source cannot opt out of it. Before any row is committed, it passes the organization's data policy: a row the policy rewrites is written rewritten, a row it blocks is set aside and counted, and the rows beside it are written as they came. A row too large for one scan is set aside unscanned rather than let through unchecked. A scan that cannot answer blocks the commit entirely — rows are never written unscanned and never dropped silently. See Classification and clearance for the no-read-up rule that then gates who can read a classified or marked row back out.
Outbound: declared actions
A data source carries no sending capability by default. The only way one gets a write, invoke or publish capability is a declared action in its manifest — a closed input schema, units, preconditions, a classification, an expiry, and an explicit requiresApproval. There is no enabled field on the declaration itself: enablement is a separate, audited decision.
- Enable. An organization administrator enables one declared action's exact definition (
action.catalog.enable, admin-only). A request against a definition that is not enabled is refused before any outbound row is written. - Request. A caller's request reaches the catalog through API Platform's
action.tasking.dispatchoperation only; nothing else can queue a unit. - Approve (if required). A declared action with
requiresApproval: trueholds every request at the same exact-request approval gate every other kernel action uses — the approver may never be the kernel's verified requester. Once approved, the requester submits the same request again, and that submission consumes the approval: one approval admits one request. Approval and enablement are independent: both gates must open. - Outbox. Only once enablement and (if required) approval both admit the request does the ontology kernel write an outbox row (
action_outbound_request) and queue exactly one unit. - Signed authority, bound to the lease. The kernel mints a short-lived (≤ 5 minutes), asymmetrically signed grant — the action's identity, target, destination, the control-lease epoch, and the approval evidence. Any holder of the public key can verify it; nothing it carries lets a verifier mint one. The dispatcher re-checks the grant against the link's current fence immediately before sending, and again on every retry, so a lease lost between issuance and the write sends nothing.
- Send. For a
link-mode destination, the dispatcher encodes and signs a MAVLink COMMAND_LONG and sends it over the exact link the grant named — and only if that command is on the allow-list (today, onlyMAV_CMD_SET_MESSAGE_INTERVAL). Every other command is refused before it is ever encoded. - Outcome. A COMMAND_ACK is correlated back to the action; a missing acknowledgement gets bounded, protocol-aware retries under the same grant. When retries are spent with no ack, the action settles as Outcome unknown — never silently Failed — and no later action on that same target is claimed for sending until the row is reconciled.
Link egress is off by default. A link-destination unit is queued but never claimed or sent unless ACTION_LINK_EGRESS_ENABLED reads "true" on api-ontology, api-ingestion and API Platform, whose credential release spends each link grant once and audits it before the send (Helm security.actionAuthority.linkEgressEnabled, default false). A MAVLink link is the only destination kind that can send anything real: every other declared action resolves to a simulation destination, and real egress for that destination kind is a hardcoded false in code — no environment variable, chart value or organization setting can turn it on. See the operator runbook for the exact settings and what each one gates.
Related
- Ingest modes — the full per-mode authoring reference, including the MAVLink link manifest.
- Data Sources — declarative data sources and track projections.
- Operator runbook — outbound actions — enabling, approving, reading history, and reconciling.
- Classification and clearance — the no-read-up rule that gates what a reader sees on a classified or marked row.
- Horizon — the operator picture that consumes the runtime's committed rows and track stream.