Types (TypeDecl)
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.
TypeDecl
A type of record.
The types slot of the doc holds these, keyed by id. In a bundle each is one file, types/<name>.json, named by its name, which the file then leaves out.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
id |
TypeId | yes (propose assigns it; a new declaration leaves it out) | — | "ty_7k2m9q4z1a" |
A type id (ty_…); renames keep it. |
name |
Ident | yes | — | "customer" |
The type name. |
label |
Text | yes (a draft may leave it out: propose writes a default made from the name, catalog.label_defaulted) |
— | "Customer" |
The words shown for it. |
idPrefix |
string (matching ^[a-z]{2,5}$) |
no | — | "bk" |
The prefix of its record ids: 2–5 lower-case letters. |
class |
"data" | "access" | "credential" | "evidence" | "queue" |
no | "data" |
"data" |
What the rows are: data. The other classes are the platform’s own, and a doc declaring one is refused (C34). |
verbs |
TypeDecl.verbs | no | {} |
(see the example) | Which generated verbs exist (runtime §4.4); default all. |
properties |
PropertyDecl[] | yes | — | (see the example) | The properties, in their default field order. |
keys |
TypeDecl.keys | no | — | (see the example) | The keys of the type. |
temporal |
TypeDecl.temporal | no | — | (see the example) | Rows are effective-dated; compiles to a no_overlap invariant. |
invariants |
InvariantDecl[] | no | — | (see the example) | The rules every write must keep. |
owner |
PropId | no | — | "pr_2d4f6h8k0m" |
The required cascade ref to the row this row belongs to. |
title |
TitleDecl | no | — | "name" |
A row’s title: pickers, ref display and the title search source. |
measures |
Record<Ident, MeasureDecl> | no | — | {"count":{"label":"Bookings","expr":"count()"}} |
The declared aggregates, by name (C79). |
presentation |
TypePresentation | no | — | (see the example) | How the type is shown (pages). |
types/customer.json
{
"label": "Customer",
"properties": [
{
"kind": "stored",
"name": "name",
"label": "Name",
"type": { "t": "text" },
"required": true
}
],
"title": "name"
}
types/booking.json
{
"label": "Booking",
"idPrefix": "bk",
"class": "data",
"verbs": { "delete": false, "end": true },
"properties": [
{
"kind": "stored",
"id": "pr_1c3e5g7j9m",
"name": "room",
"label": "Room",
"type": { "t": "text" },
"required": true
},
{
"kind": "stored",
"id": "pr_3a5c7e9g1j",
"name": "starts",
"label": "Starts",
"type": { "t": "date" },
"required": true
},
{
"kind": "stored",
"id": "pr_9t1v3x5z7b",
"name": "ends",
"label": "Ends",
"type": { "t": "date" },
"required": true
},
{
"kind": "ref",
"id": "pr_2d4f6h8k0m",
"name": "customer",
"label": "Customer",
"target": "ty_7k2m9q4z1a",
"required": true,
"onDelete": "cascade"
}
],
"keys": {
"natural": ["pr_1c3e5g7j9m"],
"unique": [["pr_1c3e5g7j9m", "pr_3a5c7e9g1j"]]
},
"temporal": {
"from": "pr_3a5c7e9g1j",
"to": "pr_9t1v3x5z7b",
"key": ["pr_1c3e5g7j9m"]
},
"invariants": [
{
"kind": "check",
"holds": "ends >= starts",
"message": { "text": "A booking cannot end before it starts." }
}
],
"owner": "pr_2d4f6h8k0m",
"title": {
"text": "Room {room} from {starts}",
"params": { "room": "room", "starts": "starts" }
},
"measures": { "count": { "label": "Bookings", "expr": "count()" } }
}
types/audit_note.json
{
"label": "Audit note",
"verbs": {
"create": true,
"update": false,
"delete": false,
"set": false,
"end": false
},
"properties": [
{
"kind": "stored",
"name": "note",
"label": "Note",
"type": { "t": "text", "format": "long" },
"required": true
}
]
}
TypeDecl.verbs
Which generated verbs exist (runtime §4.4); default all.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
create |
boolean | no | true |
true |
Whether the generated create verb exists. |
update |
boolean | no | true |
true |
Whether the generated update verb exists. |
delete |
boolean | no | true |
true |
Whether the generated delete verb exists. |
set |
boolean | no | true |
true |
Whether the generated set verb exists. |
end |
boolean | no | true |
true |
Whether the generated end verb exists. |
TypeDecl.keys
The keys of the type.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
natural |
PropId[] | no | — | ["pr_1c3e5g7j9m"] |
The natural key: required properties that name a row. |
unique |
PropId[][] | no | — | [["pr_1c3e5g7j9m","pr_3a5c7e9g1j"]] |
Each list of properties is unique together. |
TypeDecl.temporal
Rows are effective-dated; compiles to a no_overlap invariant.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
from |
PropId | yes | — | "pr_3a5c7e9g1j" |
The start of each row’s period. |
to |
PropId | yes | — | "pr_9t1v3x5z7b" |
The end of each row’s period. |
key |
PropId[] | yes | — | ["pr_1c3e5g7j9m"] |
Required properties whose rows must not overlap. |
InvariantDecl
A rule every write must keep.
One of, told apart by kind:
InvariantDecl.check
A row condition.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
kind |
"check" |
yes | — | "check" |
A condition on one row. |
id |
InvariantId | yes (propose assigns it; a new declaration leaves it out) | — | — | An invariant id (iv_…); renames keep it. |
holds |
Expr | yes | — | "ends >= starts" |
The CX condition every row must hold. |
message |
MsgRef | yes | — | {"text":"A booking cannot end before it starts."} |
What a refused write says. |
An item of invariants in a type file.
{
"kind": "check",
"holds": "total >= 0",
"message": { "text": "The total cannot be negative." }
}
InvariantDecl.unique
A uniqueness rule.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
kind |
"unique" |
yes | — | "unique" |
No two rows share these values. |
id |
InvariantId | yes (propose assigns it; a new declaration leaves it out) | — | — | An invariant id (iv_…); renames keep it. |
props |
PropId[] | yes | — | ["pr_5w7y9a1c3e"] |
The properties whose values are unique together. |
where |
Expr | no | — | "active" |
Only rows where this holds count. |
An item of invariants in a type file.
{ "kind": "unique", "props": ["pr_5w7y9a1c3e"], "where": "active" }
InvariantDecl.no_overlap
A no-overlap rule.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
kind |
"no_overlap" |
yes | — | "no_overlap" |
No two rows with the same key overlap in time. |
id |
InvariantId | yes (propose assigns it; a new declaration leaves it out) | — | — | An invariant id (iv_…); renames keep it. |
from |
PropId | yes | — | "pr_3a5c7e9g1j" |
The start of each row’s period. |
to |
PropId | yes | — | "pr_9t1v3x5z7b" |
The end of each row’s period. |
key |
PropId[] | yes | — | ["pr_1c3e5g7j9m"] |
Required properties that group rows that must not overlap. |
An item of invariants in a type file.
{
"kind": "no_overlap",
"from": "pr_3a5c7e9g1j",
"to": "pr_9t1v3x5z7b",
"key": ["pr_1c3e5g7j9m"]
}
InvariantDecl.bound
A bound over the type’s rows.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
kind |
"bound" |
yes | — | "bound" |
A condition over the rows of the type together. |
id |
InvariantId | yes (propose assigns it; a new declaration leaves it out) | — | — | An invariant id (iv_…); renames keep it. |
holds |
Expr | yes | — | "count() <= 1000" |
The CX condition every row must hold. |
message |
MsgRef | yes | — | {"text":"At most {max} orders.","params":{"max":"1000"}} |
What a refused write says. |
An item of invariants in a type file.
{
"kind": "bound",
"holds": "count() <= 1000",
"message": { "text": "At most {max} orders.", "params": { "max": "1000" } }
}
MeasureDecl
A declared aggregate, read by data.aggregate, Aggregate/Stat, nav counts and agents.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
id |
MeasureId | yes (propose assigns it; a new declaration leaves it out) | — | — | A measure id (ms_…); renames keep it. |
label |
Text | yes (a draft may leave it out: propose writes a default made from the name, catalog.label_defaulted) |
— | "Bookings" |
The words shown for it. |
expr |
Expr | yes | — | "count()" |
One CX aggregate over the type’s rows (use site measure, cost at most agg). |
groupBy |
PropId[] | no | — | ["pr_5n1v3x7c9d"] |
The properties a reader may group it by. |
where |
Expr | no | — | "status == 'placed'" |
Only rows where this holds are aggregated. |
An entry of measures in a type file, under its name (here revenue).
{
"label": "Revenue",
"expr": "sum(total)",
"groupBy": ["pr_5n1v3x7c9d"],
"where": "status == 'placed'"
}
TitleDecl
A CX text expression, or a template with CX params that present writes in the reader’s convention.
SearchSpec
Makes the property a search source.
| Field | Type | Required | Default | Example | Description |
|---|---|---|---|---|---|
weight |
"title" | "body" |
yes | — | "body" |
The weight class of its search column: title ranks above body. |
The searchable of a property.
{ "weight": "title" }