Referencia Zigspire-zig (SDK consumido)

zig/src/envelope.zig

Declaraciones públicas de zig/src/envelope.zig (spire-zig (SDK consumido)).

ImplementadoSin versión del tren todavía· generada desde apps/docs/generated/zig/spire.json

Página generada desde spire@spire-0.2.0-XvnrRek1BgCX4Bh8miuITCQgkn0FqeQrYYE3goFfDcQd (zig/src/root.zig). No se edita a mano: bun run docs:gen la regenera y bun run docs:check falla si difiere.

MessageEnvelope v2 — el sobre firmado de spire (dec-0119 §5), en su codificación binaria canónica. Especificación normativa: spec/ENVELOPE_V2.md; TS (@spire/bus) y Zig deben dar el mismo veredicto y el mismo valor decodificado sobre cualquier entrada (vectores en vectors/envelope-v2.json, fuzz diferencial en packages/bus/test).

Cuerpo (big endian). La cabecera es la región firmada:

off len campo 0 1 version = 2 1 1 kind 1 cmd · 2 qry · 3 evt · 4 reply 2 1 status 0 salvo en reply (ver Status) 3 1 flags b0 actor · b1 causation · b2 traceparent · b3 deadline 4 16 id UUIDv7 20 16 correlation_id 36 8 ts_ms reloj de pared del emisor 44 16 nonce aleatorio, 128 bits 60 2 contract_version >= 1 62 8 kid SHA-256(clave pública del emisor)[0..8] 70 32 payload_sha256 102 4 payload_len 106 1+n subject n en 1..128 1+n source n en 1..64 [16] causation_id si b1 [8] deadline_ms si b3 [55] traceparent si b2 (W3C, minúsculas) [2+n] actor si b0; n en 1..8192, ASCII visible (JWT) ─── fin de la cabecera ─── 64 firma Ed25519 sobre "spire/env/v2\0" ‖ cabecera n payload n = payload_len

La decodificación sigue el orden de los campos y el primer fallo decide el error (orden normativo, lo comparte TS). Nada reserva memoria: los campos variables son préstamos del cuerpo recibido.

envelope.VERSION

const · línea 42

pub const VERSION: u8 = 2

Sin ///.

envelope.SIGNING_DOMAIN

const · línea 43

pub const SIGNING_DOMAIN = "spire/env/v2\x00"

Sin ///.

envelope.SIGNATURE_LEN

const · línea 44

pub const SIGNATURE_LEN: usize = Ed25519.Signature.encoded_length

Sin ///.

envelope.FIXED_HEADER_LEN

const · línea 45

pub const FIXED_HEADER_LEN: usize = 106

Sin ///.

envelope.MAX_SUBJECT_LEN

const · línea 46

pub const MAX_SUBJECT_LEN: usize = 128

Sin ///.

envelope.MAX_SOURCE_LEN

const · línea 47

pub const MAX_SOURCE_LEN: usize = 64

Sin ///.

envelope.MAX_ACTOR_LEN

const · línea 48

pub const MAX_ACTOR_LEN: usize = 8192

Sin ///.

envelope.TRACEPARENT_LEN

const · línea 49

pub const TRACEPARENT_LEN: usize = 55

Sin ///.

envelope.MAX_HEADER_LEN

const · línea 51

pub const MAX_HEADER_LEN: usize = FIXED_HEADER_LEN + 1 + MAX_SUBJECT_LEN + 1 + MAX_SOURCE_LEN + 16 + 8 + TRACEPARENT_LEN + 2 + MAX_ACTOR_LEN

Cabecera más larga posible (todos los opcionales al máximo).

envelope.HARD_MAX_PAYLOAD

const · línea 54

pub const HARD_MAX_PAYLOAD: u32 = 1 << 20

Techo absoluto del payload (dec-0119 §7). El límite efectivo lo pone el llamador (Limits.max_payload), normalmente el del contrato.

envelope.Id

const · línea 56

pub const Id = [16]u8

Sin ///.

envelope.Nonce

const · línea 57

pub const Nonce = [16]u8

Sin ///.

envelope.Kid

const · línea 58

pub const Kid = [8]u8

Sin ///.

envelope.Digest

const · línea 59

pub const Digest = [32]u8

Sin ///.

envelope.Kind

type · línea 61

pub const Kind = enum

Sin ///.

envelope.Kind.fromByte

fn · línea 67

pub fn fromByte(b: u8) ?Kind

Sin ///.

envelope.Status

type · línea 74

pub const Status = enum

Resultado de una petición, sólo en reply. Los nombres son el código de error que ve el cliente (TS los expone igual).

envelope.Status.fromByte

fn · línea 86

pub fn fromByte(b: u8) ?Status

Sin ///.

envelope.Flags

type · línea 91

pub const Flags = struct

Sin ///.

envelope.Flags.actor

const · línea 92

pub const actor: u8 = 1 << 0

Sin ///.

envelope.Flags.causation

const · línea 93

pub const causation: u8 = 1 << 1

Sin ///.

