Policy Spec
What a principal may do, written as a TOML file: its grants, each some actions on some resources, and its limits. The same file is an API key's scopes, a role, an agent's grants beyond its sandbox, and what a host lets a guest it accepted do. What it doesn't grant is refused.
Every option
name and version are needed, and every other key is optional.
# ci.toml
name = "ci"
version = 1
# A grant: every action it names, on every resource it names.
[[allow]]
actions = ["cloud.read", "cloud.use"]
on = ["cloud:aws", "cloud:ci-*"]
[[allow]]
actions = ["box.*"]
on = ["box:ci-*"]
# How much: each left out is no limit but the service's own.
[limits]
boxes = 2 # boxes at once
cpus = 4 # CPUs a box
memory_gb = 8 # memory a box, in GB
disk_gb = 40 # disk a box, in GB
hours = 12 # how long a box livesA policy holds at most 64 grants. A key it doesn't have is refused by its name, as an empty table is.
Actions
An action is <kind>.<verb>, from one list: a verb the list doesn't
hold can't be granted or checked. Three verbs a kind: what's read,
what's used, what changes it.
Agent actions
agent.read reads an agent's status and logs, agent.message messages
it (a teammate's message, a post to its webhook), and agent.admin
starts, stops, moves it or changes its spec.
Team actions
team.read reads a team, team.member is on it (its chats, its
folder, its spec), and team.admin changes who's on it and what each
reaches.
Bucket actions
bucket.read reads and lists a bucket or a path of it, bucket.write
writes there, and bucket.share shares it. A path is the resource's id
after the bucket's, bucket:team-r7/drafts/, and a pattern reaches what
it begins, bucket:team-r7/drafts/*.
Cloud actions
cloud.read reads a cloud's boxes and limits. cloud.use has boxes
made on it within those limits, and cloud.admin accepts it and changes
who may use it.
Box actions
box.read reads a box, box.ssh reaches it over SSH, and box.admin
makes, deletes or resizes it. These verbs apply to box resources rather
than cloud resources.
Grant patterns
A grant's actions takes an action, <kind>.* (every verb of a
kind), or * (every action, the owner's). Its actions and its
resources are of one kind: box.ssh on cloud:aws is refused.
Resources
A resource is named by its id, <kind>:<id>; another account's is
<account>/<kind>:<id>, as in acct-7f3a/cloud:mac. A name without an
account is the principal's own account's.
Resource patterns
A grant's on takes a name or a pattern. A * ends a pattern or is
one; nothing else is a pattern, so a grant reads as what it reaches.
One resource
cloud:aws reaches that cloud alone. cloud:ci-* reaches every cloud
whose id begins ci-, within the principal's account unless an account
is named explicitly.
Clouds of one or every account
cloud:* reaches every cloud of the principal's account. */cloud:*
reaches clouds of any account where the resource's [access] lets the
principal in.
Every resource of the account
* reaches everything of the principal's account. Cross-account access
still needs an account-qualified pattern and the resource's own
[access] permission.
Principals
Each principal has a permanent id, <kind>:<id>, its id after its kind
of the characters A-Z a-z 0-9 . _ : / -, at most 128:
Signed-in principals
person: identifies a signed-in person, and machine: identifies a
machine by its machine key. Both principals end when they are signed
out.
Agent principals
agent: identifies an agent wherever it runs. Its identity remains
with the agent while it exists, and the principal ends when the agent
is removed.
Principals with an expiry
api-key: identifies an API key and always expires. guest: is issued
by a self-hosted host, without an account service, for a cloud session
it accepted; a guest always expires, in hours.
Roles
A role is a Policy Spec given to principals: each holder may do what
the role grants as if its own policy granted it, and a change to the
role reaches every holder at once. A role is named by its name,
lowercase letters, digits and -, which never changes: a renamed role
is a new one. A role's pattern on agents, teams or buckets ends a
segment, * alone or after a / (bucket:team-r7/*), since their ids
are made, not chosen, and one beginning as another does is another's. A check allowed by a role says so, as "allowed by grant 1
of the role research".
A resource's [access]
A resource reached from outside its account says who in its own spec,
in one section every resource's spec shares, a verb of its kind to a
list: * (anyone), an account (acct-<id>, every principal of it) or
a principal. A cloud's [access] with use = ["acct-7f3a"] lets every
principal of that account have boxes made on it, when their own
policy allows it too. Inside the account, the principal's policy alone
decides, and [access] isn't read.
Policy boundaries
A policy states grants and limits. Its principal and the service that holds it determine when it ends and who receives it; the policy keeps no separate deny or conditional rule system.
- No deny rules. What isn't granted is refused; a narrower principal is made rather than a wider one denied.
- No conditions on a grant. No address, time or hours: an end is
the principal's, and how much is
[limits]. - Not who it's given to. The service that holds the principal holds which policy it has.
The cases every check is held to are in tests/specs/policy/
of this workspace, each a policy and the answers it gives.
Checked reference
The field names below come from link_iam::Policy. Optional values remain unset
until the feature resolves its environment or inherited settings.
root: allow, limits, name, version
allow: actions, on
limits: boxes, cpus, disk_gb, hours, memory_gbChecked defaults
These values come from the shipped defaults, including nested settings. Omitted optional values have no stored default at this layer.
limits = {}