Kover Connector Protocol
kover specs/kover/protocol.kmd
Profile do protocolo de conectores do Koder Kover. NÃO é um wire format novo: é um perfil (namespace `kover.*` + schema de payload) sobre `specs/ipc/protocol.kmd` (JSON-RPC 2.0) reusando os schemas de telemetria de `instrumentation-contract.kmd` e o formato de erro de `errors/user-facing-messages.kmd`. Define as categorias de informação, tipos, metadados, e a operação bidirecional (ativo = request/response, passivo = notification) que um programa implementa para ser observável e controlável pelo Kover.
When this spec applies
Primary triggers
- Implementar um conector Kover em um programa
All triggers
- Implementar um conector Kover em um programa (Koder ou externo)
- Adicionar uma categoria de informação ao protocolo Kover
- Consumir o stream de um programa no cockpit do Kover
Specification body
Spec — Kover Connector Protocol (profile v0.1)
This spec defines the Kover connector profile. It is a profile, not a new protocol: the wire format, framing, transports, discovery, and capability advertisement are exactly
specs/ipc/protocol.kmd(JSON-RPC 2.0). This document adds (a) thekover.*method namespace, (b) the typed payload schema per information category, and (c) the bidirectional contract. Every ruleR*is testable; testsT*at the end.
Scope
Applies to any program that wants to be observed and/or driven by Koder Kover. Two implementation paths:
- Koder components get the profile from the SDK (
engines/sdk/koder_kitfor Dart,engines/sdk/gofor Go) — built-in, no per-component code (reuse-first; RFC-001 §4 D-protocol-5). - External programs implement the public profile directly, or are
observed without a connector (external resource sampling + capture +
OS-input; see
scenario-dsl.kmdT2).
R1 — Transport & framing are inherited, not redefined
R1.1 — The connector MUST speak specs/ipc/protocol.kmd verbatim:
JSON-RPC 2.0, newline-delimited, over the platform transport (Unix socket /
named pipe / intent). Kover MUST NOT define a second framing.
R1.2 — A Kover connector MUST answer the standard IPC capabilities
query and MUST include "kover" in its advertised capability set, with
a kover_profile semver (this doc's version).
R2 — Bidirectional contract
R2.1 — Active (Kover → program): Kover issues JSON-RPC requests;
the program answers with a response. Used to pull info and send commands
(kover.snapshot, kover.query, kover.command).
R2.2 — Passive (program → Kover): the program emits JSON-RPC
notifications (no id) that Kover did not solicit. Used to push
unsolicited info (kover.emit with a category payload, R3).
R2.3 — A connector MUST support passive emission; active handling is
SHOULD (a program may be push-only). A push-only connector still
advertises kover with active=false in its capability descriptor.
R3 — Information categories (the taxonomy)
R3.1 — Every payload carries a category from this closed enum, each
with a typed schema:
category | Direction | Schema source |
|---|---|---|
log | passive | instrumentation-contract.kmd C1 (verbatim) |
metric | passive | instrumentation-contract.kmd C2 (verbatim) |
trace | passive | instrumentation-contract.kmd C3/C4 (verbatim) |
error | passive | R4 (reuses errors/user-facing-messages.kmd ID) |
event | passive | { name, ts, attrs } — UI/app lifecycle events |
resource | passive | { pid, ts, cpu_pct, rss_bytes, disk_io, gpu_pct? } (R5) |
input | active+passive | scenario-dsl.kmd input record schema |
media-ref | passive | { kind: screen|video|audio, ref, ts_range } → object ref (R6 of capture.kmd) |
R3.2 — log/metric/trace MUST NOT define new schemas — they are the
instrumentation-contract schemas. A Kover connector that already instruments
via instrumentation-contract simply forwards those events; it does not
re-encode them. (One telemetry schema for the whole Stack.)
R3.3 — Every payload carries minimum metadata: category, ts (RFC3339 UTC
ms), source (program slug or pid), and session_id (the Kover run). Trace
correlation uses trace_id from the telemetry context (C3), not a Kover-private id.
R4 — Error identity reuses the Stack format
R4.1 — An error payload's identity is the existing
<PRODUCT>-<CATEGORY>-<CODE>-<SEQ> from
errors/user-facing-messages.kmd (e.g. KRUZE-UI-503-001). Kover MUST
NOT mint a parallel "ERR-…" scheme.
R4.2 — Required fields of an error payload: error_id (R4.1),
ts, severity (fatal|error|warn), title (humanised, from the product
registry), detail (technical), trace_id (if in a trace). PII redaction
per capture.kmd R-redact / instrumentation-contract C5 applies before emit.
R5 — Resource category
R5.1 — resource samples carry { pid, ts, cpu_pct, rss_bytes, disk_read_bytes, disk_write_bytes } as required, and gpu_pct/vram_bytes as
optional best-effort (GPU portability is not guaranteed across vendor/OS
— RFC-001 §9 D-4).
R5.2 — resource for external programs Kover launched is produced by
Kover's own sampler (L1), not by a connector — the program need not
cooperate to be resource-monitored.
R5.3 — On Koder Kodix, resource and process-lifecycle event payloads
MAY originate from the ambient daemon (kover-RFC-001 §7.3) composing
platform sources (Kolide window/input feed + procfs/cgroups + an exec-notify
hook), not from any per-program connector. Ambient sourcing is off by
default and gated per kover-RFC-001 §7.3 D-daemon-3 + capture.kmd
R-consent.3.
R6 — Versioning & forward-compat
R6.1 — Unknown category values or unknown payload fields MUST be
ignored by the receiver (forward-compat), never fatal. The capability
kover_profile semver governs negotiation; minor bumps are additive.
Test cases
| # | Check | Severity |
|---|---|---|
| T1 | A connector advertises kover in capabilities with a kover_profile semver. | hard |
| T2 | A passive log emission validates byte-for-byte against instrumentation-contract C1 (no second schema). | hard |
| T3 | An error payload's error_id matches ^[A-Z0-9]{2,8}-[A-Z]{2}-\d+-\d{3}$ (the Stack error-ID grammar). | hard |
| T4 | An active kover.command request gets a JSON-RPC response or a JSON-RPC error with koder_error_id. | hard |
| T5 | A receiver given an unknown category ignores it without erroring (R6.1). | hard |
| T6 | A push-only connector (active=false) still delivers passive emissions end to end. | soft |
| T7 | resource samples for an externally-launched program arrive even though that program implements no connector (R5.2). | hard |
Non-goals
- Wire format / transport / discovery — owned by
specs/ipc/protocol.kmd. - Telemetry schemas — owned by
instrumentation-contract.kmd. - Capture byte storage & formats — owned by
capture.kmd. - Input record/replay semantics — owned by
scenario-dsl.kmd.
Open questions
- Should
kover.*live in the same IPC socket as a host app's main IPC, or a dedicated Kover socket? Lean: dedicated, to keep the collection hot-path off the app's primary channel (mirrors the koder-x↔kolide sub-protocol precedent inipc/protocol.kmd). Decide at the Go SDK impl (KOVER-002). - Capability descriptor exact shape (
active,categories[],kover_profile) — finalise against the IPCcapabilitiesschema.
References
meta/docs/stack/specs/ipc/protocol.kmdmeta/docs/stack/specs/observability/instrumentation-contract.kmdmeta/docs/stack/specs/errors/user-facing-messages.kmdmeta/docs/stack/rfcs/kover-RFC-001-foundations.kmdengines/sdk/koder_kitengines/sdk/go