esdb_capability (reckon_gater v1.1.2)

View Source

Capability token creation, signing, and delegation

Provides functions for creating UCAN-inspired capability tokens that grant specific permissions to specific audiences. Tokens can be delegated with attenuation (reduced permissions).

Token Lifecycle

1. Create: Build a capability with issuer, audience, and grants 2. Sign: Sign with issuer's private key 3. Encode: Serialize to JWT or Erlang binary format 4. Transmit: Send with request to server 5. (Server) Verify: Check signature, expiry, revocation, permissions

Delegation

Tokens can be delegated to create child tokens with reduced permissions. The child token includes a proof reference to the parent token. Permissions can only be attenuated (reduced), never expanded.

Example

Create and sign a capability:

Issuer = esdb_identity:generate(), Audience = esdb_identity:generate(), Grants = [esdb_capability:grant(Resource, Action)], Cap = esdb_capability:create(Issuer, Audience, Grants, #{ttl => 900}), SignedCap = esdb_capability:sign(Cap, esdb_identity:private_key(Issuer)), Token = esdb_capability:encode(SignedCap, jwt).

Summary

Functions

Check if grants are attenuated (subset of parent)

Get the audience DID

Create a capability token with default TTL

Create a capability token with options

Decode a capability from either format (auto-detected)

Delegate a capability to a new audience with attenuated grants

Encode capability to default format (Erlang binary)

Encode capability to specified format

Get the expiration timestamp

Create a capability grant

Get the capability grants

Check if the capability is expired

Get the issuer DID

Get the proof chain (parent token CIDs)

Sign a capability token with the issuer's private key

Types

capability/0

-type capability() ::
          #capability{alg :: binary(),
                      typ :: binary(),
                      iss :: binary(),
                      aud :: binary(),
                      nbf :: integer() | undefined,
                      exp :: integer(),
                      iat :: integer(),
                      nnc :: binary(),
                      att :: [capability_grant()],
                      fct :: map(),
                      prf :: [binary()],
                      sig :: binary() | undefined}.

capability_grant/0

-type capability_grant() :: #{with := binary(), can := binary()}.

identity/0

-type identity() ::
          #identity{did :: binary(), public_key :: binary(), private_key :: binary() | undefined}.

Functions

attenuate(ChildGrants, ParentGrants)

-spec attenuate([capability_grant()], [capability_grant()]) ->
                   {ok, [capability_grant()]} | {error, term()}.

Check if grants are attenuated (subset of parent)

audience(Capability)

-spec audience(capability()) -> binary().

Get the audience DID

create(Issuer, Audience, Grants)

-spec create(identity(), identity() | binary(), [capability_grant()]) -> capability().

Create a capability token with default TTL

create(Issuer, Audience, Grants, Opts)

-spec create(identity(), identity() | binary(), [capability_grant()], map()) -> capability().

Create a capability token with options

Options: - ttl: Time to live in seconds (default: 900 = 15 minutes) - nbf: Not before timestamp (default: now) - facts: Additional claims map (default: #{})

decode(Bin)

-spec decode(binary()) -> {ok, capability()} | {error, term()}.

Decode a capability from either format (auto-detected)

delegate(ParentCap, NewAudience, AttenuatedGrants)

-spec delegate(capability(), identity() | binary(), [capability_grant()]) -> capability().

Delegate a capability to a new audience with attenuated grants

The new capability will include a proof reference to the parent capability. The grants must be a subset of (or equal to) the parent's grants.

delegate(Capability, NewAudience, AttenuatedGrants, Opts)

-spec delegate(capability(), identity() | binary(), [capability_grant()], map()) -> capability().

Delegate with options

encode(Cap)

-spec encode(capability()) -> binary().

Encode capability to default format (Erlang binary)

encode(Capability, Format)

-spec encode(capability(), binary | jwt) -> binary().

Encode capability to specified format

Formats: - binary: Erlang term_to_binary (compact, fast, BEAM-only) - jwt: JSON Web Token format (interoperable)

expires_at(Capability)

-spec expires_at(capability()) -> integer().

Get the expiration timestamp

grant(Resource, Action)

-spec grant(binary(), binary()) -> capability_grant().

Create a capability grant

grants(Capability)

-spec grants(capability()) -> [capability_grant()].

Get the capability grants

is_expired(Capability)

-spec is_expired(capability()) -> boolean().

Check if the capability is expired

issuer(Capability)

-spec issuer(capability()) -> binary().

Get the issuer DID

proof_chain(Capability)

-spec proof_chain(capability()) -> [binary()].

Get the proof chain (parent token CIDs)

sign(Capability, PrivateKey)

-spec sign(capability(), binary()) -> capability().

Sign a capability token with the issuer's private key