You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit a1a42d4
Browse filesBrowse the repository at this point in the historyBrowse files
A row-level-security predicate that compares a field with a `json` or `multiple` field is refused when it is authored, at `os validate` / `os build` / `os lint` and at the metadata save door, instead of only when it runs (#19886).
6
+
7
+
**BREAKING** — an accept-set narrowing, shipped by `@objectstack/lint` as `minor` under the repo's launch-window convention for accept-set narrowings. The hand-migration prescription is already registered under protocol major 18 as `cel-predicate-one-value-comparand-refused`, which names this class.
8
+
9
+
Clause-②: no (narrowing)
10
+
11
+
`record.status != record.tags`, with `tags` a `json` field or a `multiple` lookup, lowers to a legal filter shape, because the CEL lowering sees the predicate's text and not the object's field types, and the engine's filter admission does not judge a `{ $field }` reference against the referenced column's type either. Measured before this change: 400 cells (`==`, `!=`, `!(==)`, `>`, `<=`; a `json`, `address`, `multiselect`, `multiple` lookup and `multiple` user field; both operand orders; `using` on `select` / `all` / `update` / `delete` / `insert` and `check` on `insert` / `update` / `all`) were all accepted by the real `os validate` and by the save door. The runtime refused every one of them, measured through the real plugin-security on driver-sql: a read the `using` scopes answered `INVALID_FILTER` / 400, a by-id update or delete it scopes `PERMISSION_DENIED` / 403, and every insert or by-id update judged by the `check` (or by a `using` standing in as the check) `INVALID_FILTER` / 400, with nothing stored.
12
+
13
+
What changes:
14
+
15
+
-`@objectstack/lint`: `validateRlsPredicateEnforceability` reports `rls-predicate-unenforceable` for every lowered field-to-field comparison (`==`, `!=`, `>`, `>=`, `<`, `<=`, on either side, under `!` too) in which either column is DECLARED to hold a list or an object. The declaration is read from the stack's own objects through the spec's value-shape classes, the same two driver-sql refuses such a comparison by: a structured JSON type (`json`, `composite`, `repeater`, `record`, `location`, `address`, `vector`), or a multi-valued field (`multiselect`, `checkboxes`, `tags`, or `select` / `radio` / `lookup` / `user` / `file` / `image` with `multiple: true`). It judges `using` and `check` on every operation. The finding names each comparison and the declaration behind it, and states the clause's run-time consequence. A clause it refuses is not also handed to the engine's filter judge, so one defect earns one finding.
16
+
- Both doors run this rule already, so both refuse: `os validate` / `os build` / `os lint` fail, and a publish through the metadata save door answers `422 INVALID_METADATA` with the same sentence in `issues[]`. `OS_ALLOW_UNLINTED_METADATA_WRITES=1` still turns the save-door refusal into a logged warning.
17
+
18
+
Not changed: a field compared with a single-valued field (`record.status != record.owner`, `record.amount > record.budget`), a `json` or `multiple` field compared with a literal or tested against `null`, and any column the stack does not declare (an object from another package, an external object with no field map), which the rule does not judge. The runtime refusals of stages 2d and 2e stay as the backstop. The stage 2d changeset's sentence that a field compared with a `json` or `multiple` field "is not reported at authoring time" no longer holds: it is now reported at both doors.
19
+
20
+
No shipped predicate moves: 0 of the 187 `using` / `check` / `condition` strings in this repository's packages and examples, and 0 of the 3 in the cloud repository, compare a field with a `json` or `multiple` field, and the real `os validate` over `app-crm`, `app-multi-package`, `app-showcase` and `app-todo` reports no `rls-predicate-*` finding.
21
+
22
+
**What to change.** A field compared with a `json` or `multiple` field has no row-filter form: compare with a single-valued column, or with a literal or a `current_user` value ("one of these values" is `record.status in ['open', 'pending']`, or `record.owner in current_user.org_user_ids`), or move the condition into a validation rule or a hook.
23
+
24
+
<!-- adr-0087: not-required (already-registered cel-predicate-one-value-comparand-refused) The entry already names this exact class in its surface ("a field compared with another field (==, !=, or an ordering operator) where either column holds a list or an object on the record, as a json column or a multiple lookup does") and carries its prescription in its replacement ("A field compared with a json or multiple field has no pushdown form: compare with a single-valued column, or move the condition into a validation rule or hook"). This change moves where that registered class is refused, from run time to authoring time; it adds no class and no prescription the entry does not already hold, and it rewrites no stored metadata. -->
Copy file name to clipboardExpand all lines: content/docs/api/declarative-endpoints.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: Custom endpoints declared as metadata
3
3
navTitle: Declarative Endpoints
4
-
description: "Expose your app to systems outside the platform by declaring an apis: endpoint as metadata — which channel to pick, the four publish gates, and the obligation that comes with an anonymous endpoint."
4
+
description: "Expose your app to outside systems by declaring an apis: endpoint as metadata — pick the channel, pass the four publish gates, secure anonymous calls."
5
5
---
6
6
7
7
A stack can publish an HTTP endpoint as **metadata** instead of writing a handler: a URL,
Copy file name to clipboardExpand all lines: content/docs/api/plugin-endpoints.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: Plugin endpoints — add routes from a plugin
3
3
navTitle: Plugin Endpoints
4
-
description: REST endpoints that become available when the corresponding plugin is installed — auth, workflow, automation, views, realtime, notifications, AI, i18n, and file storage.
4
+
description: REST endpoints each installed plugin adds — auth, workflow, automation, views, realtime, notifications, AI, i18n and files — and how to discover them.
5
5
---
6
6
7
7
These REST endpoints are only available when the corresponding plugin is installed. Check the [discovery manifest](/docs/api#discovery)`services` map before calling them; all paths are relative to the base URL (defaults to `/api/v1`).
description: Route a record for sign-off — who can configure the automation, and the run-identity decision that keeps an approval flow from quietly bypassing row-level security.
4
+
description: Route a record for sign-off with an approval flow — who may configure it, and the run-identity choice that keeps it from bypassing row-level security.
Copy file name to clipboardExpand all lines: content/docs/automation/connectors.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: Connectors — call external systems safely
3
3
navTitle: Connectors
4
-
description: Call external systems from flows — plugin-registered connectors, and declarative provider-bound instances (rest / openapi / mcp) authored as pure metadata with reference-based credentials.
4
+
description: Call external systems from flows with plugin connectors or declarative rest, openapi and mcp instances — pure metadata with reference-based credentials.
Copy file name to clipboardExpand all lines: content/docs/capabilities/index.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: What can it do? — the capability overview
3
3
navTitle: What Can It Do?
4
-
description: The platform's capabilities in business language — data, views, automation, approvals, permissions, analytics, AI, integrations — each with a real CRM as the running example
4
+
description: What the platform can do, in business language — data, views, automation, approvals, permissions, analytics, AI and integrations, shown on a real CRM.
Copy file name to clipboardExpand all lines: content/docs/concepts/metadata-lifecycle.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: Metadata lifecycle — load, publish and HMR
3
3
navTitle: Metadata Lifecycle & HMR
4
-
description: How metadata flows through Repository → Change Log → Cache → Registry — the canonical event stream that powers Studio HMR, REST writes, and future cloud editing.
4
+
description: How metadata flows through Repository, Change Log, Cache and Registry — the event stream behind Studio hot reload, REST writes and cloud editing.
5
5
---
6
6
7
7
This page documents the metadata data path introduced by [ADR-0008](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0008-metadata-repository-and-change-log.md) and refined by [ADR-0005](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0005-metadata-customization-overlay.md). It is the canonical event stream that powers Studio Hot Module Replacement (HMR), REST writes, and future cloud editing.
Copy file name to clipboardExpand all lines: content/docs/concepts/north-star.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: North star — why this framework exists
3
3
navTitle: North Star
4
-
description: ObjectStack's current product and architecture direction.
4
+
description: "Where ObjectStack is headed: a metadata-native backend that humans and AI agents can both operate safely — its principles, runtime shape and non-goals."
5
5
---
6
6
7
7
ObjectStack is the metadata-native backend for business software that humans and
0 commit comments