Book
Book protocol schemas
Package Documentation Navigation — the book element (ADR-0046 §6).
A book is the spine of a table of contents: an ordered set of groups
(sections) plus identity and access. It deliberately does NOT store its
members. Membership — which doc sits in which group — is derived from a
rule on each group (include glob/tag) plus an optional per-doc
order/group, never held in a central array.
Why a spine and not a container (ADR-0046 §6.2.1): storing the whole tree in
one array conflates low-cardinality group definitions (curated by a human,
rarely changed) with high-cardinality membership (churned by the AI on every
new doc). A central array forces a read-modify-write on every doc the AI
adds — stale/concurrent edits silently drop or reorder siblings — and breaks
overlay (RFC 7396 replaces arrays atomically, shadowing docs a later package
version adds). A derived spine removes the write entirely: the AI creates a
doc named to match a rule and it files itself (create-and-forget), and the
only per-doc storage is the scalar doc.order, which merges cleanly.
Source: packages/spec/src/system/book.zod.ts
TypeScript Usage
import { Book, BookAudience, BookGroup, BookInclude, BookNode } from '@objectstack/spec/system';
import type { Book, BookAudience, BookGroup, BookInclude, BookNode } from '@objectstack/spec/system';
// Validate data
const result = Book.parse(data);Book
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| name | string | ✅ | Book name (namespace prefix recommended, like every metadata name) |
| label | string | optional | Display title |
| description | string | optional | |
| translations | Record<string, Object> | optional | |
| slug | string | optional | Portal URL segment; defaults to name sans prefix |
| icon | string | optional | |
| order | number | optional | Orders books within the portal |
| audience | string | string | Object | optional | Access audience; defaults to 'org' (inherits package grant) |
| groups | Object[] | ✅ | The spine: ordered sections. Two levels total. |
BookAudience
Union Options
This schema accepts one of the following structures:
Option 1
Type: string
Option 2
Type: string
Option 3
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| permissionSet | string | ✅ |
BookGroup
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| key | string | ✅ | Stable group key (used by overrides, deep links, explicit doc.group) |
| label | string | ✅ | Section title — first-class, i18n-homed |
| translations | Record<string, Object> | optional | Per-locale label variants |
| order | number | optional | Order of THIS group within the book |
| include | string | Object | optional | Rule that derives membership (glob or tag) |
| package | string | optional | Scope the rule to a package id (default: the book package; cross-package via ADR-0048) |
| pages | string | Object[] | optional | OPTIONAL explicit override — hand-pin a curated order; wins over include |
BookInclude
Union Options
This schema accepts one of the following structures:
Option 1
Glob over doc names, e.g. "crm_guide_*"
Type: string
Option 2
Match by doc tag (§5 vocabulary)
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| tag | string | ✅ |
BookNode
Union Options
This schema accepts one of the following structures:
Option 1
Type: string
Option 2
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| doc | string | optional | Doc name to reference |
| href | string | optional | External link (use instead of doc) |
| label | string | optional | Optional label override; title authority stays in the doc |
| badge | string | optional | e.g. "beta" | "new" |
| icon | string | optional |