Gunnar

mikronova/tyr

docs/PROTOCOL.md

# tyr — protocol design (draft)

Canonical design for `tyr`, Nordisk's own compact **binary** eID. Vetra's `heimdal-tyr` is a
*client*; keep protocol decisions here.

## Design principles

1. **Binary, not text.** Fixed-header + TLV framing; every field length-prefixed; versioned first
   byte. No XML/JSON on the wire — the ~100× CPU/space win is the whole point.
2. **`no_std` core.** `tyr-proto` (the codec) builds without an allocator where possible, so the
   same encoder/decoder runs on an embedded secure element and on the server.
3. **Small + locked down.** One modern signature suite, no negotiation zoo. Reject unknown
   versions/algorithms hard.
4. **Only auth + sign.** No issuance/wallet/selective-disclosure sprawl — that's `frida`'s job.

## Lifecycle (maps onto heimdal's `IdentityProvider`)

- **start_auth / start_sign** → server issues a compact binary **challenge** (nonce + context +
  optional data-to-sign digest); client returns a QR/deep link or drives a local device/card.
- **collect** → client presents the holder's signature over the challenge; server verifies against
  the holder's registered public key / card cert and returns a verified result.
- **cancel** → drop the session.

## Wire format (sketch — to be specified in `spec/`)

```
byte 0      version
byte 1      message type (StartAuth, StartSign, Challenge, Response, Result, Cancel)
bytes 2..4  length
body        TLV: {tag:u8, len:u16, value:[u8]} records
```

Signatures/attestations in a compact COSE-like structure (not full COSE). Suite: **Ed25519**
(device) / **ECDSA-P256** (cards, PKCS#11), SHA-256. Hardware-bound keys; optional device
attestation record.

## PKCS#11 (card) path

Same shape as `frida`: card signs the challenge via PKCS#11, `tyr` verifies the card cert chain to
a trusted `tyr` root + validity window. Key never leaves the card.

## Persistence — no relational database, ever

`Store` trait (in `edda`, per the `nornir-warehouse-trait` pattern), never an RDBMS:

- **single server** → embedded **redb / rocksdb** (often the entire deployment).
- **multi-server** (Kubernetes) → **append-only event log with per-event ACK** as source of truth;
  **skade** (pure-Rust Iceberg lakehouse) sinks large transactional / audit volume.

## Networking (multi-server)

**WireGuard** node-to-node, naturally via **Cilium transparent WireGuard encryption**. Cilium
guarantees the *network* (connectivity, policy, mTLS, encryption) — **not** application-level ACK;
delivery/ACK semantics live in the event protocol (append → replicate → ACK → commit).

## Open questions

- Exact TLV tag registry and version negotiation rules.
- Transport: raw TCP/QUIC with the binary frames, or the binary frames tunnelled over gRPC for ops
  convenience (decide per deployment; the codec is transport-agnostic).
- Which primitives move to `edda/` (crypto suite, cert-validity check shared with `frida`).