Declaraciones públicas de zig/src/cap/sct.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.
styx:parser
Styx Capability Token (SCT) v1: codec, signature check and resource
digests (dec-0117 §4.1, spec protocols/capability-token/SCT_SPEC.md).
The daemon only VERIFIES. The private key lives in playback-svc (A4); the
only signing code is testing.sign (sct_testing.zig), reachable from
tests.
Wire layout (big endian, fixed length, no optional fields):
off len field
0 1 version = 1
1 1 scope 1 read · 2 publish · 3 ingest · 4 control
2 1 range_kind 0 none · 1 bytes [start, end) · 2 groups [start, end)
3 1 flags = 0 (reserved; non-zero is malformed)
4 8 kid SHA-256(raw Ed25519 public key)[0..8]
12 16 aud SHA-256("styx.sct.aud\x00" ++ node id)[0..16]
28 16 sid the 16 random bytes of the daemon session id
44 16 actor SHA-256("styx.sct.actor\x00" ++ actor id)[0..16]
60 32 resource resource digest (see Resource)
92 8 range_start
100 8 range_end
108 8 nbf unix seconds
116 8 exp unix seconds
124 16 jti random, unique per token
140 64 signature Ed25519 over SIGNING_DOMAIN ++ bytes[0..140]
Everything in this file is a pure function of its input: no allocation,
no global state, no clock. Stateful checks (keys, sessions, replay, time)
live in authority.zig.
cap.sct.VERSIONconst · línea 37
pub const VERSION: u8 = 1Sin ///.
cap.sct.BODY_LENconst · línea 38
pub const BODY_LEN: usize = 140Sin ///.
cap.sct.SIGNATURE_LENconst · línea 39
pub const SIGNATURE_LEN: usize = Ed25519.Signature.encoded_lengthSin ///.
cap.sct.TOKEN_LENconst · línea 40
pub const TOKEN_LEN: usize = BODY_LEN + SIGNATURE_LENSin ///.
cap.sct.TOKEN_B64_LENconst · línea 43
pub const TOKEN_B64_LEN: usize = TOKEN_LEN / 3 * 4base64url without padding. 204 is a multiple of 3, so there are no trailing bits that a non-canonical encoding could hide data in.
cap.sct.SIGNING_DOMAINconst · línea 44
pub const SIGNING_DOMAIN = "styx-sct/v1\x00"Sin ///.
cap.sct.Kidconst · línea 52
pub const Kid = [8]u8Sin ///.
cap.sct.Digest16const · línea 53
pub const Digest16 = [16]u8Sin ///.
cap.sct.Digest32const · línea 54
pub const Digest32 = [32]u8Sin ///.
cap.sct.SessionKeyconst · línea 55
pub const SessionKey = [16]u8Sin ///.
cap.sct.Jticonst · línea 56
pub const Jti = [16]u8Sin ///.
cap.sct.Scopetype · línea 58
pub const Scope = enumSin ///.
cap.sct.Scope.fromBytefn · línea 64
pub fn fromByte(b: u8) ?ScopeSin ///.
cap.sct.Scope.isWritefn · línea 69
pub fn isWrite(self: Scope) boolWrite scopes are single-use per jti (dec-0117 §4.1).
cap.sct.RangeKindtype · línea 74
pub const RangeKind = enumSin ///.
cap.sct.RangeKind.fromBytefn · línea 82
pub fn fromByte(b: u8) ?RangeKindSin ///.
cap.sct.Claimstype · línea 87
pub const Claims = structSin ///.
cap.sct.Tokentype · línea 102
pub const Token = structSin ///.
cap.sct.DecodeErrorconst · línea 110
pub const DecodeError = error{ /// Wrong length, bad base64, unknown scope/range kind, reserved flags /// set, or an empty/inverted range. Malformed, UnsupportedVersion, }Sin ///.
cap.sct.decodefn · línea 119
pub fn decode(bytes: []const u8) DecodeError!TokenDecode a raw SCT. Checks structure only; the signature, the key and the time window are the authority's job.
cap.sct.decodeBase64fn · línea 154
pub fn decodeBase64(text: []const u8) DecodeError!TokenDecode the base64url (no padding) form used in cap= and Authorization.
cap.sct.encodeBodyfn · línea 163
pub fn encodeBody(c: Claims) [BODY_LEN]u8Serialize claims into the signed body (used by testing.sign and by the
codec round-trip tests; the daemon never re-encodes a received token).
cap.sct.SignatureErrorconst · línea 182
pub const SignatureError = error{BadSignature}Sin ///.
cap.sct.verifySignaturefn · línea 185
pub fn verifySignature(token: *const Token, public_key: Ed25519.PublicKey) SignatureError!voidStrict (cofactorless) Ed25519 verification over the domain-separated body.
cap.sct.kidOffn · línea 195
pub fn kidOf(public_key: [32]u8) Kidkid of a public key: the first 8 bytes of SHA-256 of its raw encoding.
Derived, never configured, so a key and its id cannot disagree.
cap.sct.audienceOffn · línea 208
pub fn audienceOf(node_id: []const u8) Digest16Sin ///.
cap.sct.actorOffn · línea 212
pub fn actorOf(actor_id: []const u8) Digest16Sin ///.
cap.sct.Resourcetype · línea 219
pub const Resource = structResource digests. Each kind has its own domain, and tuple elements are
length-prefixed, so no two distinct resources share a digest by
concatenation (["a/b"] vs ["a","b"], namespace vs track).
cap.sct.Resource.assetfn · línea 221
pub fn asset(id: []const u8) Digest32A media asset served over WT/H3 (the string playback-svc bound on IPC).
cap.sct.Resource.moqtNamespacefn · línea 226
pub fn moqtNamespace(ns: []const []const u8) Digest32A whole MoQT namespace (every track under it).
cap.sct.Resource.ingestRootfn · línea 235
pub fn ingestRoot(root_id: []const u8) Digest32An ingest destination (conduit, dec-0121): the id of the daemon's
ingest root (STYX_INGEST_ROOT_ID) the upload lands in.
cap.sct.Resource.moqtTrackfn · línea 240
pub fn moqtTrack(ns: []const []const u8, name: []const u8) Digest32One MoQT track.
cap.sct.sessionKeyFromIdfn · línea 268
pub fn sessionKeyFromId(session_id: []const u8) ?SessionKeyParse the 32 lowercase hex chars after sess_ of a daemon session id into
the 16 bytes an SCT carries. Anything else is not a session id.
cap.sct.packagingKeyFromIdfn · línea 276
pub fn packagingKeyFromId(packaging_id: []const u8) ?SessionKeySame for a packaging session id (pkg_<32 hex>, dec-0110 §3): an SCT for
/styx/pkg/<id>/... binds these 16 bytes. Session and packaging keys share
the authority's map, whose bindSession refuses a key already bound, so
one key names at most one live thing.
cap.sct.ingestKeyFromIdfn · línea 282
pub fn ingestKeyFromId(ingest_id: []const u8) ?SessionKeySame for an ingest session id (ing_<32 hex>, dec-0121): one upload
under one capability, bound in the same authority map.
cap.sct.parseHexFixedfn · línea 299
pub fn parseHexFixed(comptime N: usize, text: []const u8) ?[N]u8Parse exactly 2 * N lowercase hex chars into [N]u8.
cap.sct.testingnamespace · línea 320
pub const testing = @import("sct_testing.zig")Signing support for tests only (sct_testing.zig: not a parser, no
input). A daemon build has no caller of it, and no key material.
cap.authority.SessionKeyconst · línea 55
pub const SessionKey = [16]u8Sin ///.
cap.authority.Digest16const · línea 53
pub const Digest16 = [16]u8Sin ///.
cap.authority.Digest32const · línea 54
pub const Digest32 = [32]u8Sin ///.
cap.authority.Scopetype · línea 58
pub const Scope = enumSin ///.
cap.authority.Scope.fromBytefn · línea 64
pub fn fromByte(b: u8) ?ScopeSin ///.
cap.authority.Scope.isWritefn · línea 69
pub fn isWrite(self: Scope) boolWrite scopes are single-use per jti (dec-0117 §4.1).