Skip to main content

OPEN SPECIFICATION

KYA: Know Your Agent

An open specification for AI agent identity, behavioral accountability, and tamper-evident audit trails. Implementation-agnostic. MIT licensed. Free to implement and distribute.

Version 1.1.0Status: Draft. Open for Review.

Abstract

KYA (Know Your Agent) is an open specification for establishing verifiable identity, behavioral accountability, and tamper-evident audit trails for autonomous AI agents. It defines the minimum requirements for an agent passport, a governed event schema, and a cryptographic chain that implementations can produce and verifiers can check locally.

KYA is implementation-agnostic. It does not require a specific runtime, model, orchestration framework, or infrastructure vendor. Any agent that emits KYA-compliant events and carries a KYA passport can produce verifiable records, regardless of what built it or where it runs.

SECTION 1

Motivation

1. Motivation

Autonomous AI agents are executing real-world actions: moving funds, updating records, sending communications, invoking APIs. The infrastructure governing these actions has not kept pace with their capabilities.

The current state:

  • Agent behavior is observable through dashboards and logs.
  • Dashboards report what agents claim to have done.
  • Logs can be edited, deleted, or never created.
  • No independent cryptographic record links one action to the next.
  • When an auditor, compliance reviewer, or legal team asks what an agent did, the answer is often reconstructed from logs.

Visibility is not verification. KYA makes agent records easier to verify.

The standard draws a direct analogy to financial systems. Double-entry bookkeeping did not exist because accountants were dishonest. It existed because trust requires structure. KYA provides that structure for autonomous agents.

SECTION 2

Scope

2. Scope

KYA defines:

  1. The Agent Passport, a verifiable identity document issued at agent birth.
  2. The governed event schema, the minimum fields every agent action must record.
  3. The hash chain rules, how events are cryptographically linked.
  4. The snapshot format, how a day's worth of events is sealed into an immutable record.
  5. The verification protocol, how any party can check chain integrity without calling any KYA-affiliated service.
  6. The issuer authority model, how the issuing governance layer can be checked via X.509 PKI.

KYA does not define:

  • How agents are built.
  • Which model, runtime, or orchestration framework is used.
  • How events are stored (database choice is implementation-specific).
  • How dashboards or UIs present verified data.
  • Policy rules (what agents are allowed to do, this is outside KYA scope).

SECTION 3

Agent Passport

3. Agent Passport

Every KYA-governed agent receives a passport at birth, its first recorded event. The passport is the agent's permanent cryptographic identity.

3.1 Required Passport Fields

passport_id         string    Globally unique. Format: RNK-YYYY-NNNNN or
                              implementation-defined with collision resistance.
agent_id            uuid      Stable identifier for this agent instance.
agent_name          string    Human-readable name. Not required to be unique.
issued_at           RFC3339   Timestamp of passport issuance (genesis event).
issuer              string    Identity of the issuing governance layer.
public_key          hex       Ed25519 public key for this agent. ML-DSA-65 hybrid is on the roadmap.
genesis_event_hash  sha256    Hash of the agent's first recorded event.
scope               []string  Declared list of permitted action types.
status              enum      active | suspended | revoked
passport_hash       sha256    sha256(canonical_json(all fields except
                              passport_hash))

3.2 Passport Lifecycle

Active: Agent is registered and operating within declared scope.

Suspended: Agent has been paused pending review. Chain continues to record events but policy enforcement blocks execution.

Revoked: Agent is permanently decommissioned. Chain is sealed. No further events are accepted.

Status transitions are themselves recorded events in the chain.

3.3 Scope Declaration

The scope field declares what action types this agent is permitted to invoke. It is set at birth and can only be modified through a recorded update event.

{
  "scope": ["tool_call", "tool_result", "agent_output"]
}

An agent invoking an action type outside its declared scope generates a scope_violation event regardless of whether the action succeeds.

3.4 Passport Verification

A passport is valid if:

  1. passport_hash recomputes correctly from all other fields.
  2. genesis_event_hash matches the first event in the agent's chain.
  3. status is active.
  4. issued_at is not in the future.

Verification requires no network call. Any party with the passport document and the chain export can verify locally.

3.5 Issuer Authority and External Verifiability

3.5.1 The Problem This Solves

