Skip to content
Merged
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
10 changes: 10 additions & 0 deletions .changeset/30812-field-group-visible-when-requires-feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@objectstack/skills': patch
---

docs(skills): the data skill's Field Groups section teaches a group's `visibleWhen` and `requiresFeature`

Clause-②: no
Metadata-protocol: none

`skills/objectstack-data/references/examples-objects.md` now names the two ways a whole field group (header included) is hidden: `visibleWhen`, a CEL predicate over the record that hides the group when FALSE or when it faults, and `requiresFeature`, a deployment feature flag from the `PUBLIC_AUTH_FEATURES` set, refused when unknown, lowered at parse into the group's `visibleWhen` and stripped, AND-combined after an authored `visibleWhen`; both are presentation only. The real example is `sys_organization`'s Group Structure section, hidden on a single-organization deployment with `requiresFeature: 'multiOrgEnabled'`. The text is paid for by deleting restatements in the same file (the intro sentence, the migrations paragraph, the deprecated-flag aside, the strictness sentence under Metadata Protection, a dangling "see above" and a path comment), so the file's token ceiling moves down, not up.
10 changes: 9 additions & 1 deletion scripts/check-skills-token-ratchet.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,15 @@ export const CEILINGS = new Map([
// stale `{ type: 'lookup', reference: 'user' }` fields (an object that does
// not exist) became `type: 'user'`; -10 tokens, the row follows the
// measurement down, zero headroom.
['skills/objectstack-data/references/examples-objects.md', 1756],
// 1756 -> 1728: RE-LOCK at the landed count after two net cuts — the Field
// Groups section now names a group's `visibleWhen` and `requiresFeature`
// (lowered into `visibleWhen` at parse, unknown flag refused, AND-composed
// after an authored predicate) with the `sys_organization` example, paid by
// deleting restatement in the same file (-5), on top of the hook-example
// rename that dropped its intro line (-14) and left headroom, then the
// review's module pointer paid by the custom-Page aside (the ui skill's
// rule); the row follows the measurement down, zero headroom.
['skills/objectstack-data/references/examples-objects.md', 1728],
['skills/objectstack-data/references/lint-rules.md', 970],
// 1299 -> 1566 (#26297): the `columns` dataset key and `applyOn: 'create'`
// — a column a job or an admin owns after the first load is written on
Expand Down
30 changes: 13 additions & 17 deletions skills/objectstack-data/references/examples-objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,24 @@

## Field Groups (MVP)

Organize fields into logical groups (e.g., "Contact Information", "Billing",
"System") for forms, detail pages, and editors.

- Declare groups on `ObjectSchema.fieldGroups` — **array order is the display order**.
- Assign each field to a group via `Field.group`, which references an
`ObjectFieldGroup.key`. In-group display order equals the traversal order
of `fields`.
- Group keys must be `snake_case`; group labels are human-readable.
- Group keys must be `snake_case`.
- Optional per-group: `icon`, `description`, and `collapse`
(`'none'` always open · `'expanded'` collapsible, starts open ·
`'collapsed'` collapsible, starts closed — replaces the deprecated
`defaultExpanded` flag, ADR-0085). Groups render identically on forms,
modals, and detail pages; for a bespoke single-page layout assign a
custom Page instead.
`'collapsed'` collapsible, starts closed). Groups render identically on forms,
modals, and detail pages.
- Hide a whole group, header included, with `visibleWhen` (CEL over
`record.*`; FALSE or a fault hides it) or `requiresFeature` (a deployment
feature flag from `PUBLIC_AUTH_FEATURES` in `@objectstack/spec/kernel`; an
unknown flag is refused). At parse `requiresFeature` is lowered into the
group's `visibleWhen` and stripped, AND-combined after an authored
`visibleWhen`. Presentation only: the fields stay readable through the API.
`sys_organization` hides Parent Organization and Sort Order on one
organization:
`{ key: 'group_structure', label: 'Group Structure', requiresFeature: 'multiOrgEnabled' }`.

<!-- os:check -->
```typescript
Expand Down Expand Up @@ -44,10 +48,6 @@ export default ObjectSchema.create({
});
```

**Supported migrations at this layer:** add / rename / delete / reorder groups
(edit the `fieldGroups` array), assign a field to a group (edit `Field.group`).
Explicit per-field in-group ordering is deferred to a future iteration.

## Quick-Start Template

<!-- os:check -->
Expand All @@ -60,7 +60,7 @@ export default ObjectSchema.create({
pluralLabel: 'Support Cases',
description: 'A customer-reported issue tracked to resolution.',
icon: 'life-buoy',
sharingModel: 'private', // required in practice — see above
sharingModel: 'private', // required in practice
highlightFields: ['subject', 'status', 'priority'],
enable: {
trackHistory: true,
Expand Down Expand Up @@ -158,9 +158,6 @@ protection?: {
}
```

The block is `.strict()`: `reason` is **required** (min 1 / max 500 chars) and
unknown keys are rejected.

| `lock` | Edit | Delete | Typical use |
|:---|:---:|:---:|:---|
| `none` (default) | ✅ | ✅ | Normal authored metadata |
Expand All @@ -172,7 +169,6 @@ unknown keys are rejected.

<!-- os:check -->
```typescript
// src/objects/sys-user.object.ts
import { ObjectSchema } from '@objectstack/spec/data';

export const SysUserObject = ObjectSchema.create({
Expand Down
Loading