Skip to content

Commit 2479fb6

Browse files
committed
feat(spec,lint): register the record:line_items semantic entry, flip the lint pins, regenerate artifacts
Claude-Session: https://claude.ai/code/session_01UtnxvdiN376GF3sgXwAw4d Co-authored-by: Claude <noreply@anthropic.com>
1 parent e3f28a1 commit 2479fb6

17 files changed

Lines changed: 429 additions & 36 deletions

File tree

‎content/docs/references/index.mdx‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Protocol reference — every schema by module
33
navTitle: Protocol Reference
4-
description: Every schema published by @objectstack/spec — 1522 schemas across 14 protocol modules
4+
description: Every schema published by @objectstack/spec — 1523 schemas across 14 protocol modules
55
---
66

77
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
@@ -33,8 +33,8 @@ counts are sums of the rows they head. Regenerate with
3333
| [Shared Protocol](/docs/references/shared) | 10 | 31 | Primitives used across every protocol — identifiers, HTTP, expressions, error maps, enums. |
3434
| [Studio Protocol](/docs/references/studio) | 3 | 35 | Studio designer metadata — the authoring surfaces for the protocols above. |
3535
| [System Protocol](/docs/references/system) | 34 | 275 | The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance. |
36-
| [UI Protocol](/docs/references/ui) | 16 | 166 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. |
37-
| **Total** | **197** | **1522** | 14 protocol modules |
36+
| [UI Protocol](/docs/references/ui) | 16 | 167 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. |
37+
| **Total** | **197** | **1523** | 14 protocol modules |
3838

3939
---
4040

@@ -364,7 +364,7 @@ The runtime environment — logging, jobs, cache, metrics, notifications, i18n a
364364

365365
## UI Protocol
366366

367-
**Source:** `packages/spec/src/ui/` · **Import:** `@objectstack/spec/ui` · **16 pages, 166 schemas**
367+
**Source:** `packages/spec/src/ui/` · **Import:** `@objectstack/spec/ui` · **16 pages, 167 schemas**
368368

369369
Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer.
370370

@@ -375,7 +375,7 @@ Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI lay
375375
| [`app.zod.ts`](/docs/references/ui/app) | `ActionNavItem`, `App`, `AppBranding`, `AppContextSelector`, `ComponentNavItem`, `DashboardNavItem`, `DocNavItem`, `GroupNavItem`, `NavigationArea`, `NavigationContribution`, `NavigationItem`, `ObjectNavItem`, `PageNavItem`, `ReportNavItem`, `UrlNavItem` |
376376
| [`bulk-action.zod.ts`](/docs/references/ui/bulk-action) | `BulkActionDef`, `BulkActionExecution`, `BulkActionOperation`, `BulkActionParam` |
377377
| [`chart.zod.ts`](/docs/references/ui/chart) | `ChartAggregate`, `ChartAggregateFunction`, `ChartAnnotation`, `ChartAxis`, `ChartConfig`, `ChartDrillDown`, `ChartGroupBy`, `ChartInteraction`, `ChartSeries`, `ChartType` |
378-
| [`component.zod.ts`](/docs/references/ui/component) | `AIChatWindowProps`, `ActionButtonProps`, `ActionGroupProps`, `ActionIconProps`, `ActionMenuProps`, `ElementButtonProps`, `ElementDefinitionListProps`, `ElementFilterProps`, `ElementFormProps`, `ElementImageProps`, `ElementMetadataViewerProps`, `ElementNumberProps`, `ElementRecordPickerProps`, `ElementRepeaterProps`, `ElementTextInputProps`, `ElementTextProps`, `ObjectCalendarProps`, `ObjectFormProps`, `ObjectGanttProps`, `ObjectGridProps`, `ObjectKanbanProps`, `ObjectMapProps`, `ObjectMasterDetailFormProps`, `ObjectMetricProps`, `ObjectTimelineProps`, `ObjectTreeProps`, `PageAccordionProps`, `PageCardProps`, `PageContainerProps`, `PageHeaderProps`, `PageTabsProps`, `RecordActivityProps`, `RecordAlertAction`, `RecordAlertProps`, `RecordChatterProps`, `RecordDetailsProps`, `RecordHighlightsField`, `RecordHighlightsProps`, `RecordHistoryProps`, `RecordPathProps`, `RecordQuickActionsProps`, `RecordReferenceRailProps`, `RecordRelatedListProps`, `ReferenceRailEntry` |
378+
| [`component.zod.ts`](/docs/references/ui/component) | `AIChatWindowProps`, `ActionButtonProps`, `ActionGroupProps`, `ActionIconProps`, `ActionMenuProps`, `ElementButtonProps`, `ElementDefinitionListProps`, `ElementFilterProps`, `ElementFormProps`, `ElementImageProps`, `ElementMetadataViewerProps`, `ElementNumberProps`, `ElementRecordPickerProps`, `ElementRepeaterProps`, `ElementTextInputProps`, `ElementTextProps`, `ObjectCalendarProps`, `ObjectFormProps`, `ObjectGanttProps`, `ObjectGridProps`, `ObjectKanbanProps`, `ObjectMapProps`, `ObjectMasterDetailFormProps`, `ObjectMetricProps`, `ObjectTimelineProps`, `ObjectTreeProps`, `PageAccordionProps`, `PageCardProps`, `PageContainerProps`, `PageHeaderProps`, `PageTabsProps`, `RecordActivityProps`, `RecordAlertAction`, `RecordAlertProps`, `RecordChatterProps`, `RecordDetailsProps`, `RecordHighlightsField`, `RecordHighlightsProps`, `RecordHistoryProps`, `RecordLineItemsProps`, `RecordPathProps`, `RecordQuickActionsProps`, `RecordReferenceRailProps`, `RecordRelatedListProps`, `ReferenceRailEntry` |
379379
| [`dashboard.zod.ts`](/docs/references/ui/dashboard) | `Dashboard`, `DashboardHeader`, `DashboardHeaderAction`, `DashboardWidget`, `DashboardWidgetChartConfig`, `DashboardWidgetOptions`, `GlobalFilter`, `GlobalFilterOptionsFrom`, `WidgetActionType`, `WidgetColorVariant` |
380380
| [`dataset.zod.ts`](/docs/references/ui/dataset) | `Dataset`, `DatasetDimension`, `DatasetMeasure`, `DerivedMeasureOp` |
381381
| [`expression-bindable-text-keys.zod.ts`](/docs/references/ui/expression-bindable-text-keys) | `ExpressionBindableTextKey` |