A KYA passport links an agent to its hash chain. It does not, by itself, establish that the issuing governance layer was a legitimate and valid authority at the moment of issuance.

For FEDIS compatibility and evidentiary review, a third party should be able to answer two questions independently:

  1. Does this chain still verify? (Answered by hash chain verification.)
  2. Was the issuing authority valid at the moment it issued this passport? (Answered by X.509 certificate chain verification.)

These are different questions. Both must be answerable without calling any RANKIGI or third-party governance infrastructure.

3.5.2 X.509 Certificate Authority Model

KYA adopts the X.509 Public Key Infrastructure (PKI) model for issuer authority verification. This is the same model used by TLS, code signing, and document signing, and is compatible with common audit and compliance tooling.

The model has three levels:

Root CA (publicly trusted, offline)
  Intermediate CA (RANKIGI or enterprise operator, online)
    Agent Passport Certificate (issued per agent at birth)

Every KYA-compliant passport carries a certificate signed by the issuing Intermediate CA. The Intermediate CA certificate chains to an Ed25519 signing key hierarchy. Any third party can verify the full chain using standard PKI tools. No RANKIGI infrastructure required.

3.5.3 Additional Passport Fields (X.509 Extension)

passport_certificate    pem       PEM-encoded X.509 certificate for this
                                  passport, signed by the issuing
                                  Intermediate CA.
issuer_ca_url           url       URL of the issuing Intermediate CA public
                                  certificate. Publicly accessible, no auth.
issuer_ca_fingerprint   sha256    SHA-256 fingerprint of the Intermediate CA
                                  certificate at time of issuance.
certificate_serial      string    Serial number. Used for CRL/OCSP checking.
certificate_not_before  RFC3339   Certificate validity start.
certificate_not_after   RFC3339   Certificate validity end.

3.5.4 Certificate Content Requirements

Subject CN:         passport_id (e.g. RNK-2026-00187)
Subject O:          issuing organization name
Subject OU:         "KYA Agent Governance"
SAN URI:            urn:kya:agent:{agent_id}
SAN URI:            urn:kya:passport:{passport_id}

The certificate must be signed with at least RSA-2048 or ECDSA P-256. Ed25519 certificates today. Hybrid Ed25519 + ML-DSA-65 certificates on the roadmap. Ed25519-only accepted for KYA Basic conformance. Hybrid will be required for KYA Standard and Extended once ML-DSA-65 ships. Certificate validity must not exceed 2 years.

Note: All current implementations use Ed25519 only. ML-DSA-65 hybrid signing is on the RANKIGI roadmap and will be required for KYA Standard and Extended conformance once shipped.

3.5.5 Certificate Authority Hierarchy

Root CA: Offline and air-gapped. Signs only Intermediate CA certificates. RANKIGI operates the canonical Root CA for the public KYA standard. Enterprise deployments may operate their own Root CA.

Intermediate CA: Online and operational. Issues passport certificates. Published at issuer_ca_url. RANKIGI operates the canonical Intermediate CA for cloud deployments. Enterprise on-premise deployments operate their own Intermediate CA.

Passport Certificate: Issued per agent at birth. Tied to passport_id and agent_id. Cannot be reused. Revocable via CRL or OCSP.

3.5.6 External Verification Protocol

1. Extract passport_certificate from the passport document.
2. Fetch the Intermediate CA certificate from issuer_ca_url.
   Verify SHA-256 fingerprint matches issuer_ca_fingerprint.
3. Verify the passport certificate was signed by the Intermediate CA.
4. Fetch the Root CA certificate from RANKIGI well-known URL or
   the enterprise declared root URL.
5. Verify the Intermediate CA certificate was signed by the Root CA.
6. Verify certificate_not_before <= issued_at <= certificate_not_after.
7. Check revocation status via CRL or OCSP.
8. Verify Subject CN matches passport_id.
   Verify SAN URI matches agent_id.

Reference implementation:

# Verify the full certificate chain
openssl verify \
  -CAfile root-ca.pem \
  -untrusted intermediate-ca.pem \
  passport-certificate.pem

# Check certificate details
openssl x509 -in passport-certificate.pem -text -noout

# Verify fingerprint of intermediate CA
openssl x509 -in intermediate-ca.pem -fingerprint -sha256 -noout

3.5.7 Passport Renewal

