Action Type DSL
The Action Type DSL defines action types declaratively. Each type configures field constraints, content validation, processing behavior, lifecycle hooks, and permissions without touching the core processing pipeline. All built-in definitions live in cloudillo-action (dsl/definitions.rs) and are validated at compile time.
ActionDefinition Structure
Each action type is an ActionDefinition:
The action type code in the JWT t claim combines type and subtype as TYPE:SUBTYPE (e.g., POST:IMG, REACT:LIKE, CONN:DEL). The DEL subtype is the conventional delete/revoke marker.
Field Constraints
Only five fields are configurable, and only their optionality — the field types are fixed:
Each field is Required, Forbidden, or — when omitted — optional:
| Constraint | Meaning |
|---|---|
Required |
Field must be present and valid |
Forbidden |
Field must be absent |
| (omitted) | Field is optional |
The content field is additionally validated against the optional schema (string length, enum, or object properties).
Behavior Flags
Behavior flags control how an action is processed and delivered. The implemented flags:
| Flag | Description |
|---|---|
broadcast |
Send to all followers when posting to own wall (no audience) |
allow_unknown |
Accept actions from non-connected/non-following senders |
ephemeral |
Don’t persist; forward to WebSocket only (e.g. PRES) |
approvable |
Can receive an APRV approval; enables auto-approve for trusted sources |
requires_subscription |
Child actions require a valid SUBS subscription |
subscribable |
This action can have SUBS pointing to it (CONV) |
deliver_subject |
Deliver the subject action alongside this one |
deliver_to_subject_owner |
Also deliver to the subject’s owner (INVT, REPOST) |
default_flags |
Default capability flags applied at creation (e.g. rco) |
gated_by_parent_flag |
Reject if the parent’s flags disable this action (e.g. C for CMNT) |
gated_by_subject_flag |
Reject if the subject’s flags disable this action (e.g. R for REACT) |
Note
requires_acceptance, local_only, ttl, sync, and federated exist in the struct but are reserved and not yet implemented.
Hooks
Hooks run native Rust logic at four lifecycle points. In the DSL definitions they are declared as HookImplementation::None; the actual native implementations are wired up through a registry (native_hooks/).
Permissions
can_create / can_receive hold named rule strings ("authenticated", "any", "followers"). The requires_* booleans add relationship gates.
Key Pattern
key_pattern is a template that produces the database key used to deduplicate and override actions. A new action with the same key supersedes the previous one. Templates interpolate {type}, {issuer}, {audience}, {subject}, {parent}, and content fields like {content.name}.
| Type | key_pattern |
Effect |
|---|---|---|
| POST, CMNT, CONV | None |
Every action is unique (action ID is the identity) |
| REACT, SUBS | {type}:{subject}:{issuer} |
One per user per subject |
| CONN, FLLW | {type}:{issuer}:{audience} |
One per user per target |
| REPOST | {type}:{subject}:{issuer}:{audience} |
One per subject per target wall |
| STAT | {type}:{parent} |
One stat row per action |
Override example: Alice LIKEs a post, then changes to LOVE. Both REACT tokens share the key REACT:{subject}:alice.example.com, so the LOVE token supersedes the LIKE.
Validation Flow
When an action is created or received, it is validated against its definition:
- Check field constraints (
Requiredpresent,Forbiddenabsent) - Validate the
contentfield againstschema - Apply behavior gates (
gated_by_parent_flag,gated_by_subject_flag,requires_subscription) - Enforce permissions (
allow_unknown,requires_following/requires_connected)
See Also
- Actions & Action Tokens - Overview of the action system
- Action Delivery - How actions are distributed
- ABAC Permissions - Permission system