Kover Connector Protocol
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.
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 — logmetrictrace 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 windowinput feed + procfscgroups + 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, ora dedicated Kover socket? Lean: dedicated, to keep the collection hot-path off the app's primary channel (mirrors the kompose↔kolide sub-protocol precedent in
ipc/protocol.kmd). Decide at the Go SDK impl (KOVER-002). - Capability descriptor exact shape (
active,categories[],kover_profile) — finalise against the IPCcapabilitiesschema.