AppSpring Docs

Actions (ActionDecl)

Generated from the doc schema (CatalogDocSchema, @canonify/kernel-catalog/doc): each field’s type, default and description are the schema’s own, and each example is a bundle file that readBundle decodes. A field’s Example is its value in one of those examples.

ActionDecl

An action (runtime).

The actions slot of the doc holds these, keyed by id. In a bundle each is one file, actions/<name>.json, named by its name, which the file then leaves out.

Field Type Required Default Example Description
id ActionId yes (propose assigns it; a new declaration leaves it out) — — An action id (ac_…); renames keep it.
name Ident yes — "add_note" The action name.
label Text yes — "Add note" The words shown for it.
subject TypeId no — "ty_3f8v6h2n0c" The type of the row it runs on; absent = it runs on no row.
inputs InputDecl[] yes — (see the example) The inputs, in field order.
lets LetDecl[] no — [{"name":"line_count","value":"count(lines)"}] Named values, evaluated in order before the preconditions.
preconditions PreconditionDecl[] yes — (see the example) The conditions the call needs.
effects EffectDecl[] yes — (see the example) What the call does, in order, in one transaction.
outputs Record<Ident, Expr> no — {"lines":"line_count"} The CX value of each output the call returns.
approval ApprovalRule no — (see the example) The approval a call needs before it runs.
idempotency "key" | "none" no "key" "key" key: a repeated idempotency key replays the first answer (default); none: no key is accepted.
confirm ActionDecl.confirm no — (see the example) The call runs only when the caller confirms this message.
writeRights "invoker" | "action" no "invoker" "invoker" Whose rights the writes need: the invoker’s (default) or the action’s own, a declared widening.
limits ActionDecl.limits no — {"maxRowsWritten":100} The action’s own limits, under the platform’s.
presentation PresentationOverrides no — (see the example) The presentation keys the action overrides (pages).

actions/add_note.json

{
  "label": "Add note",
  "subject": "ty_3f8v6h2n0c",
  "inputs": [
    {
      "name": "note",
      "writes": { "type": "ty_3f8v6h2n0c", "prop": "pr_4p6r8t0v2x" }
    }
  ],
  "preconditions": [],
  "effects": [
    {
      "op": "update",
      "target": "this",
      "set": { "pr_4p6r8t0v2x": "input.note" }
    }
  ],
  "presentation": {
    "inputs": {
      "note": {
        "label": "Note for the kitchen",
        "help": "The kitchen reads it when it packs the order."
      }
    }
  }
}

actions/place_order.json

{
  "label": "Place order",
  "subject": "ty_3f8v6h2n0c",
  "inputs": [
    {
      "name": "delivery",
      "type": { "t": "date" },
      "label": "Delivery date",
      "required": true
    }
  ],
  "lets": [{ "name": "line_count", "value": "count(lines)" }],
  "preconditions": [
    {
      "id": "has_lines",
      "holds": "line_count > 0",
      "severity": "refuse",
      "message": { "text": "Add a line before you place the order." },
      "offer": true
    }
  ],
  "effects": [
    {
      "op": "transition",
      "target": "this",
      "lifecycle": "lc_2k4m6p8r0t",
      "transition": "tn_4g6j8m0p2r"
    }
  ],
  "outputs": { "lines": "line_count" },
  "approval": {
    "when": "total > 10000",
    "approvers": { "role": "admin" },
    "selfApproval": "forbidden"
  },
  "idempotency": "key",
  "confirm": {
    "message": {
      "text": "Place the order for {total}?",
      "params": { "total": "total" }
    }
  },
  "writeRights": "invoker",
  "limits": { "maxRowsWritten": 100 }
}

ActionDecl.confirm

The call runs only when the caller confirms this message.

Field Type Required Default Example Description
message MsgRef yes — (see the example) What the caller confirms.

ActionDecl.limits

The action’s own limits, under the platform’s.

Field Type Required Default Example Description
maxRowsWritten integer (greater than 0) no — 100 The most rows one call writes; at most the op ceiling.

InputDecl

An input of the action.

One of:

InputDecl.writes

An input that writes a property.

Field Type Required Default Example Description
name Ident yes — "note" The input name.
writes PropRef yes — {"type":"ty_3f8v6h2n0c","prop":"pr_4p6r8t0v2x"} The property it writes; its type, label and sensitivity come from there.
required boolean no — false Whether the caller must give it; absent = as the written property.
default Expr no — "''" The value when the caller gives none.
showWhen Expr no — "input.channel != 'web'" The input is shown (and accepted) only while this CX condition holds.
requiredWhen Expr no — "input.channel == 'phone'" The input is required while this CX condition holds.
options Expr no — "active" A ref input: the CX condition a target row must hold to be offered.

An item of inputs in an action file (actions/<name>.json).

