Declaraciones públicas de zig/src/cap/authority.zig (spire-zig (SDK consumido)).
apps/docs/generated/zig/spire.jsonPágina generada desde
spire@spire-0.2.0-XvnrRek1BgCX4Bh8miuITCQgkn0FqeQrYYE3goFfDcQd (zig/src/root.zig). No se edita a mano:bun run docs:genla regenera ybun run docs:checkfalla si difiere.
Capability authority (dec-0117 I1, I2, I3; §4.1). spire-zig owns the one SCT verifier of styx (dec-0119 §9); the daemon instantiates it once and shares it with every transport.
One instance per daemon, shared by every transport (WT, MoQT, H3) and by the IPC control server. It owns the state an SCT is checked against:
kid derived),Deny-by-default: an authority with no keys admits nothing, a token whose session was never bound (or was closed) is refused, and a full replay cache refuses new write tokens instead of forgetting old ones.
Thread model: admit/authorize run on the transport event-loop threads,
bindSession/unbindSession on IPC threads. Keys and audience are
immutable after init; the two maps are guarded by mutex. Signature
verification runs outside the lock.
Tokens are never logged (I12): audit lines carry the reason, the session key, the jti and the actor digest, all non-secret.
cap.authority.MAX_KEYSconst · línea 35
pub const MAX_KEYS: usize = 4Sin ///.
cap.authority.Clockconst · línea 43
pub const Clock = *const fn () u64Seconds since the Unix epoch.
cap.authority.Configtype · línea 49
pub const Config = structSin ///.
cap.authority.Rejectiontype · línea 72
pub const Rejection = structOne refused capability as Config.on_reject receives it: identifiers
only, never the token (I12).
cap.authority.Rejection.Claimedtype · línea 85
pub const Claimed = structSin ///.
cap.authority.RejectSinktype · línea 96
pub const RejectSink = structReceiver of Rejections. emitFn runs on the refusing thread, possibly
with the authority's lock held: it must not block and must not call back
into the authority.
cap.authority.Denialconst · línea 103
pub const Denial = error{ Malformed, UnsupportedVersion, NoKeysConfigured, UnknownKey, BadSignature, WrongAudience, NotYetValid, Expired, LifetimeTooLong, UnknownSession, SessionMismatch, ScopeDenied, …Why a capability was refused. Callers map these to protocol errors; the authority has already written the audit line.
cap.authority.DENIAL_KINDSconst · línea 123
pub const DENIAL_KINDS = DENIAL_NAMES.lenSin ///.
cap.authority.BindErrorconst · línea 132
pub const BindError = error{ SessionCapacityExceeded, SessionAlreadyBound }Sin ///.
cap.authority.Bindingtype · línea 135
pub const Binding = structWhat a session was opened for, as playback-svc declared it over IPC.
cap.authority.Granttype · línea 141
pub const Grant = structAn admitted SCT: what the holder may do until exp.
cap.authority.Operationtype · línea 153
pub const Operation = enumSin ///.
cap.authority.Rangetype · línea 174
pub const Range = structHalf-open [start, end).
cap.authority.Targettype · línea 176
pub const Target = structSin ///.
cap.authority.Verifiedtype · línea 200
pub const Verified = structA token whose signature, key, audience, time window and lifetime passed
(verifyBase64 / verifyRaw) and that has not been bound to its session
or spent yet: consume does that. The claims are readable (a caller can
route on them before consuming), but a Verified cannot be built outside
the authority that verified it: seal is an HMAC-SHA256 of the claims
under a random key of that authority, drawn at init and never exported.
consume recomputes it, so claims put together by hand (from
peekBase64, or edited after verification) or verified by another
authority are refused as BadSignature and audited — the Ed25519 check
cannot be skipped by constructing the struct.
cap.authority.Authoritytype · línea 220
pub const Authority = structSin ///.
cap.authority.Authority.InitErrorconst · línea 245
pub const InitError = error{ TooManyKeys, InvalidPublicKey } || std.mem.Allocator.ErrorSin ///.
cap.authority.Authority.initfn · línea 249
pub fn init(self: *Authority, allocator: std.mem.Allocator, cfg: Config) InitError!voidBoth maps are sized up front: admission never allocates, so a flood of tokens cannot turn into an OOM path.
cap.authority.Authority.deinitfn · línea 274
pub fn deinit(self: *Authority) voidSin ///.
cap.authority.Authority.nowfn · línea 282
pub fn now(self: *const Authority) u64Sin ///.
cap.authority.Authority.hasKeysfn · línea 286
pub fn hasKeys(self: *const Authority) boolSin ///.
cap.authority.Authority.bindSessionfn · línea 293
pub fn bindSession(self: *Authority, sid: SessionKey, binding: Binding) BindError!voidCalled by the IPC server when playback-svc opens a session.
cap.authority.Authority.unbindSessionfn · línea 303
pub fn unbindSession(self: *Authority, sid: SessionKey) boolCalled on IPC Close. Every later authorize on a grant for sid
fails, so closing a session revokes its capabilities.
cap.authority.Authority.boundSessionsfn · línea 319
pub fn boundSessions(self: *Authority) usizeSin ///.
cap.authority.Authority.unbindCountfn · línea 328
pub fn unbindCount(self: *const Authority) u64Sessions unbound so far. A cache of grants only has to look for dead
ones again when this moved or the clock did (checkLive depends on
nothing else).
cap.authority.Authority.admitBase64fn · línea 336
pub fn admitBase64(self: *Authority, text: []const u8) Denial!GrantBase64url form (cap= query, Authorization: Bearer): verifyBase64
then consume.
cap.authority.Authority.admitRawfn · línea 342
pub fn admitRaw(self: *Authority, raw: []const u8) Denial!GrantRaw form (MoQT AUTHORIZATION TOKEN value): verifyRaw then consume.
cap.authority.Authority.verifyBase64fn · línea 351
pub fn verifyBase64(self: *Authority, text: []const u8) Denial!VerifiedFirst half of admitBase64: decoding, signature, key, audience, time
window and lifetime. Takes no lock and spends nothing, so a caller can
pay the Ed25519 check outside its own locks and only then decide
(under them) whether to consume the token.
cap.authority.Authority.verifyRawfn · línea 357
pub fn verifyRaw(self: *Authority, raw: []const u8) Denial!VerifiedSame as verifyBase64 for the raw form.
cap.authority.Authority.peekBase64fn · línea 367
pub fn peekBase64(self: *Authority, text: []const u8) Denial!sct.ClaimsThe claims of a base64url token, NOT verified: no signature, time or
session check. Only for routing a token before admitting it (which
cache slot it would take); never grant anything on them — and they
cannot be turned into a Verified (see its seal). An undecodable
token is refused and audited here as in admitBase64.
cap.authority.Authority.consumefn · línea 403
pub fn consume(self: *Authority, v: *const Verified) Denial!GrantSecond half of admitBase64: session binding and, for write scopes,
single use. Only a Verified this authority sealed gets past the
first check (anything else is BadSignature). Consumes the jti only
when every other check passed, so a rejected attempt cannot burn a
legitimate token. Expiry is checked again: time went by since the
verification.
cap.authority.Authority.authorizefn · línea 474
pub fn authorize(self: *Authority, grant: *const Grant, op: Operation, target: Target) Denial!voidRe-checked on every request, not just at admission: expiry, session still open with the same actor and resource (revocation), scope, resource and range.
cap.authority.Authority.checkLivefn · línea 519
pub fn checkLive(self: *Authority, grant: *const Grant) Denial!voidIs an admitted grant still alive — not expired, its session still bound to the same actor and resource? Independent of any operation: long-lived flows (an open SUBSCRIBE, a FETCH being written, a publisher stream) are swept with it so expiry and IPC Close reach them, not only the next request (dec-0117 §4.1 revocation).
cap.authority.Authority.deniedCountfn · línea 534
pub fn deniedCount(self: *const Authority, reason: Denial) u64Sin ///.
cap.authority.Authority.admittedCountfn · línea 538
pub fn admittedCount(self: *const Authority) u64Sin ///.
cap.authority.parsePublicKeysfn · línea 585
pub fn parsePublicKeys(text: []const u8, out: *[MAX_KEYS][32]u8) error{ TooManyKeys, InvalidPublicKey }!usizeSTYX_SCT_PUBLIC_KEYS: comma-separated base64url (no padding) raw
Ed25519 public keys, 43 chars each. Returns how many were parsed.
cap.authority.testingtype · línea 605
pub const testing = structA throw-away issuer for tests: deterministic key, an authority that trusts it, a controllable clock, and helpers to mint tokens bound to sessions it registered. Never used outside tests.
cap.authority.testing.NODE_IDconst · línea 606
pub const NODE_ID = "test-node"Sin ///.
cap.authority.testing.ACTOR_IDconst · línea 607
pub const ACTOR_ID = "test-actor"Sin ///.
cap.authority.testing.fakeClockfn · línea 611
pub fn fakeClock() u64Sin ///.
cap.authority.testing.setNowfn · línea 615
pub fn setNow(v: u64) voidSin ///.
cap.authority.testing.Issuertype · línea 619
pub const Issuer = structSin ///.
cap.authority.testing.Issuer.initfn · línea 624
pub fn init(self: *Issuer, allocator: std.mem.Allocator) !voidSin ///.
cap.authority.testing.Issuer.deinitfn · línea 637
pub fn deinit(self: *Issuer) voidSin ///.
cap.authority.testing.Issuer.bindfn · línea 641
pub fn bind(self: *Issuer, sid: SessionKey, resource: Digest32) !voidSin ///.
cap.authority.testing.Issuer.claimsfn · línea 645
pub fn claims(self: *Issuer, sid: SessionKey, scope: Scope, resource: Digest32) sct.ClaimsSin ///.
cap.authority.testing.Issuer.signfn · línea 664
pub fn sign(self: *Issuer, c: sct.Claims) [sct.TOKEN_LEN]u8Sin ///.
cap.authority.testing.Issuer.mintfn · línea 668
pub fn mint(self: *Issuer, sid: SessionKey, scope: Scope, resource: Digest32) [sct.TOKEN_LEN]u8Sin ///.
cap.Authoritytype · línea 220
pub const Authority = structSin ///.
cap.Authority.InitErrorconst · línea 245
pub const InitError = error{ TooManyKeys, InvalidPublicKey } || std.mem.Allocator.ErrorSin ///.
cap.Authority.initfn · línea 249
pub fn init(self: *Authority, allocator: std.mem.Allocator, cfg: Config) InitError!voidBoth maps are sized up front: admission never allocates, so a flood of tokens cannot turn into an OOM path.
cap.Authority.deinitfn · línea 274
pub fn deinit(self: *Authority) voidSin ///.
cap.Authority.nowfn · línea 282
pub fn now(self: *const Authority) u64Sin ///.
cap.Authority.hasKeysfn · línea 286
pub fn hasKeys(self: *const Authority) boolSin ///.
cap.Authority.bindSessionfn · línea 293
pub fn bindSession(self: *Authority, sid: SessionKey, binding: Binding) BindError!voidCalled by the IPC server when playback-svc opens a session.
cap.Authority.unbindSessionfn · línea 303
pub fn unbindSession(self: *Authority, sid: SessionKey) boolCalled on IPC Close. Every later authorize on a grant for sid
fails, so closing a session revokes its capabilities.
cap.Authority.boundSessionsfn · línea 319
pub fn boundSessions(self: *Authority) usizeSin ///.
cap.Authority.unbindCountfn · línea 328
pub fn unbindCount(self: *const Authority) u64Sessions unbound so far. A cache of grants only has to look for dead
ones again when this moved or the clock did (checkLive depends on
nothing else).
cap.Authority.admitBase64fn · línea 336
pub fn admitBase64(self: *Authority, text: []const u8) Denial!GrantBase64url form (cap= query, Authorization: Bearer): verifyBase64
then consume.
cap.Authority.admitRawfn · línea 342
pub fn admitRaw(self: *Authority, raw: []const u8) Denial!GrantRaw form (MoQT AUTHORIZATION TOKEN value): verifyRaw then consume.
cap.Authority.verifyBase64fn · línea 351
pub fn verifyBase64(self: *Authority, text: []const u8) Denial!VerifiedFirst half of admitBase64: decoding, signature, key, audience, time
window and lifetime. Takes no lock and spends nothing, so a caller can
pay the Ed25519 check outside its own locks and only then decide
(under them) whether to consume the token.
cap.Authority.verifyRawfn · línea 357
pub fn verifyRaw(self: *Authority, raw: []const u8) Denial!VerifiedSame as verifyBase64 for the raw form.
cap.Authority.peekBase64fn · línea 367
pub fn peekBase64(self: *Authority, text: []const u8) Denial!sct.ClaimsThe claims of a base64url token, NOT verified: no signature, time or
session check. Only for routing a token before admitting it (which
cache slot it would take); never grant anything on them — and they
cannot be turned into a Verified (see its seal). An undecodable
token is refused and audited here as in admitBase64.
cap.Authority.consumefn · línea 403
pub fn consume(self: *Authority, v: *const Verified) Denial!GrantSecond half of admitBase64: session binding and, for write scopes,
single use. Only a Verified this authority sealed gets past the
first check (anything else is BadSignature). Consumes the jti only
when every other check passed, so a rejected attempt cannot burn a
legitimate token. Expiry is checked again: time went by since the
verification.
cap.Authority.authorizefn · línea 474
pub fn authorize(self: *Authority, grant: *const Grant, op: Operation, target: Target) Denial!voidRe-checked on every request, not just at admission: expiry, session still open with the same actor and resource (revocation), scope, resource and range.
cap.Authority.checkLivefn · línea 519
pub fn checkLive(self: *Authority, grant: *const Grant) Denial!voidIs an admitted grant still alive — not expired, its session still bound to the same actor and resource? Independent of any operation: long-lived flows (an open SUBSCRIBE, a FETCH being written, a publisher stream) are swept with it so expiry and IPC Close reach them, not only the next request (dec-0117 §4.1 revocation).
cap.Authority.deniedCountfn · línea 534
pub fn deniedCount(self: *const Authority, reason: Denial) u64Sin ///.
cap.Authority.admittedCountfn · línea 538
pub fn admittedCount(self: *const Authority) u64Sin ///.