envelope.Flags.traceparent

const · línea 94

pub const traceparent: u8 = 1 << 2

Sin ///.

envelope.Flags.deadline

const · línea 95

pub const deadline: u8 = 1 << 3

Sin ///.

envelope.Flags.reserved

const · línea 96

pub const reserved: u8 = 0xf0

Sin ///.

envelope.Header

type · línea 100

pub const Header = struct

Campos del sobre (sin firma ni payload). Las rebanadas son préstamos.

envelope.Header.encodedLen

fn · línea 127

pub fn encodedLen(h: *const Header) usize

Sin ///.

envelope.Decoded

type · línea 137

pub const Decoded = struct

Sin ///.

envelope.DecodeError

const · línea 147

pub const DecodeError = error{ Truncated, UnsupportedVersion, BadKind, BadStatus, BadFlags, BadId, BadContractVersion, PayloadTooLarge, BadSubject, BadSource, BadTraceparent, BadActor, TrailingBytes, } …

Errores de estructura. El nombre es el código de conformidad (TS usa el mismo string).

envelope.VerifyError

const · línea 163

pub const VerifyError = error{ BadSignature, PayloadDigestMismatch }

Sin ///.

envelope.Limits

type · línea 165

pub const Limits = struct

Sin ///.

envelope.validSubject

fn · línea 173

pub fn validSubject(s: []const u8) bool

Subject: tokens [A-Za-z0-9_-]+ separados por ., sin comodines NATS (*, >), sin vacíos ni espacios.

envelope.validSource

fn · línea 190

pub fn validSource(s: []const u8) bool

Identidad de servicio: [a-z][a-z0-9-]*, 1..64.

envelope.validTraceparent

fn · línea 210

pub fn validTraceparent(s: []const u8) bool

W3C traceparent versión 00: 00-<32 hex>-<16 hex>-<2 hex>, trace/span no nulos.

envelope.validActor

fn · línea 220

pub fn validActor(s: []const u8) bool

Actor: token compacto (JWT) en ASCII visible.

envelope.validUuidV7

fn · línea 227

pub fn validUuidV7(id: *const Id) bool

UUIDv7: nibble de versión 7 y variante RFC 9562 (10).

envelope.decode

fn · línea 243

pub fn decode(body: []const u8, limits: Limits) DecodeError!Decoded

Decodifica un cuerpo de frame envelope. Sólo estructura: la firma y el digest los comprueba verify, y el reloj/replay/policy el router.

envelope.verify

fn · línea 309

pub fn verify(d: *const Decoded, public_key: Ed25519.PublicKey) VerifyError!void

Firma estricta de la cabecera y, después, el digest del payload.

envelope.EncodeError

const · línea 322

pub const EncodeError = error{ NoSpaceLeft, InvalidField, PayloadTooLarge }

Sin ///.

envelope.Signer

type · línea 325

pub const Signer = struct

Firmante: par de claves Ed25519 + su kid derivado.

envelope.Signer.init

fn · línea 329

pub fn init(key_pair: Ed25519.KeyPair) Signer

Sin ///.

envelope.Signer.SeedError

const · línea 333

pub const SeedError = error{ InvalidSeedEncoding, WeakKey }

Sin ///.

envelope.Signer.fromSeedBase64

fn · línea 338

pub fn fromSeedBase64(text: []const u8) SeedError!Signer

Firmante desde la semilla Ed25519 de 32 bytes en base64url sin relleno (43 caracteres, forma canónica): el mismo formato que la clave pública del keyring y que signerFromSeed de @spire/bus.

envelope.kidOf

fn · línea 351

pub fn kidOf(public_key: [32]u8) Kid

Sin ///.

envelope.sealedLen

fn · línea 358

pub fn sealedLen(h: *const Header, payload_len: usize) usize

Longitud total del cuerpo para una cabecera y un payload dados.

envelope.seal

fn · línea 366

pub fn seal(out: []u8, h_in: Header, payload: []const u8, signer: *const Signer) EncodeError![]u8

Codifica y firma. Rellena en h el kid, el digest y la longitud del payload (lo que haya puesto el llamador se ignora). Valida cada campo con las mismas gramáticas que decode: spire nunca emite un sobre que él mismo rechazaría.

envelope.newId

fn · línea 432

pub fn newId(ts_ms: u64) Id

UUIDv7 (RFC 9562): 48 bits de milisegundos + 74 bits aleatorios.

envelope.newNonce

fn · línea 446

pub fn newNonce() Nonce

Sin ///.

envelope.nowMs

fn · línea 452

pub fn nowMs() u64

Sin ///.

envelope.testing

type · línea 461

pub const testing = struct

Sin ///.

envelope.testing.signer

fn · línea 462

pub fn signer(seed_byte: u8) Signer

Sin ///.

envelope.testing.header

fn · línea 468

pub fn header(subject: []const u8, source: []const u8) Header

Sin ///.

trace.TRACEPARENT_LEN

const · línea 49

pub const TRACEPARENT_LEN: usize = 55

Sin ///.