docs: document the kaptan-native protocol

This commit is contained in:
Onur Özkan committed 2026-08-24 00:56:32 +03:00
1 parent 5f91465e66
commit 4bc98adbc6
10 files changed
+314 -307

No files matched your search

+48 -53
View File
@@ -27,73 +27,68 @@ The data channel owns rate selection, mailbox consumption, message encoding,
and bounded TX classification. Board code supplies physical routes, target
schema, and factory values; it does not receive generic output authority.
Configuration and runtime observability are separate, one-way planes:
Configuration and runtime observability are separate planes:
```text
Kaptan GCS custom MAVLink V2 messages
│ (future: verified signing, source binding, replay state)
FILE_CONTROL / FILE_DATA
│
▼
kaptan-config-mavlink ──► state-only ConfigProtocol
│ borrows
kaptan-flight-runtime
├── one ConfigManager ──► kaptan-config ──► flight schema/store
└── one bounded MAVLink log-sink queue
kaptan-file-mavlink ──► virtual FileProvider
│
kaptan-diagnostics-mavlink payload adapter
KCFG importer/exporter
│
platform-owned sole encoder / DMA TX link
ConfigManager ──► private store
kaptan-log / kaptan-err-reportable
│
▼
kaptan-diagnostics-mavlink ──► platform-owned encoder / DMA TX
```
The generated dialect is intentionally custom rather than a `PARAM_*` or QGC
adapter. The core uses numeric field IDs and typed scalar values; descriptor
text is metadata, not a wire identity. Discovery/value reads, exact-index
descriptor and enum-option requests, and structured results are custom-dialect
records. Runtime logs use one bounded text message with a conventional level
and flags. Remote writes use only schema-described typed scalar setters. The core
owns one RAM transaction and the distinction
between boot-active, committed, and editable candidate snapshots. In the
current P1 policy a commit is restart-only. It cannot mutate controller or
estimator state in flight.
The file dialect is intentionally Kaptan-native rather than standard MAVLink
FTP, `PARAM_*`, or a QGC adapter. Its two messages know only bounded paths,
bytes, positions, checksums, transfer ownership, and retries. The configuration
provider maps `/config/user.kcfg` to a canonical self-describing artifact.
KCFG carries generated metadata and a complete committed value set; the target
streams it without retaining a whole-file buffer. Saving imports and validates
one complete replacement candidate. The core distinguishes only immutable
boot-active values from the latest committed values. A save cannot mutate
controller or estimator state in flight.
Target-owned stores may serialize one bounded complete CBOR snapshot. SITL
supplies the host file adapter and atomically replaces that snapshot through a
same-directory temporary file. The serialization is not configuration state
and is never exposed by the MAVLink protocol.
Target-owned stores use private persistence formats. SITL atomically replaces a
bounded CBOR snapshot. F722 alternates compact `KCSP` snapshots between two
erase sectors, retaining only the old and replacement records across the commit
boundary. Neither format is exposed as the public KCFG file.
Motor allocation/mixer topology is immutable compiled vehicle capability data,
never a scalar field or CBOR candidate member. F722 now recovers operational
settings from a generic two-slot journal before constructing consumers. Its
directly wired local UART accepts only exact-target, CRC-valid configuration
commands while physical outputs remain inhibited. CRC is integrity-only; a
shared or remote GCS still needs production authentication, durable audit
logging, source binding, and persistent anti-replay state. Disarmed activation
and flight-consumer reconstruction remain separate reviewed work and cannot be
implied by a valid snapshot or CRC.
never a scalar field or persistence member. F722 recovers operational settings
before constructing consumers. Its directly wired local UART accepts only
exact-target, CRC-valid Kaptan file requests while physical outputs remain
inhibited. CRC is integrity-only; a shared or remote GCS still needs production
authentication, source binding, and persistent anti-replay state. Disarmed
activation and flight-consumer reconstruction remain separate reviewed work.
Configuration wire layout `2.0` uses one exact response per descriptor or enum
option request. The first accepted transaction binds one source principal
through a bounded post-terminal replay lease; foreign traffic cannot evict a
lost result before that lease expires.
The MAVLink dialect root includes `kaptan/config.xml`, `kaptan/log.xml`, and
`kaptan/error.xml`.
The build watches every fragment and generates one `message::kaptan` module;
fragments are never separately generated Rust modules. `kaptan-log` itself has
The MAVLink dialect root directly includes one-message XML leaves under
`publish/` and `transfer/`. The `exchange/` contract remains empty until a
current consumer justifies a message. There are no category index XML files or
separate enum catalogs. The build watches the definitions tree and generates
one `generated::kaptan` module; leaves are never separately generated Rust
modules. `kaptan-log` itself has
no MAVLink, platform, time, allocation, or filesystem dependency; its sole
configuration coupling is compile-time enum metadata for `LevelFilter`.
`kaptan-err-reportable` independently owns explicitly assigned reportable-error
identity and a bounded nonblocking ingress; it has
no logging, MAVLink, platform, filesystem, or clock dependency. Event creation
is independent from sink filtering, allowing a future blackbox and MAVLink to
select different policies. The platform drains reportable errors before its bounded
critical and best-effort log queues and removes a pending record only after TX
admission. `KAPTAN_LOG` carries one conventional level plus one bounded text
field; `KAPTAN_ERROR` carries an explicitly assigned 16-bit ID and the bounded
`file:line` of the reporting point. Its
message kind already identifies a reportable firmware error. Heartbeat and safety
telemetry remain separate from diagnostics.
identity and a bounded nonblocking ingress; it has no logging, MAVLink,
platform, filesystem, or clock dependency. Event creation is independent from
sink filtering, allowing a future blackbox and MAVLink to select different
policies. The platform drains reportable errors before its bounded critical and
best-effort log queues and removes a pending record only after TX admission.
`LOG` carries one conventional level plus one bounded text field; `ERROR`
carries an explicitly assigned 16-bit ID and the bounded `file:line` of the
reporting point. Its message kind already identifies a reportable firmware
error. Kaptan-native heartbeat and sensor publications remain separate from
diagnostics.
See [Configuration](configuration.md) for the deployment matrix and GCS transaction
contract, [Logs](logs.md) for the receiver contract, and [Errors](errors.md)
See [Configuration](configuration.md) for KCFG and the file-transfer contract,
[Logs](logs.md) for the receiver contract, and [Errors](errors.md)
for derived-error and failure-reporting scope.
## Ownership rules