When a passport certificate approaches expiry (within 30 days of certificate_not_after), the governance layer initiates renewal:

  1. A new certificate is issued for the same agent_id and passport_id.
  2. The new certificate serial and validity fields are recorded as a system_annotation event in the agent chain.
  3. The old certificate remains valid for chain events that occurred during its validity period. Historical verification uses the certificate that was valid at the time of the event.

3.5.8 Revocation

A passport certificate may be revoked if:

  • Agent is permanently decommissioned (status: revoked).
  • Compromise of the agent private key is suspected.
  • The issuing Intermediate CA is compromised.

Revocation is published to:

  1. The CRL endpoint embedded in the Intermediate CA certificate.
  2. An OCSP responder if operated by the issuing CA.
  3. A revocation event in the agent chain.

A revoked certificate does not invalidate historical chain events that occurred before the revocation timestamp.

3.5.9 Conformance

KYA Basic: X.509 fields optional. Ed25519 passport (RFC 8032). ML-DSA-65 hybrid optional and on the roadmap.

KYA Standard: X.509 fields required. Intermediate CA must be publicly accessible.

KYA Extended: Full PKI hierarchy required. CRL or OCSP required. Enterprise deployments may operate independent CA hierarchy.

3.5.10 Relationship to FEDIS

The X.509 authority model can support evidence for the FEDIS requirement for an externally resolvable authority reference:

  • The authority is not an internal alias or system-scoped identifier.
  • Validity at the moment of issuance can be checked via certificate validity window.
  • The authority chain can be checked using standard PKI tools without access to RANKIGI or any governance infrastructure.
  • Historical events verify against the certificate active at the time of the event.

SECTION 4

Governed Event Schema

4. Governed Event Schema

Recorded actions by an agent produce governed events. Events are the atomic unit of the KYA audit trail.

4.1 Client-Provided Fields

event_id            uuid      Globally unique event identifier.
agent_id            uuid      Matches the agent passport agent_id.
timestamp           RFC3339   When the action occurred, from the agent clock.
action_type         enum      See Section 4.3.
tool_invoked        string    Name of tool called. Null if not a tool call.
input_hash          sha256    sha256(canonical_json(input_payload))
output_hash         sha256    sha256(canonical_json(output_payload))
decision_metadata   json      Small structured object. No raw sensitive content.
execution_result    enum      success | error | unknown
data_quality_flag   enum      ok | malformed | incomplete | low_confidence

4.2 Ledger Fields (Server-Computed)

server_received_at  RFC3339   When the governance layer received the event.
previous_event_hash sha256    event_hash of the prior event for this agent.
                              Null for the genesis event only.
chain_index         int       Monotonically increasing per agent. Starts at 0.
event_hash          sha256    sha256(canonical_json(all fields except
                              event_hash itself))

4.3 Action Type Enum

tool_call           Agent invoked an external tool or API.
tool_result         Result returned from a tool invocation.
agent_output        Agent produced a final output or response.
agent_error         Agent encountered an error condition.
agent_offline_start Agent stopped producing events (gap detected).
agent_offline_end   Agent resumed producing events after a gap.
scope_violation     Agent attempted an action outside declared scope.
system_annotation   Governance layer annotation (not an agent action).

4.4 Data Privacy

KYA never stores raw sensitive content. input_hash and output_hash store only the SHA-256 hash of the payload, not the payload itself. Raw content never enters the chain.

4.5 Malformed Events

Events from an authenticated, registered, active agent with field-validation issues (e.g. payload depth overflow, malformed intent block) are recorded with data_quality_flag set to malformed or incomplete rather than dropped. Unauthenticated requests, requests with an invalid API key, and requests targeting an unknown or paused agent are rejected with an HTTP error and are not written to the chain.

SECTION 5

Offline Gap Detection

5. Offline Gap Detection

If a registered agent stops producing events, the gap is itself a recorded event.

5.1 Gap Detection Rule

If no events are received for X minutes (default 15, configurable), the governance layer creates an agent_offline_start event:

action_type:        agent_offline_start
decision_metadata:  { "gap_threshold_minutes": 15,
                      "last_event_id": "<uuid>" }

When events resume, an agent_offline_end event is created:

action_type:        agent_offline_end
decision_metadata:  { "gap_duration_seconds": <int>,
                      "resumed_event_id": "<uuid>" }

