Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Runtime

Reference for each part of an application model. If you are new, start with Getting started instead.

An application is a directory

myapp/
  app.yaml                      what it is called, who may log in
  modules/sales/
    module.yaml                 the module's manifest
    domain.yaml                 what is stored
    security.yaml               who may see and change it
    flows.yaml                  logic the model cannot express
    flows/approve-order.lua     ...and the script
    metrics.yaml                what to count

Only app.yaml and one module.yaml are required. Everything else is added when you need it.

FileReference
domain.yamlModelling a domain
security.yamlSecurity
flows.yamlFlows
metrics.yamlMetrics
The API the runtime serves

Modules

A module is a bounded context: its own entities, its own roles, its own flows. app.yaml lists the modules that make up an application and maps module roles onto the roles your organisation actually has.

The indirection earns its keep — a module ships with a sensible permission model without knowing anything about the organisation deploying it.

Point your editor at the schema

Do this before writing a line. Every file starts with a modeline:

# yaml-language-server: $schema=../../runtime/assets/schema/app-model.schema.json

With the YAML extension installed you get completion on every field, inline errors, and the documentation for each option as you type. The schema is generated from the same types that parse your model, so it cannot drift from what the runtime actually accepts. runtime model schema prints it.

Read the errors

They are the product, not an afterthought:

$ runtime model validate myapp
error[M203]: `precision` is not a parameter of type `string`
  --> modules/sales/domain.yaml (entities[0].attributes[1])
  help: remove it, or change the type to `decimal`

Validation runs in three passes and which one fails determines the message: parse (is it YAML, does it match the schema), resolve (does that entity exist, does that attribute exist on it), check (is this expression well-typed against the model).

Every diagnostic has a stable code, and Diagnostics lists all of them. M2xx is a semantic problem; M9xx is a warning — legal, and nearly always unfinished.

Two things that surprise people

Money is never a number. decimal crosses every boundary as a string — in JSON and in Lua. A binary float cannot represent 0.10, and a total that is out by a cent is a total nobody trusts. Sending 12.10 as a JSON number is an error, not a rounding.

Writes need an If-Match. PATCH and DELETE without one are refused with 428. Two people editing the same record is not a race condition, it is a Tuesday, and last-write-wins loses one of the two changes with no error at all.