action|resource
object:read|documents/tutorial/welcome.txt
Pattern form | Behaviour |
|---|---|
Exact string | documents/tutorial/welcome.txt matches only that resource. |
Trailing * | documents/tutorial/* matches any required resource beginning with documents/tutorial/. It is simple prefix matching. |
Global * | Matches every resource string. It exists in the implementation, but ordinary application credentials should not use it. |
Needed by grant path | Why |
|---|---|
policy:grant on the target resource | Authorises writing the policy record. |
The delegated action on the same target resource | Prevents a caller from granting authority it does not already have. |
Term | Meaning |
|---|---|
Storage tenant | The Anvil tenant that owns the relationship records. Public callers may only use their authenticated tenant id. |
Authz realm | A namespace container within the storage tenant. The default realm id is default. The system realm id is system and belongs to Anvil's built-in admin model. |
Namespace | A product object type such as document, folder, or project. Internally, Anvil stores it with the realm prefix. |
Object id | The product object identifier within a namespace. |
Relation | The named relationship or permission, such as viewer, editor, or owner. |
Subject kind | Usually a product subject kind such as user, group, or userset. |
Subject id | The product subject id. For userset, the current format is namespace/object_id#relation. |
Tuple | One fact: namespace, object id, relation, subject kind, subject id, optional caveat hash, operation, and revision. |
Userset | A subject that points at another object relation, allowing nested relationship checks. |
Schema | A tenant-defined set of namespaces, relations, and relation rules. Current rules include inheritance, computed usersets, and tuple-to-userset forms. |
Schema binding | The active schema reference bound to an authz realm. Binding has a generation for CAS-style updates. |
Zookie | An opaque revision token for authz reads and checks. Current format is authz:<revision>. |
Consistency | Zookie requirement | Behaviour |
|---|---|---|
Empty or latest | None | Reads at the latest available authz revision. |
at_least | Requires authz:<revision> | Fails with AuthzRevisionUnavailable if the current revision is below the requested revision; otherwise reads latest. |
exact | Requires authz:<revision> | Reads at the exact requested revision if the retained journal can answer it. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Create bucket | bucket:create | Bucket name, for example documents | Region validity is a separate topology concern. |
Delete bucket | bucket:delete | Bucket name | Deletion also checks bucket emptiness/retention state. |
List buckets | bucket:list | * | Current coarse scope: there is no narrow "list only one bucket name" resource. |
Read bucket policy | bucket:read | Bucket name | Reads current bucket policy JSON. |
Set bucket public-read policy through Bucket service/public CLI | bucket:write | Bucket name | Public-read is a data exposure decision, not an admin bypass. |
Set public access through the Auth service method | policy:grant | bucket:<bucket> | Current secondary API shape; the public CLI uses the Bucket service path. |
Watch bucket metadata | bucket:watch | Bucket name, or * for all buckets in the tenant | API surface exists; current public CLI does not expose bucket metadata watch. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Put object | object:write | bucket/key, for example documents/tutorial/welcome.txt | Reserved _anvil/ object keys are rejected. |
Copy, compose, JSON patch, manifest CAS, multipart operations | object:write | Destination bucket/key | Source object reads may also need object read authority depending on the operation path. |
Delete current object or version | object:delete | bucket/key | Deletion is distinct from write. |
Get object body | object:read | bucket/key, or matching relationship object reader | Public-read buckets can permit anonymous reads through public surfaces. |
Head object | object:read | bucket/key, or matching relationship object reader | Returns current or requested version metadata depending on API field. |
List objects by prefix | object:list | Bucket name | Current coarse scope: prefix-specific object:list is not enforced by ordinary object listing. Results are then filtered by object read visibility on private buckets. |
List object versions | object:list | Bucket name | Public-read buckets bypass bearer-token list checks where the public route is used. |
Watch object prefix | object:list | Bucket name | Current coarse scope: watch authorisation is bucket-level, not prefix-level. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Create or update object link | object:write | bucket/link_key | The link is an alias descriptor, not a copy of the target object. |
Read object link metadata | object:read | bucket/link_key | Current public CLI exposes same-bucket links. |
Delete object link | object:delete | bucket/link_key | Update/delete also use link generation checks. |
List object links | object:list | bucket/prefix | Returned links are filtered by object:read on each bucket/link_key. This differs from ordinary object listing, which checks the bucket name. |
Create, verify, or delete tenant host alias | bucket:write | Bucket name | Host aliases map a hostname to a bucket/prefix; DNS, TLS, and reverse proxy setup are outside this scope. |
Read or list tenant host aliases | bucket:read | Bucket name | Listing filters aliases to buckets the caller can read. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Create tenant app credential | app:create | tenant:<tenant_id> | Current coarse scope: tenant-level, not per app name. |
List tenant apps | app:read | tenant:<tenant_id> | Needed before public CLI app list. |
Rotate tenant app secret | app:rotate_secret | tenant:<tenant_id> | Current coarse scope: tenant-level. |
Delete tenant app | app:delete | tenant:<tenant_id> | Current coarse scope: tenant-level. |
Read stored grants | policy:read | Grant resources being returned, plus tenant app-management read | Results are filtered to grants covered by policy read/grant/revoke. |
Grant policy | policy:grant plus delegated action | The resource being granted | Public delegation is non-escalating. |
Revoke policy | policy:revoke | The resource being revoked | Does not require holding the delegated action. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Write tuple | authz:tuple_write | namespace/object_id#relation | Tuple operation strings are add or remove. |
Batch write tuples | authz:tuple_write | Each tuple's namespace/object_id#relation | Batch must target one authz scope. |
Read tuples with full filter | authz:tuple_read | namespace/object_id#relation | Empty filter components broaden the resource as below. |
Read all tuples in namespace | authz:tuple_read | namespace | Current filter resource when object id and relation are empty. |
Read tuples for a relation across objects | authz:tuple_read | namespace/*#relation | Produced by the current filter-resource helper. |
Read tuples for all relations on one object | authz:tuple_read | namespace/object_id#* | Produced by the current filter-resource helper. |
Read all tuples | authz:tuple_read | * | Broad and should be avoided for application credentials. |
Check permission | authz:check | namespace/object_id#relation | Supports latest, at_least, and exact consistency in the API. |
List objects for subject/relation | authz:tuple_read | namespace/*#relation | Returns object ids reachable for the subject. |
List subjects for object/relation | authz:tuple_read | namespace/object_id#relation | Returns matching subjects. |
Put schema revision | authz:schema_write | Each namespace in the schema | Caller must cover every namespace supplied. |
Bind schema to realm | authz:schema_write | Authz realm id, for example default | Binding has an expected-generation field. |
Get schema by id | authz:schema_read | Schema id | Used by the schema-ref path. |
Get current namespace schema | authz:schema_read | Namespace, or * for all namespaces | Listing all schemas is broad. |
Get schema binding | authz:schema_read | Authz realm id | Reads the active binding for a realm. |
Watch tuple log | authz:watch | Namespace, or * if namespace is empty | Watch is scoped to the requested authz realm. |
Watch namespace schema events | authz:watch | Namespace | API-only watch surface. |
Watch derived authz lag | authz:watch | Derived index id | API-only watch surface. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Create index | index:create | bucket/index_name | Applies to path, metadata, typed JSON, full-text, vector, hybrid, and accepted source kinds. |
Update index | index:update | bucket/index_name | Also used by disable. |
Drop index | index:delete | bucket/index_name | Removes the definition. |
List indexes | index:read | Bucket name | Current coarse scope: not one index definition. |
Query index | index:read | Bucket name | Available as a non-authoritative preview in 0.4.0; completeness and freshness are not release-qualified. |
Index diagnostics | index:read | Bucket name | Available in 0.4.0. |
Watch index definitions | index:watch | Bucket name | Unavailable in 0.4.0. |
Watch index partitions | index:watch | Bucket name | Unavailable in 0.4.0. |
Watch surface | Action | Resource checked | Notes |
|---|---|---|---|
Bucket metadata watch | bucket:watch | Bucket name or * | API-only in current public CLI. |
Object prefix watch | object:list | Bucket name | Current scope is bucket-level, not prefix-level. |
Index definition watch | index:watch | Bucket name | Returns Unimplemented in 0.4.0. |
Index partition watch | index:watch | Bucket name | Returns Unimplemented in 0.4.0. |
Authz tuple watch | authz:watch | Namespace or * | Public CLI exposes tuple-log watch by namespace. |
Authz namespace and derived-lag watches | authz:watch | Namespace or derived index id | API-only surfaces. |
PersonalDB group/projection watch | personaldb:watch | PersonalDB resource or projection resource, or matching relationship | Public CLI exposes compact PersonalDB watch helpers. |
Git source watch | git_source:watch | repository:<repository_id> | Returns Unimplemented in 0.4.0. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Create append stream | object:write | bucket/stream_key | Stream key is object-like. |
Append record | object:write | bucket/stream_key | Uses object mutation context and optional write preconditions. |
Seal append stream segment | object:write | bucket/stream_key | Segment sealing is not a general close permission. |
Read append records | object:read or object:list | Bucket name | Current read path accepts either bucket-level object read or bucket-level object list. |
Tail append stream | object:read or object:list | Bucket name | Tail repeatedly uses the same read path. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Acquire task lease | coordination:lease_write | task_lease/<task_id> | Owner is derived from the authenticated caller and optional label; callers cannot spoof another principal. |
Checkpoint task lease | coordination:lease_write | task_lease/<task_id> | Fence token is checked by the service. |
Commit task lease | coordination:lease_write | task_lease/<task_id> | Completes the lease for the owning principal/fence. |
Read task lease | coordination:lease_read | task_lease/<task_id> | Read is separate from write. |
Force release task lease | coordination:lease_admin | task_lease/<task_id> | Tenant-scoped administrative lease release. |
Acquire, renew, transfer, or non-forced release ownership fence | coordination:lease_write | ownership/tenant-<tenant_id>/<resource_kind>/<resource_id> | API-only public ownership-fence surface. |
Force expire ownership fence or forced release | coordination:lease_admin | ownership/tenant-<tenant_id>/<resource_kind>/<resource_id> | Administrative tenant coordination action. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Create group | personaldb:create | tenant-<tenant_id>/<database_id> | Group identity is tenant-scoped. |
Read group | personaldb:read or relationship personaldb reader | tenant-<tenant_id>/<database_id> | Relationship fallback uses namespace personaldb, object id equal to the resource string, relation reader. |
Create projection | personaldb:create | tenant-<tenant_id>/<database_id>/projections/<projection_id> | Projection definition is tenant-owned. |
Read projection | personaldb:read or relationship personaldb_projection reader | Projection resource | Relationship fallback uses namespace personaldb_projection. |
Watch group/projection | personaldb:watch or relationship watcher | Group or projection resource | Watch relation is watcher. |
Submit changeset | personaldb:commit or relationship committer | Group resource | Session principal must match the authenticated bearer when a bearer is bound. |
Row effects | personaldb:insert, personaldb:update, personaldb:delete, or another parsed action from the verified effect | tenant-<tenant_id>/<database_id>/<resource_type>/<resource_id> | Effects can require additional scopes or relationship permissions per resource binding. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Create key | hf_key:create | Key name | Stores encrypted server-side credential material. |
Delete key | hf_key:delete | Key name | Removes a named key. |
List keys | hf_key:list | * | Current coarse scope: no narrow list resource. |
Start ingestion | hf_ingestion:create | * | Unavailable in 0.4.0. |
Read ingestion status | hf_ingestion:read | Ingestion id | Unavailable in 0.4.0. |
Cancel ingestion | hf_ingestion:delete | Ingestion id | Unavailable in 0.4.0. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Write source pack | git_source:write | Tenant administrator | Service stores pack objects under object storage internally; repository-scoped delegation is unavailable in 0.4.0. |
Read source query/blob data | git_source:read | repository:<repository_id> | Returns Unimplemented in 0.4.0. Read the stored pack through the authorised object API or S3 gateway. |
Watch source records | git_source:watch | repository:<repository_id> | Returns Unimplemented in 0.4.0. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Repair index | repair:run | bucket/index_name | Tenant-scoped repair. |
Repair directory index | repair:run | Bucket name | Tenant-scoped directory/path repair. |
Repair authz derived userset index | repair:run | tenant-<tenant_id>/authz/<derived_index_id> | Tenant-scoped authz derived repair. |
Repair PersonalDB log chain | repair:run | tenant-<tenant_id>/<database_id> | Tenant-scoped PersonalDB repair. |
List repair findings | repair:read | Scope id supplied in the request | Scope kind is separate metadata; the scope id is what is authorised. |
Public index diagnostics | index:read | Bucket name | There is no separate public diagnostics:* action today. |
Public tenant audit list | Authenticated tenant token only | Tenant id from claims | Current coarse surface: no separate public audit:* action is checked for tenant audit listing. Admin audit uses a system relation. |
Operation | Action | Resource checked | Notes |
|---|---|---|---|
Node-to-node object proxy | internal:proxy_object | Internal proxy resource | This is not user-facing tenant authority. Do not grant internal proxy actions to tenant applications. |
System relation | Admin operation families |
|---|---|
manage_tenants | Create storage tenants. |
manage_apps | Create and rotate tenant application credentials through the admin plane. |
manage_policies | Grant and revoke tenant public policy scopes through the admin plane. |
manage_secret_encryption_keys | Rotate server-side secret encryption envelopes. |
manage_buckets | Admin bucket creation and public-access changes. |
manage_regions | Region lifecycle plus cell register/activate/drain/remove/list. |
manage_nodes | Node register/activate/drain/force-offline/remove/list. |
manage_routing | List and repair materialised routing records. |
manage_host_aliases | Admin host-alias create/activate/suspend/delete/read/list. |
manage_links | Relation exists in the system schema; the current anvil-admin CLI does not expose an admin object-link family. |
run_repair | Run administrative repair jobs. |
view_diagnostics | List administrative diagnostics. |
view_audit_log | List administrative audit events. |
Goal | Action | Resource |
|---|---|---|
Create bucket documents | bucket:create | documents |
List tenant buckets | bucket:list | * |
Read or change public-read policy on documents | bucket:read / bucket:write | documents |
Write one object | object:write | documents/tutorial/welcome.txt |
Read one object | object:read | documents/tutorial/welcome.txt |
Delete one object | object:delete | documents/tutorial/welcome.txt |
List objects under any prefix in a bucket | object:list | documents |
Create or update link latest.txt | object:write | documents/releases/latest.txt |
Create app credentials in tenant 42 | app:create | tenant:42 |
Read app grants in tenant 42 | app:read and policy:read | tenant:42 plus covered grant resources |
Grant document read | policy:grant plus object:read | documents/tutorial/welcome.txt |
Create index by_status | index:create | documents/by_status |
Query any index in bucket documents | index:read | documents |
Watch index definitions in bucket documents | index:watch | documents |
Write tuple for document viewer | authz:tuple_write | document/doc-42#viewer |
Check document viewer | authz:check | document/doc-42#viewer |
Put schema for namespace document | authz:schema_write | document |
Bind default authz realm | authz:schema_write | default |
Acquire task lease import-docs | coordination:lease_write | task_lease/import-docs |
Read task lease import-docs | coordination:lease_read | task_lease/import-docs |
Create PersonalDB group notes in tenant 42 | personaldb:create | tenant-42/notes |
Commit PersonalDB changeset | personaldb:commit | tenant-42/notes |
Run index repair | repair:run | documents/by_status |
Read repair findings for an index scope | repair:read | Service-specific scope id |
Area | Current behaviour |
|---|---|
Bucket listing | bucket:list checks *, so there is no narrow resource for listing only one bucket name. |
Object listing and object prefix watch | object:list checks the bucket name. Prefix-specific list/watch grants are not enough for ordinary object listing. |
Public CLI upload helper | The CLI discovers the bucket id with ListBuckets, which can require broader bucket-list authority than the object write itself. The API/Rust client is better for strict least-privilege upload tests. |
Object links | Link list checks object:list on bucket/prefix, but ordinary object list checks only the bucket name. Keep the distinction clear in runbooks. |
Index read/query/diagnostics | index:read checks the bucket name, not bucket/index_name. Create/update/delete remain index-definition scoped. |
Index watches | index:watch checks the bucket name. |
App lifecycle | App create/read/rotate/delete checks tenant:<tenant_id>, not one app name. |
Policy listing | Requires app-management read at tenant level and filters returned grant records by policy coverage. |
Tenant audit listing | Current public tenant audit listing uses authenticated tenant identity and does not check a separate public audit action. |
HF key list | Key listing checks * within its action family. Ingestion RPCs are unavailable in 0.4.0. |
Authz caveats | Caveat hashes are stored and matched; expressions are not evaluated today. |
System realm management | The admin system realm is bootstrapped and checked by server code. There is no public tenant path to alter its schema. |