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
|**app**|`{ name: string; label?: string; icon?: string; nav?: object[] }`| optional | The navigation shell (app) that surfaces the created objects/dashboards to end users |
233
233
|**seedData**|`{ object: string; records: Record<string, any>[] }[]`| optional | Suggested seed data (reported, not auto-applied in Phase C) |
234
234
235
235
@@ -244,10 +244,10 @@ const result = BlueprintAppSchema.parse(data);
244
244
|**summary**|`string`| ✅ | One-line description of the proposed solution |
245
245
|**assumptions**|`string[]`| ✅ | Design assumptions made from the underspecified goal |
246
246
|**questions**|`string[] \| null`| ✅ | At most 1-2 structure-deciding questions to confirm before building, or null |
|**active**|`never`| optional |[REMOVED]`flow.active` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never had an effect: the engine arms flows from `status`, and `active: false` did NOT stop a flow (worse, the default read as disabled while the engine treated unset as enabled). Delete the key. Use `status: 'obsolete'` (or 'invalid') to unbind and disable a flow, `status: 'active'` to arm it. |
101
101
|**runAs**|`Enum<'system' \| 'user'>`| optional | Execution identity for the run: system = elevated (bypasses RLS), user = the triggering user (RLS-respecting). A run with no trigger user has no identity to scope to, so under user its data operations are REFUSED — declare system to make the elevation explicit. This covers schedule/time-relative/api triggers AND any record-change flow fired by a write that carried no user. |
|**data**|`{ id?: string; success: boolean; errors?: { code: Enum<'VALIDATION_ERROR' \| 'INVALID_FIELD' \| 'MISSING_REQUIRED_FIELD' \| … +257 more>; message: string; category?: string; httpStatus?: integer; … }[]; index?: number; … }[]`| ✅ | Results for each item in the batch |
351
+
|**data**|`{ id?: string; success: boolean; errors?: object[]; index?: number; … }[]`| ✅ | Results for each item in the batch |
352
352
353
353
354
354
---
@@ -417,7 +417,7 @@ const result = ApiErrorSchema.parse(data);
417
417
|**having**|`any`| optional | HAVING — filter over the AGGREGATED rows (aggregation aliases + groupBy projections); applied engine-side after aggregation |
418
418
|**windowFunctions**|`never`| optional |[REMOVED]`query.windowFunctions` was removed in @objectstack/spec 17 (#4286, ADR-0049) — `find()` never applied it: no engine or driver read the key on the query path, so every OVER clause it declared was silently dropped. Delete the key. Window functions are a SQL-driver capability behind `SqlDriver.findWithWindowFunctions(object, query)` (embedder-level; not on the `IDataDriver` contract or the REST surface); request-level analytics are `aggregations` + `groupBy`. |
419
419
|**distinct**|`never`| optional |[REMOVED]`query.distinct` was removed in @objectstack/spec 17 (#4286, ADR-0049 / ADR-0078) — no driver ever rendered SELECT DISTINCT; the flag's only observable effect was MIS-WIRED: the REST list path treated a distinct query as not countable and silently degraded `total`/`hasMore` to a page-local estimate while still returning duplicate rows. Delete the key; `QueryBuilder.distinct()` was removed with it, and the count suppression is gone (`total` is truthful again). For unique values of one column use the SQL/memory drivers' `distinct(object, field)` door; for unique combinations, `groupBy`; for a deduplicated count, the `count_distinct` aggregation. |
420
-
|**expand**|`Record<string, { object: string; fields?: string[]; where?: any; search?: string \| { query: string; fields?: string[]; fuzzy: boolean; operator: Enum<'and' \| 'or'>; … }; … }>`| optional | Recursive relation loading map. Keys are lookup/master_detail field names; values are nested QueryAST objects that control select (`fields`) and filter (`where`, AND-merged with the batch $in), plus further expansion on the related object. The engine resolves expand via batch $in queries (driver-agnostic) with a default max depth of 3; per-parent `limit`/`offset`/`orderBy` are NOT applied on this path. |
420
+
|**expand**|`Record<string, { object: string; fields?: string[]; where?: any; search?: string \| object; … }>`| optional | Recursive relation loading map. Keys are lookup/master_detail field names; values are nested QueryAST objects that control select (`fields`) and filter (`where`, AND-merged with the batch $in), plus further expansion on the related object. The engine resolves expand via batch $in queries (driver-agnostic) with a default max depth of 3; per-parent `limit`/`offset`/`orderBy` are NOT applied on this path. |
0 commit comments