Both gap events are full KYA events with hashes and chain links. The gap can be verified, not just observed.

SECTION 6

The Verification Protocol (V10)

6. The Verification Protocol (V10)

V10 is the canonical verification protocol for all new KYA chains. Three improvements over V1: NFC normalization prevents encoding-based hash attacks. State-machine architecture provides O(1) memory footprint regardless of chain length. Type-safe canonicalization ensures cross-language compatibility in polyglot environments.

6.1 Canonical JSON

All hashes use canonical JSON:

  • Keys sorted alphabetically, recursively.
  • No whitespace.
  • UTF-8 encoding.
  • Strings use double quotes.
  • No trailing commas.
  • Null values included as null (not omitted).

Correct:

{"action_type":"tool_call","agent_id":"abc","chain_index":1}

6.2 Hash Computation

input_hash  = SHA-256(canonical_json(input_payload))
output_hash = SHA-256(canonical_json(output_payload))
event_hash  = SHA-256(canonical_json(event_object_excluding_event_hash))

6.3 Chain Linking

Event 0:  previous_event_hash = null  (genesis)
Event 1:  previous_event_hash = event_hash(Event 0)
Event N:  previous_event_hash = event_hash(Event N-1)

The chain is per-agent. Each agent has its own independent chain.

6.4 Tamper Detection

A chain is valid if and only if:

  1. Recomputing event_hash from stored fields produces the stored value.
  2. For every event N greater than 0, previous_event_hash equals event_hash of event N-1.
  3. chain_index values are monotonically increasing with no gaps.

6.5 Chain Verification (No Network Required)

# SPDX-License-Identifier: MIT
# KYA V10 Steel-Core Verification Engine
import hashlib, json, sys, unicodedata

class RankigiV10:
    def __init__(self):
        self.head = None
        self.count = 0

    def _canonicalize(self, data):
        if isinstance(data, str):
            return json.dumps(
                unicodedata.normalize('NFC', data)
            )
        if isinstance(data, (int, bool)) \
                or data is None:
            return json.dumps(data)
        if isinstance(data, dict):
            items = [
                f"{self._canonicalize(k)}:"
                f"{self._canonicalize(data[k])}"
                for k in sorted(data.keys())
            ]
            return "{" + ",".join(items) + "}"
        if isinstance(data, list):
            return "[" + ",".join(
                self._canonicalize(x) for x in data
            ) + "]"
        raise TypeError(
            f"V10 Protocol Error: "
            f"Unsupported type {type(data)}"
        )

    def verify_event(self, event):
        idx = event.get("chain_index")
        provided_hash = event.get("event_hash")
        prev_hash = event.get(
            "previous_event_hash"
        )
        if idx != self.count:
            raise ValueError(
                f"GAP_DETECTED: Expected "
                f"{self.count}, got {idx}"
            )
        if prev_hash != self.head:
            raise ValueError(
                f"LINKAGE_ERROR: Break at {idx}"
            )
        body = {
            k: v for k, v in event.items()
            if k != "event_hash"
        }
        serialized = self._canonicalize(
            body
        ).encode('utf-8')
        computed = hashlib.sha256(
            serialized
        ).hexdigest()
        if computed != provided_hash:
            raise ValueError(
                f"INTEGRITY_FAILURE: "
                f"Tamper detected at {idx}"
            )
        self.head = computed
        self.count += 1
        return self.head

if __name__ == "__main__":
    engine = RankigiV10()
    try:
        data = json.load(sys.stdin)
        for ev in data:
            engine.verify_event(ev)
        print(
            f"VERIFIED: {engine.count} events"
            f" | HEAD: {engine.head}"
        )
    except Exception as e:
        print(f"SECURITY_ALERT: {str(e)}")
        sys.exit(1)

No external dependencies. No API calls. The chain is self-verifying.

SECTION 7

Daily Snapshot

7. Daily Snapshot

7.1 Snapshot Fields

snapshot_id         uuid      Unique identifier for this snapshot.
date                YYYY-MM-DD  The calendar day this snapshot covers.
agent_id            uuid      Agent this snapshot covers. Null for global.
total_events        int       Count of events in this snapshot period.
first_event_hash    sha256    event_hash of the first event of the day.
last_event_hash     sha256    event_hash of the last event of the day.
generated_at        RFC3339   When the snapshot was generated.
snapshot_hash       sha256    sha256(canonical_json(all fields except
                              snapshot_hash))