{
  "name": "customer",
  "writes": { "type": "ty_3f8v6h2n0c", "prop": "pr_5n1v3x7c9d" },
  "required": false,
  "showWhen": "input.channel != 'web'",
  "requiredWhen": "input.channel == 'phone'",
  "options": "active"
}

An item of inputs in an action file (actions/<name>.json).

{
  "name": "note",
  "writes": { "type": "ty_3f8v6h2n0c", "prop": "pr_4p6r8t0v2x" },
  "default": "''"
}

InputDecl.type

An input with its own type.

Field Type Required Default Example Description
name Ident yes — "delivery" The input name.
type ValueType yes — {"t":"date"} What the input holds.
label Text yes — "Delivery date" The words shown for it.
required boolean no false true Whether the caller must give it; default false.
help Text no — "Shown to the customer." The help text shown with the field.
default Expr no — "''" The value when the caller gives none.
showWhen Expr no — "input.kind == 'other'" The input is shown (and accepted) only while this CX condition holds.
requiredWhen Expr no — "input.kind == 'other'" The input is required while this CX condition holds.
sensitive "personal" | "secret" no — "personal" Personal input is masked for readers without the right; a secret is never shown (authz C4).

An item of inputs in an action file (actions/<name>.json).

{
  "name": "reason",
  "type": { "t": "text", "format": "long" },
  "label": "Reason",
  "help": "Shown to the customer.",
  "required": false,
  "default": "''",
  "showWhen": "input.kind == 'other'",
  "requiredWhen": "input.kind == 'other'",
  "sensitive": "personal"
}

InputDecl.parts

The part rows of an owner type.

Field Type Required Default Example Description
name Ident yes — "lines" The input name.
parts TypeId yes — "ty_9d4r7t1x5b" The part type: rows owned by the subject (a Lines grid).
max integer (greater than 0) yes — 50 The most part rows one call may send.

An item of inputs in an action file (actions/<name>.json).

{ "name": "lines", "parts": "ty_9d4r7t1x5b", "max": 50 }

InputDecl.ref

An input that names a row of a type, which the action reads (a selector); CX reads it as a ref.

Field Type Required Default Example Description
name Ident yes — "bill_to" The input name.
ref TypeId yes — "ty_7k2m9q4z1a" The type of the row it names: the caller picks one row of this type (a selector the action reads).
label Text yes — "Bill to" The words shown for it.
required boolean no false false Whether the caller must give it; default false.
help Text no — "The customer the invoice goes to; the order keeps its own." The help text shown with the field.
default Expr no — "customer" The value when the caller gives none.
showWhen Expr no — "input.channel != 'web'" The input is shown (and accepted) only while this CX condition holds.
requiredWhen Expr no — "input.channel == 'phone'" The input is required while this CX condition holds.
options Expr no — "active" A ref input: the CX condition a target row must hold to be offered.

An item of inputs in an action file (actions/<name>.json).

{
  "name": "bill_to",
  "ref": "ty_7k2m9q4z1a",
  "label": "Bill to",
  "help": "The customer the invoice goes to; the order keeps its own.",
  "required": false,
  "default": "customer",
  "showWhen": "input.channel != 'web'",
  "requiredWhen": "input.channel == 'phone'",
  "options": "active"
}

InputDecl.items

A list of records whose fields are not the properties of one part type; CX reads it as a collection (input.lines).

Field Type Required Default Example Description
name Ident yes — "returns" The input name.
items InputFieldDecl[] (at least one) yes — (see the example) The fields of each record, in column order.
label Text yes — "Returned lines" The words shown for it.
required boolean no false true Whether the caller must give it; default false.
max integer (greater than 0) yes — 50 The most records one call may send.

An item of inputs in an action file (actions/<name>.json).

{
  "name": "returns",
  "items": [
    {
      "name": "line",
      "ref": "ty_9d4r7t1x5b",
      "label": "Line",
      "required": true
    },
    {
      "name": "qty",
      "type": { "t": "integer" },
      "label": "Returned",
      "required": true
    }
  ],
  "label": "Returned lines",
  "required": true,
  "max": 50
}

InputFieldDecl

A field of each record of an input list.

One of:

InputFieldDecl.type

A field with its own type.

Field Type Required Default Example Description
name Ident yes — "qty" The field name; CX reads it as l.<name> of each record.
type ValueType yes — {"t":"integer"} What the input holds.
label Text yes — "Returned" The words shown for it.
required boolean no false true Whether the caller must give it; default false.

An item of items in an input list of records (an item of inputs in an action file).

{
  "name": "reason",
  "type": { "t": "enum", "values": [{ "code": "damaged", "label": "Damaged" }] },
  "label": "Reason",
  "required": false
}

InputFieldDecl.ref

A field that names a row of a type.

Field Type Required Default Example Description
name Ident yes — "line" The field name; CX reads it as l.<name> of each record.
ref TypeId yes — "ty_9d4r7t1x5b" The type of the row it names: the caller picks one row of this type (a selector the action reads).
label Text yes — "Line" The words shown for it.
required boolean no false true Whether the caller must give it; default false.

