.actor
Authorisation
Actors, capabilities and obligations
consumed byphero-backend-cedar
Who may do what: actors, delegation, capability grants with typed when conditions, obligations, and Cedar policy generation.
Why it exists
What .actor is for
Policy can live in a standalone .actor file beside the domain it governs: the file imports one or more .mox domains and declares actors, capabilities, grants, obligations and separation-of-duty constraints.
The compiled policy set is the union of the file’s blocks followed by every imported domain’s inline actors blocks, so capabilities and when conditions type-check against the real classes and the separation-of-duty checks span files. A construct the decidable subset cannot express is a generate-time error naming the capability — never a quietly weakened rule.
Vocabulary
What it models
The concepts .actor declares, and what each one means to the compiler.
- actor / agent
- A principal.
agentdeclares an autonomous LLM agent,actora human; a declared kind is inherited down anextendschain. - extends
- Confers authority: an actor’s effective permits are its own grants plus its ancestors’.
- capability … on …
- A named action bound to a domain class. That class is what the capability’s
whenconditions are typed against. - grant
- A block of
permitandforbidentries, optionally guarded bywhen (…), a session-kind modifier, and obligations. - when
- A typed boolean guard over the capability’s class. Only the decidable subset survives Cedar generation.
- obligation
- A declared duty, referenced by name from a grant entry.
- never_both
- A separation-of-duty pair: no principal may hold both capabilities.
- delegation
- A grant made
toanother principal — one hop, checked structurally. - cedar { … }
- An escape hatch for a rule the DSL cannot express, carried verbatim into the generated policy.
Source
A working example
Quoted from the example this page's artifact was compiled from — not a snippet written for the website.
Lines 9–25 of examples/support/support.actor, reproduced byte for byte, read from the file at build time:
capability ReadTicket on Ticket
capability UpdateTicket on Ticket
capability ResolveTicket on Ticket
capability RaiseRefund on Ticket
capability ApproveRefund on Ticket
obligation audit
obligation notifyCustomer
grant Customer {
permit ReadTicket when (!internal)
}
grant Agent {
permit ReadTicket
permit UpdateTicket when (!internal) obligation audit
permit RaiseRefund when (refundCents > 0 && refundCents <= 5000) obligation audit obligation notifyCustomer
}Five capabilities on `Ticket`, two declared obligations, and the `Customer` and `Agent` grants: an unconditional permit, a guarded one, and one that attaches both obligations.
The whole file is CI-tested: pherolang check examples/ checks every surface in the tree, and the example harness compiles each one on every run. What you see above is the input to the artifact below.
Neighbours
How it relates to the other surfaces
A .actor file is a policy dimension over imported domains, not a second model of them. .ddd service operations name these capabilities by name only, .uc checks requires: against the permits held by the participating actors (and refuses a never_both pair), .cmmn roles bind to actor names, and .ifml resolves requires: and roles: against the capability and actor tables union-wide.
Commands
How to compile and validate
Three commands, one file. They run from the repository root against the example on this page.
pherolang check examples/support/support.actor
pherolang ir examples/support/support.actor -o site/data/artifacts/actor.json
pherolang artifact check site/data/artifacts/actor.jsoncheck parses, resolves, validates and type-checks the file and printsOK examples/support/support.actor. ir writes the artifact and prints nothing on success. artifact check then validates the serialized JSON on its own — no model, no import resolution, no compiler — and prints OK site/data/artifacts/actor.json.
Directories work too: pherolang check examples/ enters project mode and checks every supported surface under the tree, each file's imports resolving from the snapshot.
Artifact
What it produces
One versioned JSON artifact, emitted by the compiler and consumed by whatever reads this surface.
One ActorModel: the block with its actors, capabilities, grants, obligations and neverBoth pairs — the artifact the Cedar backend consumes.
The artifact is site/data/artifacts/actor.json, and it is committed here exactly as the released pherolang binary emits it. Its top-level shape:
blocks1 entry
Provenance
- formatVersion = 2
- The compatibility gate. A reader accepts this number or refuses the file.
- pheroVersion — not present
- This standalone surface artifact is versioned on its own
formatVersion; only the domain model artifact carries the compiler-version stamp. - 3,794 bytes
- 162 lines, two-space indented, in the file's own key order.
The compiled artifact
The first 21 of 162 lines, verbatim — the exact bytes pherolang ir writes, not a hand-written sample. The slice stops at a JSON boundary; the ellipsis marker is outside the JSON, and the full file is site/data/artifacts/actor.json.
artifacts/actor.json · lines 1–21
{
"formatVersion": 2,
"blocks": [
{
"name": "Support",
"actors": [
{
"name": "Customer"
},
{
"name": "Agent",
"extends": "Customer"
},
{
"name": "Manager",
"extends": "Agent"
},
{
"name": "Finance"
}
],… 141 more lines in site/data/artifacts/actor.json
Regenerate it from the repository root — the second command validates the serialized bytes with no compiler in the loop:
pherolang ir examples/support/support.actor -o site/data/artifacts/actor.json
pherolang artifact check site/data/artifacts/actor.jsonThe whole data directory is regenerated by node scripts/sync-model.mjs (run from site/) with the released binary; CI fails on a one-byte difference.
Reference
Documentation
The normative reference for this surface, rendered from the repository's own documentation.
docs.pherolang.com
Authorisation reference
Generated from docs/LANGUAGE.md in the repository. The page above summarises it; the reference is normative.