diff --git a/.changeset/30812-field-group-visible-when-requires-feature.md b/.changeset/30812-field-group-visible-when-requires-feature.md new file mode 100644 index 00000000000..855822ebac1 --- /dev/null +++ b/.changeset/30812-field-group-visible-when-requires-feature.md @@ -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. diff --git a/scripts/check-skills-token-ratchet.mjs b/scripts/check-skills-token-ratchet.mjs index 2d2a9b19146..1936d3d219f 100644 --- a/scripts/check-skills-token-ratchet.mjs +++ b/scripts/check-skills-token-ratchet.mjs @@ -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 diff --git a/skills/objectstack-data/references/examples-objects.md b/skills/objectstack-data/references/examples-objects.md index 1520ebb4284..b0da44a9cb4 100644 --- a/skills/objectstack-data/references/examples-objects.md +++ b/skills/objectstack-data/references/examples-objects.md @@ -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' }`. ```typescript @@ -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 @@ -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, @@ -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 | @@ -172,7 +169,6 @@ unknown keys are rejected. ```typescript -// src/objects/sys-user.object.ts import { ObjectSchema } from '@objectstack/spec/data'; export const SysUserObject = ObjectSchema.create({