‎content/docs/references/ui/component.mdx‎

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Component schema — UI Protocol reference
33
navTitle: Component
4-
description: "Component schemas of the ObjectStack UI Protocol: AIChatWindowProps and 43 more — each property with its type, default and a TypeScript example."
4+
description: "Component schemas of the ObjectStack UI Protocol: AIChatWindowProps and 44 more — each property with its type, default and a TypeScript example."
55
---
66

77
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
@@ -13,8 +13,8 @@ description: "Component schemas of the ObjectStack UI Protocol: AIChatWindowProp
1313
## TypeScript Usage
1414

1515
```typescript
16-
import { AIChatWindowProps, ActionButtonPropsSchema, ActionGroupPropsSchema, ActionIconPropsSchema, ActionMenuPropsSchema, ElementButtonPropsSchema, ElementDefinitionListPropsSchema, ElementFilterPropsSchema, ElementFormPropsSchema, ElementImagePropsSchema, ElementMetadataViewerPropsSchema, ElementNumberPropsSchema, ElementRecordPickerPropsSchema, ElementRepeaterPropsSchema, ElementTextInputPropsSchema, ElementTextPropsSchema, ObjectCalendarPropsSchema, ObjectFormPropsSchema, ObjectGanttPropsSchema, ObjectGridPropsSchema, ObjectKanbanPropsSchema, ObjectMapPropsSchema, ObjectMasterDetailFormPropsSchema, ObjectMetricPropsSchema, ObjectTimelinePropsSchema, ObjectTreePropsSchema, PageAccordionProps, PageCardProps, PageContainerProps, PageHeaderProps, PageTabsProps, RecordActivityProps, RecordAlertActionSchema, RecordAlertProps, RecordChatterProps, RecordDetailsProps, RecordHighlightsField, RecordHighlightsProps, RecordHistoryProps, RecordPathProps, RecordQuickActionsProps, RecordReferenceRailProps, RecordRelatedListProps, ReferenceRailEntrySchema } from '@objectstack/spec/ui';
17-
import type { ActionButtonProps, ActionGroupProps, ActionIconProps, ActionMenuProps, ElementDefinitionListProps, ElementNumberProps, ElementRecordPickerProps, ElementRepeaterProps, ObjectCalendarProps, ObjectFormProps, ObjectGanttProps, ObjectGridProps, ObjectKanbanProps, ObjectMapProps, ObjectMasterDetailFormProps, ObjectMetricProps, ObjectTimelineProps, ObjectTreeProps, PageContainerProps, RecordAlertAction, RecordAlertProps, RecordHighlightsField, RecordHistoryProps, RecordPathProps, RecordQuickActionsProps, RecordReferenceRailProps, ReferenceRailEntry } from '@objectstack/spec/ui';
16+
import { AIChatWindowProps, ActionButtonPropsSchema, ActionGroupPropsSchema, ActionIconPropsSchema, ActionMenuPropsSchema, ElementButtonPropsSchema, ElementDefinitionListPropsSchema, ElementFilterPropsSchema, ElementFormPropsSchema, ElementImagePropsSchema, ElementMetadataViewerPropsSchema, ElementNumberPropsSchema, ElementRecordPickerPropsSchema, ElementRepeaterPropsSchema, ElementTextInputPropsSchema, ElementTextPropsSchema, ObjectCalendarPropsSchema, ObjectFormPropsSchema, ObjectGanttPropsSchema, ObjectGridPropsSchema, ObjectKanbanPropsSchema, ObjectMapPropsSchema, ObjectMasterDetailFormPropsSchema, ObjectMetricPropsSchema, ObjectTimelinePropsSchema, ObjectTreePropsSchema, PageAccordionProps, PageCardProps, PageContainerProps, PageHeaderProps, PageTabsProps, RecordActivityProps, RecordAlertActionSchema, RecordAlertProps, RecordChatterProps, RecordDetailsProps, RecordHighlightsField, RecordHighlightsProps, RecordHistoryProps, RecordLineItemsProps, RecordPathProps, RecordQuickActionsProps, RecordReferenceRailProps, RecordRelatedListProps, ReferenceRailEntrySchema } from '@objectstack/spec/ui';
17+
import type { ActionButtonProps, ActionGroupProps, ActionIconProps, ActionMenuProps, ElementDefinitionListProps, ElementNumberProps, ElementRecordPickerProps, ElementRepeaterProps, ObjectCalendarProps, ObjectFormProps, ObjectGanttProps, ObjectGridProps, ObjectKanbanProps, ObjectMapProps, ObjectMasterDetailFormProps, ObjectMetricProps, ObjectTimelineProps, ObjectTreeProps, PageContainerProps, RecordAlertAction, RecordAlertProps, RecordHighlightsField, RecordHistoryProps, RecordLineItemsProps, RecordPathProps, RecordQuickActionsProps, RecordReferenceRailProps, ReferenceRailEntry } from '@objectstack/spec/ui';
1818

1919
// Validate data
2020
const result = AIChatWindowProps.parse(data);
@@ -1509,6 +1509,75 @@ Type: `string`
15091509
| **unknownUserText** | `string` | optional | Copy substituted when an entry has no resolvable actor. Literal string, every locale (renderer default: "Unknown user"). |
15101510

15111511

1512+
---
1513+
1514+
## RecordLineItemsProps
1515+
1516+
### Properties
1517+
1518+
| Property | Type | Required | Description |
1519+
| :--- | :--- | :--- | :--- |
1520+
| **childObject** | `string` | optional | Child object whose records this grid lists, edits and saves. Optional because the component-level `dataSource` binding can supply the object instead; with neither, the panel shows a configuration hint and fetches nothing |
1521+
| **relationshipField** | `string` | ✅ | FK on the child object pointing back to the parent record — the rows are queried as `{ [relationshipField]: parentId }`. Required: this panel does not auto-detect it |
1522+
| **columns** | `{ name: string; label?: string; type?: Enum<'text' \| 'number' \| 'currency' \| 'date' \| 'datetime' \| 'time' \| 'select' \| 'lookup' \| 'file'>; width?: number; … }[]` | ✅ | Editable grid columns, drawn exactly as declared. Each entry is the strict, name-keyed inline grid column a relationship field's `inlineColumns` takes (`{ name, label?, type?, options?, … }` — objectui GridColumn); unknown keys and the retired `field` spelling are refused. Unlike the master-detail carriers, this block does NOT hydrate a column from the child object's field: declare `label`, `type` and `options` yourself — an identity-only `{ name }` column is a text cell headed by its name. Required, with at least one column: nothing derives them, and an empty list draws a grid with no cells |
1523+
| **parentObject** | `string` | optional | Parent object the `totalField` rollup is written to (default: the object of the record on the page) |
1524+
| **parentId** | `string` | optional | Parent record id the rows belong to (default: the record on the page). Wins over `recordId` |
1525+
| **recordId** | `string` | optional | Alternate spelling of `parentId` the renderer also reads; `parentId` wins when both are set |
1526+
| **amountField** | `string` | optional | Numeric child column summed for the running total and for the `totalField` rollup (default `amount` when only `totalField` is set) |
1527+
| **totalField** | `string` | optional | Parent field to receive the rolled-up sum on save |
1528+
| **title** | `string` | optional | Panel title. A literal string rendered as-is in every locale (no inline locale map — the panel renders it as a React child); renderer default: the localized "Line Items" |
1529+
| **readonly** | `boolean` | optional | Render the grid read-only: cells locked, no Save button, and no adding or removing lines (renderer default: editable) |
1530+
| **minRows** | `number` | optional | Minimum number of rows |
1531+
| **maxRows** | `number` | optional | Maximum number of rows |
1532+
| **filter** | `{ field: string; operator: Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>; value?: string \| number \| boolean \| null \| (string \| number)[] }[]` | optional | Additional criteria for the child rows — the ViewFilterRule array form `[{ field, operator, value }, ...]`, AND-combined with the parent relationship condition, never substituted for it: it can only narrow this record's lines |
1533+
| **sort** | `{ field: string; order: Enum<'asc' \| 'desc'> }[]` | optional | Load order for the child rows — the SortItem array form `[{ field, order }, ...]` (renderer default: storage order) |
1534+
| **limit** | `integer` | optional | Row cap for the child fetch (renderer default: 500). The grid has no pagination, so this is the window of rows that are editable and saved together |
1535+
1536+
### Nested Shape: `RecordLineItemsProps.columns[number]`
1537+
1538+
| Property | Type | Required | Description |
1539+
| :--- | :--- | :--- | :--- |
1540+
| **name** | `string` | ✅ | Child field this column shows — the key the grid reads and writes on each row object (objectui GridColumn.name). The retired `field` spelling is refused. |
1541+
| **label** | `string` | optional | Column header; defaults to the child field's label via hydration. |
1542+
| **type** | `Enum<'text' \| 'number' \| 'currency' \| 'date' \| 'datetime' \| 'time' \| 'select' \| 'lookup' \| 'file'>` | optional | Cell control, derived from the child field's type when omitted. Declaring it opts the column out of schema hydration — supply the extras (options / reference / …) yourself. |
1543+
| **width** | `number` | optional | Fixed column width in px; omitted columns use type-based role sizing (text flexes, numeric/date/select stay fixed). |
1544+
| **required** | `boolean` | optional | Cell is flagged inline-invalid while empty. Computed columns are never required. |
1545+
| **options** | `{ label: string; value: string }[]` | optional | Select-cell options for `type: 'select'`; derived from the child field's options when the column declares no `type`. |
1546+
| **prefix** | `string` | optional | Symbol shown in a `currency` cell in place of the resolved currency's own symbol. No default: when omitted, the cell shows the symbol of the currency it resolves. It replaces the symbol only — the amount's decimal places stay the currency's. |
1547+
| **step** | `number` | optional | Input step for numeric cells. |
1548+
| **reference** | `string` | optional | Referenced object for `type: 'lookup'` cells; derived from the child lookup field when the column declares no `type`. |
1549+
| **displayField** | `string` | optional | Label field shown for a picked lookup record. |
1550+
| **idField** | `string` | optional | Id field stored for a picked lookup record. |
1551+
| **multiple** | `boolean` | optional | Multi-value column: multi-record lookup, or multi-file upload cell. |
1552+
| **accept** | `string[]` | optional | Accepted MIME types / extensions for a `file` cell's picker (e.g. ['image/*', '.pdf']); omit to accept anything. |
1553+
| **defaultHidden** | `boolean` | optional | Collapsed into the grid's column chooser by default (not dropped); required columns are never default-hidden. |
1554+
| **computed** | `boolean` | optional | Read-only computed column, recomputed live from sibling cells via `expr` and written back into the row. |
1555+
| **expr** | `string` | optional | Arithmetic expression for a computed column — a BARE string over `+ - * / %`, parentheses, numeric literals and field refs (`record.qty` or `qty`), evaluated by the grid's own safe evaluator. Deliberately NOT a CEL Expression envelope; `{ dialect, source }` is refused here. |
1556+
| **scale** | `integer` | optional | Decimal places to round a computed numeric result to (integer 0-100). REFUSED on a column declaring `type: 'currency'` — delete it there: the currency's ISO 4217 minor unit decides. The upper bound is the renderer's: the grid rounds with `toFixed`, which throws a RangeError above 100. |
1557+
| **autofill** | `boolean` | optional | For `lookup` columns: picking a record copies its same-named fields into sibling columns (a product's unit_price/description). On by default; set false to disable. |
1558+
| **readonlyWhen** | `string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source: string; ast?: any; meta?: object }` | optional | Predicate (CEL) — the cell is read-only when TRUE, evaluated per row against the row as `record` plus the header as `parent` (e.g. P`parent.status == 'paid'`). |
1559+
| **requiredWhen** | `string \| { dialect: Enum<'cel' \| 'cron' \| 'template'>; source: string; ast?: any; meta?: object }` | optional | Predicate (CEL) — the cell is required when TRUE. Same `record` + `parent` scope as `readonlyWhen`. PRESENTATION ONLY: this flags the cell inline-invalid in the grid; nothing on the write path reads it. The server-enforced contract is the child FIELD's own `requiredWhen` — a transition gate, see `Field.requiredWhen` — which hydration copies onto an identity-only column, so declaring the requirement here alone enforces nothing. |
1560+
1561+
### Nested Shape: `RecordLineItemsProps.filter[number]`
1562+
1563+
View filter rule
1564+
1565+
| Property | Type | Required | Description |
1566+
| :--- | :--- | :--- | :--- |
1567+
| **field** | `string` | ✅ | Field name to filter on |
1568+
| **operator** | `Enum<'equals' \| 'not_equals' \| 'contains' \| 'not_contains' \| 'icontains' \| …>` | ✅ | Filter operator |
1569+
| **value** | `string \| number \| boolean \| null \| (string \| number)[]` | optional | Filter value. The accepted SHAPE depends on the operator: `in` / `not_in` take an array (any length, including []), `between` takes exactly [min, max], every other operator takes a scalar. The unary operators (is_empty / is_not_empty / is_null / is_not_null) take their direction from the operator name and ignore this key. One operator bounds the VALUE as well as the shape: `icontains` takes a NON-EMPTY STRING, the comparand the Filter Protocol conformance table declares for it — an empty comparand constrains nothing and a non-string one would answer a query nobody wrote, and both are refused at the query path too. |
1570+
1571+
### Nested Shape: `RecordLineItemsProps.sort[number]`
1572+
1573+
Sort field and direction pair
1574+
1575+
| Property | Type | Required | Description |
1576+
| :--- | :--- | :--- | :--- |
1577+
| **field** | `string` | ✅ | Field name to sort by |
1578+
| **order** | `Enum<'asc' \| 'desc'>` | ✅ | Sort direction |
1579+
1580+
15121581
---
15131582

15141583
## RecordPathProps

‎docs/audits/2026-07-unknown-key-strictness-ledger.counts/ui.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The `strict` column is the one the campaign schedules against; it counts both th
2121

2222
| Dir | Sites | strict | passthrough | catchall | strip |
2323
|---|---|---|---|---|---|
24-
| `ui/` | 189 | 179 | 3 | 0 | 7 |
24+
| `ui/` | 190 | 180 | 3 | 0 | 7 |
2525

2626
## `ui/` — sites
2727

@@ -36,7 +36,7 @@ classify and is not listed (it becomes reportable the day it grows its first sit
3636
| `app.zod.ts` | 19 |
3737
| `bulk-action.zod.ts` | 4 |
3838
| `chart.zod.ts` | 8 |
39-
| `component.zod.ts` | 57 |
39+
| `component.zod.ts` | 58 |
4040
| `dashboard.zod.ts` | 11 |
4141
| `dataset.zod.ts` | 4 |
4242
| `i18n.zod.ts` | 1 |
@@ -46,23 +46,23 @@ classify and is not listed (it becomes reportable the day it grows its first sit
4646
| `sharing.zod.ts` | 1 |
4747
| `view.zod.ts` | 62 |
4848
| `widget.zod.ts` | 1 |
49-
| **total** | **189** |
49+
| **total** | **190** |
5050

5151
## `ui/` — open
5252

5353
Per file, how many of its sites still silently discard unknown keys. The `Class`
5454
column that decides the bucket split is hand-written in the ledger; the arithmetic
5555
over it is here.
5656

57-
**7 strip of 189**, in 4 file(s).
57+
**7 strip of 190**, in 4 file(s).
5858

5959
| File | Strip | Sites |
6060
|---|---|---|
6161
| `action-params.zod.ts` | 1 | 1 |
6262
| `app.zod.ts` | 1 | 19 |
6363
| `view.zod.ts` | 4 | 62 |
6464
| `widget.zod.ts` | 1 | 1 |
65-
| **total** | **7** | **189** |
65+
| **total** | **7** | **190** |
6666

6767
| Bucket | Sites |
6868
|---|---|

0 commit comments

Comments
 (0)