7.2 Snapshot Verification

  1. snapshot_hash recomputes correctly from all other fields.
  2. first_event_hash and last_event_hash exist in the chain.
  3. total_events matches the count of events between first and last.

7.3 External Anchoring (Optional)

Implementations may anchor snapshot_hash to an external notarization service (e.g. Sigstore Rekor) to provide independent timestamp proof.

7.4 Public Revocation API

Any party can query the revocation status of any KYA passport without authentication. No API key required. No RANKIGI account required.

GET https://rankigi.com/api/public/revocation?passport_id=RNK-2026-00187

Response (active passport):

{
  "passport_id": "RNK-2026-00187",
  "agent_id": "8c9d0e1f-2a3b-4c5d-6e7f-8a9b0c1d2e3f",
  "status": "active",
  "issued_at": "2026-04-29T13:00:00.000Z",
  "revoked_at": null,
  "revocation_reason": null,
  "issuing_org": "Acme Corp",
  "kya_version": "1.1.0",
  "verified_at": "2026-05-02T10:14:32.119Z",
  "rankigi_url": "https://rankigi.com/verify"
}

Response (unknown passport):

{
  "status": "unknown",
  "passport_id": "RNK-2026-99999",
  "kya_version": "1.1.0",
  "verified_at": "2026-05-02T10:14:32.119Z"
}

This endpoint is part of the KYA public verification surface. It returns the current status of any issued passport. Cache-Control is no-store. Always query fresh.

SECTION 8

Compliance Mapping

8. Compliance Mapping

RequirementKYA Mechanism
Tamper-evident recordsSHA-256 hash chain
Agent identity verificationEd25519 passport + X.509 certificate
Issuer authority verificationX.509 certificate chain (Sec. 3.5)
Action attributionagent_id on every event
Time of actiontimestamp + server_received_at
What inputs were usedinput_hash (content verifiable)
What outputs were producedoutput_hash (content verifiable)
Gap detectionoffline_start / offline_end events
Immutable daily recordsealed snapshot
Independent verificationlocal chain verify (no API needed)
Evidence package formattingchain export + snapshot + passport
FEDIS closure record inputpassport_certificate + chain export

Regulation mapping:

  • SOC 2 CC7.1: KYA offline detection and scope violation events can support evidence for monitoring.
  • EU AI Act Article 13: KYA chain exports can support evidence for technical documentation requirements.
  • EU AI Act Article 14: Owner of record and transfer history can support evidence for accountability.
  • HIPAA 164.312(b): KYA provides a tamper-evident audit record pattern for review by covered entities.

SECTION 9

Conformance Levels

9. Conformance Levels

KYA Basic: Passport issuance, event schema, hash chain, local verification. X.509 fields optional. Minimum viable verifiable agent record.

KYA Standard: Adds offline detection, scope violation detection, daily snapshots, snapshot verification, and X.509 passport certificate with publicly accessible Intermediate CA.

KYA Extended: Adds external snapshot anchoring, federation handshake protocol, full PKI hierarchy with CRL or OCSP, passport renewal protocol, and regulation-specific export formats. Enterprise deployments may operate independent CA hierarchy.

9.1 Signing Key Requirements per Tier

KYA Basic: Ed25519 signing accepted.

KYA Standard: Ed25519 required (RFC 8032). ML-DSA-65 hybrid is on the roadmap for KYA Standard and Extended conformance levels.

KYA Extended: Ed25519 required today. Hybrid Ed25519 + ML-DSA-65 will be required when the post-quantum codepath ships. See the roadmap section.

SECTION 10

Versioning

10. Versioning

This document is version 1.1.0 of the KYA specification.

Version 1.1.0 upgrades the verification protocol to V10 Steel-Core (Section 6).

Version 1.0.1 added Section 3.5 (Issuer Authority and External Verifiability).

  • Breaking changes increment the major version.
  • Additive changes increment the minor version.
  • Clarifications increment the patch version.

Implementations must declare which version of KYA they conform to.

Chain Specification

The chain has one property that matters above all others: self-verifying. Any party with a chain export can verify its integrity without calling any API, contacting any server, or trusting any third party. The hash chain is the record.

