Referencia Zigspire-zig (SDK consumido)

zig/src/router.zig

Declaraciones públicas de zig/src/router.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.

Router de spire: el único camino por el que un sobre recibido llega a un handler, en cualquier transporte (dec-0119 §1, §4–§8).

Tubería de dispatch, en este orden (el primer fallo decide):

  1. estructura del sobre (envelope.decode) → drop + audit
  2. kid en el keyring → drop + audit
  3. source = dueño del kid → drop + audit
  4. source = identidad autenticada del peer (unix) → drop + audit
  5. firma Ed25519 + digest del payload → drop + audit
  6. subject registrado (deny-by-default), kind, versión → reply denied / invalid_request
  7. allowlist de la policy → reply denied
  8. anti-replay (ventana + nonce, cuota por fuente); duplicado idempotente → respuesta cacheada (sólo la de esa misma petición firmada: RequestKey)
  9. deadline vencido → reply deadline_exceeded
  10. actor: regla, JWT verificado, authorize → reply denied
  11. tamaño por contrato, rate por (source, subject), concurrencia
  12. payload contra el contrato (JSON + validate) → reply invalid_request
  13. handler → reply handler_error
  14. respuesta contra el contrato → reply invalid_reply

Lo que falla antes de autenticar (1–5) no recibe respuesta: responder a un sobre sin autenticar sería un oráculo. Todo lo demás recibe una respuesta firmada con status (salvo los evt, que nunca responden).

La allowlist va antes del anti-replay: sólo un emisor admitido en la ruta gasta memoria de la caché de nonces, y cada uno dentro de su cuota (lo que su rate admite en una ventana, reservado al registrar). Un emisor que inunda se queda sin su cuota, nunca deja sin servicio a otro. Lo que se deniega antes del anti-replay no ejecuta nada, así que repetirlo sólo vuelve a dar denied. El rate va después del anti-replay a propósito: un sobre rechazado por rate queda registrado (el cliente re-sella su reintento), y sus bytes no se pueden reproducir más tarde para ejecutarlo.

Los handlers se registran con register(Contract, policy, handler), los tres comptime. policy no tiene default: sin ella no compila.

router.Peer

type · línea 54

pub const Peer = struct

Quién está al otro lado del transporte.

router.Outcome

type · línea 63

pub const Outcome = enum

Sin ///.

router.Options

type · línea 72

pub const Options = struct

Sin ///.

router.RegisterError

const · línea 87

pub const RegisterError = error{ AlreadyStarted, DuplicateSubject } || replay_mod.ReserveError

Sin ///.

router.Router

fn · línea 96

pub fn Router(comptime App: type) type

Sin ///.

router.Router.Context

type · línea 100

pub const Context = struct

Sin ///.

router.Router.Context.Undo

type · línea 113

pub const Undo = struct

Sin ///.

router.Router.Context.onReplyFailure

fn · línea 122

pub fn onReplyFailure(ctx: *Context, comptime T: type, ptr: *T, comptime run: fn (*T) void) void

Un handler que crea estado (una sesión, un binding) registra aquí cómo deshacerlo por si su respuesta no llega a sellarse: respuesta fuera de contrato, sin memoria para serializarla o para el sobre. Sin esto el efecto quedaría huérfano (hecho, pero sin que nadie reciba su id para cerrarlo). Una por mensaje; ptr tiene que vivir hasta el final del mensaje (la arena sirve). Si la respuesta sale, no se llama.

router.Router.Context.setReplyTraceparent

fn · línea 134

pub fn setReplyTraceparent(ctx: *Context, tp: []const u8) bool

El handler declara el span que abrió para este mensaje; la respuesta lo lleva en vez de repetir el del request. No cambia el formato del sobre. Un valor que no sea W3C v00 se ignora (y devuelve false): la respuesta repite el del request.

router.Router.init

fn · línea 171

pub fn init(allocator: std.mem.Allocator, app: *App, opts: Options) std.mem.Allocator.Error!Self

Sin ///.

router.Router.deinit

fn · línea 181

pub fn deinit(self: *Self) void

Sin ///.

router.Router.register

fn · línea 194

pub fn register(self: *Self, comptime C: type, comptime p: Policy, comptime handler: anytype) RegisterError!void

Registra handler para el contrato C con la política p. handler: fn (*Context, C.Request) anyerror!C.Reply.

router.Router.start

fn · línea 232

pub fn start(self: *Self) void

Congela el registro. dispatch antes de start responde unavailable.

router.Router.subjects

fn · línea 236

pub fn subjects(self: *const Self, out: [][]const u8) usize

Sin ///.

router.Router.dispatch

fn · línea 260

pub fn dispatch(self: *Self, peer: Peer, body: []const u8, out: *std.ArrayList(u8)) std.mem.Allocator.Error!Outcome

Procesa un cuerpo de frame envelope. Si devuelve .replied, out (vaciado antes) contiene el sobre de respuesta.

Router

fn · línea 96

pub fn Router(comptime App: type) type

Sin ///.

Router.Context

type · línea 100

pub const Context = struct

Sin ///.

Router.Context.Undo

type · línea 113

pub const Undo = struct

Sin ///.

Router.Context.onReplyFailure

fn · línea 122

pub fn onReplyFailure(ctx: *Context, comptime T: type, ptr: *T, comptime run: fn (*T) void) void

Un handler que crea estado (una sesión, un binding) registra aquí cómo deshacerlo por si su respuesta no llega a sellarse: respuesta fuera de contrato, sin memoria para serializarla o para el sobre. Sin esto el efecto quedaría huérfano (hecho, pero sin que nadie reciba su id para cerrarlo). Una por mensaje; ptr tiene que vivir hasta el final del mensaje (la arena sirve). Si la respuesta sale, no se llama.

Router.Context.setReplyTraceparent

fn · línea 134

pub fn setReplyTraceparent(ctx: *Context, tp: []const u8) bool

El handler declara el span que abrió para este mensaje; la respuesta lo lleva en vez de repetir el del request. No cambia el formato del sobre. Un valor que no sea W3C v00 se ignora (y devuelve false): la respuesta repite el del request.

Router.init

fn · línea 171

pub fn init(allocator: std.mem.Allocator, app: *App, opts: Options) std.mem.Allocator.Error!Self

Sin ///.

Router.deinit

fn · línea 181

pub fn deinit(self: *Self) void

Sin ///.

Router.register

fn · línea 194

pub fn register(self: *Self, comptime C: type, comptime p: Policy, comptime handler: anytype) RegisterError!void

Registra handler para el contrato C con la política p. handler: fn (*Context, C.Request) anyerror!C.Reply.

Router.start

fn · línea 232

pub fn start(self: *Self) void

Congela el registro. dispatch antes de start responde unavailable.

Router.subjects

fn · línea 236

pub fn subjects(self: *const Self, out: [][]const u8) usize

Sin ///.

Router.dispatch

fn · línea 260

pub fn dispatch(self: *Self, peer: Peer, body: []const u8, out: *std.ArrayList(u8)) std.mem.Allocator.Error!Outcome

Procesa un cuerpo de frame envelope. Si devuelve .replied, out (vaciado antes) contiene el sobre de respuesta.