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.