Biscuit authorization

Space and Time relies on biscuits to support decentralized authorization. This page describes how biscuits are used in the platform.

To learn more about biscuit authorization and generating biscuits, check out this blog post.


Biscuits are used to authorize access to resources (e.g. tables) and are associated with a public/private key pair. Public keys are provided when the user creates a resource and are used to validate biscuit signatures during request authorization. Users create and attenuate their own tokens (using the corresponding private key) without involving the platform. A biscuit must contain, at minimum, a single capability specifying what operation is allowed on which resource.
For more information on biscuits, please see the official Biscuit documentation.

Public Key Cryptography

Biscuit authorization is based on public key cryptography, meaning each biscuit is associated with a public key and private key. The private key is used to sign the biscuit during creation, and the public key is used to validate the biscuit. When creating a table, you must specify a public key. It will be used to validate signatures on all biscuits provided during request authorization thereafter, and the public key cannot be changed. Make sure to keep your private key safe, as anyone with access can generate biscuits with any level of authority.


Biscuit public/private keys are independent of user public/private keys. Do not use the keypair you use for authentication for resource authorization.

Biscuit Standards

This section outlines the biscuit standards supported by Space and Time.


We are working on adding new standards to enable even more authorization support. Check back soon!


Operations define what action is being performed in a request. They are defined as follows:


The $operation must be a string and match one of the below:

  • SQL operations:
    • DDL: for operating on database objects & schema (e.g. table, view)
      • ddl_create : SQL CREATE command
      • ddl_alter : SQL ALTER command
      • ddl_drop : SQL DROP command
    • DML: for performing data manipulation
      • dml_insert : SQL INSERT command
      • dml_update : SQL UPDATE command
      • dml_merge : DQL MERGE command
      • dml_delete : SQL DELETE command
    • DQL: for performing queries
      • dql_select : SQL SELECT command
  • Kafka ICM operations:
    • kafka_icm_create : ICM create
    • kafka_icm_read : ICM read
    • kafka_icm_update : ICM update
    • kafka_icm_delete : ICM delete


Resourced define what is being accessed in a request. They are defined as follows:


The $resource must be a lowercase string and match a valid, existing resource.

  • SQL resources: It must include the full resource identifier (i.e., it must include both the namespace and resource name). As an example, the Transactions table in the ETH namespace would be eth.transactions.
  • Kafka ICM resources:
    • kafka_icm_infrastructure_group : Kafka infrastructure groups
    • kafka_icm_user : Kafka users
    • kafka_icm_acl : Kafka ACLs
    • kafka_icm_topic : Kafka topics
    • kafka_icm_topic_mapping_config : Kafka topic mapping configuration


Capabilities define what operation is allowed on a given resource, enabling easy specification of a operation-resource matrix. They are defined as follows:

capability($operation, $resource);

The $operation must conform to Operation requirements, and the $resource must conform to Resource requirements.

Working with Biscuits

Biscuit manipulation (creating, testing, attenuating, etc.) does not involve the platform, meaning you can create biscuits however you want, whenever you want. Please refer to the biscuit cli guide for more details on how to operate on biscuits on your local machine. The only requirement to create a biscuit is to have access to the appropriate private key. If you use the wrong private key, your biscuit signature won't be valid for the desired table.

Let's say you just created a table called TEST.CUSTOMER and want to give yourself read-write access. You would specify the following payload in your biscuit:

capability("dql_select", "test.customer");
capability("dml_insert", "test.customer");
capability("dml_update", "test.customer");
capability("dml_delete", "test.customer");

If you later decide you want to give your friend access to query your table, you have two options. You can either generate a new biscuit with only the dql_select capability, or you can attenuate your existing biscuit. Note that biscuits can never grow in scope, they can only become more restrictive (i.e., attenuated). So if you share a biscuit with someone else, they can never add new capabilities!


Biscuit specifications allow for namespacing facts. We're working on adding namespacing support across the platform for all SxT standards to help prevent potential future collisions. We'll work with Controlled Release customers when it's time to transition, but in case you're wondering what our updated namespaces will look like, see the below (we're just adding the sxt: prefix):

sxt:capability($operation, $resource);