valis / Reference / API reference
Capabilities - API reference
Exported surface for the capability subsystem. Part of the API reference.
Package valis/src/capability/directive
Classes
mount-directive
Immutable value carrying an authorization to mount a designated namespace subtree with a given set of rights. Both wire presentations — the signed delegation token and the compact bearer name — resolve to a mount-directive; the namespace assembler consumes these objects to build per-connection views.
This is a pure value type: no side effects, no crypto imports, no 9P symbols.
Generic functions
mount-directive-designation
(mount-directive-designation object)
Undocumented: this exported symbol needs a docstring.
mount-directive-rights
(mount-directive-rights object)
Undocumented: this exported symbol needs a docstring.
mount-directive-rights-bitmask
(mount-directive-rights-bitmask object)
Undocumented: this exported symbol needs a docstring.
Functions
bitmask->rights
(bitmask->rights bits)
Convert integer bitmask BITS back to a keyword list. The returned list preserves declaration order: (:read :write :mount :delegate).
(bitmask->rights 3) => (:READ :WRITE) (bitmask->rights 8) => (:DELEGATE)
designation-prefix-p
(designation-prefix-p parent-designation child-designation)
Return true if CHILD-DESIGNATION is PARENT-DESIGNATION or a path-segment extension of it. Used for attenuation checking: a delegated designation must lie within the granting subtree. The match must land on a path separator, so a grant does not leak across sibling boundaries that merely share a leading substring.
(designation-prefix-p "/proto" "/proto/smtp") => T (designation-prefix-p "/proto" "/proto") => T (designation-prefix-p "/proto/smtp" "/proto") => NIL (designation-prefix-p "/pro" "/proto/smtp") => NIL (designation-prefix-p "/proto" "/protox") => NIL
make-mount-directive
(make-mount-directive designation rights)
Construct an immutable MOUNT-DIRECTIVE from DESIGNATION (a non-empty string) and RIGHTS (a list of keywords from {:read :write :mount :delegate :admit}).
Signals an error if DESIGNATION is not a non-empty string, or if RIGHTS contains any keyword outside the closed set.
(make-mount-directive "/proto/smtp" '(:read :write)) => a MOUNT-DIRECTIVE with designation "/proto/smtp" and bitmask 3
rights->bitmask
(rights->bitmask rights)
Convert a keyword list RIGHTS to an integer bitmask. Each keyword in the list must be a member of {:read :write :mount :delegate :admit}. Returns 0 for an empty list.
(rights->bitmask '(:read :write)) => 3 (rights->bitmask '(:delegate)) => 8
rights-subset-p
(rights-subset-p child-rights parent-rights)
Return true if every right in CHILD-RIGHTS is also in PARENT-RIGHTS. Both arguments are keyword lists from the closed rights set. Used for attenuation checking: a delegated grant must not claim rights the granting token does not itself hold.
(rights-subset-p '(:read) '(:read :write)) => T (rights-subset-p '(:read :write) '(:read)) => NIL
Package valis/src/capability/name
Functions
capability-name-bound-generation
(capability-name-bound-generation instance)
Undocumented: this exported symbol needs a docstring.
capability-name-designation
(capability-name-designation instance)
Undocumented: this exported symbol needs a docstring.
capability-name-expiry
(capability-name-expiry instance)
Undocumented: this exported symbol needs a docstring.
capability-name-nonce
(capability-name-nonce instance)
Undocumented: this exported symbol needs a docstring.
capability-name-rights-bitmask
(capability-name-rights-bitmask instance)
Undocumented: this exported symbol needs a docstring.
capability-name-signature
(capability-name-signature instance)
Undocumented: this exported symbol needs a docstring.
decode-capability-name
(decode-capability-name name-string)
Decode a "valis:"-prefixed capability name string.
Returns a DECODED-CAPABILITY-NAME struct with six fields: capability-name-designation — string capability-name-rights-bitmask — integer capability-name-expiry — Unix timestamp integer capability-name-nonce — 16-byte octet vector capability-name-bound-generation — head generation integer capability-name-signature — 64-byte octet vector
The wire decode is the shared hekate bearer-name codec (fail-closed on a wrong prefix, invalid base58btc, a payload too short for the fixed layout, or a length inconsistent with the encoded designation length). This wrapper carries the recovered fields into valis's own struct so OCAP callers keep a stable accessor surface independent of the wire codec's representation.
encode-capability-name
(encode-capability-name designation rights expiry-unix nonce-16 sig-64 &optional (bound-generation 0))
Encode a capability name as a "valis:"-prefixed base58btc string.
DESIGNATION: a non-empty string naming the namespace subtree granted. RIGHTS: either an integer bitmask or a keyword list from {:read :write :mount :delegate} — if a list, it is converted to a bitmask via RIGHTS->BITMASK. EXPIRY-UNIX: Unix timestamp integer (seconds since 1970-01-01T00:00:00Z). NONCE-16: 16-byte octet vector. SIG-64: 64-byte Ed25519 signature over (NAME-CANONICAL-BYTES …) produced by the owner's custody store. BOUND-GENERATION: the head generation current at mint time, stamped inside the signed canonical bytes. Defaults to 0 (the genesis generation, never fenced) so a caller without a head still encodes a valid genesis-stamped name.
The rights vocabulary is valis's OCAP concern; the wire marshalling is the shared hekate bearer-name codec. Returns a string beginning with "valis:".
name-canonical-bytes
(name-canonical-bytes designation rights-bitmask expiry-unix nonce-16 bound-generation)
Lay out the deterministic bytes a bearer-name signature covers.
DESIGNATION is a string, RIGHTS-BITMASK a u8 integer, NONCE-16 a 16-byte octet vector. Two calls with equal fields return EQUALP vectors — the byte-for-byte contract every already-minted name depends on.
Package valis/src/capability/revocation
Classes
revocation-store
Append-only set of 32-byte SHA-256 hashes identifying revoked tokens and capability names. The TABLE maps hash vectors to T for O(1) membership tests (EQUALP so byte-vector keys compare by value). PATH is the backing flat file (a pathname or NIL for in-memory-only stores used in tests).
Functions
fence-epoch-hash
(fence-epoch-hash superseded-generation)
The 32-byte revocation-set member expressing that SUPERSEDED-GENERATION is fenced: a SHA-256 over a fixed ASCII prefix and the 8-byte big-endian generation.
A head bump appends this hash to the same append-only set that holds revoked token and name hashes, so the verifier's existing membership check rejects a write capability bound to a superseded generation on the same path it rejects a revoked token. The literal ASCII prefix is the collision firewall: token and name hashes are a SHA-256 over canonical bytes and a signature and never begin with a constant string, so a fence-epoch hash can never alias one. Consumers call this constructor rather than re-deriving the format, so the verifier, the eviction sweep, and the tests all agree on one encoding.
load-or-create-revocation-store
(load-or-create-revocation-store path)
Return a REVOCATION-STORE backed by PATH.
If PATH exists: read and intern all 32-byte hash blocks into the in-memory table. If PATH does not exist: return an empty store with the path slot set — the backing file is created lazily on the first REVOKE-HASH call, avoiding a confusing empty file that could be mistaken for corruption.
The store's PATH slot is set in both branches so REVOKE-HASH knows where to append future hashes.
make-revocation-store
(make-revocation-store &key path)
Construct an empty in-memory revocation store. If PATH is non-nil the store is backed by that file; REVOKE-HASH will persist hashes there. No file I/O is performed at construction time.
revocation-store-contains-p
(revocation-store-contains-p store hash-32-bytes)
Return T if HASH-32-BYTES has been revoked in STORE, NIL otherwise. HASH-32-BYTES must be a 32-byte octet vector (EQUALP comparison).
revoke-hash
(revoke-hash store hash-32-bytes)
Add HASH-32-BYTES (a 32-octet vector) to the revocation store.
The hash is added to the in-memory table immediately. If STORE has a backing file (PATH non-nil) the hash is also appended to that file; if the file does not yet exist it is created with mode 0600 (matching the custody keyfile discipline — the revoked-hash list must not be readable by other processes).
Returns (VALUES) — no meaningful return value.
Variables
*eviction-hook*
A function of one argument (HASH-32-BYTES) called by REVOKE-HASH after the hash is persisted. Set by start-fabric to #'evict-by-hash from the assembler package; cleared by stop-fabric.
This seam breaks the compile-time dependency cycle: revocation is upstream of assembler (verifier → cap → assembler → root; verifier also imports revocation), so revocation cannot import assembler back. Fabric is downstream of both and installs the hook at start time, matching the base-view-fn pattern in root.
Package valis/src/capability/token
Classes
capability-token
Immutable UCAN-mould capability token. Carries the grant (issuer, audience, capabilities, expiry, nonce) plus the cryptographic proof (signature, canonical-hash) and the ancestry (inline proof chain). All slots are reader-only; the minter constructs a complete instance with MAKE-TOKEN after obtaining the signature and hash from custody.
Generic functions
token-audience-did
(token-audience-did object)
Undocumented: this exported symbol needs a docstring.
token-bound-generation
(token-bound-generation object)
Undocumented: this exported symbol needs a docstring.
token-canonical-hash
(token-canonical-hash object)
Undocumented: this exported symbol needs a docstring.
token-capabilities
(token-capabilities object)
Undocumented: this exported symbol needs a docstring.
token-expiry
(token-expiry object)
Undocumented: this exported symbol needs a docstring.
token-issuer-did
(token-issuer-did object)
Undocumented: this exported symbol needs a docstring.
token-nonce
(token-nonce object)
Undocumented: this exported symbol needs a docstring.
token-proofs
(token-proofs object)
Undocumented: this exported symbol needs a docstring.
token-signature
(token-signature object)
Undocumented: this exported symbol needs a docstring.
Functions
make-token
(make-token issuer-did audience-did capabilities proofs expiry nonce signature canonical-hash &optional (bound-generation 0))
Construct a CAPABILITY-TOKEN from the supplied fields.
ISSUER-DID, AUDIENCE-DID: non-empty DID strings. CAPABILITIES: a list of MOUNT-DIRECTIVE objects. PROOFS: a list of parent CAPABILITY-TOKEN objects (empty list for root tokens), ordered immediate-parent first through to the owner-issued root last. EXPIRY: a positive Unix timestamp (nil or zero expiry is rejected — expiry is mandatory on every token). NONCE: a 16-byte octet vector. SIGNATURE: a 64-byte Ed25519 signature over TOKEN-CANONICAL-BYTES. CANONICAL-HASH: a 32-byte SHA-256 hash of (canonical-bytes then signature). BOUND-GENERATION: the head generation current at mint time, stamped inside the signed canonical bytes. A non-negative integer below 264. Defaults to 0 (the genesis generation, which is never fenced) so a caller that does not carry a head still mints a valid genesis-stamped token.
Signals an error if EXPIRY is non-positive, BOUND-GENERATION is out of range, or any fixed-width field is the wrong length — the value type fails closed rather than emit canonical bytes a conformant verifier cannot reconstruct.
token-canonical-bytes
(token-canonical-bytes tok)
Produce the deterministic octet vector encoding TOK's grant fields — the bytes the token signature covers. Proofs are excluded: the canonical encoding covers this token's own claim, not its ancestry. Two calls with the same field values return EQUALP vectors.
A thin adapter: it reads TOK's slots and delegates the byte layout to the shared hekate token-wire codec, so valis and every sister that marshals a token lay down byte-identical canonical bytes. Capabilities are handed over as (designation . rights-bitmask) pairs, the field shape hekate's encoder takes.
token-expired-p
(token-expired-p tok)
Return T if TOK's expiry (a Unix timestamp) is in the past.
unix-now
(unix-now &aux (ut (get-universal-time)))
Current time as a Unix timestamp (seconds since 1970-01-01T00:00:00Z).
Package valis/src/capability/verifier
Functions
token-grant-hash
(token-grant-hash tok)
The 32-byte revocation identity of capability token TOK: SHA-256 of (canonical-bytes || signature). This is the hash the revocation store is keyed by, so recording it at mint time and revoking it later name exactly the token the verifier rejects — the minter, the revocation store, and the enrolled-client record all agree on one encoding because they all call this. Exported so the mint-on-proof driver records the grant hash the verifier will consult, without re-deriving the format.
verify-capability-name-sig
(verify-capability-name-sig name-string owner-ed25519-pub-bytes revocation-store)
Verify a capability name string against the owner's Ed25519 public key.
NAME-STRING is a "valis:"-prefixed bearer name. OWNER-ED25519-PUB-BYTES is the 32-byte raw Ed25519 public key that signed it. REVOCATION-STORE is consulted to detect revoked names (revocation applies to names too).
The generation a write-bearing name was bound to is a field on the name — stamped inside the owner-signed canonical bytes at mint time — not a caller- supplied argument. When the name carries the write right, it is fenced using the stamp read from the decoded name: a write-bearing name minted under a superseded generation is rejected on the same revocation store that holds revoked name hashes, so the two share one membership test and cannot drift. A read-only name never reaches the fence path. A write-bearing name whose stamp is missing is rejected (fail closed); the codec normally guarantees the stamp is present.
Returns (values mount-directive nil) if valid; the mount-directive carries the decoded designation and rights for use by the namespace assembler. Returns (values nil reason-string) on any failure. All conditions are caught internally.
verify-token-chain
(verify-token-chain token owner-ed25519-pub-bytes revocation-store)
Verify a capability token chain against the owner's Ed25519 public key.
TOKEN is the leaf (or sole) token; its PROOFS list carries parent tokens forming an inline chain. OWNER-ED25519-PUB-BYTES is the 32-byte raw Ed25519 public key of the owner who issued the root token. REVOCATION-STORE is a REVOCATION-STORE object consulted for every token.
The generation a write authority was bound to is a field on the capability — stamped inside the owner-signed canonical bytes at mint time — not a caller- supplied argument. When the leaf token carries the write right, the chain is fenced using the stamp read from the token: a write capability minted under a superseded generation is rejected on the same revocation store that holds revoked token hashes, so the fence and the revocation log share one membership test and cannot drift. A read-only capability never reaches the fence path. A write- bearing token whose stamp is somehow missing is rejected (fail closed); the codec normally guarantees the stamp is present.
Returns (values T nil) if the chain is valid. Returns (values nil reason-string) on any failure. All conditions are caught internally — callers never receive an unhandled signal.