DSL reference
The quick lookup surface: one line and a minimal snippet per construct. For rules, edge cases and worked examples, follow the links into the specification.
| Construct | What it gives you |
|---|---|
entities | tables + CRUD UI + a generated data layer & API |
| field / relation attributes | uniqueness, layout, read-only, dropdown filtering, cascades |
entities.unique | a business key spanning more than one field or to-one relation |
visibleTo | an allow-list of roles that may read one field, enforced on the wire |
pattern | an input-format regular expression enforced in the UI and server-side |
defaultValue | a field default: column default, satisfies required, and seeds a new row in the UI |
dependsOn | link a dropdown to another, copy a value from the referenced record, or default a line from the open document header |
function | an explicit presentation role (Document, Setting, ...) |
label | a stored, read-only display name for lookups |
number | a platform-numbered, gap-free document field |
checks | cross-field / cross-line validations |
checks: kind: guard | a precondition over an aggregate: block, mark for a task, or reject |
immutableWhen / immutable | reject user writes in a status / append-only |
lifecycle | the whole legal status graph, enforced on every status write |
locksWithMaster | a child collection that stays writable while its master is locked |
history | a shadow, append-only trail of every write: property, old and new value, who, when, user or system |
hierarchy / leafOnly | tree entities, leaf-only references |
| calculated fields | server + UI-evaluated expressions, date helpers, call-outs |
relations / composition | associations and master-detail compositions |
uses | reuse entities owned by another intent model |
related | a read-only register of the records referencing this entity, on its own page |
processes | workflows: user tasks, decisions, waits, boundary timers |
| task assignment | route a user task to a role, the record owner, or a relation walk |
abortOn | cancel the running instance when the document reaches a terminal status |
function: Attachment / Snapshot | a Files panel / immutable versioned printed copies |
forms | task data-entry pages |
actions | developer-defined buttons opening custom pages |
view | an additional calendar / range page, or a slot-booking page |
documentItemsLayout: chat | render a document's items as a chat thread |
reports | aggregations, charts, dashboard KPI tiles, balance reports |
scope | which lifecycle rows an aggregating report counts |
widgets | custom KPI / embedded-page dashboard tiles |
notify.forEach | fan the block out over a related collection: one message per row, every bare path resolved against the row |
attach: recordPrint | in a fan-out: attach the ANCHOR record's document, rendered once, to every recipient ({record.<field>} addresses that record) |
payload | the declared envelope an outward-facing message carries (integrations and outbound alike), instead of the record as stored |
| the event axis | what a reacting glue entry binds to: an entity lifecycle event, or a process step reached / completed |
notifications | email on an event of the axis |
| notify link placeholders | {recordUrl} / {inboxUrl} / {appUrl} - a message that carries the way back into the application |
the notify block / attach: print | send a message about a record - with the record's own document attached - from a process step, a transition or a schedule |
schedules | cron: notify or generate records per matching row; where values may be moments relative to the firing |
integrations | outbound HTTP on a data change |
inbound | records arriving from outside: a webhook, a queue/topic message, a dropped file |
outbound | a record emitted on a queue or a topic when an event fires |
rollups | counts, sums, balance + status maintenance |
settlements | auto-allocation of payments across open invoices |
expansions | generated child rows per day / week / month |
generates | one-click document-from-document cloning |
generates.event | mint the document on a source event - a status write, a create, or a process step |
generates.event.mode | one target per source (once, default) or one per delivered event (append) |
resolves | fill a to-one from the register row valid on the record's date |
transitions | guarded on-demand status flips (void / cancel / reopen) |
postings | declarative source-document to balanced-document posting - on a status transition, or on create for a lifecycle-less source |
aggregates | keyed cross-entity totals materialised into their own entity |
posts | derived ledger rows emitted idempotently on an event |
personal / partner | per-user and per-partner row-scoped surfaces |
seeds | initial data, CSV-backed sets, translations |
multilingual / languages | translation tables + read-time translation overlay, on entity reads and report columns alike |
permissions | roles |
Snippets
entities
yaml
entities:
- name: Member
icon: user
group: master-data
audit: true
fields:
- { name: id, type: integer, primaryKey: true, generated: true }
- { name: name, type: string, required: true, length: 200 }
relations:
- { name: loans, kind: oneToMany, to: Loan }field / relation attributes
yaml
- { name: code, type: string, unique: true, length: 30 }
- { name: total, type: decimal, precision: 18, scale: 2, readOnly: true }
- { name: period, type: month }
- { name: Number, type: string, number: { series: Sales Invoice, per: Company, stampOn: create } }
- { name: Status, kind: manyToOne, to: OrderStatus, function: EntityStatus, init: 1 }
- { name: City, kind: manyToOne, to: City, dependsOn: { relation: Country, filterBy: Country } }
- { name: Product, kind: manyToOne, to: Product, where: { Type: 1 } }function
yaml
- name: ProjectTimesheet
function: Document # header + line items + status pill + totals
- name: EmployeeTimesheet
function: DocumentItemchecks
yaml
- name: JournalEntry
checks:
- { kind: itemsMin, count: 1, status: 2, message: "An entry needs at least one line" }
- { kind: itemsSumEqual, over: [debit, credit], status: 2, message: "Debits must equal credits" }
- name: JournalEntryItem
checks:
- { kind: exactlyOne, fields: [debit, credit], message: "Exactly one of debit / credit" }processes
yaml
processes:
- name: OrderApproval
trigger: { onCreate: Order }
steps:
- { name: review, kind: userTask, args: { assignee: manager, form: ApproveOrder } }
- { name: decide, kind: decision, args: { if: "action == 'approve'", then: activate, else: cancel } }
- { name: activate, kind: serviceTask, args: { setRelationField: Status, value: 2, next: end } }
- { name: cancel, kind: serviceTask, args: { setRelationField: Status, value: 3, next: end } }
- { name: end, kind: end }reports
yaml
reports:
- name: OrdersByMonth
source: Order
dimensions: ["month(orderDate)"]
measures: ["count(*)", "sum(total)"]
filter: "total > 0"
scope: live # all | draft | live | cancelled | void
chart: bar
widget: { value: "sum(total)", at: { "month(orderDate)": now }, label: Revenue (this month) }generates / transitions
yaml
generates:
- { name: invoice-from-order, from: Order, to: Invoice, map: { Customer: Customer }, sourceStatus: 3 }
# ...or minted with no click at all, at most once per source:
- name: delivery-from-order
from: Order
to: Delivery
event: { onTransition: Order, when: "Status == CONFIRMED" }
map: { Order: id }
transitions:
- { name: VoidInvoice, forEntity: Invoice, from: [ISSUED, SENT], setStatus: VOIDED, when: "Paid == 0", label: Void, icon: ban }seeds
yaml
seeds:
- name: statuses
entity: OrderStatus
rows:
- { id: 1, name: DRAFT, stage: draft }
- { id: 2, name: POSTED, stage: live }
- name: countries
entity: Country
file: data/countries.csvPlanned — recognised but not yet implemented
The following are parsed (or reserved) but not yet materialised by a generator; a conforming tool rejects or ignores them with a clear message rather than failing obscurely:
- Reserved
functionvalues for upcoming presentations (Board,Gantt,Timeline). manyToMany— parsed but never materialised; the supported shape is the explicit intermediate entity.- Cross-model status names and stage scopes — a nomenclature owned by another model is seeded there, so its stages and names cannot be resolved from the referencing file; such references are rejected with the numeric-id fallback named.