---
title: "Lifecycles (LifecycleDecl)"
description: "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…"
order: 9
id: "model/lifecycle"
---

# Lifecycles (LifecycleDecl)

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.

## LifecycleDecl {#lifecycledecl}

A lifecycle: the states and transitions of a state property (runtime).

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

| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
| `id` | [FsmId](shapes.md#fsmid) | yes (propose assigns it; a new declaration leaves it out) | — | — | A lifecycle id (`lc_…`); renames keep it. |
| `name` | [Ident](shapes.md#ident) | yes | — | `"order_status"` | The lifecycle name. |
| `label` | [Text](shapes.md#text) | yes (a draft may leave it out: propose writes a default made from the name, `catalog.label_defaulted`) | — | `"Order status"` | The words shown for it. |
| `subject` | [TypeId](shapes.md#typeid) | yes | — | `"ty_3f8v6h2n0c"` | The type whose state property follows it. |
| `states` | [StateDecl](lifecycle.md#statedecl)[] | yes | — | (see the example) | The states, in their display order. |
| `initial` | [StateId](shapes.md#stateid) | yes | — | `"st_1a3c5e7g9j"` | The state a new row starts in. |
| `transitions` | [TransitionDecl](lifecycle.md#transitiondecl)[] | yes | — | (see the example) | The transitions between the states. |

`lifecycles/order_status.json`

```json
{
  "label": "Order status",
  "subject": "ty_3f8v6h2n0c",
  "states": [
    { "code": "draft", "label": "Draft" },
    { "code": "placed", "label": "Placed", "meaning": "live" },
    {
      "code": "cancelled",
      "label": "Cancelled",
      "terminal": true,
      "meaning": "terminal-bad"
    }
  ],
  "initial": "st_1a3c5e7g9j",
  "transitions": [
    {
      "name": "place",
      "label": "Place",
      "from": ["st_1a3c5e7g9j"],
      "to": "st_5m7p9r1t3v"
    },
    { "name": "cancel", "label": "Cancel", "from": "*", "to": "st_8x0z2b4d6f" }
  ]
}
```

## StateDecl {#statedecl}

A state of the lifecycle.

| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
| `id` | [StateId](shapes.md#stateid) | yes (propose assigns it; a new declaration leaves it out) | — | — | A lifecycle state id (`st_…`); renames keep it. |
| `code` | [Ident](shapes.md#ident) | yes | — | `"draft"` | The code the state property stores and readers compare with. |
| `label` | [Text](shapes.md#text) | yes (a draft may leave it out: propose writes a default made from the name, `catalog.label_defaulted`) | — | `"Draft"` | The words shown for it. |
| `terminal` | `true` | no | — | `true` | The state ends the lifecycle: no transition leaves it, and refs that settle lock (runtime). |
| `meaning` | [ValueMeaning](value-type.md#valuemeaning) | no | — | `"live"` | What the state means (pages reads it). |
| `color` | [EnumColorToken](value-type.md#enumcolortoken) | no | — | `"hot"` | The tone the state is shown in. |

An item of `states` in a lifecycle file (`lifecycles/<name>.json`).

```json
{
  "code": "cancelled",
  "label": "Cancelled",
  "terminal": true,
  "meaning": "terminal-bad",
  "color": "hot"
}
```

## TransitionDecl {#transitiondecl}

A transition of the lifecycle.

| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
| `id` | [TransitionId](shapes.md#transitionid) | yes (propose assigns it; a new declaration leaves it out) | — | — | A lifecycle transition id (`tn_…`); renames keep it. |
| `name` | [Ident](shapes.md#ident) | yes | — | `"place"` | The transition name. |
| `label` | [Text](shapes.md#text) | yes (a draft may leave it out: propose writes a default made from the name, `catalog.label_defaulted`) | — | `"Place"` | The words shown for it. |
| `from` | `"*"` \| [StateId](shapes.md#stateid)[] | yes | — | `["st_1a3c5e7g9j"]` | The states it leaves from: a list, or * for every non-terminal state except to. |
| `to` | [StateId](shapes.md#stateid) | yes | — | `"st_5m7p9r1t3v"` | The state it moves to. |

An item of `transitions` in a lifecycle file.

```json
{
  "name": "place",
  "label": "Place",
  "from": ["st_1a3c5e7g9j"],
  "to": "st_5m7p9r1t3v"
}
```
