Skip to content
Draft
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/30893-bare-field-ref-symptom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@objectstack/skills': patch
---

docs(skills): three skills describe a bare field ref in a predicate as the fault it is today, not a silent `null`

Clause-②: no
Metadata-protocol: none

`objectstack-platform/references/operations.md`, `objectstack-data` and `objectstack-ui` said a bare field ref (`done` instead of `record.done`) "evaluates to `null`" and silently hides or never fires. It faults. On the server an `error` validation rule and a `requiredWhen` refuse the write and name the rule, an option `visibleWhen` refuses only a write that picks that option (forms still offer it), a `readonlyWhen` field stays editable on the form while the server drops the change with a warning and the save succeeds, and a formula reads `null` with a logged warning. In the console an action's `visible` hides it, its `disabled` greys it out, and a field `visibleWhen` shows the field, each with a console warning. The data skill no longer lists RLS / sharing predicates here: their compiler reads a bare name as the column. The prevention advice (`os validate` / `os build`, `record.<field>`) is unchanged. Growth is paid by same-file deletions of restated prose.
16 changes: 9 additions & 7 deletions skills/objectstack-data/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export const Invoice = ObjectSchema.create({
set → field permission `when`, rules/security.md).
- **`readonly: true` governs the end-user surface, not trusted system writers.**
A non-system write (REST/UI, and any `runAs:'user'` flow — the default) has
the field **stripped** from any non-system write; the write reports
the field **stripped**; the write reports
success but the value never lands. System-context writes —
`runAs:'system'` flows, system hooks, seeds, imports, migrations — are exempt
and DO write it. So the pattern "users can't edit this, but automation
Expand Down Expand Up @@ -447,13 +447,15 @@ os validate # Zod schema + CEL predicates (record.<field> existence) + bindi
# or: os build # the same gates, plus emits dist/
```

It catches what otherwise fails **silently at runtime**: a bare field ref in a
`requiredWhen` / `readonlyWhen` / `visibleWhen`, a validation rule, a formula, or
a row-level-security/sharing predicate (`done` instead of `record.done`) that
evaluates to `null` and never fires. `os lint` is a *separate*
It catches what otherwise surfaces only at runtime, where a bare field ref
(`done` for `record.done`) faults: an `error` validation rule or `requiredWhen`
refuses the write naming it, an option `visibleWhen` only a write picking the
option (forms still offer it); a `readonlyWhen` field stays editable and the
save succeeds without its change (logged); a formula reads `null` (logged).
`os lint` is a *separate*
pass that additionally checks the data model against the conventions in this
skill (relationships, master-detail, roll-ups) — run it too, but it does **not**
replace `os validate`. In a scaffolded project the gate is `npm run validate`.
skill (relationships, master-detail, roll-ups) — run it too.
In a scaffolded project the gate is `npm run validate`.

---

Expand Down
10 changes: 5 additions & 5 deletions skills/objectstack-platform/references/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@

## Verify your work

ObjectStack metadata mistakes fail **silently at runtime**, not at edit time:
a bare field ref in a predicate (`done` instead of `record.done`) evaluates to
`null` and silently hides an action/validation on every record; a
dangling dashboard widget binding renders an empty chart (ADR-0021). Both are
caught at author time by one command:
Metadata mistakes surface at runtime, not at edit time: a bare field ref in a
predicate (`done` for `record.done`) faults, so an `error` validation rule
refuses each write naming the rule and an action's `visible` hides it; a
dangling dashboard widget binding renders an empty chart. Both are caught at
author time by one command:

```bash
os validate # Zod schema + CEL predicates + widget bindings — no artifact
Expand Down
9 changes: 4 additions & 5 deletions skills/objectstack-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,18 +264,17 @@ os validate # CEL predicates (record.<field>) + widget bindings + schema
# or: os build # the same gates, plus emits dist/
```

Two UI-specific traps it catches, both **silent at runtime** otherwise:
Two UI-specific traps it catches, otherwise met only at runtime:

- **Action / field predicate** — a bare field ref in an action `visible` /
`disabled` or a field `visibleWhen` (`done` instead of `record.done`)
evaluates to `null` and hides the control on *every* record (the
"button never shows" trap).
faults on *every* record: the action hides (`visible`) or greys out
(`disabled`), the field shows; the console logs the fault.
- **Dashboard widget binding** — a widget `dataset` / `dimensions` / `values`
that doesn't resolve to a declared dataset/field renders an empty chart
(ADR-0021).

Don't report a view/action/dashboard done until `os validate` passes. In a
scaffolded project the gate is `npm run validate`.
In a scaffolded project the gate is `npm run validate`.

---

Expand Down
Loading