Design Principles

  • Append-only: Events are never modified or deleted.
  • Per-agent: Each agent has its own independent chain.
  • No raw content: The chain stores hashes of inputs and outputs, not the payloads.
  • Minimal dependencies: Verification requires only SHA-256.
  • Gap-inclusive: Offline periods are recorded as explicit events.

Canonical JSON Rules

  1. Keys sorted alphabetically, recursively for nested objects.
  2. No whitespace.
  3. UTF-8 encoding.
  4. Strings use double quotes.
  5. Numbers use minimal representation (no trailing zeros).
  6. No trailing commas.
  7. Null values included as null (not omitted).
  8. Arrays preserve original order (not sorted).

Reference Implementation (Python)

import json

def canonical_json(obj: dict) -> bytes:
    return json.dumps(
        obj,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False
    ).encode('utf-8')

Reference Implementation (Node.js)

function sortedJson(obj) {
  if (typeof obj !== 'object' || obj === null) return obj;
  if (Array.isArray(obj)) return obj.map(sortedJson);
  return Object.keys(obj).sort().reduce((acc, key) => {
    acc[key] = sortedJson(obj[key]);
    return acc;
  }, {});
}

function canonicalJson(obj) {
  return Buffer.from(JSON.stringify(sortedJson(obj)), 'utf-8');
}

Chain Export Format

A KYA chain export is a JSON array of events in ascending chain_index order:

[
  {
    "event_id": "...",
    "agent_id": "...",
    "timestamp": "...",
    "action_type": "tool_call",
    "tool_invoked": "...",
    "input_hash": "...",
    "output_hash": "...",
    "decision_metadata": {},
    "execution_result": "success",
    "data_quality_flag": "ok",
    "server_received_at": "...",
    "previous_event_hash": null,
    "chain_index": 0,
    "event_hash": "..."
  }
]

Export file naming convention:

kya-chain-{agent_id}-{start_date}-{end_date}.json

Tamper Evidence Properties

  • Forward Integrity: Modifying event N requires recomputing all subsequent hashes.
  • Insertion Resistance: Inserting between N and N+1 produces a detectable divergence.
  • Deletion Resistance: Deleting N breaks the chain at N+1.

Whitepaper: Why AI Agents Need an Open Audit Standard

The default assumption in AI agent infrastructure is that observability is audit infrastructure. If you can see what your agents are doing, you can audit them.

This assumption is wrong in the same way it was wrong for financial systems before double-entry bookkeeping, for software before code signing, and for internet traffic before TLS. Visibility tells you what a system reports. It does not tell you what a system did.

The Volkswagen Effect:In 2015, Volkswagen programmed engines to detect testing and behave differently. AI agents exhibit an analogous property. An agent's observability layer is built by the same team, runs in the same process, and reports through the same infrastructure. Observing an agent through its own reporting layer means seeing what it chooses to report. This is not audit infrastructure. KYA specifies a passive sidecar architecture specifically to break this dependency.

The pattern has worked before: double-entry bookkeeping for financial systems, supply chain attestation after SolarWinds, TLS for internet security. All three required an open specification, not a proprietary product, to establish category-wide trust.

Why open verification matters at scale: If your audit trail is stored in a vendor proprietary format and verifiable only through vendor tools, your audit trail depends on that vendor remaining available. A KYA chain export from 2026 can be checked in 2036 with a SHA-256 library and this specification.

The timing argument:The EU AI Act, NIST AI RMF, and state-level AI legislation are all defining what constitutes adequate audit evidence for AI agent actions. Organizations that provide concrete technical answers during this definition period may help shape what “adequate” means.

Read the full whitepaper at rankigi.com/whitepaper.

IMPLEMENT KYA

Build to the standard.

Any agent that emits KYA-compliant events and carries a KYA passport can produce verifiable records. Framework agnostic. Runtime agnostic. MIT licensed.

View reference implementation →See RANKIGI in action →

NODE.JS SDK

Official SDK for emitting KYA-compliant execution proof events. Zero runtime dependencies. MIT licensed.

github.com/Rankigi-Inc/rankigi-sdk →npm install @rankigi/sdk

CONTRIBUTE

Found a gap in the spec?

If you are implementing KYA and encounter something the spec does not cover, that is a bug. Open an issue. The goal is a standard that outlives any single vendor.

github.com/kya-standard/spec →wes@rankigi.com →