An item of items in an input list of records (an item of inputs in an action file).

{ "name": "line", "ref": "ty_9d4r7t1x5b", "label": "Line", "required": true }

LetDecl

A named value of the action.

Field Type Required Default Example Description
name Ident yes — "line_count" The name everything after it reads.
value Expr yes — "count(lines)" The CX value.
rights Elevated no — (see the example) A widened read: the value is one aggregate over rows the invoker may not read.

An item of lets in an action file.

{ "name": "line_count", "value": "count(lines)" }

PreconditionDecl

A precondition of the action.

Field Type Required Default Example Description
id Ident yes — "has_lines" The precondition name: refusals and on-fail triggers name it.
holds Expr yes — "line_count > 0" The CX condition that must hold.
severity "refuse" | "warn" yes — "refuse" refuse stops the call; warn needs the caller to confirm.
message MsgRef yes — {"text":"Add a line before you place the order."} What the refusal says.
offer boolean yes — true Whether it also decides if the action is offered on a row; then it may not read input.
reveals true no — true The refusal may carry the values it compared (disclosable ones only).

An item of preconditions in an action file.

{
  "id": "within_limit",
  "holds": "total <= customer.credit_limit",
  "severity": "warn",
  "message": {
    "text": "The total passes the credit limit of {limit}.",
    "params": { "limit": "customer.credit_limit" }
  },
  "offer": false,
  "reveals": true
}

ItemPreconditionDecl

A condition each item of the forEach needs before the body runs for it.

Field Type Required Default Example Description
id Ident yes — "positive_amount" The precondition name: refusals and on-fail triggers name it.
holds Expr yes — "item.amount > 0" The CX condition that must hold.
severity "refuse" yes — "refuse" It stops the call (the only value: it is checked while the effects run).
message MsgRef yes — (see the example) What the refusal says.
reveals true no — true The refusal may carry the values it compared (disclosable ones only).

An item of preconditions in a forEach effect of an action file.

{
  "id": "positive_amount",
  "holds": "item.amount > 0",
  "severity": "refuse",
  "message": {
    "text": "Each line needs an amount above zero, not {amount}.",
    "params": { "amount": "item.amount" }
  },
  "reveals": true
}

ApprovalRule

The approval a call needs before it runs.

Field Type Required Default Example Description
when Expr no — "total > 10000" The call needs approval only while this CX condition holds; absent = always.
approvers Subject yes — {"role":"admin"} Who may approve: a role, a group or a member.
selfApproval "forbidden" yes — "forbidden" The requester may never approve their own call (the only value, R14).
expiresAfter integer (greater than 0) no — 604800000 How long a pending request waits, in milliseconds (C18); absent = 30 days.

The approval of an action file.

{
  "when": "total > 10000",
  "approvers": { "role": "admin" },
  "selfApproval": "forbidden",
  "expiresAfter": 604800000
}

Elevated

A widened read: one aggregate over rows the invoker may not read (authz Elevated).

Field Type Required Default Example Description
discloses Elevated.discloses yes — "count" The one aggregate the value may be: exists, count, or a sum, min or max of a property.
reason MsgRef yes — {"text":"Shows how many open orders exist."} Why the read is widened, shown in policies.effective.

The rights of an action’s let.

{
  "discloses": "count",
  "reason": { "text": "Shows how many open orders exist." }
}

The rights of an action’s let.

{
  "discloses": { "sum": { "type": "ty_3f8v6h2n0c", "prop": "pr_8b2f4h6j0k" } },
  "reason": { "text": "Shows the customer’s open balance." }
}

The rights of an action’s let.

{
  "discloses": { "min": { "type": "ty_6c8e0g2j4m", "prop": "pr_3a5c7e9g1j" } },
  "reason": { "text": "Shows when the room is next taken." }
}

The rights of an action’s let.

{
  "discloses": { "max": { "type": "ty_6c8e0g2j4m", "prop": "pr_9t1v3x5z7b" } },
  "reason": { "text": "Shows when the room is free again." }
}

Elevated.discloses

The one aggregate the value may be: exists, count, or a sum, min or max of a property.

One of:

Elevated.discloses.sum

The sum of a property.

Field Type Required Default Example Description
sum PropRef yes — {"type":"ty_3f8v6h2n0c","prop":"pr_8b2f4h6j0k"} The property it sums.

Elevated.discloses.min

The least value of a property.

Field Type Required Default Example Description
min PropRef yes — {"type":"ty_6c8e0g2j4m","prop":"pr_3a5c7e9g1j"} The property it takes the least of.

Elevated.discloses.max

The greatest value of a property.

Field Type Required Default Example Description
max PropRef yes — {"type":"ty_6c8e0g2j4m","prop":"pr_9t1v3x5z7b"} The property it takes the greatest of.

This page as Markdown