Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/spec/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Generates a seed-import descriptor + CSV per seed. Two shapes:
- **`file: data/<name>.csv`** — an authored CSV under a `data/` subfolder, right for bulk nomenclatures and prepopulated demo data. A foreign key is set by the relation name (`Country: 34`).

::: info Normative
Row keys must match a field or relation name **exactly** (case-sensitive). A key matching neither is an authoring error — a silently dropped column becomes a NOT NULL failure at import time.
Row keys must match a field name, a **to-one** relation name (a collection has no column to set), or the `stage` marker below, **exactly** (case-sensitive). A key matching none of those is an authoring error, reported with the nearest declared name — see [unrecognised keys](/spec/#unrecognised-keys). Accepting it would drop the column, and a dropped NOT NULL foreign key makes the import skip **every** row: a nomenclature that imports as zero rows, behind a fully green pipeline.
:::

A seed with `language: <code>` is a **translation** seed: it fills the per-language values of a `multilingual: true` entity, carrying the base row's `id` plus the translatable fields only.
Expand Down
28 changes: 28 additions & 0 deletions docs/spec/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,34 @@ These rules keep the file diff-stable, safe to parse, and friendly for both huma
- **No type tags.** Blocked by the safe parser.
- **Quote unquoted braces in scalars.** `to: {member.email}` is parsed by YAML as an object, not a string - write `to: member.email`. Braces are only for `{...}` interpolation inside `subject` / `body` text.
- **An event-binding key is `event:`, never `on:`** - YAML 1.1 resolves a bare `on` (and `off` / `yes` / `no`) to a boolean. An action key is `do:`.
- **Only the keys this specification declares exist, and they are case-sensitive.** An invented key, or a case slip (`Required:` for `required:`), is an authoring error - never a key that is accepted and ignored.

### Unrecognised keys

A typed mapping normally drops a key it does not know. That silence is the worst failure this format can have: the file is accepted, generation succeeds, the application deploys, and the only symptom is that the promise the author wrote is absent at runtime - with every step of the pipeline reporting success. The rule is therefore the same one the format applies to a reference it cannot resolve.

::: info Normative
A conforming generator MUST report a key it does not recognise as an authoring error rather than
ignoring it, and the report MUST name the key, where it appears, and - where one exists - the
nearest declared name. Key names are **case-sensitive**: a key differing from a declared one only in
case is unrecognised, and the report SHOULD say so, since it is the slip hardest to see by eye. This
applies equally to a [seed row](/spec/data#seeds), whose keys are the target entity's own names
rather than this specification's. A map whose keys are drawn from the model being described (a
`map:` projection, a relation's `where:`, a widget's `at:`, a delegate's injected `fields:`) is
validated against that model, not against this vocabulary.
:::

Being written as a mapping does not make a block free-form. A process [`trigger:`](/spec/processes),
an [`abortOn:`](/spec/processes#aborton-cancel-the-instance-on-a-terminal-status), a glue
[`event:`](/spec/glue#notifications) binding, a step's [`args:`](/spec/processes) and the blocks
nested inside them are each a fixed vocabulary, and a key outside it is unrecognised like any other.

::: info Normative
A step's `args:` are recognised **per step kind**: an argument declared on a kind that does not read
it (a decision's `if` on a user task, a boundary `timeout` on a service task) MUST be reported like
an unrecognised one, and the report SHOULD name the kind that does read it. This is the same failure
and not a lesser one - the step reads nothing, so the argument does nothing.
:::

## In this section

Expand Down