Privacy and bubbles

The document and records contain fields and formulas that are privacy checked before they can be viewed by users. This section outlines how data is exposed to users. At the core, each field is prefixed with a privacy modifier.

publicAnyone can see it
privateNo one can see it
viewer_is<field>Only the viewer indicated by the given field is able to see it
use_policy<policy>Validate the viewer can witness the value via code; policies are defined within documents and records via the policy keyword.

These modifiers are great for revealing simple data common between all viewers of the document. Viewer-dependent data is achievable via a privacy bubble using the bubble keyword.

record Row {
  // it's public
  public int pub;

  // it's private, no one can see it
  private int pri;

  // a private person
  private principal who;

  // data that is only visible to the who
  viewer_is<who> int whos_age;

  // a custom policy based on code
  use_policy<my_policy> int custom;

  // defining the policy
  policy my_policy(c) {
    return pub < pri;

  require p1;

table<Row> tbl;

// reveal mine via a formula where me represents the client viewing the document
bubble mine = iterate tbl where who == @who;

Diving Into Details


The private modifier hides data from users. The public modifier discloses data to users. If no modifier is specified, the default is private.


Inside the angle brackets denotes a variable local to the document or record which must be of type client. For instance:

principal owner;
viewer_is<owner> int data_only_for_owner;

Here, the field owner is referenced via the privacy modifier for data_only_for_owner such that only the device/client authenticated can see that data.

use_policy<> & policy

As visibility may depend on some intrinsic logic or internal state, use_policy will leverage code outlined via a policy. This code is then run when the client wishes to see the data.

record Card {
  // some internal state
  private bool played;

  // who owns the card
  private principal owner;

  // the value of the card
  use_policy<is_in_play> value; // 0 to 51 for a standard playing deck

  // who can see the card
  policy is_in_play(who) {
  	// if it has been played, then everyone knows
  	// otherwise, only the owner can see it
  	return played || owner == who;


While privacy policies ensure compliance, we can leverage bubbles to efficiently query the document based on the viewer.

table<Card> deck;

bubble hand = iterate deck where owner == @who;