@objectstack/console 17.0.0-rc.2 → 17.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/assets/{AdapterProvider-CtRy19L4.js → AdapterProvider-Bur-uZKZ.js} +1 -1
  3. package/dist/assets/{ApiConsolePage-CGg1YX-S.js → ApiConsolePage-D0rZy0lx.js} +1 -1
  4. package/dist/assets/{AppDocsIndex-BhbMTMti.js → AppDocsIndex-CQo6tZPY.js} +1 -1
  5. package/dist/assets/{AppManagementPage-H6lFpmYT.js → AppManagementPage-jLhhl_WS.js} +1 -1
  6. package/dist/assets/{ApprovalsInboxPage-CbWL6D_v.js → ApprovalsInboxPage-COyyj1KQ.js} +1 -1
  7. package/dist/assets/{CreateViewDialog-Dt1MUhLX.js → CreateViewDialog-C6sZGaIB.js} +1 -1
  8. package/dist/assets/{DashboardView-OZHG8o0x.js → DashboardView-S5Fshq0v.js} +1 -1
  9. package/dist/assets/{FlowRunsPage-DTUvw7r2.js → FlowRunsPage-DGyj2PBP.js} +1 -1
  10. package/dist/assets/{InterfaceListPage-bZdYVg1W.js → InterfaceListPage-DcFmVgXg.js} +1 -1
  11. package/dist/assets/{MarketplacePackagePage-MX3QKebj.js → MarketplacePackagePage-DZkqNaao.js} +1 -1
  12. package/dist/assets/{MetadataProvider-87BSQkFa.js → MetadataProvider-D9fSVVZp.js} +1 -1
  13. package/dist/assets/{ObjectDataPage-JASSibf6.js → ObjectDataPage-BZ4pf0ji.js} +1 -1
  14. package/dist/assets/{PageView-DwZUXknG.js → PageView-B8qkF17f.js} +1 -1
  15. package/dist/assets/{PublicFormsPage-Cu_VttTH.js → PublicFormsPage-C3z0TH0k.js} +1 -1
  16. package/dist/assets/{RecordFormPage-qcCOHj3T.js → RecordFormPage-CyAjEE1O.js} +1 -1
  17. package/dist/assets/{ReportDefaultInspector-Byof8OYm.js → ReportDefaultInspector-BqgFtk2E.js} +1 -1
  18. package/dist/assets/{ReportView-D91loQjH.js → ReportView-CfQ-Z9TJ.js} +1 -1
  19. package/dist/assets/{SearchResultsPage-Dzm_0iUD.js → SearchResultsPage-Ct2q9Lrf.js} +1 -1
  20. package/dist/assets/{SystemHubPage-B3uHe11N.js → SystemHubPage-BSunYA-X.js} +1 -1
  21. package/dist/assets/{createDerive-DmbuzviK.js → createDerive-CGF05Hgy.js} +1 -1
  22. package/dist/assets/{data-adapter-sj_1S7TJ.js → data-adapter-rnhaIuyx.js} +2 -2
  23. package/dist/assets/{index-rkbFgKQu.js → index-U6sSlA28.js} +1 -1
  24. package/dist/assets/{metadata-admin-DA08xWlg.js → metadata-admin-Ci8bBNxq.js} +1 -1
  25. package/dist/assets/{runtime-metadata-persistence-BsgvioOn.js → runtime-metadata-persistence-BjYxldgR.js} +1 -1
  26. package/dist/assets/{src-D0ueU0ix.js → src-CSrGzA_t.js} +2 -2
  27. package/dist/assets/{src-Chkzn0bG.js → src-DzTCerTm.js} +1 -1
  28. package/dist/assets/{use-book-data-CAZ23DZb.js → use-book-data-D8LHn21q.js} +1 -1
  29. package/dist/index.html +1 -1
  30. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import{t as e}from"./rolldown-runtime-C0FnF6B9.js";import{Fn as t,Yt as n,_t as r,in as i,t as a}from"./framework-UESyszCj.js";import{n as o}from"./vendor-zod-wjRCZ0l-.js";var s=e((e=>{var t=o();function n(e){if(typeof process<`u`&&{}.OS_EAGER_SCHEMAS===`1`)return e();let t,n=()=>(t===void 0&&(t=e()),t),r=function(){},i,a=e=>{let t=e._zod;if(!t||typeof t.processJSONSchema!=`function`)return t;let n=t.processJSONSchema;return Object.create(t,{processJSONSchema:{enumerable:!0,value:(t,r,i)=>{let a=t?.seen;if(a&&typeof a.get==`function`){let t=a.get(o);t!==void 0&&!a.has(e)&&a.set(e,t)}return n(t,r,i)}}})},o=new Proxy(r,{get(e,t){let r=n();if(t===`_zod`)return i??=a(r),i;let o=r[t];return typeof o==`function`?o.bind(r):o},set(e,t,r){let i=n();return i[t]=r,!0},has(e,t){return t in n()},ownKeys(){return Reflect.ownKeys(n())},getOwnPropertyDescriptor(e,t){return Reflect.getOwnPropertyDescriptor(n(),t)},getPrototypeOf(){return Reflect.getPrototypeOf(n())}});return o}var r=n(()=>t.z.object({$field:t.z.string().describe(`Field Reference/Column Name`)})),i=n(()=>t.z.object({$eq:t.z.any().optional(),$ne:t.z.any().optional()})),a=n(()=>t.z.object({$gt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$gte:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lte:t.z.union([t.z.number(),t.z.date(),r]).optional()})),s=n(()=>t.z.object({$in:t.z.array(t.z.any()).optional(),$nin:t.z.array(t.z.any()).optional()})),c=n(()=>t.z.object({$between:t.z.tuple([t.z.union([t.z.number(),t.z.date(),r]),t.z.union([t.z.number(),t.z.date(),r])]).optional()})),l=n(()=>t.z.object({$contains:t.z.string().optional(),$notContains:t.z.string().optional(),$startsWith:t.z.string().optional(),$endsWith:t.z.string().optional()})),ee=n(()=>t.z.object({$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),u=n(()=>t.z.object({$eq:t.z.any().optional(),$ne:t.z.any().optional(),$gt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$gte:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lte:t.z.union([t.z.number(),t.z.date(),r]).optional(),$in:t.z.array(t.z.any()).optional(),$nin:t.z.array(t.z.any()).optional(),$between:t.z.tuple([t.z.union([t.z.number(),t.z.date(),r]),t.z.union([t.z.number(),t.z.date(),r])]).optional(),$contains:t.z.string().optional(),$notContains:t.z.string().optional(),$startsWith:t.z.string().optional(),$endsWith:t.z.string().optional(),$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),d=t.z.lazy(()=>t.z.record(t.z.string(),t.z.unknown()).and(t.z.object({$and:t.z.array(d).optional(),$or:t.z.array(d).optional(),$not:d.optional()}))),te=n(()=>t.z.object({where:d.optional()})),f=t.z.lazy(()=>t.z.object({$and:t.z.array(t.z.union([t.z.record(t.z.string(),u),f])).optional(),$or:t.z.array(t.z.union([t.z.record(t.z.string(),u),f])).optional(),$not:t.z.union([t.z.record(t.z.string(),u),f]).optional()})),p={"=":`$eq`,"==":`$eq`,equals:`$eq`,eq:`$eq`,"!=":`$ne`,"<>":`$ne`,ne:`$ne`,neq:`$ne`,not_equals:`$ne`,notequals:`$ne`,">":`$gt`,gt:`$gt`,greater_than:`$gt`,greaterthan:`$gt`,">=":`$gte`,gte:`$gte`,greater_than_or_equal:`$gte`,greaterthanorequal:`$gte`,greaterorequal:`$gte`,"<":`$lt`,lt:`$lt`,less_than:`$lt`,lessthan:`$lt`,"<=":`$lte`,lte:`$lte`,less_than_or_equal:`$lte`,lessthanorequal:`$lte`,lessorequal:`$lte`,before:`$lt`,after:`$gt`,in:`$in`,nin:`$nin`,not_in:`$nin`,notin:`$nin`,contains:`$contains`,notcontains:`$notContains`,not_contains:`$notContains`,like:`$contains`,startswith:`$startsWith`,starts_with:`$startsWith`,endswith:`$endsWith`,ends_with:`$endsWith`,between:`$between`,is_null:`$null`,is_not_null:`$null`,isnull:`$null`,isnotnull:`$null`,is_empty:`$null`,is_not_empty:`$null`,isempty:`$null`,isnotempty:`$null`},m=new Set(Object.keys(p)),ne={$eq:`=`,$ne:`!=`,$gt:`>`,$gte:`>=`,$lt:`<`,$lte:`<=`,$in:`in`,$nin:`nin`,$contains:`contains`,$notContains:`not_contains`,$startsWith:`starts_with`,$endsWith:`ends_with`,$between:`between`};function h(e){let t=String(e).toLowerCase();if(t===`is_null`||t===`isnull`||t===`is_empty`||t===`isempty`)return`is_null`;if(t===`is_not_null`||t===`isnotnull`||t===`is_not_empty`||t===`isnotempty`)return`is_not_null`;if(t===`like`||t===`ilike`)return t;let n=p[t];return n?ne[n]??t:t}function g(e){if(!Array.isArray(e)||e.length===0)return!1;let t=e[0];if(typeof t==`string`){let n=t.toLowerCase();if(n===`and`||n===`or`)return e.length>=2&&e.slice(1).every(e=>g(e));if(e.length>=2&&typeof e[1]==`string`)return m.has(e[1].toLowerCase())}return e.every(e=>g(e))?e.length>0:!1}function re(e){let[t,n,r]=e,i=n.toLowerCase();if(i===`=`||i===`==`||i===`equals`||i===`eq`)return{[t]:r};if(i===`is_null`||i===`isnull`||i===`is_empty`||i===`isempty`)return{[t]:{$null:!0}};if(i===`is_not_null`||i===`isnotnull`||i===`is_not_empty`||i===`isnotempty`)return{[t]:{$null:!1}};let a=p[i];return a?{[t]:{[a]:r}}:{[t]:{[`$${i}`]:r}}}function ie(e){if(e==null)return;if(!Array.isArray(e))return e;if(e.length===0)return;let t=e[0];if(typeof t==`string`&&(t.toLowerCase()===`and`||t.toLowerCase()===`or`)){let n=`$${t.toLowerCase()}`,r=e.slice(1).map(e=>ie(e)).filter(Boolean);return r.length===0?void 0:r.length===1?r[0]:{[n]:r}}if(e.length>=2&&typeof t==`string`)return re(e);if(e.every(e=>Array.isArray(e))){let t=e.map(e=>ie(e)).filter(Boolean);return t.length===0?void 0:t.length===1?t[0]:{$and:t}}}var _=[`$eq`,`$ne`,`$gt`,`$gte`,`$lt`,`$lte`,`$in`,`$nin`,`$between`,`$contains`,`$notContains`,`$startsWith`,`$endsWith`,`$null`,`$exists`],ae=[`$and`,`$or`,`$not`],oe=[..._,...ae];function v(e){return t.z.never({error:()=>e}).optional().describe(`[REMOVED] ${e}`)}var se=n(()=>t.z.object({field:t.z.string(),order:t.z.enum([`asc`,`desc`]).default(`asc`)})),ce=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`array_agg`,`string_agg`]),le=t.z.enum([`day`,`week`,`month`,`quarter`,`year`]),ue=n(()=>t.z.union([t.z.string(),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:le.optional().describe(`Bucket date values into uniform periods (day/week/month/quarter/year)`),alias:t.z.string().optional().describe(`Alias for the projected group value`)})])),de=n(()=>t.z.object({function:ce.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (optional for COUNT(*))`),alias:t.z.string().describe(`Result column alias`),distinct:t.z.boolean().optional().describe(`Apply DISTINCT before aggregation`),filter:d.optional().describe("[EXPERIMENTAL — not enforced] Per-aggregation filter (SQL FILTER (WHERE …)). Neither the SQL builders nor the in-memory fallback applies it (#4286); filter the whole query with `where` instead.")})),fe="A `fields[]` entry is a field name (string). The nested-select object form `{ field, fields, alias }` was removed in @objectstack/spec 17 (#4196, ADR-0049) — nothing ever produced it and nothing ever read `.fields`/`.alias`: every consumer on this path treats the list as `string[]`, so the object form was dropped by the SQL and memory drivers, projected as a column literally named \"[object Object]\" by MongoDB, and refused as an unknown field by the REST ingress. Select related records with `expand` — `expand: { owner: { object: 'user', fields: ['name'] } }` — or name a single related column with a dotted path (`fields: ['owner.name']`). `alias` has no replacement here; an aliased projection is an `aggregations` or `windowFunctions` entry, which carry their own `alias`.",pe=t.z.string({error:e=>e.code===`invalid_type`&&typeof e.input==`object`&&e.input!==null&&!Array.isArray(e.input)?fe:void 0}),me="`query.joins` was removed in @objectstack/spec 17 (#4286, ADR-0049) — no engine or driver ever read it: a query carrying `joins` behaved exactly as if the key were absent, while its name squatted on the reserved REST parameter set. Delete the key. Related records are read through `expand` — `expand: { owner: { object: 'user', fields: ['name'] } }` — which the engine resolves via batch $in queries, and a single related column is a dotted `fields` path (`fields: ['owner.name']`).",he='`query.cursor` was removed in @objectstack/spec 17 (#4286, ADR-0049) — no driver ever implemented keyset pagination, so the cursor was accepted and ignored and every page came back identical (a caller looping "until hasMore is false" never terminates). Delete the key; `QueryBuilder.cursor()` was removed with it. Express the keyset as an ordinary `where` predicate on your sort key — `where: { created_at: { $gt: last.created_at } }` with the matching `orderBy` — which every driver executes with canonicalised comparands. A first-class cursor, if ever built, will be a response-minted opaque token, not this caller-built record.',ge="`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.",_e="`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`.",y=n(()=>t.z.object({query:t.z.string().describe(`Search query text`),fields:t.z.array(t.z.string()).optional().describe(`Fields to search in (if not specified, searches all text fields)`),fuzzy:t.z.boolean().optional().default(!1).describe("[EXPERIMENTAL — not enforced] Fuzzy matching (tolerate typos). The ADR-0061 expansion reads only `query` + `fields`; no executor receives this flag (#4286)."),operator:t.z.enum([`and`,`or`]).optional().default(`or`).describe(`[EXPERIMENTAL — not enforced] Logical operator between terms. The ADR-0061 expansion applies its own term semantics; no executor receives this flag (#4286).`),boost:t.z.record(t.z.string(),t.z.number()).optional().describe(`[EXPERIMENTAL — not enforced] Field-specific relevance boosting (field name -> boost factor). No executor scores results (#4286).`),minScore:t.z.number().optional().describe(`[EXPERIMENTAL — not enforced] Minimum relevance score threshold. No executor scores results (#4286).`),language:t.z.string().optional().describe(`[EXPERIMENTAL — not enforced] Language for text analysis (e.g., "en", "zh", "es"). No executor selects an analyzer (#4286).`),highlight:t.z.boolean().optional().default(!1).describe(`[EXPERIMENTAL — not enforced] Search result highlighting. No executor emits highlights (#4286).`)})),ve=t.z.object({object:t.z.string().describe(`Object name (e.g. account)`),fields:t.z.array(pe).optional().describe("Fields to retrieve — field names, optionally dotted to reach through a relationship (`owner.name`). Related *records* are selected with `expand`, not from inside this list."),where:d.optional().describe(`Filtering criteria (WHERE)`),search:t.z.union([t.z.string(),y]).optional().describe(`Full-text search — the query text (canonical, ADR-0061 D1), or a structured FullTextSearch configuration`),searchFields:t.z.array(t.z.string()).optional().describe(`Narrow the search to these fields (server-intersected with the allowed searchable set — can only narrow, never widen; ADR-0061 D1)`),orderBy:t.z.array(se).optional().describe(`Sorting instructions (ORDER BY)`),limit:t.z.number().optional().describe(`Max records to return (LIMIT)`),offset:t.z.number().optional().describe(`Records to skip (OFFSET)`),top:t.z.number().optional().describe(`Alias for limit (OData compatibility)`),cursor:v(he),joins:v(me),aggregations:t.z.array(de).optional().describe(`Aggregation functions`),groupBy:t.z.array(ue).optional().describe("GROUP BY targets (strings or `{field, dateGranularity?}` objects for date bucketing)"),having:d.optional().describe(`HAVING — filter over the AGGREGATED rows (aggregation aliases + groupBy projections); applied engine-side after aggregation`),windowFunctions:v(_e),distinct:v(ge)}),b=n(()=>ve.extend({expand:t.z.lazy(()=>t.z.record(t.z.string(),b)).optional().describe("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.")})),x=[{id:`1`,a:`x`,b:`y`,c:`z`,owner:`u1`,status:`active`,parent_object:`case`,parent_id:`c1`},{id:`2`,a:`x`,b:`zz`,c:`z`,owner:`u1`,status:`archived`,parent_object:`case`,parent_id:`c2`},{id:`3`,a:`qq`,b:`y`,c:`z`,owner:`u2`,status:`active`,parent_object:`todo`,parent_id:`t1`},{id:`4`,a:`qq`,b:`zz`,c:`z`,owner:`u2`,status:`archived`,parent_object:`todo`,parent_id:`c1`}],ye=[{name:`multi-key $or branch ANDs its own keys`,filter:{$or:[{a:`x`,b:`y`}]},expected:[`1`],note:"#3774: compiled to `a = x OR b = y`, matching 1,2,3."},{name:`each $or branch ANDs independently`,filter:{$or:[{a:`x`,b:`y`},{a:`qq`,b:`zz`}]},expected:[`1`,`4`]},{name:`top-level multi-key ANDs`,filter:{a:`x`,b:`y`},expected:[`1`]},{name:`a $or AND-s with a sibling top-level key`,filter:{$or:[{a:`x`},{b:`y`}],b:`zz`},expected:[`2`]},{name:`multiple operators on one field AND within a branch`,filter:{$or:[{a:{$ne:`qq`,$eq:`x`},b:`y`}]},expected:[`1`],note:`#3774: a single-key branch is miscompilable too — the operator map is looped with the same flag.`},{name:`an abutting $gte/$lt window ANDs its bounds`,filter:{$or:[{b:{$gte:`y`,$lt:`z`}}]},expected:[`1`,`3`],note:`The multi-tier scheduled-flow window pattern. OR-ing the bounds matches every row.`},{name:`$and branch OR-s against a sibling multi-key branch`,filter:{$or:[{$and:[{a:`x`},{b:`y`}]},{a:`qq`,b:`zz`}]},expected:[`1`,`4`]},{name:`multi-key branch OR-s against a sibling $and branch`,filter:{$or:[{a:`x`,b:`y`},{$and:[{a:`qq`},{b:`zz`}]}]},expected:[`1`,`4`]},{name:`$and ANDs with a key that FOLLOWS it in the same branch`,filter:{$or:[{c:`nope`},{$and:[{a:`qq`}],b:`y`}]},expected:[`3`],note:`Key order must not matter; this ordering and the next must agree.`},{name:`$and ANDs with a key that PRECEDES it in the same branch`,filter:{$or:[{c:`nope`},{b:`y`,$and:[{a:`qq`}]}]},expected:[`3`]},{name:`keys AND inside a $or nested in a $or branch`,filter:{$or:[{$or:[{a:`x`,b:`zz`}]}]},expected:[`2`]},{name:`a $or nested under a top-level $and`,filter:{$and:[{$or:[{a:`x`},{b:`y`}]},{b:`y`}]},expected:[`1`,`3`]},{name:`$not ANDs with its sibling keys inside a branch`,filter:{$or:[{c:`nope`},{$not:{a:`x`},b:`zz`}]},expected:[`4`]},{name:`single-key $or branches stay a plain OR`,filter:{$or:[{a:`x`},{b:`y`}]},expected:[`1`,`2`,`3`],note:`The control: the shape that was always correct must stay correct.`},{name:`read scope: own AND active, OR another owner's row`,filter:{$or:[{owner:`u1`,status:`active`},{owner:`u2`,status:`active`}]},expected:[`1`,`3`],note:`Widening here returns rows the scope excludes — an unauthorized read, not a wrong count.`},{name:`read scope: owner $in AND status`,filter:{$or:[{owner:{$in:[`u1`]},status:`active`},{owner:`u2`,status:`archived`}]},expected:[`1`,`4`]},{name:`read scope: parent type paired with its own id list`,filter:{$or:[{parent_object:`case`,parent_id:{$in:[`c1`]}},{parent_object:`todo`,parent_id:{$in:[`t1`]}}]},expected:[`1`,`3`],note:`Row 4 is parent_object=todo with parent_id=c1 — it matches neither pairing, and is the row a widened compile leaks.`}],be=`2026-07-28T12:00:00.000Z`,xe=[{id:`a_epoch`,at:`1969-12-31T23:00:00.000Z`,on:`1969-12-31`,writerForm:`wire`,why:`pre-epoch instant (negative epoch ms) — any surface assuming a non-negative epoch, or reading one as a Julian day (#3773), breaks here first`},{id:`a_old`,at:`2026-04-19T10:00:00.000Z`,on:`2026-04-19`,writerForm:`wire`,why:`well before any window here`},{id:`b_prev`,at:`2026-07-27T14:00:00.000Z`,on:`2026-07-27`,writerForm:`native`,why:`the day before the boundary day`},{id:`c_open`,at:`2026-07-28T00:00:00.000Z`,on:`2026-07-28`,writerForm:`native`,why:`boundary day at exactly 00:00 — the only instant a midnight-anchored bound keeps`},{id:`d_mid`,at:`2026-07-28T09:15:00.000Z`,on:`2026-07-28`,writerForm:`wire`,why:`boundary day, morning — dropped by the #3777 bug`},{id:`e_late`,at:`2026-07-28T21:40:00.000Z`,on:`2026-07-28`,writerForm:`wire`,why:`boundary day, evening — dropped by the #3777 bug`},{id:`f_next`,at:`2026-07-29T00:00:00.000Z`,on:`2026-07-29`,writerForm:`native`,why:`next midnight — the exclusive edge a half-open bound must NOT keep`},{id:`g_eom`,at:`2026-07-31T23:59:59.999Z`,on:`2026-07-31`,writerForm:`wire`,why:`last representable instant of a month — month rollover`},{id:`h_leap`,at:`2024-02-29T12:00:00.000Z`,on:`2024-02-29`,writerForm:`native`,why:`leap day — February rollover`}],Se=[{name:`datetime: bare-day $lte keeps the whole final day`,field:`at`,kind:`datetime`,filter:{at:{$gte:`2026-04-29`,$lte:`2026-07-28`}},tokenFilter:{at:{$gte:`{90_days_ago}`,$lte:`{today}`}},dateRange:[`{90_days_ago}`,`{today}`],expected:[`b_prev`,`c_open`,`d_mid`,`e_late`],note:`#3777: the default dashboard window. Pre-fix returned only b_prev + c_open — everything after 00:00 on the final day vanished.`},{name:`date: the same window is unchanged (already whole-day)`,field:`on`,kind:`date`,filter:{on:{$gte:`2026-04-29`,$lte:`2026-07-28`}},tokenFilter:{on:{$gte:`{90_days_ago}`,$lte:`{today}`}},dateRange:[`{90_days_ago}`,`{today}`],expected:[`b_prev`,`c_open`,`d_mid`,`e_late`],note:"A `date` column compares as calendar-day text, so `<= day` was always right there. The two rows must agree — that is the invariant."},{name:`datetime: a bare-day $lte alone stops at the next midnight`,field:`at`,kind:`datetime`,filter:{at:{$lte:`2026-07-28`}},tokenFilter:{at:{$lte:`{today}`}},expected:[`a_epoch`,`a_old`,`b_prev`,`c_open`,`d_mid`,`e_late`,`h_leap`],note:`f_next sits exactly on the exclusive edge and must stay out — a half-open bound, never an inclusive 23:59:59.999.`},{name:`datetime: $between inherits the rule on its max`,field:`at`,kind:`datetime`,filter:{at:{$between:[`2026-04-29`,`2026-07-28`]}},tokenFilter:{at:{$between:[`{90_days_ago}`,`{today}`]}},expected:[`b_prev`,`c_open`,`d_mid`,`e_late`],note:`knex whereBetween is inclusive on both ends, so it had the same midnight-anchored upper bound $lte had.`},{name:`datetime: $between still bounds its min`,field:`at`,kind:`datetime`,filter:{at:{$between:[`2026-07-28`,`2026-07-28`]}},tokenFilter:{at:{$between:[`{today}`,`{today}`]}},dateRange:[`{today}`,`{today}`],expected:[`c_open`,`d_mid`,`e_late`],note:`The "today" preset degenerates to a single day: the min stays midnight-anchored while the max spans the day.`},{name:`datetime: bare-day $gte is that midnight`,field:`at`,kind:`datetime`,filter:{at:{$gte:`2026-07-28`}},tokenFilter:{at:{$gte:`{today}`}},expected:[`c_open`,`d_mid`,`e_late`,`f_next`,`g_eom`],note:`A LOWER bound anchors to 00:00 — c_open is included precisely because the bound is inclusive of that instant.`},{name:`datetime: bare-day $lt is that midnight`,field:`at`,kind:`datetime`,filter:{at:{$lt:`2026-07-28`}},tokenFilter:{at:{$lt:`{today}`}},expected:[`a_epoch`,`a_old`,`b_prev`,`h_leap`],note:`Strict-less keeps its anchoring: c_open is AT midnight, so it is excluded.`},{name:`date: bare-day $gt excludes the bound day`,field:`on`,kind:`date`,filter:{on:{$gt:`2026-07-28`}},tokenFilter:{on:{$gt:`{today}`}},expected:[`f_next`,`g_eom`],note:`The boundary day itself is out; the mirror-image of widening a lower bound.`},{name:`datetime: a full-ISO $lte keeps exact-instant semantics`,field:`at`,kind:`datetime`,filter:{at:{$lte:`2026-07-28T12:00:00.000Z`}},expected:[`a_epoch`,`a_old`,`b_prev`,`c_open`,`d_mid`,`h_leap`],note:`Only the day-granular STRING carries whole-day intent. e_late (21:40) is after noon and must stay out.`},{name:`datetime: a full-ISO $gte is exact too`,field:`at`,kind:`datetime`,filter:{at:{$gte:`2026-07-28T09:15:00.000Z`}},expected:[`d_mid`,`e_late`,`f_next`,`g_eom`],note:`d_mid is exactly the bound and inclusive.`},{name:`datetime: month-end $lte spans to the next month`,field:`at`,kind:`datetime`,filter:{at:{$gte:`2026-07-29`,$lte:`2026-07-31`}},tokenFilter:{at:{$gte:`{tomorrow}`,$lte:`{current_month_end}`}},dateRange:[`{tomorrow}`,`{current_month_end}`],expected:[`f_next`,`g_eom`],note:`g_eom is 23:59:59.999 on the 31st — kept only if the bound rolled to 2026-08-01.`},{name:`datetime: leap-day $lte includes Feb 29`,field:`at`,kind:`datetime`,filter:{at:{$gte:`2024-02-01`,$lte:`2024-02-29`}},expected:[`h_leap`],note:`The next day is 2024-03-01; a naive month-increment would produce 2024-02-30.`},{name:`datetime: the day BEFORE the leap day excludes it`,field:`at`,kind:`datetime`,filter:{at:{$gte:`2024-02-01`,$lte:`2024-02-28`}},expected:[],note:`Guards the opposite error: rolling 02-28 to 03-01 (skipping the 29th) would wrongly include h_leap.`},{name:`datetime: a pre-epoch day is an ordinary calendar day`,field:`at`,kind:`datetime`,filter:{at:{$gte:`1969-12-31`,$lte:`1969-12-31`}},expected:[`a_epoch`],note:`Negative epoch ms. The #3773 family: any surface that assumes a datetime is a non-negative epoch, or reads one as a Julian day, breaks here first.`},{name:`date: equality against a resolved day matches the whole day`,field:`on`,kind:`date`,filter:{on:`2026-07-28`},tokenFilter:{on:`{today}`},expected:[`c_open`,`d_mid`,`e_late`],note:"#1874: `date == today` silently matched nothing while dates were stored as instants. Equality on a date column is plain calendar-day text equality — Phase 1's whole point."},{name:`date: $in of two resolved days`,field:`on`,kind:`date`,filter:{on:{$in:[`2026-07-28`,`2026-07-27`]}},tokenFilter:{on:{$in:[`{today}`,`{yesterday}`]}},expected:[`b_prev`,`c_open`,`d_mid`,`e_late`],note:"The `expires_on: { $in: [daysFromNow(30)] }` template shape from the #1874 family — element-wise, order-independent."}],S=[{id:`a_midnight`,at:`00:00:00`,writerForm:`native`,why:`the day's lower extreme, written as a Date — epoch 0 on SQLite, which sorts before every TEXT row`},{id:`b_early`,at:`08:00:00`,writerForm:`wire`,why:`before opening — the row a business-hours lower bound must exclude`},{id:`c_open`,at:`09:00:00`,writerForm:`native`,why:`exactly the opening bound, which is inclusive`},{id:`d_mid`,at:`14:30:00`,writerForm:`wire`,why:"mid-afternoon, zero milliseconds — the `HH:MM:SS` spelling every dialect's native TIME emits"},{id:`e_mid_ms`,at:`14:30:00.500`,writerForm:`native`,why:`the same wall clock plus 500ms: the width change lexicographic order has to survive, and what MySQL bare TIME rounded away`},{id:`f_close`,at:`18:00:00`,writerForm:`wire`,why:`exactly the closing bound, which is inclusive`},{id:`g_last`,at:`23:59:59.999`,writerForm:`native`,why:`the day's upper extreme — the last representable wall clock`}],Ce=[{name:`time: a business-hours window keeps both bounds`,filter:{at:{$gte:`09:00:00`,$lte:`18:00:00`}},expected:[`c_open`,`d_mid`,`e_mid_ms`,`f_close`],note:"#3994, measured: 4 of 7 rows silently dropped. An epoch-ms row failed `>= 09:00:00` outright (INTEGER < TEXT on SQLite) and a full-timestamp row failed `<= 18:00:00` lexicographically."},{name:`time: an inclusive upper bound is EXACT, not widened`,filter:{at:{$lte:`14:30:00`}},expected:[`a_midnight`,`b_early`,`c_open`,`d_mid`],note:"The bare-day whole-day rule (D-D) must not reach a time column: `nextUtcCalendarDay` widens only a `YYYY-MM-DD` string. If it leaked, e_mid_ms (14:30:00.500) would appear."},{name:`time: the millisecond suffix sorts after its zero-ms twin`,filter:{at:{$gt:`14:30:00`}},expected:[`e_mid_ms`,`f_close`,`g_last`],note:"The variable-width canon (D-C1) only works because `.` sorts below every digit; d_mid is excluded by strict-greater and e_mid_ms is kept."},{name:`time: a sub-second window bounds the millisecond row`,filter:{at:{$gte:`14:30:00.100`,$lt:`14:30:01`}},expected:[`e_mid_ms`],note:"Guards the same ordering from the other side — `14:30:00.500` must fall inside a window whose bounds differ only after the decimal point."},{name:`time: equality on a canonical wall clock`,filter:{at:`14:30:00`},expected:[`d_mid`],note:`Determinism is what equality and distinct() rest on: one wall clock has exactly one canonical spelling, so e_mid_ms is a DIFFERENT value, not a near-match.`},{name:`time: $in of two canonical wall clocks`,filter:{at:{$in:[`09:00:00`,`18:00:00`]}},expected:[`c_open`,`f_close`]},{name:`time: $between spans the working day inclusively`,filter:{at:{$between:[`08:00:00`,`18:00:00`]}},expected:[`b_early`,`c_open`,`d_mid`,`e_mid_ms`,`f_close`],note:`Both ends inclusive, and — like the $lte case — NOT widened by the calendar-day rule.`},{name:`time: midnight is an ordinary wall clock, not a null`,filter:{at:{$lt:`09:00:00`}},expected:[`a_midnight`,`b_early`],note:"A `00:00:00` write that became INTEGER 0 (a bound `Date` at UTC midnight) sorted before every TEXT row on SQLite and was reachable by no text bound at all."},{name:`time: the last wall clock of the day is reachable`,filter:{at:{$gte:`23:59:59`}},expected:[`g_last`],note:`The upper extreme, where an implementation that truncates or rounds the millisecond suffix (MySQL bare TIME did) loses the row.`}],we=[{id:`r07`,status:`open`,rank:2,name:`Alpha`},{id:`r03`,status:`done`,rank:1,name:`Bravo`},{id:`r11`,status:`open`,rank:3,name:`Charlie`},{id:`r01`,status:`hold`,rank:2,name:`Delta`},{id:`r09`,status:`done`,rank:3,name:`Echo`},{id:`r05`,status:`open`,rank:1,name:`Foxtrot`},{id:`r12`,status:`hold`,rank:1,name:`Golf`},{id:`r02`,status:`done`,rank:2,name:`Hotel`},{id:`r08`,status:`hold`,rank:3,name:`India`},{id:`r04`,status:`open`,rank:2,name:`Juliett`},{id:`r10`,status:`done`,rank:1,name:`Kilo`},{id:`r06`,status:`hold`,rank:3,name:`Lima`}],Te=[{name:`single ascending key with 4-row ties`,orderBy:[{field:`status`,order:`asc`}],pageSize:5},{name:`single descending key with 4-row ties`,orderBy:[{field:`status`,order:`desc`}],pageSize:5},{name:`numeric key with 4-row ties`,orderBy:[{field:`rank`,order:`asc`}],pageSize:4},{name:`page size 1 walks every boundary`,orderBy:[{field:`status`,order:`asc`}],pageSize:1},{name:`multi-key sort with residual ties`,orderBy:[{field:`status`,order:`asc`},{field:`rank`,order:`desc`}],pageSize:5}],Ee=[{name:`page size 5 over 12 rows`,pageSize:5},{name:`page size 7 leaves a short last page`,pageSize:7},{name:`page size 1 walks every boundary`,pageSize:1}],De=we.map(e=>e.id),Oe=[`today`,`yesterday`,`tomorrow`,`now`],ke=[`current_week_start`,`current_week_end`,`current_month_start`,`current_month_end`,`current_quarter_start`,`current_quarter_end`,`current_year_start`,`current_year_end`,`last_week_start`,`last_week_end`,`last_month_start`,`last_month_end`,`last_quarter_start`,`last_quarter_end`,`last_year_start`,`last_year_end`,`next_week_start`,`next_week_end`,`next_month_start`,`next_month_end`,`next_quarter_start`,`next_quarter_end`,`next_year_start`,`next_year_end`],Ae=[`week_start`,`week_end`,`month_start`,`month_end`,`quarter_start`,`quarter_end`,`year_start`,`year_end`],je=[...Oe,...ke,...Ae],C=/^(\d+)_(minutes?|hours?|days?|weeks?|months?|years?)_(ago|from_now)$/,Me=[`minute`,`hour`,`day`,`week`,`month`,`year`];function Ne(e){return je.includes(e)||C.test(e)}function Pe(e){let t=e.match(C);if(!t)return null;let n=t[2].replace(/s$/,``);return{n:parseInt(t[1],10),unit:n,direction:t[3]}}var Fe=t.z.string().refine(Ne,{message:`Unknown date macro. Must be a fixed token (see DATE_MACRO_TOKENS) or match {N_<unit>_(ago|from_now)} where unit is one of: `+Me.join(`, `)}),Ie=/^\$?\{([a-zA-Z0-9_]+)\}$/,Le=t.z.string().refine(e=>{let t=e.match(Ie);return!!t&&Ne(t[1])},{message:`Not a recognised {date-macro} placeholder`}),Re={today:`Start of today (YYYY-MM-DD).`,yesterday:`Start of yesterday.`,tomorrow:`Start of tomorrow.`,now:`Current timestamp (full ISO).`,current_week_start:`Monday 00:00 of this week.`,current_week_end:`Sunday of this week.`,current_month_start:`1st of this month.`,current_month_end:`Last day of this month.`,current_quarter_start:`1st day of this quarter.`,current_quarter_end:`Last day of this quarter.`,current_year_start:`Jan 1 of this year.`,current_year_end:`Dec 31 of this year.`,last_week_start:`Monday of last week.`,last_week_end:`Sunday of last week.`,last_month_start:`1st of last month.`,last_month_end:`Last day of last month.`,last_quarter_start:`1st day of last quarter.`,last_quarter_end:`Last day of last quarter.`,last_year_start:`Jan 1 of last year.`,last_year_end:`Dec 31 of last year.`,next_week_start:`Monday of next week.`,next_week_end:`Sunday of next week.`,next_month_start:`1st of next month.`,next_month_end:`Last day of next month.`,next_quarter_start:`1st day of next quarter.`,next_quarter_end:`Last day of next quarter.`,next_year_start:`Jan 1 of next year.`,next_year_end:`Dec 31 of next year.`,week_start:`Alias for current_week_start.`,week_end:`Alias for current_week_end.`,month_start:`Alias for current_month_start.`,month_end:`Alias for current_month_end.`,quarter_start:`Alias for current_quarter_start.`,quarter_end:`Alias for current_quarter_end.`,year_start:`Alias for current_year_start.`,year_end:`Alias for current_year_end.`};function ze(e){if(typeof e!=`string`)return null;let t=e.trim(),n=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t);if(!n)return null;let[r,i,a]=[Number(n[1]),Number(n[2]),Number(n[3])];return Ve(new Date(Date.UTC(r,i-1,a)))===t?Ve(new Date(Date.UTC(r,i-1,a+1))):null}function Be(e){if(e instanceof Date){let t=e.getTime();return Number.isNaN(t)?null:t}if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e!=`string`)return null;let t=e.trim();if(/^\d{4}-\d{2}-\d{2}$/.test(t))return ze(t)===null?null:Date.parse(`${t}T00:00:00.000Z`);let n=/^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?)(Z|[+-]\d{2}:?\d{2})?$/.exec(t);if(!n)return null;let r=Date.parse(`${n[1]}T${n[2]}${n[3]??`Z`}`);return Number.isNaN(r)?null:r}function Ve(e){return`${String(e.getUTCFullYear()).padStart(4,`0`)}-${String(e.getUTCMonth()+1).padStart(2,`0`)}-${String(e.getUTCDate()).padStart(2,`0`)}`}var He=[`current_user_id`,`current_org_id`];function Ue(e){return He.includes(e)}var We=Ie,Ge=t.z.string().refine(Ue,{message:`Unknown context token. Must be one of: ${He.join(`, `)}`}),Ke=t.z.string().refine(e=>{let t=e.match(We);return!!t&&Ue(t[1])},{message:`Not a recognised {context-token} placeholder`}),qe={current_user_id:"The signed-in user's id (`sys_user.id`).",current_org_id:`The active organization id.`},Je={current_user:`current_user_id`,current_user_email:`current_user_id`,user_id:`current_user_id`,userid:`current_user_id`,me:`current_user_id`,current_organization_id:`current_org_id`,org_id:`current_org_id`,organization_id:`current_org_id`,current_tenant_id:`current_org_id`};function Ye(e){return Ue(e)||Ne(e)}function Xe(e){if(typeof e!=`string`)return null;let t=e.match(We);if(!t)return null;let n=t[1];return Ue(n)?{kind:`context`,token:n}:Ne(n)?{kind:`date-macro`,token:n}:{kind:`unknown`,token:n,suggestion:Je[n.toLowerCase()]}}var Ze=`NOW()`,Qe=`current_user`,$e=[Ze,Qe],et={"NOW()":`The database clock at insert time. Emitted as a native column DEFAULT.`,current_user:`The acting user's id at insert time, from the request's ExecutionContext. Never emitted as a column DEFAULT — with no authenticated user the field stays unset.`};function tt(e){return typeof e==`string`&&/^now\(\)$/i.test(e.trim())}function nt(e){return e===Qe}function rt(e){return tt(e)||nt(e)}function it(e){return rt(e)&&!tt(e)}function at(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array(r+1),a=Array(r+1);for(let e=0;e<=r;e++)i[e]=e;for(let o=1;o<=n;o++){a[0]=o;for(let n=1;n<=r;n++){let r=e[o-1]===t[n-1]?0:1;a[n]=Math.min(i[n]+1,a[n-1]+1,i[n-1]+r)}[i,a]=[a,i]}return i[r]}function ot(e,t,n=3,r=3){let i=e.toLowerCase().replace(/[-\s]/g,`_`);return t.map(e=>({value:e,distance:at(i,e)})).filter(e=>e.distance<=n&&e.distance>0).sort((e,t)=>e.distance-t.distance).slice(0,r).map(e=>e.value)}var st=e=>e.toLowerCase().replace(/[_\-\s]/g,``);function w(e){let{surface:t,knownKeys:n,guidance:r={},history:i}=e,a={};for(let[t,n]of Object.entries(e.aliases??{}))a[st(t)]=n;return e=>{if(e.code!==`unrecognized_keys`)return;let o=e.keys??[],s=[],c=[];for(let e of o){let t=r[e];if(t){c.push(t);continue}let i=Math.max(2,Math.floor(e.length/3)),o=a[st(e)]??ot(e,n,i,1)[0];o&&o!==e&&s.push(`\`${e}\` \u2192 \`${o}\``)}let l=`Unrecognized key(s) on ${t}: ${o.map(e=>`\`${e}\``).join(`, `)}. ${i}`;return s.length&&(l+=` Did you mean ${s.join(`, `)}?`),c.length&&(l+=`
2
2
  ${c.map(e=>` \u2022 ${e}`).join(`
3
- `)}`),l}}function ct(e,t=0){if(t>6)return!1;let n=e._zod?.def;if(!n?.type)return!1;if(n.type===`never`)return!0;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`readonly`:case`nonoptional`:case`catch`:return ct(n.innerType,t+1);default:return!1}}function T(e,n){let{surface:r,history:i,aliases:a,guidance:o,extraKeys:s=[]}=e,c;return t.z.object(n,{error:e=>(c??=w({surface:r,knownKeys:[...Object.keys(n).filter(e=>!ct(n[e])),...s],history:i,aliases:a,guidance:o}))(e)}).strict()}var lt=t.z.enum([`none`,`no-overlay`,`no-delete`,`full`]),ut=t.z.enum([`artifact`,`package`,`env-forced`]),E=t.z.enum([`package`,`org`,`env-forced`]),D={_lock:lt.optional().describe(`Item-level lock — controls overlay & delete (ADR-0010).`),_lockReason:t.z.string().max(500).optional().describe(`Human-readable reason shown when a write is refused by _lock.`),_lockSource:ut.optional().describe(`Layer that set _lock (artifact | package | env-forced).`),_provenance:E.optional().describe(`Origin of the item (package | org | env-forced).`),_packageId:t.z.string().optional().describe(`Owning package machine id.`),_packageVersion:t.z.string().optional().describe(`Owning package version.`),_lockDocsUrl:t.z.string().optional().describe(`Optional documentation link surfaced next to _lockReason.`)},dt=n(()=>t.z.string().min(2,{message:`System identifier must be at least 2 characters`}).regex(/^[a-z][a-z0-9_.]*$/,{message:`System identifier must be lowercase, starting with a letter, and may contain letters, numbers, underscores, or dots (e.g., "user_profile" or "order.created")`}).describe(`System identifier (lowercase with underscores or dots)`)),O=n(()=>t.z.string().min(2,{message:`Identifier must be at least 2 characters`}).regex(/^[a-z][a-z0-9_]*$/,{message:`Identifier must be lowercase snake_case, starting with a letter, and may contain only letters, numbers, and underscores (e.g., "user_profile")`}).describe(`Snake case identifier (lowercase with underscores only)`));n(()=>t.z.string().min(3,{message:`Event name must be at least 3 characters`}).regex(/^[a-z][a-z0-9_.]*$/,{message:`Event name must be lowercase with dots for namespacing (e.g., "user.created", "order.paid")`}).describe(`Event name (lowercase with dot notation for namespacing)`));var ft=t.z.enum([`cel`,`cron`,`template`]),pt=t.z.object({rationale:t.z.string().optional(),generatedBy:t.z.string().optional()}),mt=t.z.object({dialect:ft,source:t.z.string().min(1).optional(),ast:t.z.unknown().optional(),meta:pt.optional()}).refine(e=>e.source!==void 0||e.ast!==void 0,{message:"Expression requires at least one of `source` or `ast`"}),k=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cel`,source:e})),mt]);t.z.union([t.z.string().min(1).transform(e=>({dialect:`cron`,source:e})),mt]);var ht=t.z.union([t.z.string().min(1).transform(e=>({dialect:`template`,source:e})),mt]),gt=Object.freeze({referenceFilter:{to:`lookupFilters`},cascadeDelete:{to:`deleteBehavior`},formula:{to:`expression`},displayFormat:{to:`autonumberFormat`},summaryType:{to:`summaryOperations`},summaryField:{to:`summaryOperations`},index:{why:"field-level index flags built no index and were removed in the 16.x line (#2377, ADR-0049) — declare the index in the object's `indexes[]` instead."},indexed:{why:"never a FieldSchema key; a field-level index flag built no index (#2377). Declare the index in the object's `indexes[]`."},immutable:{why:"never a FieldSchema key. Use the `readonlyWhen` predicate to lock a field after creation."},filterable:{why:"never a FieldSchema key — every declared column is filterable. `sortable` and `searchable` are the real knobs."},placeholder:{why:"never a FieldSchema key. Author hint text through `inlineHelpText` or `description`."},startingNumber:{why:"never a FieldSchema key. An autonumber counter resets per rendered prefix, which `autonumberFormat` itself determines."},validation:{why:"field-level predicates are not a FieldSchema key — author a `validation` metadata item on the object, which carries its own message."},errorMessage:{why:"pairs with the `validation` key that never existed; a `validation` metadata item carries its own message."},audit:{why:"the `auditTrail` family was pruned in 2026-06 as dead in both layers. Use `trackHistory` for the activity timeline."},auditTrail:{why:"pruned in 2026-06 as dead in both layers. Use `trackHistory` for the activity timeline."},pii:{why:"the `dataQuality` governance family was pruned in 2026-06 as dead in both layers — it enforced nothing."},dataQuality:{why:`pruned in 2026-06 as dead in both layers (#3726) — it enforced nothing.`},encrypted:{why:"the `encryptionConfig` family was pruned in 2026-06: it implied at-rest protection that never happened. The real channel is `type: 'secret'`."},encryptionConfig:{why:"pruned in 2026-06 — it implied at-rest protection that never happened. The real channel is `type: 'secret'`."},maskingRule:{why:`pruned in 2026-06 as dead in both layers — masking was never applied.`},cached:{why:`computed-field caching was pruned in 2026-06 (#3733); nothing read it.`}}),_t=Object.freeze({capabilities:{to:`enable`},features:{to:`enable`},namespace:{why:"deprecated and removed — the object `name` is the canonical id everywhere. For module grouping embed a prefix in the name (`sys_user`)."},tableName:{why:"removed — the table name always equals the object `name`."}}),vt=Object.freeze({storage:{why:`the file-storage backend is a deployment concern, not an application declaration. Configure it with the OS_STORAGE_* environment variables, or per-deployment in Setup → Settings → Storage (which also holds credentials — a stack definition would commit them to git and to any published artifact).`}}),yt=Object.freeze([`onEnable`,`functions`]);function A(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function bt(e,t,n,r,i,a){let o=[...t];for(let s of Object.keys(e)){if(t.has(s)||s.startsWith(`_`))continue;let e=n[s],c=e?.to??(e?.why?void 0:ot(s,o,3,1)[0]);a.push({path:`${i}.${s}`,surface:r,key:s,...c?{suggestion:c}:{},...e?.why?{guidance:e.why}:{}})}}function xt(e){let t=`${e.path}: '${e.key}' is not a declared ${e.surface} key, so its value is dropped at load`;return e.guidance?`${t} \u2014 ${e.guidance}`:e.suggestion?`${t} \u2014 did you mean '${e.suggestion}'?`:`${t}.`}var St=t.z.enum(`text.textarea.email.url.phone.password.secret.markdown.html.richtext.number.currency.percent.date.datetime.time.boolean.toggle.select.multiselect.radio.checkboxes.lookup.master_detail.tree.user.image.file.avatar.video.audio.formula.summary.autonumber.composite.repeater.record.location.address.code.json.color.rating.slider.signature.qrcode.progress.tags.vector`.split(`.`)),Ct=`Until #4001 closed this shape these were dropped silently — the field was still created, minus whatever the key was meant to constrain, protect or compute.`,wt=n(()=>T({surface:`this select option`,history:Ct,aliases:{text:`label`,name:`label`,title:`label`,key:`value`,id:`value`,isDefault:`default`,selected:`default`,colour:`color`,visible:`visibleWhen`,showWhen:`visibleWhen`}},{label:t.z.string().describe(`Display label (human-readable, any case allowed)`),value:dt.describe(`Stored value (lowercase machine identifier)`),color:t.z.string().optional().describe(`Color code for badges/charts`),default:t.z.boolean().optional().describe(`Is default option`),visibleWhen:k.optional().describe("Per-option visibility predicate (CEL) — option is offered only when TRUE (else omitted). Same env as field visibleWhen (record + current_user). e.g. P`record.country == 'cn'` or P`'admin' in current_user.positions`")})),Tt=n(()=>t.z.object({latitude:t.z.number().min(-90).max(90).describe(`Latitude coordinate`),longitude:t.z.number().min(-180).max(180).describe(`Longitude coordinate`),altitude:t.z.number().optional().describe(`Altitude in meters`),accuracy:t.z.number().optional().describe(`Accuracy in meters`)})),Et=n(()=>T({surface:`this currency configuration`,history:Ct,aliases:{decimals:`precision`,scale:`precision`,mode:`currencyMode`,currency:`defaultCurrency`,code:`defaultCurrency`,isoCode:`defaultCurrency`}},{precision:t.z.number().int().min(0).max(10).default(2).describe(`Decimal precision (default: 2)`),currencyMode:t.z.enum([`dynamic`,`fixed`]).default(`dynamic`).describe(`Currency mode: dynamic (user selectable) or fixed (single currency)`),defaultCurrency:t.z.string().length(3).default(`CNY`).describe(`Default or fixed currency code (ISO 4217, e.g., USD, CNY, EUR)`)})),Dt=n(()=>t.z.object({value:t.z.number().describe(`Monetary amount`),currency:t.z.string().length(3).describe(`Currency code (ISO 4217)`)})),Ot=n(()=>t.z.object({street:t.z.string().optional().describe(`Street address`),city:t.z.string().optional().describe(`City name`),state:t.z.string().optional().describe(`State/Province`),postalCode:t.z.string().optional().describe(`Postal/ZIP code`),country:t.z.string().optional().describe(`Country name or code`),countryCode:t.z.string().optional().describe(`ISO country code (e.g., US, GB)`),formatted:t.z.string().optional().describe(`Formatted address string`)})),kt=n(()=>t.z.union([t.z.boolean(),t.z.literal(`global`)]));function At(e){return e===`global`}function jt(e){return e===!0||e===`global`}function Mt(){let e={},t={};for(let[n,r]of Object.entries(gt))r.to?e[n]=r.to:r.why&&(t[n]=r.why);return{aliases:e,guidance:t}}var Nt=n(()=>T({surface:`this field`,history:Ct,aliases:{...Mt().aliases,fieldName:`name`,key:`name`,column:`name`,dataType:`type`,fieldType:`type`,title:`label`,displayName:`label`,help:`inlineHelpText`,helpText:`inlineHelpText`,hint:`inlineHelpText`,tooltip:`inlineHelpText`,default:`defaultValue`,initialValue:`defaultValue`,isRequired:`required`,mandatory:`required`,notNull:`required`,isUnique:`unique`,values:`options`,choices:`options`,picklist:`options`,selectOptions:`options`,relatedTo:`reference`,referenceTo:`reference`,target:`reference`,targetObject:`reference`,lookupObject:`reference`,onDelete:`deleteBehavior`,deleteRule:`deleteBehavior`,cascade:`deleteBehavior`,formula:`expression`,calculation:`expression`,compute:`expression`,rollup:`summaryOperations`,rollUp:`summaryOperations`,summary:`summaryOperations`,aggregate:`summaryOperations`,length:`maxLength`,size:`maxLength`,decimals:`scale`,decimalPlaces:`scale`,digits:`precision`,isReadonly:`readonly`,disabled:`readonly`,isHidden:`hidden`,invisible:`hidden`,section:`group`,category:`group`,fieldset:`group`,component:`widget`,renderer:`widget`,control:`widget`,mimeTypes:`accept`,allowedTypes:`accept`,fileTypes:`accept`,maxFileSize:`maxSize`,maxBytes:`maxSize`,trackChanges:`trackHistory`,feedTracked:`trackHistory`,permissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`},guidance:{...Mt().guidance,columnName:"`columnName` was removed in the 16.x line (#2377) — the SQL driver hardcodes the physical column to the field key, so a custom name was ignored. External/federated objects map physical columns with `external.columnMap` (ADR-0062 D7).",referenceFilters:"`referenceFilters` (string[]) was removed in the 16.x line (#2377) — the lookup picker only ever read the structured form. Use `lookupFilters: [{ field, operator, value }]`.",storageNotNull:"physical column constraints live under `storage` — write `storage: { notNull: true }` (ADR-0113). `required` is the WRITE contract and deliberately does not imply the column constraint.",tracked:"`tracked` is not a field key — per-field timeline tracking is `trackHistory: true` (ADR-0052 §5b)."}},{name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Machine name (snake_case)`).optional(),label:t.z.string().optional().describe(`Human readable label`),type:St.describe(`Field Data Type`),description:t.z.string().optional().describe(`Tooltip/Help text`),format:t.z.string().optional().describe(`Format string (e.g. email, phone)`),required:t.z.boolean().default(!1).describe("Write-time contract (ADR-0113): an insert must provide a non-null value, and an update may not null it out. NOT a column constraint — the physical NOT NULL is a separate explicit opt-in (`storage.notNull`), so tightening this on a deployed object is safe: existing null rows stay readable, and editable as long as the write does not touch this field."),storage:t.z.object({notNull:t.z.boolean().optional().describe("Emit a physical NOT NULL on the column (ADR-0113). Absent = the column stays nullable even under `required: true` — the write contract is enforced at the engine, the only sanctioned write path, not by the database. Declaring this over existing null rows is a destructive migration gated by the schema-drift ceremony. Incompatible with `requiredWhen` (a conditional contract cannot be an unconditional column constraint).")}).strict().optional().describe(`Physical storage constraints (ADR-0113). Owns the DDL the write contract deliberately does not imply. Absent = no storage-level constraint requested.`),searchable:t.z.boolean().default(!1).describe(`Is searchable`),multiple:t.z.boolean().default(!1).describe(`Allow multiple values (Stores as Array/JSON). Applicable for select, lookup, file, image.`),unique:kt.default(!1).describe(`Unique constraint. true = unique within the tenant (composite with the tenant column on tenant-scoped objects); 'global' = unique platform-wide across all tenants`),defaultValue:t.z.unknown().optional().describe(`Default value`),maxLength:t.z.number().optional().describe(`Max character length`),minLength:t.z.number().optional().describe(`Min character length`),precision:t.z.number().optional().describe(`Total digits`),scale:t.z.number().optional().describe(`Decimal places`),min:t.z.number().optional().describe(`Minimum value`),max:t.z.number().optional().describe(`Maximum value`),accept:t.z.array(t.z.string()).optional().describe(`Permitted upload types for media fields, as MIME types or extensions (e.g. ["image/*", ".pdf"]). Offered to the file picker AND enforced on write.`),maxSize:t.z.number().int().positive().optional().describe(`Maximum permitted file size in BYTES for media fields. Enforced on write against the stored file size, not just checked in the browser.`),options:t.z.array(wt).optional().describe(`Static options for select/multiselect`),reference:t.z.string().optional().describe(`Target object name (snake_case) for lookup/master_detail fields. Required for relationship types. Used by $expand to resolve foreign key IDs into full objects.`),deleteBehavior:t.z.enum([`set_null`,`cascade`,`restrict`]).optional().default(`set_null`).describe(`What happens if referenced record is deleted`),inlineEdit:t.z.union([t.z.boolean(),t.z.enum([`grid`,`form`])]).optional().describe(`Edit these child records inline within the parent's form (atomic master-detail). true = auto-pick grid/form by child shape; 'grid' = editable line-item grid; 'form' = list + per-row full form.`),inlineTitle:t.z.string().optional().describe(`Title for the inline master-detail grid`),inlineColumns:t.z.array(t.z.any()).optional().describe(`Explicit columns for the inline grid (derived from the child object when omitted)`),inlineAmountField:t.z.string().optional().describe(`Numeric child field summed for the inline grid total`),relatedList:t.z.union([t.z.boolean(),t.z.literal(`primary`)]).optional().describe(`Show this child collection as a related list on the parent's detail page (read-side mirror of inlineEdit). false = suppress; true/absent = shown (stacked under the shared "Related" tab); 'primary' = core relationship, promoted to its own tab. Prominence intent, not a layout switch (ADR-0085).`),relatedListTitle:t.z.string().optional().describe(`Title for the detail-page related list`),relatedListColumns:t.z.array(t.z.any()).optional().describe(`Explicit columns for the detail-page related list (derived from the child object when omitted)`),displayField:t.z.string().optional().describe(`Field shown as each candidate's label in the picker/popover (defaults to the referenced object's name/title).`),descriptionField:t.z.string().optional().describe(`Secondary field shown under the label in the quick-select popover.`),lookupColumns:t.z.array(t.z.union([t.z.string(),T({surface:`this lookup column`,history:Ct,aliases:{name:`field`,fieldName:`field`,key:`field`,title:`label`,header:`label`,size:`width`}},{field:t.z.string(),label:t.z.string().optional(),width:t.z.string().optional(),type:t.z.string().optional()})])).optional().describe(`Explicit columns for the record-picker table; auto-derived from the referenced object when omitted.`),lookupPageSize:t.z.number().int().positive().optional().describe(`Rows per page in the record-picker dialog (default 10).`),lookupFilters:t.z.array(T({surface:`this lookup filter`,history:Ct,aliases:{name:`field`,fieldName:`field`,op:`operator`,comparator:`operator`,condition:`operator`},guidance:{$in:"the operator vocabulary here is flat, not Mongo-style — write `{ field, operator: 'in', value: [...] }`",values:"a multi-value filter puts the array in `value` with `operator: 'in'`"}},{field:t.z.string(),operator:t.z.enum([`eq`,`ne`,`gt`,`lt`,`gte`,`lte`,`contains`,`in`,`notIn`]),value:t.z.any()})).optional().describe(`Base filters restricting which records are selectable (e.g. only active). The structured, picker-honoured lookup filter.`),dependsOn:t.z.array(t.z.union([t.z.string(),T({surface:`this dependsOn entry`,history:Ct,aliases:{name:`field`,fieldName:`field`,local:`field`,remote:`param`,remoteField:`param`,key:`param`}},{field:t.z.string(),param:t.z.string().optional()})])).optional().describe("Declares that this field's available values depend on the value of other field(s) on the same record — the form gates the field until they are set and re-evaluates as they change. For `lookup`/`master_detail` it scopes the candidate query (string = same local/remote key; {field,param} when the remote filter key differs — the {field,param} form is lookup-only). For `select`/`multiselect`/`radio` the actual per-option rule lives in each option's `visibleWhen`; list the referenced fields here (string form) so the option list gates and refreshes with the parent."),allowCreate:t.z.boolean().optional().describe(`Allow inline quick-create from the record picker: when no match exists the user can create a record from the typed text (optimistic dataSource.create with the display field). Best for simple objects whose only required field is the display field.`),expression:k.optional().describe("Formula expression (CEL). e.g. F`record.amount * 0.1`"),returnType:t.z.enum([`number`,`text`,`boolean`,`date`]).optional().describe(`Inferred value type of a formula field (number/text/boolean/date)`),summaryOperations:T({surface:`this roll-up summary`,history:Ct,aliases:{child:`object`,childObject:`object`,from:`object`,source:`object`,aggregate:`function`,operation:`function`,op:`function`,aggregation:`function`,summaryField:`field`,targetField:`field`,foreignKey:`relationshipField`,fk:`relationshipField`,via:`relationshipField`,parentField:`relationshipField`,where:`filter`,criteria:`filter`,condition:`filter`}},{object:t.z.string().describe(`Source child object name for roll-up`),field:t.z.string().describe(`Field on child object to aggregate (ignored for count)`),function:t.z.enum([`count`,`sum`,`min`,`max`,`avg`]).describe(`Aggregation function to apply`),relationshipField:t.z.string().optional().describe(`FK field on the child pointing back to this parent. Auto-detected from the child's lookup/master_detail field referencing this object when omitted; set explicitly only when the child has more than one such reference.`),filter:d.optional().describe("Predicate restricting which child rows are aggregated (a query `where` FilterCondition, e.g. { status: 'received' } or { type: { $in: ['signup','trial'] } }). Omit to aggregate all children. Lets one child object feed multiple filtered roll-ups.")}).optional().describe(`Roll-up summary definition. The engine recomputes the value when child records are inserted/updated/deleted.`),language:t.z.string().optional().describe(`Programming language for syntax highlighting (e.g., javascript, python, sql)`),step:t.z.number().optional().describe(`Step increment for slider (default: 1)`),currencyConfig:Et.optional().describe(`Configuration for currency field type`),dimensions:t.z.number().int().min(1).max(1e4).optional().describe(`Vector dimensionality (e.g., 1536 for OpenAI embeddings)`),trackHistory:t.z.boolean().optional().describe(`Render this field's value changes as human-readable entries on the record activity timeline (ADR-0052 §5b). Opt-in per field.`),group:t.z.string().optional().describe(`Field group name for organizing fields in forms and layouts (e.g., "contact_info", "billing", "system")`),visibleWhen:k.optional().describe("Predicate (CEL) — field is shown only when TRUE (else hidden). e.g. P`record.type == 'invoice'`"),readonlyWhen:k.optional().describe("Predicate (CEL) — field is read-only when TRUE. e.g. P`record.status == 'paid'`"),requiredWhen:k.optional().describe("Predicate (CEL) — field is required when TRUE. The only slot; the `conditionalRequired` alias was removed in protocol 17 (#3855)."),conditionalRequired:v("`conditionalRequired` was removed in @objectstack/spec 17 (#3855) — use `requiredWhen`. Rename the key; the value (a CEL predicate) is unchanged. Run `os migrate meta --from 16` to rewrite it automatically."),widget:t.z.string().optional().describe('Form widget override — names a registered field component (resolved as `field:<widget>`) to render this field instead of the `type` default. Degrades to the `type` renderer when unregistered. e.g. "object-ref", "filter-condition", "recipient-picker".'),hidden:t.z.boolean().default(!1).describe(`Hidden from default UI`),readonly:t.z.boolean().default(!1).describe('Read-only — never editable in forms, AND server-enforced on BOTH write paths: a non-system write to this field is silently dropped from the payload on UPDATE (#2948/#3003) and on INSERT (#3043; a create can no longer directly seed e.g. `approval_status: "approved"`), symmetric with `readonlyWhen`. A stripped INSERT field still falls back to its `defaultValue`. Exempt from the strip: `isSystem` writes (seed replay, migration), and an opt-in "historical" import (`preserveAudit`, #3493) — which admits a whitelist (the audit/timestamp family plus author-declared business `readonly` fields). A normal (non-system) import is NOT system-context and still strips.'),requiredPermissions:t.z.array(t.z.string()).optional().describe(`[ADR-0066 D3] Capabilities required to read/edit this field (mask on read, deny on write; AND-gate).`),ackPlaintextMasking:t.z.boolean().optional().describe("[ADR-0100] Affirm a generic `password` field's plaintext-at-rest / masked-on-read contract is intended, silencing the author-time warning (#3420). No effect on non-password fields."),system:t.z.boolean().optional().describe(`Auto-injected system/audit field (e.g. created_at, updated_by, organization_id). Tools that surface system fields separately from author-declared business fields should branch on this flag.`),sortable:t.z.boolean().optional().default(!0).describe(`Whether field is sortable in list views`),inlineHelpText:t.z.string().optional().describe(`Help text displayed below the field in forms`),autonumberFormat:t.z.string().optional().describe(`Auto-number format: literal text + {0000} counter, {YYYY}/{MM}/{DD}/{YYYYMMDD} date tokens (business tz), and {field_name} interpolation. Counter resets per rendered prefix (e.g. AD{YYYYMMDD}{0000} resets daily).`),externalId:t.z.boolean().default(!1).describe(`Is external ID for upsert operations`),...D}).superRefine((e,t)=>{e.storage?.notNull===!0&&e.requiredWhen!==void 0&&t.addIssue({code:`custom`,path:[`storage`,`notNull`],message:"`storage.notNull` cannot be combined with `requiredWhen` (ADR-0113): when the condition is false the write contract permits null, but the column would refuse it. Use `required: true` + `storage.notNull` for an unconditional constraint, or `requiredWhen` alone for a conditional write contract (the column stays nullable)."})})),Pt={text:(e={})=>({type:`text`,...e}),textarea:(e={})=>({type:`textarea`,...e}),number:(e={})=>({type:`number`,...e}),boolean:(e={})=>({type:`boolean`,...e}),date:(e={})=>({type:`date`,...e}),datetime:(e={})=>({type:`datetime`,...e}),currency:(e={})=>({type:`currency`,...e}),percent:(e={})=>({type:`percent`,...e}),url:(e={})=>({type:`url`,...e}),email:(e={})=>({type:`email`,...e}),phone:(e={})=>({type:`phone`,...e}),image:(e={})=>({type:`image`,...e}),file:(e={})=>({type:`file`,...e}),avatar:(e={})=>({type:`avatar`,...e}),formula:(e={})=>({type:`formula`,...e}),summary:(e={})=>({type:`summary`,...e}),autonumber:(e={})=>({type:`autonumber`,...e}),markdown:(e={})=>({type:`markdown`,...e}),html:(e={})=>({type:`html`,...e}),password:(e={})=>({type:`password`,...e}),secret:(e={})=>({type:`secret`,...e}),select:(e,t)=>{let n=e=>e.toLowerCase().replace(/\s+/g,`_`).replace(/[^a-z0-9_]/g,``),r,i;if(Array.isArray(e))r=e.map(e=>typeof e==`string`?{label:e,value:n(e)}:{...e,value:e.value.toLowerCase()}),i=t||{};else{r=(e.options||[]).map(e=>typeof e==`string`?{label:e,value:n(e)}:{...e,value:e.value.toLowerCase()});let{options:t,...a}=e;i=a}return{type:`select`,options:r,...i}},lookup:(e,t={})=>({type:`lookup`,reference:e,...t}),masterDetail:(e,t={})=>({type:`master_detail`,reference:e,...t}),user:(e={})=>({type:`user`,reference:`sys_user`,...e}),location:(e={})=>({type:`location`,...e}),address:(e={})=>({type:`address`,...e}),richtext:(e={})=>({type:`richtext`,...e}),code:(e,t={})=>({type:`code`,language:e,...t}),color:(e={})=>({type:`color`,...e}),rating:(e=5,t={})=>({type:`rating`,max:e,...t}),signature:(e={})=>({type:`signature`,...e}),slider:(e={})=>({type:`slider`,...e}),qrcode:(e={})=>({type:`qrcode`,...e}),json:(e={})=>({type:`json`,...e}),vector:(e,t={})=>({type:`vector`,dimensions:e,...t})},Ft={name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique rule name (snake_case)`),label:t.z.string().optional().describe(`Human-readable label for the rule listing`),description:t.z.string().optional().describe(`Administrative notes explaining the business reason`),active:t.z.boolean().default(!0),events:t.z.array(t.z.enum([`insert`,`update`])).default([`insert`,`update`]).describe("Write contexts the rule runs on. `delete` is intentionally absent — the evaluator only runs on the insert/update write path; guard deletions with a `beforeDelete` lifecycle hook"),priority:t.z.number().int().min(0).max(9999).default(100).describe(`Execution priority (lower runs first, default: 100)`),tags:t.z.array(t.z.string()).optional().describe(`Categorization tags (e.g., "compliance", "billing")`),severity:t.z.enum([`error`,`warning`,`info`]).default(`error`),message:t.z.string().describe(`Error message to display to the user`),...D},It=n(()=>T({surface:`this script validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`,predicate:`condition`,rule:`condition`}},{...Ft,type:t.z.literal(`script`),condition:k.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),Lt=n(()=>T({surface:`this state-machine validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{states:`transitions`,statefield:`field`,from:`transitions`,initial:`initialStates`,initialstate:`initialStates`}},{...Ft,type:t.z.literal(`state_machine`),field:t.z.string().describe(`State field (e.g. status)`),transitions:t.z.record(t.z.string(),t.z.array(t.z.string())).describe(`Map of { OldState: [AllowedNewStates] }`),initialStates:t.z.array(t.z.string()).optional().describe("States a record may be CREATED in. When set, an INSERT whose state field carries a value outside this list is rejected (server-enforced) — the FSM entry point. `transitions` only governs UPDATE, and a `select` field permits ANY declared option as an initial value, so without this a record could be born mid-flow (e.g. created already `approved`). Omit to keep the legacy behavior (no initial-state check on insert). #3165.")})),Rt=n(()=>T({surface:`this format validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{pattern:`regex`,fieldname:`field`}},{...Ft,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),zt=n(()=>T({surface:`this cross-field validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`}},{...Ft,type:t.z.literal(`cross_field`),condition:k.describe("Predicate (CEL) comparing fields. e.g. P`record.end_date > record.start_date`"),fields:t.z.array(t.z.string()).describe(`Fields involved. Only fields[0] is read (labels which field the violation attaches to); the rest are advisory. Shares script’s evaluation path.`)})),Bt=n(()=>T({surface:`this JSON-schema validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{jsonschema:`schema`,fieldname:`field`}},{...Ft,type:t.z.literal(`json_schema`),field:t.z.string().describe(`JSON field to validate`),schema:t.z.record(t.z.string(),t.z.unknown()).describe(`JSON Schema object definition`)})),Vt=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[It,Lt,Rt,zt,Bt,Ht])),Ht=n(()=>T({surface:`this conditional validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{if:`when`,condition:`when`,match:`when`,else:`otherwise`}},{...Ft,type:t.z.literal(`conditional`),when:k.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:Vt.describe(`Validation rule to apply when condition is true`),otherwise:Vt.optional().describe(`Validation rule to apply when condition is false`)}));n(()=>t.z.object({key:t.z.string().describe(`Translation key (e.g., "views.task_list.label")`),defaultValue:t.z.string().optional().describe(`Fallback value when translation key is not found`),params:t.z.record(t.z.string(),t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Interpolation parameters (e.g., { count: 5 })`)}));var j=n(()=>t.z.string().describe(`Display label (plain string; i18n keys are auto-generated by the framework)`)),Ut=n(()=>t.z.object({ariaLabel:j.optional().describe(`Accessible label for screen readers (WAI-ARIA aria-label)`),ariaDescribedBy:t.z.string().optional().describe(`ID of element providing additional description (WAI-ARIA aria-describedby)`),role:t.z.string().optional().describe(`WAI-ARIA role attribute (e.g., "dialog", "navigation", "alert")`)}).describe(`ARIA accessibility attributes`));n(()=>t.z.object({key:t.z.string().describe(`Translation key`),zero:t.z.string().optional().describe(`Zero form (e.g., "No items")`),one:t.z.string().optional().describe(`Singular form (e.g., "{count} item")`),two:t.z.string().optional().describe(`Dual form (e.g., "{count} items" for exactly 2)`),few:t.z.string().optional().describe(`Few form (e.g., for 2-4 in some languages)`),many:t.z.string().optional().describe(`Many form (e.g., for 5+ in some languages)`),other:t.z.string().describe(`Default plural form (e.g., "{count} items")`)}).describe(`ICU plural rules for a translation key`));var Wt=n(()=>t.z.object({style:t.z.enum([`decimal`,`currency`,`percent`,`unit`]).default(`decimal`).describe(`Number formatting style`),currency:t.z.string().optional().describe(`ISO 4217 currency code (e.g., "USD", "EUR")`),unit:t.z.string().optional().describe(`Unit for unit formatting (e.g., "kilometer", "liter")`),minimumFractionDigits:t.z.number().optional().describe(`Minimum number of fraction digits`),maximumFractionDigits:t.z.number().optional().describe(`Maximum number of fraction digits`),useGrouping:t.z.boolean().optional().describe(`Whether to use grouping separators (e.g., 1,000)`)}).describe(`Number formatting rules`)),Gt=n(()=>t.z.object({dateStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Date display style`),timeStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Time display style`),timeZone:t.z.string().optional().describe(`IANA time zone (e.g., "America/New_York")`),hour12:t.z.boolean().optional().describe(`Use 12-hour format`)}).describe(`Date/time formatting rules`));n(()=>t.z.object({code:t.z.string().describe(`BCP 47 language code (e.g., "en-US", "zh-CN")`),fallbackChain:t.z.array(t.z.string()).optional().describe(`Fallback language codes in priority order (e.g., ["zh-TW", "en"])`),direction:t.z.enum([`ltr`,`rtl`]).default(`ltr`).describe(`Text direction: left-to-right or right-to-left`),numberFormat:Wt.optional().describe(`Default number formatting rules`),dateFormat:Gt.optional().describe(`Default date/time formatting rules`)}).describe(`Locale configuration`));var Kt='`crypto.hash` was removed from `HookBodyCapability` in @objectstack/spec 17 (#4391, ADR-0049 enforce-or-remove) — the sandbox never implemented it. `installCtx` wired only `ctx.crypto.randomUUID`, so `ctx.crypto.hash(...)` threw inside the VM on every call the token ever "granted", while the build-time extractor inferred the token from that very call and let `os build` pass. Delete the capability from `capabilities` AND delete the `ctx.crypto.hash(...)` call it was declared for — the call has never returned a value, so nothing that works today depends on it. There is no replacement inside the sandbox: hash in the host (a Connector recipe, or an engine-side hook) instead. If you need hashing in a body, reopen it through the capability admission process — implementation first, the declaration lands with the implementation. Run `os migrate meta --from 16` to rewrite it automatically.',qt=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?Kt:void 0}),Jt=[`language`,`source`],Yt=[`language`,`source`,`capabilities`,`timeoutMs`,`memoryMb`],Xt='is an L2 key — it only applies to `language: "js"`. An expression body is a pure formula: it performs no IO, so it has nothing to grant and no sandbox to bound.',Zt=w({surface:`this expression (L1) hook body`,knownKeys:Jt,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${Xt}`,timeoutMs:`\`timeoutMs\` ${Xt}`,memoryMb:`\`memoryMb\` ${Xt}`},history:`Until #4001 these were dropped silently.`}),Qt=w({surface:`this sandboxed JS (L2) hook body`,knownKeys:Yt,aliases:{capability:`capabilities`,caps:`capabilities`,permissions:`capabilities`,timeout:`timeoutMs`,timeoutms:`timeoutMs`,memory:`memoryMb`,memorymb:`memoryMb`,code:`source`,script:`source`,body:`source`},history:`Until #4001 these were dropped silently — the body still ran, just not under the limits or grants that were written.`}),$t=t.z.object({language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)},{error:Zt}).strict().describe(`L1 expression body — pure formula, no IO`),M=t.z.object({language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(qt).default([]).describe(`Granted capability tokens`),timeoutMs:t.z.number().int().positive().max(3e4).optional().describe(`Per-invocation timeout (ms)`),memoryMb:t.z.number().int().positive().max(256).optional().describe(`Per-invocation memory cap (MB)`)},{error:Qt}).strict().describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),en=t.z.discriminatedUnion(`language`,[$t,M]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),tn={twoFactor:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.enable_two_factor`,`sys_user.actions.disable_two_factor`,`sys_user.actions.generate_backup_codes`,`sys_two_factor.actions.enable_two_factor`,`sys_two_factor.actions.disable_two_factor`,`sys_two_factor.actions.regenerate_backup_codes`],notes:`Login-surface 2FA challenge is server-driven remediation (ADR-0069), so the flag is intentionally unread by objectui LoginForm.`},passkeys:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no passkey UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},magicLink:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no magic-link UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},organization:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_user.actions.invite_user`,`sys_member.actions.add_member`,`sys_member.actions.update_member_role`,`sys_member.actions.remove_member`,`sys_member.actions.transfer_ownership`,`sys_invitation.actions.invite_user`,`sys_invitation.actions.cancel_invitation`,`sys_invitation.actions.resend_invitation`,`sys_team.actions.create_team`,`sys_team.actions.update_team`,`sys_team.actions.remove_team`,`sys_team_member.actions.add_team_member`,`sys_team_member.actions.remove_team_member`],notes:`Org CAPABILITY gate, not multi-org (ADR-0081 D1).`},multiOrgEnabled:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_organization.actions.create_organization`,`sys_organization.actions.update_organization`,`sys_organization.actions.delete_organization`,`sys_organization.actions.set_active_organization`,`sys_organization.actions.leave_organization`,`sys_organization.actions.change_slug`],notes:"Reflects ACTUAL multi-tenancy capability (the tenancy posture enforces an organization wall — `group` or `isolated`, ADR-0093 D4 / ADR-0105 D1), not just the requested posture."},degradedTenancy:{surface:`status`,semantics:`opt-in`,exempt:{reason:`Operator status banner (ADR-0093 D5) — signals degraded tenant isolation, not an input capability gate.`}},oidcProvider:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_oauth_application.actions.create_oauth_application`,`sys_oauth_application.actions.delete_oauth_application`,`sys_oauth_application.actions.disable_oauth_application`,`sys_oauth_application.actions.enable_oauth_application`,`sys_oauth_application.actions.rotate_client_secret`],notes:`Default-ON: the embedded OIDC authorization server follows the default-on MCP surface (resolveOidcProviderEnabled). Login surface consumes the socialProviders[] array (per-provider enabled), not this flag.`},sso:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Deliberately ungated on the CRUD surface: the served value is refined to "usable" (≥1 provider configured) via isSsoUsable() at /auth/config, so gating sys_sso_provider registration actions on it would deadlock first-provider setup. Login consumption verified: objectui LoginForm gates the "Sign in with SSO" button.`}},ssoEnforced:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: objectui LoginForm hides the password form and self-registration (break-glass link remains). No spec input to gate.`}},deviceAuthorization:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input (sys_device_code declares no actions). Known gap: objectui DeviceAuthPage hits the device-auth endpoints without checking this flag (absent from its client type) — tracked in objectui#2513 (#2874 P2②).`}},admin:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user`,`sys_user.actions.ban_user`,`sys_user.actions.unban_user`,`sys_user.actions.unlock_user`,`sys_user.actions.set_user_password`,`sys_user.actions.set_user_role`,`sys_user.actions.impersonate_user`],notes:`SCIM forces the admin plugin (and this flag) on — ADR-0071.`},phoneNumber:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user.params.phoneNumber`],notes:`The original #2871 fix. Also read by objectui LoginForm for the phone+password sign-in mode.`},phoneNumberOtp:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: gates the "sign in with verification code" link (LoginForm) and the phone branch of forgot-password. Only advertised when SMS is actually deliverable (#2780).`}}},nn=Object.keys(tn);function rn(e){return`features.${e} ${tn[e].semantics===`opt-in`?`== true`:`!= false`}`}function an(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=rn(n),a=r.visible;return a===void 0?{...r,visible:{dialect:`cel`,source:i}}:a.dialect!==`cel`||typeof a.source!=`string`?(t.addIssue({code:`custom`,path:[`requiresFeature`],message:"`requiresFeature` composes only with a CEL `visible` carrying a `source` string; this expression is AST-only or non-CEL — write the combined predicate by hand."}),r):{...r,visible:{...a,source:`(${a.source}) && ${i}`}}}var on=w({surface:`this action param`,knownKeys:[`name`,`field`,`objectOverride`,`label`,`type`,`required`,`options`,`placeholder`,`helpText`,`defaultValue`,`multiple`,`accept`,`maxSize`,`reference`,`defaultFromRow`,`visible`,`requiresFeature`],aliases:{referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},history:`Until #3405 these were dropped silently — the param still parsed, so a mis-spelled config shipped as a control that quietly ignored it.`}),sn=n(()=>t.z.object({name:t.z.string().optional(),field:O.optional(),objectOverride:O.optional(),label:j.optional(),type:St.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(t.z.object({label:j,value:t.z.string()})).optional(),placeholder:t.z.string().optional(),helpText:t.z.string().optional(),defaultValue:t.z.unknown().optional(),multiple:t.z.boolean().optional().describe(`Allow multiple values (array value shape); mirrors FieldSchema.multiple.`),accept:t.z.array(t.z.string()).optional().describe(`Accepted upload types (MIME types / extensions) for file/image params.`),maxSize:t.z.number().int().positive().optional().describe(`Max upload size in bytes for file/image params.`),reference:O.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:k.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(nn).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")},{error:on}).strict().refine(e=>!!e.name||!!e.field,{message:`ActionParam requires either "name" or "field"`}).refine(e=>!(!e.field&&(e.type===`lookup`||e.type===`master_detail`)&&!e.reference),{path:[`reference`],message:`ActionParam with type "lookup"/"master_detail" requires "reference" (the target object) when declared inline — without it the param dialog degrades to a raw record-id text input. Set \`reference: '<object>'\`, or use a field-backed param (\`{ field: '<lookup_field>' }\`) to inherit it.`}).transform((e,t)=>an(e,t))),cn=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),ln=new Set(cn.options.filter(e=>e!==`script`)),un=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`,`global_nav`]),dn=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),N=`Until #4001 closed this shape these were dropped silently — the action still registered and still ran, without whatever the key was meant to configure or gate.`,fn=T({surface:`this action's AI exposure block`,history:N,aliases:{enabled:`exposed`,enable:`exposed`,aiEnabled:`exposed`,expose:`exposed`,visible:`exposed`,prompt:`description`,toolDescription:`description`,summary:`description`,type:`category`,kind:`category`,toolCategory:`category`,hints:`paramHints`,parameterHints:`paramHints`,params:`paramHints`,returns:`outputSchema`,responseSchema:`outputSchema`,output:`outputSchema`,confirm:`requiresConfirmation`,requireConfirmation:`requiresConfirmation`,hitl:`requiresConfirmation`,humanInTheLoop:`requiresConfirmation`},guidance:{permissions:"AI invocation is not gated by a key here — an agent reaches this action only if a surface-compatible SKILL declares it (ADR-0064), and who may talk to that agent is gated by the agent's `access` / `permissions` (enforced at the chat route since #1884). For a human-approval step on the call itself, use `requiresConfirmation: true`.",approval:"there is no approval workflow key here — `requiresConfirmation: true` forces a human-in-the-loop gate on the AI call. A multi-step business approval is an `approval` metadata item, not an action field."}},{exposed:t.z.boolean().default(!1).describe("Expose this action to AI agents. Requires `description` when true."),description:t.z.string().min(40).optional().describe(`LLM-facing description (≥40 chars). Required when exposed.`),category:dn.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),T({surface:`this AI parameter hint`,history:N,aliases:{desc:`description`,hint:`description`,values:`enum`,options:`enum`,choices:`enum`,allowed:`enum`,example:`examples`,sample:`examples`}},{description:t.z.string().optional(),enum:t.z.array(t.z.union([t.z.string(),t.z.number()])).optional(),examples:t.z.array(t.z.unknown()).optional()})).optional().describe(`Per-parameter AI hints keyed by param name.`),outputSchema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`JSON Schema for the action return value.`),requiresConfirmation:t.z.boolean().optional().describe(`Override HITL confirmation for AI invocations.`)}),pn=()=>T({surface:`this action`,history:N,aliases:{title:`label`,displayName:`label`,text:`label`,object:`objectName`,entity:`objectName`,actionType:`type`,url:`target`,endpoint:`target`,path:`target`,href:`target`,parameters:`params`,args:`params`,inputs:`params`,fields:`params`,confirm:`confirmText`,confirmation:`confirmText`,confirmMessage:`confirmText`,success:`successMessage`,successText:`successMessage`,toast:`successMessage`,visibleWhen:`visible`,showWhen:`visible`,disabledWhen:`disabled`,style:`variant`,color:`variant`,appearance:`variant`,placement:`locations`,location:`locations`,position:`locations`,verb:`method`,httpMethod:`method`,body:`bodyExtra`,payload:`bodyExtra`,llm:`ai`,tool:`ai`,dialog:`resultDialog`,result:`resultDialog`,refresh:`refreshAfter`,reload:`refreshAfter`,permissions:`requiredPermissions`,capabilities:`requiredPermissions`,requiresPermissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`,acl:`requiredPermissions`},guidance:{hidden:"`hidden` is not an action key, and hiding is not gating — `visible` and `disabled` are UI predicates that hide or grey a button, they do not stop a request. To actually gate invocation use `requiredPermissions` (ADR-0066 D4, enforced with a 403 on the platform action route). To declare an action with no UI surface at all, set `locations: []`.",exposed:"AI exposure lives under `ai` — write `ai: { exposed: true, description: … }`. The description is the LLM-facing contract and is REQUIRED (≥40 chars) whenever exposed.",requiresConfirmation:"the AI human-in-the-loop override lives under `ai` — write `ai: { requiresConfirmation: true }`. `confirmText` is the separate UI confirm prompt."}},{name:O.describe(`Machine name (lowercase snake_case)`),label:j.describe(`Display label`),objectName:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).optional().describe(`Target object this action belongs to. When set, the action is auto-merged into the object's actions array by defineStack().`),icon:t.z.string().optional().describe(`Icon name`),locations:t.z.array(un).optional().describe(`Locations where this action is visible`),component:t.z.enum([`action:button`,`action:icon`,`action:menu`,`action:group`]).optional().describe(`Visual component override`),type:cn.default(`script`).describe(`Action functionality type`),target:t.z.string().optional().describe("URL, Script Name, Flow ID, or API Endpoint. Supports ${param.X} and ${ctx.X} interpolation."),openIn:t.z.enum([`self`,`new-tab`]).optional().describe("For type:'url' — where to open `target`. 'new-tab' opens a new browser tab; 'self' navigates in place. When omitted, external/absolute URLs open in a new tab and relative URLs navigate in place. Static execution option — keep it OUT of `params` (which is user-input-collection only)."),body:en.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:v("`execute` was removed in @objectstack/spec 17 (#3855) — use `target`. Rename the key; the value (a handler / flow / URL ref) is unchanged. Run `os migrate meta --from 16` to rewrite it automatically."),params:t.z.array(sn).optional().describe(`Input parameters required from user`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`link`]).optional().describe(`Button visual variant for styling (primary = highlighted, danger = destructive, ghost = transparent)`),order:t.z.number().optional().describe("Sort order within a location group (lower = higher). Promotes/demotes an action toward the record_header primary button; stable, so actions without `order` keep their registration order."),confirmText:j.optional().describe(`Confirmation message before execution`),successMessage:j.optional().describe(`Success message to show after execution`),errorMessage:j.optional().describe(`Error message to show when the action fails (overrides the raw error).`),refreshAfter:t.z.boolean().default(!1).describe(`Refresh view after execution`),undoable:t.z.boolean().optional().describe(`Offer an Undo affordance after this single-record update action succeeds.`),resultDialog:T({surface:`this result dialog`,history:N,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:j.optional(),description:j.optional(),acknowledge:j.optional().describe(`Acknowledge button label, e.g. "I have saved this"`),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Default format for fields without their own format. Defaults to json when omitted.`),fields:t.z.array(T({surface:`this result dialog field`,history:N,aliases:{key:`path`,field:`path`,name:`path`,title:`label`,display:`format`,render:`format`}},{path:t.z.string().describe(`Dot path into result.data (e.g. "totpURI", "client.client_secret").`),label:j.optional(),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Per-field format override.`)})).optional().describe(`Which fields from result.data to render. Omit to dump full JSON.`)}).optional().describe(`Render API response in a one-shot reveal dialog (suppresses successMessage when set).`),visible:k.optional().describe(`Visibility predicate (CEL).`),requiresFeature:t.z.enum(nn).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:t.z.union([t.z.boolean(),k]).optional().describe(`Boolean or predicate (CEL) — action is disabled when TRUE.`),requiredPermissions:t.z.array(t.z.string()).optional().describe("[ADR-0066 D4] Capabilities required to invoke this action. Enforced with 403 on the platform action route (script/flow/modal + MCP) and mirrored as a UI hide; a `type: api` action pointed at a custom endpoint must re-check it there."),shortcut:v("`action.shortcut` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never triggered anything: no keydown listener feeds ActionEngine.getShortcuts(), and objectui's keyboard stack (useKeyboardShortcuts) is hand-registered and never consults action metadata. Delete the key. For a real shortcut, register the key in the Console keyboard stack and have its handler invoke the action by name."),bulkEnabled:v("`action.bulkEnabled` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — the multi-select toolbar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, never by this flag, so setting it changed nothing. Delete the key and declare the action in the view's `bulkActions` instead."),ai:fn.optional().describe(`AI exposure (opt-in). Set ai.exposed=true + ai.description to make this callable by agents.`),recordIdParam:t.z.string().optional().describe(`Body key to inject the row id into when running from a list_item context.`),recordIdField:t.z.string().optional().describe(`Row field whose value seeds recordIdParam. Defaults to "id".`),bodyShape:t.z.union([t.z.literal(`flat`),T({surface:`this body shape`,history:N,aliases:{key:`wrap`,under:`wrap`,nest:`wrap`,root:`wrap`}},{wrap:t.z.string()})]).optional().describe(`Body wrapping: flat (default) or { wrap: key } to nest user-collected params under a key.`),method:t.z.enum([`POST`,`PATCH`,`PUT`,`DELETE`]).optional().describe(`HTTP method for type:"api" actions. Defaults to POST.`),bodyExtra:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Constant body fields merged into the API request (applied last; overrides user params).`),mode:t.z.enum([`create`,`edit`,`delete`,`custom`]).optional().describe(`Semantic mode of the action.`),opensInNewTab:t.z.boolean().optional().describe(`Open the action result in a new tab. The renderer pre-opens the tab synchronously on click (popup-blocker-safe) and navigates it to the handler's redirectUrl.`),newTabUrl:t.z.string().optional().describe(`Direct new-tab URL template ({recordId} placeholder). When set with opensInNewTab, the renderer navigates the pre-opened tab here immediately — no action POST. The endpoint must enforce auth itself.`),aria:Ut.optional().describe(`ARIA accessibility attributes`),...D}),mn=n(()=>pn().refine(e=>!(ln.has(e.type)&&!e.target),{message:`Action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form'.`,path:[`target`]}).refine(e=>!(e.type===`script`&&!e.body&&!e.target),{message:"A 'script' action requires either an inline `body` (sandboxed L1/L2 handler) or a `target` (a registered bundle function name).",path:[`body`]}).refine(e=>!(e.type!==`script`&&e.body),{message:"`body` only runs for `type: 'script'` — a non-script action dispatches on `target` and silently ignores its body. To collect `params` and then run the body, use `type: 'script'`; to open a page/modal, drop the `body` and keep `type: 'modal'` with `target` naming the page.",path:[`body`]}).refine(e=>!(e.ai?.exposed===!0&&!e.ai.description),{message:`ai.description is required (≥40 chars) when ai.exposed is true.`,path:[`ai`,`description`]}).refine(e=>{let t=e.ai?.paramHints;if(!t)return!0;let n=new Set([`recordId`]);for(let t of e.params??[]){let e=t.name??t.field;e&&n.add(e)}return Object.keys(t).every(e=>n.has(e))},{message:`ai.paramHints keys must match a declared param name (or "recordId").`,path:[`ai`,`paramHints`]}).transform((e,t)=>an(e,t)));function hn(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e,n=t.type===`navigation`,r=t.target===void 0&&typeof t.to==`string`;if(!n&&!r&&!(`to`in t))return e;let i={...t};return n&&(i.type=`url`),r&&(i.target=t.to),delete i.to,i}n(()=>t.z.preprocess(hn,pn().pick({type:!0,name:!0,label:!0,target:!0,openIn:!0,method:!0,params:!0,confirmText:!0,successMessage:!0,errorMessage:!0,refreshAfter:!0,opensInNewTab:!0}).partial({name:!0,label:!0}).refine(e=>!(ln.has(e.type)&&!e.target),{message:"Inline action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form' (`to` is accepted as a legacy spelling).",path:[`target`]})));var gn=t.z.object({lock:lt.describe(`Lock policy — none | no-overlay | no-delete | full.`),reason:t.z.string().min(1).max(500).describe(`User-visible reason shown when the lock blocks an action.`),docsUrl:t.z.string().url().optional().describe(`Optional URL the Studio banner links to for more context.`)}).strict();function _n(e){let{visibleOn:t,visibility:n,...r}=e,i=r.visibleWhen===void 0?t===void 0?n:t:r.visibleWhen;return i===void 0?r:{...r,visibleWhen:i}}function vn(e){return/vis|conceal|hidden|show.?when/i.test(e)}var yn=e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=`Unrecognized key(s) on this view/page schema: ${t.map(e=>`\`${e}\``).join(`, `)}. Before ADR-0089 D3a these were dropped silently, shipping inert metadata; a mis-layered or stale key is now a loud parse error.`;return t.some(vn)?n+" If this is the conditional-visibility predicate, the canonical key is `visibleWhen` (ADR-0089) — `visibleOn` (view form) and `visibility` (page component) are still accepted as deprecated aliases.":n},bn=n(()=>t.z.enum([`bar`,`horizontal-bar`,`column`,`line`,`area`,`pie`,`donut`,`funnel`,`scatter`,`treemap`,`sankey`,`combo`,`gauge`,`solid-gauge`,`metric`,`kpi`,`bullet`,`radar`,`table`,`pivot`])),xn=n(()=>t.z.object({field:t.z.string().describe(`Data field key`),title:j.optional().describe(`Axis display title`),format:t.z.string().optional().describe(`Value format string (e.g., "$0,0.00")`),min:t.z.number().optional().describe(`Minimum value`),max:t.z.number().optional().describe(`Maximum value`),stepSize:t.z.number().optional().describe(`Step size for ticks`),showGridLines:t.z.boolean().default(!0),position:t.z.enum([`left`,`right`,`top`,`bottom`]).optional().describe(`Axis position`),logarithmic:t.z.boolean().default(!1)})),Sn=n(()=>t.z.object({name:t.z.string().describe(`Field name or series identifier`),label:j.optional().describe(`Series display label`),type:bn.optional().describe(`Override chart type for this series`),color:t.z.string().optional().describe(`Series color (hex/rgb/token)`),stack:t.z.string().optional().describe(`Stack identifier to group series`),yAxis:t.z.enum([`left`,`right`]).default(`left`).describe(`Bind to specific Y-Axis`),variant:t.z.enum([`primary`,`comparison`]).default(`primary`).optional().describe(`Series visual role`),dashArray:t.z.string().optional().describe(`SVG stroke-dasharray override`),opacity:t.z.number().min(0).max(1).optional().describe(`Series opacity override`)})),Cn=n(()=>t.z.object({type:t.z.enum([`line`,`region`]).default(`line`),axis:t.z.enum([`x`,`y`]).default(`y`),value:t.z.union([t.z.number(),t.z.string()]).describe(`Start value`),endValue:t.z.union([t.z.number(),t.z.string()]).optional().describe(`End value for regions`),color:t.z.string().optional(),label:j.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),wn=n(()=>t.z.object({tooltips:t.z.boolean().default(!0).describe(`Show the hover tooltip`),brush:t.z.boolean().default(!1).describe(`Show the range selector under the plot`)}));n(()=>t.z.object({type:bn,title:j.optional().describe(`Chart title`),subtitle:j.optional().describe(`Chart subtitle`),description:j.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:xn.optional().describe(`X-Axis configuration`),yAxis:t.z.array(xn).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(Sn).optional().describe(`Defined series configuration`),colors:t.z.union([t.z.array(t.z.string()),t.z.record(t.z.string(),t.z.string())]).optional().describe(`Color palette (string[]) or value→color map ({ value: color })`),height:t.z.number().optional().describe(`Fixed plot height in pixels (overrides the container default)`),showLegend:t.z.boolean().default(!0).describe(`Display legend`),showDataLabels:t.z.boolean().default(!1).describe(`Display data labels`),annotations:t.z.array(Cn).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:wn.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:Ut.optional().describe(`ARIA accessibility attributes`)}));var Tn=n(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),En=n(()=>t.z.union([t.z.string().describe(`Field to group by`),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:t.z.enum([`day`,`week`,`month`,`quarter`,`year`]).optional().describe(`Bucket date values into uniform periods`),alias:t.z.string().optional().describe("Alias for the projected group value (defaults to `field`) — this becomes the category column")})]));n(()=>t.z.object({field:t.z.string().optional().describe(`Field to aggregate — required for sum/avg/min/max, optional for count`),function:Tn.describe(`Aggregation function`),groupBy:En.describe(`Field the rows are grouped by — the chart category axis`)}).superRefine((e,t)=>{e.function!==`count`&&!e.field&&t.addIssue({code:`custom`,path:[`field`],message:`aggregate.function "${e.function}" needs a "field" to aggregate (only "count" may omit it).`})}).describe(`Inline aggregation for an object-bound chart`));var Dn=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable public sharing`),publicLink:t.z.string().optional().describe(`Generated public share URL`),password:t.z.string().optional().describe(`Password required to access shared link`),allowedDomains:t.z.array(t.z.string()).optional().describe(`Restrict access to specific email domains (e.g. ["example.com"])`),expiresAt:t.z.string().optional().describe(`Expiration date/time in ISO 8601 format`),allowAnonymous:t.z.boolean().optional().default(!1).describe(`Allow access without authentication`)}));n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable iframe embedding`),allowedOrigins:t.z.array(t.z.string()).optional().describe(`Allowed iframe parent origins (e.g. ["https://example.com"])`),width:t.z.string().optional().default(`100%`).describe(`Embed width (CSS value)`),height:t.z.string().optional().default(`600px`).describe(`Embed height (CSS value)`),showHeader:t.z.boolean().optional().default(!0).describe(`Show interface header in embed`),showNavigation:t.z.boolean().optional().default(!1).describe(`Show navigation in embed`),responsive:t.z.boolean().optional().default(!0).describe(`Enable responsive resizing`)}));var On=t.z.enum([`update`,`delete`,`custom`]),kn=t.z.enum([`perRecord`,`aggregate`]),An=n(()=>t.z.object({name:t.z.string().min(1).describe(`Param key — becomes params[name] in the patch / action params bag.`),label:t.z.string().optional().describe(`Field label in the dialog. Plain string: an authored def is not i18n-resolved (see module header).`),help:t.z.string().optional().describe("Help text under the field. (An ActionParam spells this `helpText` — known divergence, module header.)"),type:St.describe(`Field widget to render, from the standard field-type vocabulary (text/number/select/lookup/date/…).`),required:t.z.boolean().optional().describe(`Blocks the Confirm button until a value is present.`),default:t.z.unknown().optional().describe("Value applied when the dialog opens. (An ActionParam spells this `defaultValue`.)"),options:t.z.array(t.z.object({label:t.z.string().describe(`Option label (plain string — not i18n-resolved on this path).`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Stored value.`)})).optional().describe(`Static options for select-style widgets.`),object:O.optional().describe("Target object for a `lookup` widget. (An ActionParam spells this `reference`.)"),labelField:t.z.string().optional().describe("Related-object field used as the option label for a `lookup` widget (defaults to name/full_name/email/id)."),multiple:t.z.boolean().optional().describe(`Allow picking multiple values — the param value becomes an array and is written to the patch as-is.`),placeholder:t.z.string().optional().describe(`Placeholder text.`)}).passthrough()),jn=w({surface:`this bulk action definition`,knownKeys:[`name`,`label`,`icon`,`variant`,`operation`,`execution`,`patch`,`params`,`confirmText`,`confirmLabel`,`visible`,`maxRecords`,`batchSize`],aliases:{action:`name`,actionname:`name`,title:`label`,op:`operation`,mode:`execution`,confirm:`confirmText`,confirmmessage:`confirmText`,limit:`maxRecords`,max:`maxRecords`,batch:`batchSize`},guidance:{actionDef:"`actionDef` is attached by the renderer, not authored: `resolveBulkActions` looks the action up by `name` and inlines it. Writing it by hand smuggles an action definition past the action registry — no permission gate, no param contract, no lint. Declare the action normally and let this def name it.",bulkEnabled:"`action.bulkEnabled` was retired in spec 17: the selection bar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, which is this array. There is nothing to set.",recordIdParam:"`recordIdParam` belongs on the ACTION, not on the def that names it — a per-record bulk run reuses the action's own declaration, and an `execution: 'aggregate'` run carries the whole selection in `params._selectedIds` instead of a single record id."},history:"Until #4457 the whole array was `z.array(z.record(z.string(), z.any()))` — every key parsed, so a mis-spelled one shipped as a button that silently ran the DEFAULT behaviour (or none at all)."}),Mn=n(()=>t.z.object({name:O.describe(`Stable identifier — the audit-log action key, and (for an aggregate def) the name of the object action to dispatch.`),label:t.z.string().optional().describe("Button + dialog-header text. Plain string: an authored def is not i18n-resolved (declare a real action and name it in `bulkActions` to get localization)."),icon:t.z.string().optional().describe(`Lucide icon name (e.g. "user-check", "trash-2").`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`outline`]).optional().describe(`Visual treatment of the button.`),operation:On.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:kn.optional().describe("For `operation: 'custom'` — 'aggregate' dispatches the named action ONCE for the whole selection, carrying every id in `params._selectedIds` (objectui#3139). Required on a custom def: the per-record form is declared as `bulkActions: ['<name>']` instead."),patch:t.z.record(t.z.string(),t.z.unknown()).optional().describe("For `operation: 'update'` — static field values applied to every selected record, merged UNDER the user-supplied params so a fixed value can be declared without exposing it in the dialog."),params:t.z.array(An).optional().describe(`Inputs collected once before the run. Omit to skip the params step and go straight to confirm.`),confirmText:t.z.string().optional().describe(`Confirmation text shown above the affected-record summary.`),confirmLabel:t.z.string().optional().describe(`Custom Confirm button label (default: "Run").`),visible:k.optional().describe("Eligibility predicate (CEL), same shape as `action.visible`. Evaluated once PER SELECTED RECORD with that record bound: the button is offered when at least one passes, the run covers only those, and the rest are reported as skipped. A record-free predicate (`features.x`, `current_user.y`) therefore behaves as a plain button-level gate. Fail-closed — a predicate that faults excludes the record."),maxRecords:t.z.number().int().positive().optional().describe(`Selection size above which the run is blocked. Set it on defs whose server work is expensive — an aggregate def carries every selected id in one request.`),batchSize:t.z.number().int().positive().optional().describe(`Records per executor batch (default 200). Data-plane operations only — an aggregate run is a single call by definition.`)},{error:jn}).strict().superRefine((e,t)=>{e.operation===`custom`&&e.execution!==`aggregate`&&t.addIssue({code:`custom`,path:[`execution`],message:`Bulk action "${e.name}" declares \`operation: 'custom'\` without \`execution: 'aggregate'\`, which the renderer treats as a no-op \u2014 the button runs, reports success for every selected record, and does nothing. Pick the form you meant: to run the action ONCE PER record, drop this def and name the action in the view's \`bulkActions: ['${e.name}']\` (it is promoted with the action's label, params and \`visible\`); to run it ONCE for the whole selection, add \`execution: 'aggregate'\` (the handler reads \`params._selectedIds\`). For a mass field update or delete, use \`operation: 'update'\` / \`'delete'\` instead.`}),e.execution!==void 0&&e.operation!==`custom`&&t.addIssue({code:`custom`,path:[`execution`],message:`\`execution\` only applies to \`operation: 'custom'\` \u2014 a '${e.operation}' def is a data-plane mass mutation, always batched per record. Remove it, or switch the def to \`operation: 'custom'\` if you meant to dispatch an action.`}),e.patch!==void 0&&e.operation!==`update`&&t.addIssue({code:`custom`,path:[`patch`],message:`\`patch\` only applies to \`operation: 'update'\` \u2014 a '${e.operation}' def never writes fields, so these values are silently dropped. Use \`operation: 'update'\`, or move the constant into the action's own \`bodyExtra\`/\`params\` if this is a custom def.`}),e.params!==void 0&&e.operation===`delete`&&t.addIssue({code:`custom`,path:[`params`],message:"`params` on a `delete` def collects values the executor never reads — a bulk delete takes ids only. Remove them, or use `operation: 'update'` if the dialog is meant to write something."}),e.batchSize!==void 0&&e.execution===`aggregate`&&t.addIssue({code:`custom`,path:[`batchSize`],message:"`batchSize` does not apply to an aggregate def — the whole selection goes out in ONE call by definition, which is the point of `execution: 'aggregate'`. To bound how much a single call may carry, use `maxRecords`."})})),Nn=t.z.enum([`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`]),Pn=n(()=>t.z.enum([`GET`,`POST`,`PUT`,`PATCH`,`DELETE`])),Fn=n(()=>t.z.object({url:t.z.string().describe(`API endpoint URL`),method:Pn.optional().default(`GET`).describe(`HTTP method`),headers:t.z.record(t.z.string(),t.z.string()).optional().describe(`Custom HTTP headers`),params:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Query parameters`),body:t.z.unknown().optional().describe(`Request body for POST/PUT/PATCH`)}));n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable CORS`),origins:t.z.union([t.z.string(),t.z.array(t.z.string())]).default(`*`).describe(`Allowed origins (* for all)`),methods:t.z.array(Nn).optional().describe(`Allowed HTTP methods`),credentials:t.z.boolean().default(!1).describe(`Allow credentials (cookies, authorization headers)`),maxAge:t.z.number().int().optional().describe(`Preflight cache duration in seconds`)})),n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable rate limiting`),windowMs:t.z.number().int().default(6e4).describe(`Time window in milliseconds`),maxRequests:t.z.number().int().default(100).describe(`Max requests per window`)})),n(()=>t.z.object({path:t.z.string().describe(`URL path to serve from`),directory:t.z.string().describe(`Physical directory to serve`),cacheControl:t.z.string().optional().describe(`Cache-Control header value`)}));var P=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,In=n(()=>t.z.discriminatedUnion(`provider`,[t.z.object({provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),t.z.object({provider:t.z.literal(`api`),read:Fn.optional().describe(`Configuration for fetching data`),write:Fn.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),t.z.object({provider:t.z.literal(`value`),items:t.z.array(t.z.unknown()).describe(`Static data array`)}),t.z.object({provider:t.z.literal(`schema`),schemaId:t.z.string().describe(`Schema identifier — typically the metadata type name`),schema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Inline JSON Schema (Draft 2020-12). Optional when schemaId is resolvable.`)})])),Ln=[`equals`,`not_equals`,`contains`,`not_contains`,`starts_with`,`ends_with`,`greater_than`,`less_than`,`greater_than_or_equal`,`less_than_or_equal`,`in`,`not_in`,`is_empty`,`is_not_empty`,`is_null`,`is_not_null`,`before`,`after`,`between`],Rn={eq:`equals`,ne:`not_equals`,neq:`not_equals`,notequals:`not_equals`,notEquals:`not_equals`,notcontains:`not_contains`,notContains:`not_contains`,startswith:`starts_with`,startsWith:`starts_with`,endswith:`ends_with`,endsWith:`ends_with`,gt:`greater_than`,greaterthan:`greater_than`,greaterThan:`greater_than`,lt:`less_than`,lessthan:`less_than`,lessThan:`less_than`,gte:`greater_than_or_equal`,greaterorequal:`greater_than_or_equal`,greaterOrEqual:`greater_than_or_equal`,greaterThanOrEqual:`greater_than_or_equal`,lte:`less_than_or_equal`,lessorequal:`less_than_or_equal`,lessOrEqual:`less_than_or_equal`,lessThanOrEqual:`less_than_or_equal`,nin:`not_in`,notin:`not_in`,notIn:`not_in`,isempty:`is_empty`,isEmpty:`is_empty`,isnotempty:`is_not_empty`,isNotEmpty:`is_not_empty`,isnull:`is_null`,isNull:`is_null`,isnotnull:`is_not_null`,isNotNull:`is_not_null`};function zn(e){return typeof e!=`string`||Ln.includes(e)?e:Rn[e]??Rn[e.toLowerCase()]??e}var Bn=n(()=>T({surface:`this view filter rule`,history:P},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(zn,t.z.enum(Ln)).describe(`Filter operator`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean(),t.z.null(),t.z.array(t.z.union([t.z.string(),t.z.number()]))]).optional().describe(`Filter value`)}).describe(`View filter rule`)),Vn=n(()=>t.z.enum([`none`,`count`,`count_empty`,`count_filled`,`count_unique`,`percent_empty`,`percent_filled`,`sum`,`avg`,`min`,`max`]).describe(`Aggregation function for column footer summary`)),Hn=n(()=>T({surface:`this column summary configuration`,history:P},{type:Vn.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),Un=n(()=>T({surface:`this column prefix`,history:P},{field:t.z.string().describe(`Field whose value renders before the cell value`),type:t.z.enum([`badge`,`text`]).default(`text`).describe(`How the prefix value is rendered`)}).describe(`Compound-cell prefix configuration`)),Wn=n(()=>T({surface:`this list column`,history:P},{field:t.z.string().describe(`Field name (snake_case)`),label:j.optional().describe(`Display label override`),width:t.z.number().positive().optional().describe(`Column width in pixels`),align:t.z.enum([`left`,`center`,`right`]).optional().describe(`Text alignment`),hidden:t.z.boolean().optional().describe(`Hide column by default`),sortable:t.z.boolean().optional().describe(`Allow sorting by this column`),resizable:t.z.boolean().optional().describe(`Allow resizing this column`),wrap:t.z.boolean().optional().describe(`Allow text wrapping`),type:t.z.string().optional().describe(`Renderer type override (e.g., "currency", "date")`),pinned:t.z.enum([`left`,`right`]).optional().describe(`Pin/freeze column to left or right side`),summary:t.z.union([Vn,Hn]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:Un.optional().describe(`Field rendered inline before this cell value`),link:t.z.boolean().optional().describe(`Functions as the primary navigation link (triggers View navigation)`),action:t.z.string().optional().describe(`Registered Action ID to execute when clicked`)})),Gn=n(()=>T({surface:`this selection configuration`,history:P},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),Kn=n(()=>T({surface:`this pagination configuration`,history:P},{pageSize:t.z.number().int().positive().default(25).describe(`Number of records per page`),pageSizeOptions:t.z.array(t.z.number().int().positive()).optional().describe(`Available page size options`)})),qn=n(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),Jn=n(()=>T({surface:`this grouping field`,history:P},{field:t.z.string().describe(`Field name to group by`),order:t.z.enum([`asc`,`desc`]).default(`asc`).describe(`Group sort order`),collapsed:t.z.boolean().default(!1).describe(`Collapse groups by default`)})),Yn=n(()=>T({surface:`this grouping configuration`,history:P},{fields:t.z.array(Jn).min(1).describe(`Fields to group by (supports up to 3 levels)`)}).describe(`Record grouping configuration`)),F=n(()=>T({surface:`this gallery configuration`,history:P},{coverField:t.z.string().optional().describe(`Attachment/image field to display as card cover`),coverFit:t.z.enum([`cover`,`contain`]).default(`cover`).describe(`Image fit mode for card cover`),cardSize:t.z.enum([`small`,`medium`,`large`]).default(`medium`).describe(`Card size in gallery view`),titleField:t.z.string().optional().describe(`Field to display as card title`),visibleFields:t.z.array(t.z.string()).optional().describe(`Fields to display on card body`)}).describe(`Gallery/card view configuration`)),Xn=n(()=>T({surface:`this timeline configuration`,history:P},{startDateField:t.z.string().describe(`Field for timeline item start date`),endDateField:t.z.string().optional().describe(`Field for timeline item end date`),titleField:t.z.string().describe(`Field to display as timeline item title`),groupByField:t.z.string().optional().describe(`Field to group timeline rows`),colorField:t.z.string().optional().describe(`Field to determine item color`),scale:t.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).default(`week`).describe(`Default timeline scale`)}).describe(`Timeline view configuration`)),Zn=n(()=>T({surface:`this view sharing`,history:P},{type:t.z.enum([`personal`,`collaborative`]).default(`collaborative`).describe(`View ownership type`),lockedBy:t.z.string().optional().describe(`User who locked the view configuration`)}).describe(`View sharing and access configuration`)),Qn=n(()=>T({surface:`this row color configuration`,history:P},{field:t.z.string().describe(`Field to derive color from (typically a select/status field)`),colors:t.z.record(t.z.string(),t.z.string()).optional().describe(`Map of field value to color (hex/token)`)}).describe(`Row color configuration based on field values`)),$n=n(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),I=n(()=>T({surface:`this user actions configuration`,history:P},{sort:t.z.boolean().default(!0).describe(`Allow users to sort records`),search:t.z.boolean().default(!0).describe(`Allow users to search records`),filter:t.z.boolean().default(!0).describe(`Allow users to filter records`),refresh:t.z.boolean().default(!0).describe(`Allow users to reload the view data from the backend without a full page reload`),rowHeight:t.z.boolean().default(!0).describe(`Allow users to toggle row height/density`),addRecordForm:t.z.boolean().default(!1).describe(`Add records through a form instead of inline`),editInline:t.z.boolean().default(!1).describe(`Allow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in.`),buttons:t.z.array(t.z.string()).optional().describe(`Custom action button IDs to show in the toolbar`)}).describe(`User action toggles for the view toolbar`)),er=n(()=>T({surface:`this appearance configuration`,history:P},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array($n).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),tr=n(()=>T({surface:`this view tab`,history:P},{name:O.describe(`Tab identifier (snake_case)`),label:j.optional().describe(`Display label`),icon:t.z.string().optional().describe(`Tab icon name`),view:t.z.string().optional().describe(`Referenced list view name from listViews`),filter:t.z.array(Bn).optional().describe(`Tab-specific filter criteria`),order:t.z.number().int().min(0).optional().describe(`Tab display order`),pinned:t.z.boolean().default(!1).describe(`Pin tab (cannot be removed by users)`),isDefault:t.z.boolean().default(!1).describe(`Set as the default active tab`),visible:t.z.boolean().default(!0).describe(`Tab visibility`)}).describe(`Tab configuration for multi-tab view interface`)),nr=n(()=>T({surface:`this user filter field`,history:P},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:j.optional().describe(`Display label override (defaults to the field label)`),type:t.z.enum([`select`,`multi-select`,`boolean`,`date-range`,`text`]).optional().describe(`Filter control type. Omit to infer from the field definition`),options:t.z.array(t.z.object({value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Option value`),label:j.describe(`Option label`),color:t.z.string().optional().describe(`Option color token/hex`)})).optional().describe(`Static options. Omit to derive from the field definition (select options / lookup records)`),showCount:t.z.boolean().optional().describe(`Show per-option record counts`),defaultValues:t.z.array(t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Pre-selected values when the view loads`)}).describe(`Quick-filter field configuration`)),rr=n(()=>t.z.object({element:t.z.enum([`dropdown`,`tabs`,`toggle`]).default(`dropdown`).describe(`Filter control style: "dropdown" (per-field value selectors) or "tabs" (named presets). "toggle" is deprecated.`),fields:t.z.array(nr).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(tr).optional().describe(`Named filter presets rendered as tabs (tabs element). Reuses ViewTabSchema`),showAllRecords:t.z.boolean().optional().describe(`Show an "All records" tab before the presets (tabs element)`)}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),ir=n(()=>T({surface:`this add record configuration`,history:P},{enabled:t.z.boolean().default(!0).describe(`Show the add record entry point`),position:t.z.enum([`top`,`bottom`,`both`]).default(`bottom`).describe(`Position of the add record button`),mode:t.z.enum([`inline`,`form`,`modal`]).default(`inline`).describe(`How to add a new record`),formView:t.z.string().optional().describe(`Named form view to use when mode is "form" or "modal"`)}).describe(`Add record entry point configuration`)),ar=n(()=>T({surface:`this kanban configuration`,history:P},{groupByField:t.z.string().describe(`Field to group columns by (usually status/select)`),summarizeField:t.z.string().optional().describe(`Field to sum at top of column (e.g. amount)`),columns:t.z.array(t.z.string()).describe(`Fields to show on cards`)})),or=n(()=>T({surface:`this list chart configuration`,history:P},{chartType:bn.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:O.describe(`Dataset name to bind (ADR-0021)`),dimensions:t.z.array(t.z.string()).optional().describe(`Dimension names — X/group/split`),values:t.z.array(t.z.string()).min(1).describe(`Measure names — Y (at least one)`)}).describe(`List chart view configuration`)),sr=n(()=>T({surface:`this calendar configuration`,history:P},{startDateField:t.z.string().describe(`Field providing the event start date/time`),endDateField:t.z.string().optional().describe(`Field providing the event end date/time (defaults to a single-day event)`),titleField:t.z.string().describe(`Field displayed as the event title`),colorField:t.z.string().optional().describe(`Field whose value determines the event color`)})),cr=n(()=>T({surface:`this gantt quick filter`,history:P},{field:t.z.string().describe(`Record field / dot-path the dimension filters on`),label:t.z.string().optional().describe(`Trigger label (falls back to the field label)`),options:t.z.array(t.z.union([t.z.string(),t.z.object({value:t.z.union([t.z.string(),t.z.number()]),label:t.z.string().optional()})])).optional().describe(`Explicit option override for fixed enums`)})),lr=n(()=>T({surface:`this gantt configuration`,history:P},{startDateField:t.z.string().describe(`Field providing the task start date`),endDateField:t.z.string().describe(`Field providing the task end date`),titleField:t.z.string().describe(`Field displayed as the task title`),progressField:t.z.string().optional().describe(`Field providing the task completion percentage`),dependenciesField:t.z.string().optional().describe(`Field listing the task's predecessor (dependency) record ids`),colorField:t.z.string().optional().describe(`Field that drives the bar color`),parentField:t.z.string().optional().describe(`Field holding the parent task id (builds the summary → step tree)`),typeField:t.z.string().optional().describe(`Field whose value maps to task/summary/milestone`),baselineStartField:t.z.string().optional().describe(`Baseline (planned) start field`),baselineEndField:t.z.string().optional().describe(`Baseline (planned) end field`),groupByField:t.z.string().optional().describe(`Field to group leaf tasks by (synthesized summary rows)`),resourceView:t.z.boolean().optional().describe(`Render a per-resource workload histogram instead of the timeline`),assigneeField:t.z.string().optional().describe(`Resource field to bucket load by (resource view)`),effortField:t.z.string().optional().describe(`Per-task load units (resource view; default 1)`),capacity:t.z.number().optional().describe(`Per-resource capacity ceiling; loads above this flag overload`),tooltipFields:t.z.array(t.z.union([t.z.string(),t.z.object({field:t.z.string(),label:t.z.string().optional()})])).optional().describe(`Fields to surface in the hover tooltip, in display order`),quickFilters:t.z.array(cr).optional().describe(`Multi-select filter dropdowns rendered above the chart`),autoZoomToFilter:t.z.boolean().optional().describe(`When true (default), filtering zooms the range to the filtered tasks`)}).passthrough()),ur=n(()=>T({surface:`this tree configuration`,history:P},{parentField:t.z.string().optional().describe(`Single-parent pointer field (auto-detected from the object schema when omitted)`),labelField:t.z.string().optional().describe(`Field rendered indented in the first column (defaults to "name")`),fields:t.z.array(t.z.string()).optional().describe(`Additional fields rendered as flat columns alongside the label`),defaultExpandedDepth:t.z.number().int().min(0).optional().describe(`Initial expansion depth (0 = roots only; omit = expand all)`)}).passthrough()),dr=n(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),fr=n(()=>T({surface:`this navigation configuration`,history:P},{mode:dr.default(`page`),view:t.z.string().optional().describe(`Name of the form view to use for details (e.g. "summary_view", "edit_form")`),preventNavigation:t.z.boolean().default(!1).describe(`Disable standard navigation entirely`),openNewTab:t.z.boolean().default(!1).describe(`Force open in new tab (applies to page mode)`),size:t.z.enum([`auto`,`sm`,`md`,`lg`,`xl`,`full`]).default(`auto`).describe("[#2578] Overlay size bucket for drawer/modal detail: 'auto' (default — renderer derives from field count + viewport; AI writes nothing) or a coarse override sm/md/lg/xl/full. Prefer this over the pixel `width`; page mode ignores it."),width:t.z.union([t.z.string(),t.z.number()]).optional().describe('[DEPRECATED → size] Pixel/percent width of the drawer/modal (e.g. "600px"). A pixel width cannot be chosen at authoring time without knowing the client viewport — use the `size` bucket.')})),L=n(()=>T({surface:`this list view`,history:P},{name:O.optional().describe(`Internal view name (lowercase snake_case)`),label:j.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:In.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(Wn)]).describe(`Fields to display as columns`),filter:t.z.array(Bn).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(t.z.object({field:t.z.string(),order:t.z.enum([`asc`,`desc`])}))]).optional(),searchableFields:t.z.array(t.z.string()).optional().describe(`Fields enabled for search`),filterableFields:t.z.array(t.z.string()).optional().describe(`Legacy shorthand for userFilters.fields — bare field names enabled for end-user filtering. Prefer userFilters`),userFilters:rr.optional().describe(`End-user quick-filter bar: dropdown/toggle fields or tab presets. Omit to let the renderer derive filters from select/boolean fields`),resizable:t.z.boolean().optional().describe(`Enable column resizing`),striped:t.z.boolean().optional().describe(`Striped row styling`),bordered:t.z.boolean().optional().describe(`Show borders`),compactToolbar:t.z.boolean().optional().describe(`Collapse Group/Color/Density/Hide-fields into a single View settings popover`),selection:Gn.optional().describe(`Row selection configuration`),navigation:fr.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:Kn.optional().describe(`Pagination configuration`),kanban:ar.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:sr.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:lr.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:F.optional(),timeline:Xn.optional(),chart:or.optional(),tree:ur.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:j.optional().describe(`View description for documentation/tooltips`),sharing:Zn.optional().describe(`View sharing and access configuration`),rowHeight:qn.optional().describe(`Row height / density setting`),grouping:Yn.optional().describe(`Group records by one or more fields`),rowColor:Qn.optional().describe(`Color rows based on field value`),hiddenFields:t.z.array(t.z.string()).optional().describe(`Fields to hide in this specific view`),fieldOrder:t.z.array(t.z.string()).optional().describe(`Explicit field display order for this view`),rowActions:t.z.array(t.z.string()).optional().describe(`Actions available for individual row items`),bulkActions:t.z.array(t.z.string()).optional().describe(`Actions available when multiple rows are selected`),bulkActionDefs:t.z.array(Mn).optional().describe("Rich bulk action definitions (schema-driven, executed via BulkActionDialog). Use a def for a mass data-plane mutation ('update' with a `patch` / 'delete') that no action expresses, or for an `operation: 'custom'` + `execution: 'aggregate'` entry (objectui#3139) that dispatches the action it NAMES once for the whole selection — the renderer injects `params._selectedIds: string[]` (read that on the server, not `recordId`) so a single call can produce one aggregate artifact (zip of QR codes, merged PDF, batch print). Aggregate results are all-or-nothing: a handler that cannot cover the whole selection must reject, and per-row retry is replaced by re-running the action. `batchSize` does not apply (the call is never chunked); set `maxRecords` on defs whose server work is expensive. For the PER-RECORD dispatch use `bulkActions: ['<name>']` instead — the bare-string form, promoted with the action's own label, params and `visible`; a 'custom' def without `execution: 'aggregate'` has no dispatcher and is refused at parse time (#4457). Toolbar url/api actions can also interpolate the current selection via `${ctx.selection.ids}` / `${ctx.selection.count}`."),virtualScroll:t.z.boolean().optional().describe(`Enable virtual scrolling for large datasets`),conditionalFormatting:t.z.array(t.z.object({condition:k.describe(`Predicate (CEL) to evaluate.`),style:t.z.record(t.z.string(),t.z.string()).describe(`CSS styles to apply when condition is true`)})).optional().describe(`Conditional formatting rules for list rows`),inlineEdit:t.z.boolean().optional().describe(`Allow inline editing of records directly in the list view`),exportOptions:t.z.array(t.z.enum([`csv`,`xlsx`,`pdf`,`json`])).optional().describe(`Available export format options`),userActions:I.optional().describe(`User action toggles for the view toolbar`),appearance:er.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(tr).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:ir.optional().describe(`Add record entry point configuration`),showRecordCount:t.z.boolean().optional().describe(`Show record count at the bottom of the list`),allowPrinting:t.z.boolean().optional().describe(`Allow users to print the view`),emptyState:t.z.object({title:j.optional(),message:j.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:Ut.optional().describe(`ARIA accessibility attributes for the list view`),responsive:v("`view.responsive` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer ever read it; the grid is responsive by its own layout rules. Delete the key."),performance:v("`view.performance` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer or runtime read it; list-view performance tuning was never implemented. Delete the key.")})),pr=n(()=>t.z.object({field:t.z.string().describe(`Field name (snake_case)`),type:St.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(wt).optional().describe(`Options for select/multiselect/radio/checkboxes fields`),reference:t.z.string().optional().describe(`Target object name for lookup/master_detail fields`),maxLength:t.z.number().optional().describe(`Maximum character length (for text/textarea/email/url/phone)`),minLength:t.z.number().optional().describe(`Minimum character length`),min:t.z.number().optional().describe(`Minimum value (for number/currency/percent/slider)`),max:t.z.number().optional().describe(`Maximum value`),precision:t.z.number().optional().describe(`Total digits (for number/currency)`),scale:t.z.number().optional().describe(`Decimal places`),multiple:t.z.boolean().optional().describe(`Allow multiple values (for select/lookup/file/image)`),label:j.optional().describe(`Display label override`),placeholder:j.optional().describe(`Placeholder text`),helpText:j.optional().describe(`Help/hint text`),readonly:t.z.boolean().optional().describe(`Read-only override`),immutable:t.z.boolean().optional().describe(`Editable on create, locked once the record exists (e.g. machine names).`),required:t.z.boolean().optional().describe(`Required override`),hidden:t.z.boolean().optional().describe(`Hidden override`),colSpan:t.z.number().int().min(1).max(4).optional().describe("[legacy — prefer `span`] Absolute column span (1-4). Fragile when the column count is derived per surface (mobile 1 / modal 2 / page 3-4): a fixed span only lines up at the width the author imagined. The renderer clamps it to the current column count. Prefer `span`."),span:t.z.enum([`auto`,`full`]).default(`auto`).describe("Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count (wide widgets like textarea/richtext/json/file/subform take the whole row). 'full': whole row at any column count. Prefer this over the absolute `colSpan`."),widget:t.z.string().optional().describe(`Custom widget/component name (overrides type-based inference)`),language:t.z.string().optional().describe(`Code editor language (for type=code)`),keyField:t.z.object({field:t.z.string().default(`name`).describe(`Property name that holds the key inside each item (defaults to "name")`),label:j.optional().describe(`Display label for the key column`),placeholder:j.optional().describe(`Placeholder when entering a new key`),helpText:j.optional().describe(`Help text under the key input`),regex:t.z.string().optional().describe(`JS regex source string the key must match (no flags)`),immutable:t.z.boolean().default(!0).describe(`If true, the key is read-only after creation`)}).optional().describe(`Key column config for record-typed fields`),dependsOn:t.z.string().optional().describe(`Parent field name for cascading`),visibleWhen:k.optional().describe("Visibility predicate (CEL) — field shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms). e.g. P`record.priority == 'urgent'`"),visibleOn:k.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Normalized to `visibleWhen` at parse."),disclosure:t.z.enum([`inline`,`popover`]).optional().describe(`Composite rendering: inline bordered box (default) or a summary line + gear popover (progressive disclosure).`)},{error:yn})),R=n(()=>pr.extend({fields:t.z.array(t.z.lazy(()=>R)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(_n)),mr=n(()=>t.z.object({name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:j.optional(),description:t.z.string().optional().describe(`Optional description rendered under the section header.`),collapsible:t.z.boolean().default(!1),collapsed:t.z.boolean().default(!1),visibleWhen:k.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms)."),visibleOn:k.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Hides the whole section when false. Normalized to `visibleWhen` at parse."),columns:t.z.union([t.z.enum([`1`,`2`,`3`,`4`]),t.z.literal(1),t.z.literal(2),t.z.literal(3),t.z.literal(4)]).default(1).transform(e=>typeof e==`string`?parseInt(e):e),pane:t.z.enum([`primary`,`secondary`]).optional().describe(`Split pane this section renders in (split forms only; a parse error elsewhere). Omitted → first section 'primary', others 'secondary'.`),fields:t.z.array(t.z.union([t.z.string(),R]))},{error:yn}).strict().transform(_n)),hr=n(()=>T({surface:`this form button configuration`,history:P},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:j.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict()),gr=n(()=>T({surface:`this form view`,history:P},{type:t.z.enum([`simple`,`tabbed`,`wizard`,`split`,`drawer`,`modal`]).default(`simple`),layout:t.z.enum([`vertical`,`horizontal`,`inline`,`grid`]).optional().describe(`Field layout direction`),columns:t.z.number().int().min(1).optional().describe(`Number of columns for the form body`),title:t.z.string().optional().describe(`Form title`),description:t.z.string().optional().describe(`Form description`),defaultTab:t.z.string().optional().describe(`Initially active tab (tabbed forms)`),tabPosition:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Tab strip position (tabbed forms)`),allowSkip:t.z.boolean().optional().describe(`Allow skipping steps (wizard forms)`),showStepIndicator:t.z.boolean().optional().describe(`Show the step indicator (wizard forms)`),splitDirection:t.z.enum([`horizontal`,`vertical`]).optional().describe(`Split orientation (split forms)`),splitSize:t.z.number().optional().describe(`Primary split panel size, % (split forms)`),splitResizable:t.z.boolean().optional().describe(`Whether the split is resizable (split forms)`),drawerSide:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Drawer side (drawer forms)`),drawerWidth:t.z.string().optional().describe(`[DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it.`),modalSize:t.z.enum([`sm`,`default`,`lg`,`xl`,`full`]).optional().describe(`Modal size (modal forms)`),data:In.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(mr).optional(),groups:t.z.array(mr).optional(),subforms:t.z.array(t.z.object({childObject:t.z.string().describe(`Child object whose records are entered inline`),relationshipField:t.z.string().optional().describe(`FK on the child pointing back to the parent (auto-detected when omitted)`),columns:t.z.array(t.z.any()).optional().describe(`Editable grid columns (derived from the child object when omitted)`),amountField:t.z.string().optional().describe(`Numeric child column summed for the running total`),totalField:t.z.string().optional().describe(`Parent field to receive the rolled-up sum`),title:t.z.string().optional().describe(`Section title`),addLabel:t.z.string().optional().describe(`Add-row button label`),minRows:t.z.number().optional(),maxRows:t.z.number().optional()})).optional().describe(`Inline master-detail child collections`),defaultSort:v("`form.defaultSort` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — nothing read it: a related list inside a form sorts by its own list view's `sort`. Delete the key and set the sort on the related list view instead."),sharing:Dn.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.union([t.z.object({kind:t.z.literal(`thank-you`),title:t.z.string().optional(),message:t.z.string().optional()}),t.z.object({kind:t.z.literal(`redirect`),url:t.z.string(),delayMs:t.z.number().int().min(0).optional()}),t.z.object({kind:t.z.literal(`continue`)}),t.z.object({kind:t.z.literal(`next-record`)})]).optional().describe(`Post-submit behavior`),buttons:t.z.object({submit:hr.optional().describe(`Submit button`),cancel:hr.optional().describe(`Cancel button`),reset:hr.optional().describe(`Reset button`)}).strict().optional().describe(`Form action-button visibility & labels; folded onto the flat renderer props by ObjectUI ObjectForm (framework#1894 / #2998).`),defaults:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Initial field values for create-mode forms (folded into ObjectUI ObjectForm initial values; framework#1894 / #2998).`),aria:v("`form.aria` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no form renderer ever applied it, so declared ARIA attributes silently did not reach the DOM. Delete the key. The form renderer emits its own semantic markup; report gaps as renderer issues rather than per-view attribute overrides.")}).superRefine((e,t)=>{if(e.type!==`split`)for(let[n,r]of[[`sections`,e.sections],[`groups`,e.groups]])r?.forEach((r,i)=>{r?.pane!=null&&t.addIssue({code:`custom`,path:[n,i,`pane`],message:`\`pane\` places a section in a split pane and is only valid on \`type: 'split'\` form views (this form is '${e.type}'). Remove the key or change the form type.`})})})),z=n(()=>rr.omit({tabs:!0,showAllRecords:!0}).extend({element:t.z.enum([`dropdown`,`toggle`]).default(`dropdown`).describe('Filter control style on object views: "dropdown" (per-field value chips). "toggle" is deprecated. "tabs" is page-only — use `listViews` for named presets.')})),_r=n(()=>L.omit({userFilters:!0}).extend({userFilters:z.optional()})),vr=n(()=>T({surface:`this view container`,history:P,guidance:Object.fromEntries([`type`,`columns`,`data`,`viewKind`,`filters`,`sort`].map(e=>[e,`\`${e}\` belongs to a single VIEW, not to the container. Wrap it: \`defineView({ list: { type, data, columns, \u2026 } })\`, or name it \u2014 \`defineView({ listViews: { my_view: { \u2026 } } })\`. The container's own keys are \`list\`, \`form\`, \`listViews\`, \`formViews\`.`]))},{name:t.z.string().optional().describe(`Item name — supplied by the metadata door; for an object-scoped container it is the object name.`),label:j.optional().describe(`Human-readable label shown in metadata lists.`),object:t.z.string().optional().describe("Object this container binds to — how a stack-level `views: [...]` entry says which object its views belong to; read by `getViewsByObject()` / `GET /meta/view?object=`."),list:_r.optional(),form:gr.optional(),listViews:t.z.record(t.z.string(),_r).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),gr).optional().describe(`Additional named form views`),protection:gn.optional().describe(`Package author protection block — lock policy for this view.`),...D})),yr=t.z.string().regex(/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/,`View item name must be a dotted snake_case qualified name, e.g. "crm_lead.pipeline".`).describe("Globally-unique view id, `<object>.<viewKey>`."),br=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),xr=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function Sr(){return{name:yr,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:j.optional().describe(`Display label (supports i18n).`),isDefault:t.z.boolean().optional().describe(`Whether this is the object's default view in the switcher.`),order:t.z.number().int().optional().describe(`Sort order within the object's view switcher / left rail.`),scope:br.optional().describe("Identity layer (defaults to `package` for source-loaded views)."),owner:t.z.string().optional().describe("Owner user id — set when `scope` is `personal`."),hidden:t.z.boolean().optional().describe(`Hidden from the switcher (per-user / per-org declutter).`),protection:gn.optional().describe(`Package author protection block — lock policy for this view.`),...D}}var Cr=n(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({viewKind:t.z.literal(`list`),config:L.describe(`List-family view configuration.`),...Sr()}),t.z.object({viewKind:t.z.literal(`form`),config:gr.describe(`Form view configuration.`),...Sr()})]));function wr(){return{name:t.z.string().optional().describe(`Save name / qualified view id (stamped by the write path).`),object:t.z.string().optional().describe(`Bound object name (inherited from the shadowed entry — #2555).`),viewKind:xr.optional().describe(`View family (inherited from the shadowed entry — #2555).`),label:j.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:br.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:gn.optional(),...D,config:t.z.undefined().optional(),list:t.z.undefined().optional(),form:t.z.undefined().optional(),listViews:t.z.undefined().optional(),formViews:t.z.undefined().optional()}}function Tr(e){if(!e||typeof e!=`object`)return!1;let t=e;return!!(t.list||t.form||t.listViews&&typeof t.listViews==`object`&&Object.keys(t.listViews).length>0||t.formViews&&typeof t.formViews==`object`&&Object.keys(t.formViews).length>0)}n(()=>t.z.union([Cr,vr.refine(Tr,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."}),L.extend(wr()).strip(),gr.extend(wr()).strip()]));function Er(e){let{schemaId:t,...n}=e;return gr.parse({...n,data:{provider:`schema`,schemaId:t}})}var Dr=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),Or=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],kr={upsert:"declare ['create','update'] — `upsert` derives from create ∧ update",aggregate:"declare ['list'] — `aggregate` derives from list",history:"declare ['get'] with `enable.trackHistory: true` — `history` derives from get ∧ trackHistory",search:"declare ['list'] (with `searchable` not false) — `search` derives from list ∧ searchable",restore:"delete the value — `restore` never derives (`enable.trash` retired, #2377); it returns only with a real recycle bin (#3146, parked)",purge:"delete the value — `purge` never derives (`enable.trash` retired, #2377)",import:"declare ['create'] and/or ['update'] — `import` derives from create ∨ update (writeMode-precise at the gate)",export:"declare ['list'] — `export` derives from list"},Ar=[`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],jr=t.z.enum(Ar),Mr=new Set(Or),B=new Set;function Nr(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&Mr.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&Mr.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return B.has(i)||(B.add(i),(t?.warn??(e=>console.warn(e)))(`[spec] enable.apiMethods declares retired legacy value(s) [${n.join(`, `)}] \u2014 the ApiMethod enum is the six primitives get/list/create/update/delete/bulk (#3543). Legacy values are stripped at parse; their semantics are DERIVED from the primitives:
3
+ `)}`),l}}function ct(e,t=0){if(t>6)return!1;let n=e._zod?.def;if(!n?.type)return!1;if(n.type===`never`)return!0;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`readonly`:case`nonoptional`:case`catch`:return ct(n.innerType,t+1);default:return!1}}function T(e,n){let{surface:r,history:i,aliases:a,guidance:o,extraKeys:s=[]}=e,c;return t.z.object(n,{error:e=>(c??=w({surface:r,knownKeys:[...Object.keys(n).filter(e=>!ct(n[e])),...s],history:i,aliases:a,guidance:o}))(e)}).strict()}var lt=t.z.enum([`none`,`no-overlay`,`no-delete`,`full`]),ut=t.z.enum([`artifact`,`package`,`env-forced`]),E=t.z.enum([`package`,`org`,`env-forced`]),D={_lock:lt.optional().describe(`Item-level lock — controls overlay & delete (ADR-0010).`),_lockReason:t.z.string().max(500).optional().describe(`Human-readable reason shown when a write is refused by _lock.`),_lockSource:ut.optional().describe(`Layer that set _lock (artifact | package | env-forced).`),_provenance:E.optional().describe(`Origin of the item (package | org | env-forced).`),_packageId:t.z.string().optional().describe(`Owning package machine id.`),_packageVersion:t.z.string().optional().describe(`Owning package version.`),_lockDocsUrl:t.z.string().optional().describe(`Optional documentation link surfaced next to _lockReason.`)},dt=n(()=>t.z.string().min(2,{message:`System identifier must be at least 2 characters`}).regex(/^[a-z][a-z0-9_.]*$/,{message:`System identifier must be lowercase, starting with a letter, and may contain letters, numbers, underscores, or dots (e.g., "user_profile" or "order.created")`}).describe(`System identifier (lowercase with underscores or dots)`)),O=n(()=>t.z.string().min(2,{message:`Identifier must be at least 2 characters`}).regex(/^[a-z][a-z0-9_]*$/,{message:`Identifier must be lowercase snake_case, starting with a letter, and may contain only letters, numbers, and underscores (e.g., "user_profile")`}).describe(`Snake case identifier (lowercase with underscores only)`));n(()=>t.z.string().min(3,{message:`Event name must be at least 3 characters`}).regex(/^[a-z][a-z0-9_.]*$/,{message:`Event name must be lowercase with dots for namespacing (e.g., "user.created", "order.paid")`}).describe(`Event name (lowercase with dot notation for namespacing)`));var ft=t.z.enum([`cel`,`cron`,`template`]),pt=t.z.object({rationale:t.z.string().optional(),generatedBy:t.z.string().optional()}),mt=t.z.object({dialect:ft,source:t.z.string().min(1).optional(),ast:t.z.unknown().optional(),meta:pt.optional()}).refine(e=>e.source!==void 0||e.ast!==void 0,{message:"Expression requires at least one of `source` or `ast`"}),k=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cel`,source:e})),mt]);t.z.union([t.z.string().min(1).transform(e=>({dialect:`cron`,source:e})),mt]);var ht=t.z.union([t.z.string().min(1).transform(e=>({dialect:`template`,source:e})),mt]),gt=Object.freeze({referenceFilter:{to:`lookupFilters`},cascadeDelete:{to:`deleteBehavior`},formula:{to:`expression`},displayFormat:{to:`autonumberFormat`},summaryType:{to:`summaryOperations`},summaryField:{to:`summaryOperations`},index:{why:"field-level index flags built no index and were removed in the 16.x line (#2377, ADR-0049) — declare the index in the object's `indexes[]` instead."},indexed:{why:"never a FieldSchema key; a field-level index flag built no index (#2377). Declare the index in the object's `indexes[]`."},immutable:{why:"never a FieldSchema key. Use the `readonlyWhen` predicate to lock a field after creation."},filterable:{why:"never a FieldSchema key — every declared column is filterable. `sortable` and `searchable` are the real knobs."},placeholder:{why:"never a FieldSchema key. Author hint text through `inlineHelpText` or `description`."},startingNumber:{why:"never a FieldSchema key. An autonumber counter resets per rendered prefix, which `autonumberFormat` itself determines."},validation:{why:"field-level predicates are not a FieldSchema key — author a `validation` metadata item on the object, which carries its own message."},errorMessage:{why:"pairs with the `validation` key that never existed; a `validation` metadata item carries its own message."},audit:{why:"the `auditTrail` family was pruned in 2026-06 as dead in both layers. Use `trackHistory` for the activity timeline."},auditTrail:{why:"pruned in 2026-06 as dead in both layers. Use `trackHistory` for the activity timeline."},pii:{why:"the `dataQuality` governance family was pruned in 2026-06 as dead in both layers — it enforced nothing."},dataQuality:{why:`pruned in 2026-06 as dead in both layers (#3726) — it enforced nothing.`},encrypted:{why:"the `encryptionConfig` family was pruned in 2026-06: it implied at-rest protection that never happened. The real channel is `type: 'secret'`."},encryptionConfig:{why:"pruned in 2026-06 — it implied at-rest protection that never happened. The real channel is `type: 'secret'`."},maskingRule:{why:`pruned in 2026-06 as dead in both layers — masking was never applied.`},cached:{why:`computed-field caching was pruned in 2026-06 (#3733); nothing read it.`}}),_t=Object.freeze({capabilities:{to:`enable`},features:{to:`enable`},namespace:{why:"deprecated and removed — the object `name` is the canonical id everywhere. For module grouping embed a prefix in the name (`sys_user`)."},tableName:{why:"removed — the table name always equals the object `name`."}}),vt=Object.freeze({storage:{why:`the file-storage backend is a deployment concern, not an application declaration. Configure it with the OS_STORAGE_* environment variables, or per-deployment in Setup → Settings → Storage (which also holds credentials — a stack definition would commit them to git and to any published artifact).`}}),yt=Object.freeze([`onEnable`,`functions`]);function A(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function bt(e,t,n,r,i,a){let o=[...t];for(let s of Object.keys(e)){if(t.has(s)||s.startsWith(`_`))continue;let e=n[s],c=e?.to??(e?.why?void 0:ot(s,o,3,1)[0]);a.push({path:`${i}.${s}`,surface:r,key:s,...c?{suggestion:c}:{},...e?.why?{guidance:e.why}:{}})}}function xt(e){let t=`${e.path}: '${e.key}' is not a declared ${e.surface} key, so its value is dropped at load`;return e.guidance?`${t} \u2014 ${e.guidance}`:e.suggestion?`${t} \u2014 did you mean '${e.suggestion}'?`:`${t}.`}var St=t.z.enum(`text.textarea.email.url.phone.password.secret.markdown.html.richtext.number.currency.percent.date.datetime.time.boolean.toggle.select.multiselect.radio.checkboxes.lookup.master_detail.tree.user.image.file.avatar.video.audio.formula.summary.autonumber.composite.repeater.record.location.address.code.json.color.rating.slider.signature.qrcode.progress.tags.vector`.split(`.`)),Ct=`Until #4001 closed this shape these were dropped silently — the field was still created, minus whatever the key was meant to constrain, protect or compute.`,wt=n(()=>T({surface:`this select option`,history:Ct,aliases:{text:`label`,name:`label`,title:`label`,key:`value`,id:`value`,isDefault:`default`,selected:`default`,colour:`color`,visible:`visibleWhen`,showWhen:`visibleWhen`}},{label:t.z.string().describe(`Display label (human-readable, any case allowed)`),value:dt.describe(`Stored value (lowercase machine identifier)`),color:t.z.string().optional().describe(`Color code for badges/charts`),default:t.z.boolean().optional().describe(`Is default option`),visibleWhen:k.optional().describe("Per-option visibility predicate (CEL) — option is offered only when TRUE (else omitted). Same env as field visibleWhen (record + current_user). e.g. P`record.country == 'cn'` or P`'admin' in current_user.positions`")})),Tt=n(()=>t.z.object({latitude:t.z.number().min(-90).max(90).describe(`Latitude coordinate`),longitude:t.z.number().min(-180).max(180).describe(`Longitude coordinate`),altitude:t.z.number().optional().describe(`Altitude in meters`),accuracy:t.z.number().optional().describe(`Accuracy in meters`)})),Et=n(()=>T({surface:`this currency configuration`,history:Ct,aliases:{decimals:`precision`,scale:`precision`,mode:`currencyMode`,currency:`defaultCurrency`,code:`defaultCurrency`,isoCode:`defaultCurrency`}},{precision:t.z.number().int().min(0).max(10).default(2).describe(`Decimal precision (default: 2)`),currencyMode:t.z.enum([`dynamic`,`fixed`]).default(`dynamic`).describe(`Currency mode: dynamic (user selectable) or fixed (single currency)`),defaultCurrency:t.z.string().length(3).default(`CNY`).describe(`Default or fixed currency code (ISO 4217, e.g., USD, CNY, EUR)`)})),Dt=n(()=>t.z.object({value:t.z.number().describe(`Monetary amount`),currency:t.z.string().length(3).describe(`Currency code (ISO 4217)`)})),Ot=n(()=>t.z.object({street:t.z.string().optional().describe(`Street address`),city:t.z.string().optional().describe(`City name`),state:t.z.string().optional().describe(`State/Province`),postalCode:t.z.string().optional().describe(`Postal/ZIP code`),country:t.z.string().optional().describe(`Country name or code`),countryCode:t.z.string().optional().describe(`ISO country code (e.g., US, GB)`),formatted:t.z.string().optional().describe(`Formatted address string`)})),kt=n(()=>t.z.union([t.z.boolean(),t.z.literal(`global`)]));function At(e){return e===`global`}function jt(e){return e===!0||e===`global`}function Mt(){let e={},t={};for(let[n,r]of Object.entries(gt))r.to?e[n]=r.to:r.why&&(t[n]=r.why);return{aliases:e,guidance:t}}var Nt=n(()=>T({surface:`this field`,history:Ct,aliases:{...Mt().aliases,fieldName:`name`,key:`name`,column:`name`,dataType:`type`,fieldType:`type`,title:`label`,displayName:`label`,help:`inlineHelpText`,helpText:`inlineHelpText`,hint:`inlineHelpText`,tooltip:`inlineHelpText`,default:`defaultValue`,initialValue:`defaultValue`,isRequired:`required`,mandatory:`required`,notNull:`required`,isUnique:`unique`,values:`options`,choices:`options`,picklist:`options`,selectOptions:`options`,relatedTo:`reference`,referenceTo:`reference`,target:`reference`,targetObject:`reference`,lookupObject:`reference`,onDelete:`deleteBehavior`,deleteRule:`deleteBehavior`,cascade:`deleteBehavior`,formula:`expression`,calculation:`expression`,compute:`expression`,rollup:`summaryOperations`,rollUp:`summaryOperations`,summary:`summaryOperations`,aggregate:`summaryOperations`,length:`maxLength`,size:`maxLength`,decimals:`scale`,decimalPlaces:`scale`,digits:`precision`,isReadonly:`readonly`,disabled:`readonly`,isHidden:`hidden`,invisible:`hidden`,section:`group`,category:`group`,fieldset:`group`,component:`widget`,renderer:`widget`,control:`widget`,mimeTypes:`accept`,allowedTypes:`accept`,fileTypes:`accept`,maxFileSize:`maxSize`,maxBytes:`maxSize`,trackChanges:`trackHistory`,feedTracked:`trackHistory`,permissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`},guidance:{...Mt().guidance,columnName:"`columnName` was removed in the 16.x line (#2377) — the SQL driver hardcodes the physical column to the field key, so a custom name was ignored. External/federated objects map physical columns with `external.columnMap` (ADR-0062 D7).",referenceFilters:"`referenceFilters` (string[]) was removed in the 16.x line (#2377) — the lookup picker only ever read the structured form. Use `lookupFilters: [{ field, operator, value }]`.",storageNotNull:"physical column constraints live under `storage` — write `storage: { notNull: true }` (ADR-0113). `required` is the WRITE contract and deliberately does not imply the column constraint.",tracked:"`tracked` is not a field key — per-field timeline tracking is `trackHistory: true` (ADR-0052 §5b)."}},{name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Machine name (snake_case)`).optional(),label:t.z.string().optional().describe(`Human readable label`),type:St.describe(`Field Data Type`),description:t.z.string().optional().describe(`Tooltip/Help text`),format:t.z.string().optional().describe(`Format string (e.g. email, phone)`),required:t.z.boolean().default(!1).describe("Write-time contract (ADR-0113): an insert must provide a non-null value, and an update may not null it out. NOT a column constraint — the physical NOT NULL is a separate explicit opt-in (`storage.notNull`), so tightening this on a deployed object is safe: existing null rows stay readable, and editable as long as the write does not touch this field."),storage:t.z.object({notNull:t.z.boolean().optional().describe("Emit a physical NOT NULL on the column (ADR-0113). Absent = the column stays nullable even under `required: true` — the write contract is enforced at the engine, the only sanctioned write path, not by the database. Declaring this over existing null rows is a destructive migration gated by the schema-drift ceremony. Incompatible with `requiredWhen` (a conditional contract cannot be an unconditional column constraint).")}).strict().optional().describe(`Physical storage constraints (ADR-0113). Owns the DDL the write contract deliberately does not imply. Absent = no storage-level constraint requested.`),searchable:t.z.boolean().default(!1).describe(`Is searchable`),multiple:t.z.boolean().default(!1).describe(`Allow multiple values (Stores as Array/JSON). Applicable for select, lookup, file, image.`),unique:kt.default(!1).describe(`Unique constraint. true = unique within the tenant (composite with the tenant column on tenant-scoped objects); 'global' = unique platform-wide across all tenants`),defaultValue:t.z.unknown().optional().describe(`Default value`),maxLength:t.z.number().optional().describe(`Max character length`),minLength:t.z.number().optional().describe(`Min character length`),precision:t.z.number().optional().describe(`Total digits`),scale:t.z.number().optional().describe(`Decimal places`),min:t.z.number().optional().describe(`Minimum value`),max:t.z.number().optional().describe(`Maximum value`),accept:t.z.array(t.z.string()).optional().describe(`Permitted upload types for media fields, as MIME types or extensions (e.g. ["image/*", ".pdf"]). Offered to the file picker AND enforced on write.`),maxSize:t.z.number().int().positive().optional().describe(`Maximum permitted file size in BYTES for media fields. Enforced on write against the stored file size, not just checked in the browser.`),options:t.z.array(wt).optional().describe(`Static options for select/multiselect`),reference:t.z.string().optional().describe(`Target object name (snake_case) for lookup/master_detail fields. Required for relationship types. Used by $expand to resolve foreign key IDs into full objects.`),deleteBehavior:t.z.enum([`set_null`,`cascade`,`restrict`]).optional().default(`set_null`).describe(`What happens if referenced record is deleted`),inlineEdit:t.z.union([t.z.boolean(),t.z.enum([`grid`,`form`])]).optional().describe(`Edit these child records inline within the parent's form (atomic master-detail). true = auto-pick grid/form by child shape; 'grid' = editable line-item grid; 'form' = list + per-row full form.`),inlineTitle:t.z.string().optional().describe(`Title for the inline master-detail grid`),inlineColumns:t.z.array(t.z.any()).optional().describe(`Explicit columns for the inline grid (derived from the child object when omitted)`),inlineAmountField:t.z.string().optional().describe(`Numeric child field summed for the inline grid total`),relatedList:t.z.union([t.z.boolean(),t.z.literal(`primary`)]).optional().describe(`Show this child collection as a related list on the parent's detail page (read-side mirror of inlineEdit). false = suppress; true/absent = shown (stacked under the shared "Related" tab); 'primary' = core relationship, promoted to its own tab. Prominence intent, not a layout switch (ADR-0085).`),relatedListTitle:t.z.string().optional().describe(`Title for the detail-page related list`),relatedListColumns:t.z.array(t.z.any()).optional().describe(`Explicit columns for the detail-page related list (derived from the child object when omitted)`),displayField:t.z.string().optional().describe(`Field shown as each candidate's label in the picker/popover (defaults to the referenced object's name/title).`),descriptionField:t.z.string().optional().describe(`Secondary field shown under the label in the quick-select popover.`),lookupColumns:t.z.array(t.z.union([t.z.string(),T({surface:`this lookup column`,history:Ct,aliases:{name:`field`,fieldName:`field`,key:`field`,title:`label`,header:`label`,size:`width`}},{field:t.z.string(),label:t.z.string().optional(),width:t.z.string().optional(),type:t.z.string().optional()})])).optional().describe(`Explicit columns for the record-picker table; auto-derived from the referenced object when omitted.`),lookupPageSize:t.z.number().int().positive().optional().describe(`Rows per page in the record-picker dialog (default 10).`),lookupFilters:t.z.array(T({surface:`this lookup filter`,history:Ct,aliases:{name:`field`,fieldName:`field`,op:`operator`,comparator:`operator`,condition:`operator`},guidance:{$in:"the operator vocabulary here is flat, not Mongo-style — write `{ field, operator: 'in', value: [...] }`",values:"a multi-value filter puts the array in `value` with `operator: 'in'`"}},{field:t.z.string(),operator:t.z.enum([`eq`,`ne`,`gt`,`lt`,`gte`,`lte`,`contains`,`in`,`notIn`]),value:t.z.any()})).optional().describe(`Base filters restricting which records are selectable (e.g. only active). The structured, picker-honoured lookup filter.`),dependsOn:t.z.array(t.z.union([t.z.string(),T({surface:`this dependsOn entry`,history:Ct,aliases:{name:`field`,fieldName:`field`,local:`field`,remote:`param`,remoteField:`param`,key:`param`}},{field:t.z.string(),param:t.z.string().optional()})])).optional().describe("Declares that this field's available values depend on the value of other field(s) on the same record — the form gates the field until they are set and re-evaluates as they change. For `lookup`/`master_detail` it scopes the candidate query (string = same local/remote key; {field,param} when the remote filter key differs — the {field,param} form is lookup-only). For `select`/`multiselect`/`radio` the actual per-option rule lives in each option's `visibleWhen`; list the referenced fields here (string form) so the option list gates and refreshes with the parent."),allowCreate:t.z.boolean().optional().describe(`Allow inline quick-create from the record picker: when no match exists the user can create a record from the typed text (optimistic dataSource.create with the display field). Best for simple objects whose only required field is the display field.`),expression:k.optional().describe("Formula expression (CEL). e.g. F`record.amount * 0.1`"),returnType:t.z.enum([`number`,`text`,`boolean`,`date`]).optional().describe(`Inferred value type of a formula field (number/text/boolean/date)`),summaryOperations:T({surface:`this roll-up summary`,history:Ct,aliases:{child:`object`,childObject:`object`,from:`object`,source:`object`,aggregate:`function`,operation:`function`,op:`function`,aggregation:`function`,summaryField:`field`,targetField:`field`,foreignKey:`relationshipField`,fk:`relationshipField`,via:`relationshipField`,parentField:`relationshipField`,where:`filter`,criteria:`filter`,condition:`filter`}},{object:t.z.string().describe(`Source child object name for roll-up`),field:t.z.string().describe(`Field on child object to aggregate (ignored for count)`),function:t.z.enum([`count`,`sum`,`min`,`max`,`avg`]).describe(`Aggregation function to apply`),relationshipField:t.z.string().optional().describe(`FK field on the child pointing back to this parent. Auto-detected from the child's lookup/master_detail field referencing this object when omitted; set explicitly only when the child has more than one such reference.`),filter:d.optional().describe("Predicate restricting which child rows are aggregated (a query `where` FilterCondition, e.g. { status: 'received' } or { type: { $in: ['signup','trial'] } }). Omit to aggregate all children. Lets one child object feed multiple filtered roll-ups.")}).optional().describe(`Roll-up summary definition. The engine recomputes the value when child records are inserted/updated/deleted.`),language:t.z.string().optional().describe(`Programming language for syntax highlighting (e.g., javascript, python, sql)`),step:t.z.number().optional().describe(`Step increment for slider (default: 1)`),currencyConfig:Et.optional().describe(`Configuration for currency field type`),dimensions:t.z.number().int().min(1).max(1e4).optional().describe(`Vector dimensionality (e.g., 1536 for OpenAI embeddings)`),trackHistory:t.z.boolean().optional().describe(`Render this field's value changes as human-readable entries on the record activity timeline (ADR-0052 §5b). Opt-in per field.`),group:t.z.string().optional().describe(`Field group name for organizing fields in forms and layouts (e.g., "contact_info", "billing", "system")`),visibleWhen:k.optional().describe("Predicate (CEL) — field is shown only when TRUE (else hidden). e.g. P`record.type == 'invoice'`"),readonlyWhen:k.optional().describe("Predicate (CEL) — field is read-only when TRUE. e.g. P`record.status == 'paid'`"),requiredWhen:k.optional().describe("Predicate (CEL) — field is required when TRUE. The only slot; the `conditionalRequired` alias was removed in protocol 17 (#3855)."),conditionalRequired:v("`conditionalRequired` was removed in @objectstack/spec 17 (#3855) — use `requiredWhen`. Rename the key; the value (a CEL predicate) is unchanged. Run `os migrate meta --from 16` to rewrite it automatically."),widget:t.z.string().optional().describe('Form widget override — names a registered field component (resolved as `field:<widget>`) to render this field instead of the `type` default. Degrades to the `type` renderer when unregistered. e.g. "object-ref", "filter-condition", "recipient-picker".'),hidden:t.z.boolean().default(!1).describe(`Hidden from default UI`),readonly:t.z.boolean().default(!1).describe('Read-only — never editable in forms, AND server-enforced on BOTH write paths: a non-system write to this field is silently dropped from the payload on UPDATE (#2948/#3003) and on INSERT (#3043; a create can no longer directly seed e.g. `approval_status: "approved"`), symmetric with `readonlyWhen`. A stripped INSERT field still falls back to its `defaultValue`. Exempt from the strip: `isSystem` writes (seed replay, migration), and an opt-in "historical" import (`preserveAudit`, #3493) — which admits a whitelist (the audit/timestamp family plus author-declared business `readonly` fields). A normal (non-system) import is NOT system-context and still strips.'),requiredPermissions:t.z.array(t.z.string()).optional().describe(`[ADR-0066 D3] Capabilities required to read/edit this field (mask on read, deny on write; AND-gate).`),ackPlaintextMasking:t.z.boolean().optional().describe("[ADR-0100] Affirm a generic `password` field's plaintext-at-rest / masked-on-read contract is intended, silencing the author-time warning (#3420). No effect on non-password fields."),system:t.z.boolean().optional().describe(`Auto-injected system/audit field (e.g. created_at, updated_by, organization_id). Tools that surface system fields separately from author-declared business fields should branch on this flag.`),sortable:t.z.boolean().optional().default(!0).describe(`Whether field is sortable in list views`),inlineHelpText:t.z.string().optional().describe(`Help text displayed below the field in forms`),autonumberFormat:t.z.string().optional().describe(`Auto-number format: literal text + {0000} counter, {YYYY}/{MM}/{DD}/{YYYYMMDD} date tokens (business tz), and {field_name} interpolation. Counter resets per rendered prefix (e.g. AD{YYYYMMDD}{0000} resets daily).`),externalId:t.z.boolean().default(!1).describe(`Is external ID for upsert operations`),...D}).superRefine((e,t)=>{e.storage?.notNull===!0&&e.requiredWhen!==void 0&&t.addIssue({code:`custom`,path:[`storage`,`notNull`],message:"`storage.notNull` cannot be combined with `requiredWhen` (ADR-0113): when the condition is false the write contract permits null, but the column would refuse it. Use `required: true` + `storage.notNull` for an unconditional constraint, or `requiredWhen` alone for a conditional write contract (the column stays nullable)."})})),Pt={text:(e={})=>({type:`text`,...e}),textarea:(e={})=>({type:`textarea`,...e}),number:(e={})=>({type:`number`,...e}),boolean:(e={})=>({type:`boolean`,...e}),date:(e={})=>({type:`date`,...e}),datetime:(e={})=>({type:`datetime`,...e}),currency:(e={})=>({type:`currency`,...e}),percent:(e={})=>({type:`percent`,...e}),url:(e={})=>({type:`url`,...e}),email:(e={})=>({type:`email`,...e}),phone:(e={})=>({type:`phone`,...e}),image:(e={})=>({type:`image`,...e}),file:(e={})=>({type:`file`,...e}),avatar:(e={})=>({type:`avatar`,...e}),formula:(e={})=>({type:`formula`,...e}),summary:(e={})=>({type:`summary`,...e}),autonumber:(e={})=>({type:`autonumber`,...e}),markdown:(e={})=>({type:`markdown`,...e}),html:(e={})=>({type:`html`,...e}),password:(e={})=>({type:`password`,...e}),secret:(e={})=>({type:`secret`,...e}),select:(e,t)=>{let n=e=>e.toLowerCase().replace(/\s+/g,`_`).replace(/[^a-z0-9_]/g,``),r,i;if(Array.isArray(e))r=e.map(e=>typeof e==`string`?{label:e,value:n(e)}:{...e,value:e.value.toLowerCase()}),i=t||{};else{r=(e.options||[]).map(e=>typeof e==`string`?{label:e,value:n(e)}:{...e,value:e.value.toLowerCase()});let{options:t,...a}=e;i=a}return{type:`select`,options:r,...i}},lookup:(e,t={})=>({type:`lookup`,reference:e,...t}),masterDetail:(e,t={})=>({type:`master_detail`,reference:e,...t}),user:(e={})=>({type:`user`,reference:`sys_user`,...e}),location:(e={})=>({type:`location`,...e}),address:(e={})=>({type:`address`,...e}),richtext:(e={})=>({type:`richtext`,...e}),code:(e,t={})=>({type:`code`,language:e,...t}),color:(e={})=>({type:`color`,...e}),rating:(e=5,t={})=>({type:`rating`,max:e,...t}),signature:(e={})=>({type:`signature`,...e}),slider:(e={})=>({type:`slider`,...e}),qrcode:(e={})=>({type:`qrcode`,...e}),json:(e={})=>({type:`json`,...e}),vector:(e,t={})=>({type:`vector`,dimensions:e,...t})},Ft={name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique rule name (snake_case)`),label:t.z.string().optional().describe(`Human-readable label for the rule listing`),description:t.z.string().optional().describe(`Administrative notes explaining the business reason`),active:t.z.boolean().default(!0),events:t.z.array(t.z.enum([`insert`,`update`])).default([`insert`,`update`]).describe("Write contexts the rule runs on. `delete` is intentionally absent — the evaluator only runs on the insert/update write path; guard deletions with a `beforeDelete` lifecycle hook"),priority:t.z.number().int().min(0).max(9999).default(100).describe(`Execution priority (lower runs first, default: 100)`),tags:t.z.array(t.z.string()).optional().describe(`Categorization tags (e.g., "compliance", "billing")`),severity:t.z.enum([`error`,`warning`,`info`]).default(`error`),message:t.z.string().describe(`Error message to display to the user`),...D},It=n(()=>T({surface:`this script validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`,predicate:`condition`,rule:`condition`}},{...Ft,type:t.z.literal(`script`),condition:k.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),Lt=n(()=>T({surface:`this state-machine validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{states:`transitions`,statefield:`field`,from:`transitions`,initial:`initialStates`,initialstate:`initialStates`}},{...Ft,type:t.z.literal(`state_machine`),field:t.z.string().describe(`State field (e.g. status)`),transitions:t.z.record(t.z.string(),t.z.array(t.z.string())).describe(`Map of { OldState: [AllowedNewStates] }`),initialStates:t.z.array(t.z.string()).optional().describe("States a record may be CREATED in. When set, an INSERT whose state field carries a value outside this list is rejected (server-enforced) — the FSM entry point. `transitions` only governs UPDATE, and a `select` field permits ANY declared option as an initial value, so without this a record could be born mid-flow (e.g. created already `approved`). Omit to keep the legacy behavior (no initial-state check on insert). #3165.")})),Rt=n(()=>T({surface:`this format validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{pattern:`regex`,fieldname:`field`}},{...Ft,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),zt=n(()=>T({surface:`this cross-field validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`}},{...Ft,type:t.z.literal(`cross_field`),condition:k.describe("Predicate (CEL) comparing fields. e.g. P`record.end_date > record.start_date`"),fields:t.z.array(t.z.string()).describe(`Fields involved. Only fields[0] is read (labels which field the violation attaches to); the rest are advisory. Shares script’s evaluation path.`)})),Bt=n(()=>T({surface:`this JSON-schema validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{jsonschema:`schema`,fieldname:`field`}},{...Ft,type:t.z.literal(`json_schema`),field:t.z.string().describe(`JSON field to validate`),schema:t.z.record(t.z.string(),t.z.unknown()).describe(`JSON Schema object definition`)})),Vt=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[It,Lt,Rt,zt,Bt,Ht])),Ht=n(()=>T({surface:`this conditional validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{if:`when`,condition:`when`,match:`when`,else:`otherwise`}},{...Ft,type:t.z.literal(`conditional`),when:k.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:Vt.describe(`Validation rule to apply when condition is true`),otherwise:Vt.optional().describe(`Validation rule to apply when condition is false`)}));n(()=>t.z.object({key:t.z.string().describe(`Translation key (e.g., "views.task_list.label")`),defaultValue:t.z.string().optional().describe(`Fallback value when translation key is not found`),params:t.z.record(t.z.string(),t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Interpolation parameters (e.g., { count: 5 })`)}));var j=n(()=>t.z.string().describe(`Display label (plain string; i18n keys are auto-generated by the framework)`)),Ut=n(()=>t.z.object({ariaLabel:j.optional().describe(`Accessible label for screen readers (WAI-ARIA aria-label)`),ariaDescribedBy:t.z.string().optional().describe(`ID of element providing additional description (WAI-ARIA aria-describedby)`),role:t.z.string().optional().describe(`WAI-ARIA role attribute (e.g., "dialog", "navigation", "alert")`)}).describe(`ARIA accessibility attributes`));n(()=>t.z.object({key:t.z.string().describe(`Translation key`),zero:t.z.string().optional().describe(`Zero form (e.g., "No items")`),one:t.z.string().optional().describe(`Singular form (e.g., "{count} item")`),two:t.z.string().optional().describe(`Dual form (e.g., "{count} items" for exactly 2)`),few:t.z.string().optional().describe(`Few form (e.g., for 2-4 in some languages)`),many:t.z.string().optional().describe(`Many form (e.g., for 5+ in some languages)`),other:t.z.string().describe(`Default plural form (e.g., "{count} items")`)}).describe(`ICU plural rules for a translation key`));var Wt=n(()=>t.z.object({style:t.z.enum([`decimal`,`currency`,`percent`,`unit`]).default(`decimal`).describe(`Number formatting style`),currency:t.z.string().optional().describe(`ISO 4217 currency code (e.g., "USD", "EUR")`),unit:t.z.string().optional().describe(`Unit for unit formatting (e.g., "kilometer", "liter")`),minimumFractionDigits:t.z.number().optional().describe(`Minimum number of fraction digits`),maximumFractionDigits:t.z.number().optional().describe(`Maximum number of fraction digits`),useGrouping:t.z.boolean().optional().describe(`Whether to use grouping separators (e.g., 1,000)`)}).describe(`Number formatting rules`)),Gt=n(()=>t.z.object({dateStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Date display style`),timeStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Time display style`),timeZone:t.z.string().optional().describe(`IANA time zone (e.g., "America/New_York")`),hour12:t.z.boolean().optional().describe(`Use 12-hour format`)}).describe(`Date/time formatting rules`));n(()=>t.z.object({code:t.z.string().describe(`BCP 47 language code (e.g., "en-US", "zh-CN")`),fallbackChain:t.z.array(t.z.string()).optional().describe(`Fallback language codes in priority order (e.g., ["zh-TW", "en"])`),direction:t.z.enum([`ltr`,`rtl`]).default(`ltr`).describe(`Text direction: left-to-right or right-to-left`),numberFormat:Wt.optional().describe(`Default number formatting rules`),dateFormat:Gt.optional().describe(`Default date/time formatting rules`)}).describe(`Locale configuration`));var Kt='`crypto.hash` was removed from `HookBodyCapability` in @objectstack/spec 17 (#4391, ADR-0049 enforce-or-remove) — the sandbox never implemented it. `installCtx` wired only `ctx.crypto.randomUUID`, so `ctx.crypto.hash(...)` threw inside the VM on every call the token ever "granted", while the build-time extractor inferred the token from that very call and let `os build` pass. Delete the capability from `capabilities` AND delete the `ctx.crypto.hash(...)` call it was declared for — the call has never returned a value, so nothing that works today depends on it. There is no replacement inside the sandbox: hash in the host (a Connector recipe, or an engine-side hook) instead. If you need hashing in a body, reopen it through the capability admission process — implementation first, the declaration lands with the implementation. Run `os migrate meta --from 16` to rewrite it automatically.',qt=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?Kt:void 0}),Jt=[`language`,`source`],Yt=[`language`,`source`,`capabilities`,`timeoutMs`,`memoryMb`],Xt='is an L2 key — it only applies to `language: "js"`. An expression body is a pure formula: it performs no IO, so it has nothing to grant and no sandbox to bound.',Zt=w({surface:`this expression (L1) hook body`,knownKeys:Jt,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${Xt}`,timeoutMs:`\`timeoutMs\` ${Xt}`,memoryMb:`\`memoryMb\` ${Xt}`},history:`Until #4001 these were dropped silently.`}),Qt=w({surface:`this sandboxed JS (L2) hook body`,knownKeys:Yt,aliases:{capability:`capabilities`,caps:`capabilities`,permissions:`capabilities`,timeout:`timeoutMs`,timeoutms:`timeoutMs`,memory:`memoryMb`,memorymb:`memoryMb`,code:`source`,script:`source`,body:`source`},history:`Until #4001 these were dropped silently — the body still ran, just not under the limits or grants that were written.`}),$t=t.z.object({language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)},{error:Zt}).strict().describe(`L1 expression body — pure formula, no IO`),M=t.z.object({language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(qt).default([]).describe(`Granted capability tokens`),timeoutMs:t.z.number().int().positive().max(3e4).optional().describe(`Per-invocation timeout (ms)`),memoryMb:t.z.number().int().positive().max(256).optional().describe(`Per-invocation memory cap (MB)`)},{error:Qt}).strict().describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),en=t.z.discriminatedUnion(`language`,[$t,M]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),tn={twoFactor:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.enable_two_factor`,`sys_user.actions.disable_two_factor`,`sys_user.actions.generate_backup_codes`,`sys_two_factor.actions.enable_two_factor`,`sys_two_factor.actions.disable_two_factor`,`sys_two_factor.actions.regenerate_backup_codes`],notes:`Login-surface 2FA challenge is server-driven remediation (ADR-0069), so the flag is intentionally unread by objectui LoginForm.`},passkeys:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no passkey UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},magicLink:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no magic-link UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},organization:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_user.actions.invite_user`,`sys_member.actions.add_member`,`sys_member.actions.update_member_role`,`sys_member.actions.remove_member`,`sys_member.actions.transfer_ownership`,`sys_invitation.actions.invite_user`,`sys_invitation.actions.cancel_invitation`,`sys_invitation.actions.resend_invitation`,`sys_team.actions.create_team`,`sys_team.actions.update_team`,`sys_team.actions.remove_team`,`sys_team_member.actions.add_team_member`,`sys_team_member.actions.remove_team_member`],notes:`Org CAPABILITY gate, not multi-org (ADR-0081 D1).`},multiOrgEnabled:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_organization.actions.create_organization`,`sys_organization.actions.update_organization`,`sys_organization.actions.delete_organization`,`sys_organization.actions.set_active_organization`,`sys_organization.actions.leave_organization`,`sys_organization.actions.change_slug`],notes:"Reflects ACTUAL multi-tenancy capability (the tenancy posture enforces an organization wall — `group` or `isolated`, ADR-0093 D4 / ADR-0105 D1), not just the requested posture."},degradedTenancy:{surface:`status`,semantics:`opt-in`,exempt:{reason:`Operator status banner (ADR-0093 D5) — signals degraded tenant isolation, not an input capability gate.`}},oidcProvider:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_oauth_application.actions.create_oauth_application`,`sys_oauth_application.actions.delete_oauth_application`,`sys_oauth_application.actions.disable_oauth_application`,`sys_oauth_application.actions.enable_oauth_application`,`sys_oauth_application.actions.rotate_client_secret`],notes:`Default-ON: the embedded OIDC authorization server follows the default-on MCP surface (resolveOidcProviderEnabled). Login surface consumes the socialProviders[] array (per-provider enabled), not this flag.`},sso:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Deliberately ungated on the CRUD surface: the served value is refined to "usable" (≥1 provider configured) via isSsoUsable() at /auth/config, so gating sys_sso_provider registration actions on it would deadlock first-provider setup. Login consumption verified: objectui LoginForm gates the "Sign in with SSO" button.`}},ssoEnforced:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: objectui LoginForm hides the password form and self-registration (break-glass link remains). No spec input to gate.`}},deviceAuthorization:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input (sys_device_code declares no actions). Known gap: objectui DeviceAuthPage hits the device-auth endpoints without checking this flag (absent from its client type) — tracked in objectui#2513 (#2874 P2②).`}},admin:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user`,`sys_user.actions.ban_user`,`sys_user.actions.unban_user`,`sys_user.actions.unlock_user`,`sys_user.actions.set_user_password`,`sys_user.actions.set_user_role`,`sys_user.actions.impersonate_user`],notes:`SCIM forces the admin plugin (and this flag) on — ADR-0071.`},phoneNumber:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user.params.phoneNumber`],notes:`The original #2871 fix. Also read by objectui LoginForm for the phone+password sign-in mode.`},phoneNumberOtp:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: gates the "sign in with verification code" link (LoginForm) and the phone branch of forgot-password. Only advertised when SMS is actually deliverable (#2780).`}}},nn=Object.keys(tn);function rn(e){return`features.${e} ${tn[e].semantics===`opt-in`?`== true`:`!= false`}`}function an(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=rn(n),a=r.visible;return a===void 0?{...r,visible:{dialect:`cel`,source:i}}:a.dialect!==`cel`||typeof a.source!=`string`?(t.addIssue({code:`custom`,path:[`requiresFeature`],message:"`requiresFeature` composes only with a CEL `visible` carrying a `source` string; this expression is AST-only or non-CEL — write the combined predicate by hand."}),r):{...r,visible:{...a,source:`(${a.source}) && ${i}`}}}var on=w({surface:`this action param`,knownKeys:[`name`,`field`,`objectOverride`,`label`,`type`,`required`,`options`,`placeholder`,`helpText`,`defaultValue`,`multiple`,`accept`,`maxSize`,`reference`,`defaultFromRow`,`visible`,`requiresFeature`],aliases:{referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},history:`Until #3405 these were dropped silently — the param still parsed, so a mis-spelled config shipped as a control that quietly ignored it.`}),sn=n(()=>t.z.object({name:t.z.string().optional(),field:O.optional(),objectOverride:O.optional(),label:j.optional(),type:St.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(t.z.object({label:j,value:t.z.string()})).optional(),placeholder:t.z.string().optional(),helpText:t.z.string().optional(),defaultValue:t.z.unknown().optional(),multiple:t.z.boolean().optional().describe(`Allow multiple values (array value shape); mirrors FieldSchema.multiple.`),accept:t.z.array(t.z.string()).optional().describe(`Accepted upload types (MIME types / extensions) for file/image params.`),maxSize:t.z.number().int().positive().optional().describe(`Max upload size in bytes for file/image params.`),reference:O.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:k.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(nn).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")},{error:on}).strict().refine(e=>!!e.name||!!e.field,{message:`ActionParam requires either "name" or "field"`}).refine(e=>!(!e.field&&(e.type===`lookup`||e.type===`master_detail`)&&!e.reference),{path:[`reference`],message:`ActionParam with type "lookup"/"master_detail" requires "reference" (the target object) when declared inline — without it the param dialog degrades to a raw record-id text input. Set \`reference: '<object>'\`, or use a field-backed param (\`{ field: '<lookup_field>' }\`) to inherit it.`}).transform((e,t)=>an(e,t))),cn=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),ln=new Set(cn.options.filter(e=>e!==`script`)),un=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`,`global_nav`]),dn=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),N=`Until #4001 closed this shape these were dropped silently — the action still registered and still ran, without whatever the key was meant to configure or gate.`,fn=T({surface:`this action's AI exposure block`,history:N,aliases:{enabled:`exposed`,enable:`exposed`,aiEnabled:`exposed`,expose:`exposed`,visible:`exposed`,prompt:`description`,toolDescription:`description`,summary:`description`,type:`category`,kind:`category`,toolCategory:`category`,hints:`paramHints`,parameterHints:`paramHints`,params:`paramHints`,returns:`outputSchema`,responseSchema:`outputSchema`,output:`outputSchema`,confirm:`requiresConfirmation`,requireConfirmation:`requiresConfirmation`,hitl:`requiresConfirmation`,humanInTheLoop:`requiresConfirmation`},guidance:{permissions:"AI invocation is not gated by a key here — an agent reaches this action only if a surface-compatible SKILL declares it (ADR-0064), and who may talk to that agent is gated by the agent's `access` / `permissions` (enforced at the chat route since #1884). For a human-approval step on the call itself, use `requiresConfirmation: true`.",approval:"there is no approval workflow key here — `requiresConfirmation: true` forces a human-in-the-loop gate on the AI call. A multi-step business approval is an `approval` metadata item, not an action field."}},{exposed:t.z.boolean().default(!1).describe("Expose this action to AI agents. Requires `description` when true."),description:t.z.string().min(40).optional().describe(`LLM-facing description (≥40 chars). Required when exposed.`),category:dn.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),T({surface:`this AI parameter hint`,history:N,aliases:{desc:`description`,hint:`description`,values:`enum`,options:`enum`,choices:`enum`,allowed:`enum`,example:`examples`,sample:`examples`}},{description:t.z.string().optional(),enum:t.z.array(t.z.union([t.z.string(),t.z.number()])).optional(),examples:t.z.array(t.z.unknown()).optional()})).optional().describe(`Per-parameter AI hints keyed by param name.`),outputSchema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`JSON Schema for the action return value.`),requiresConfirmation:t.z.boolean().optional().describe(`Override HITL confirmation for AI invocations.`)}),pn=()=>T({surface:`this action`,history:N,aliases:{title:`label`,displayName:`label`,text:`label`,object:`objectName`,entity:`objectName`,actionType:`type`,url:`target`,endpoint:`target`,path:`target`,href:`target`,parameters:`params`,args:`params`,inputs:`params`,fields:`params`,confirm:`confirmText`,confirmation:`confirmText`,confirmMessage:`confirmText`,success:`successMessage`,successText:`successMessage`,toast:`successMessage`,visibleWhen:`visible`,showWhen:`visible`,disabledWhen:`disabled`,style:`variant`,color:`variant`,appearance:`variant`,placement:`locations`,location:`locations`,position:`locations`,verb:`method`,httpMethod:`method`,body:`bodyExtra`,payload:`bodyExtra`,llm:`ai`,tool:`ai`,dialog:`resultDialog`,result:`resultDialog`,refresh:`refreshAfter`,reload:`refreshAfter`,permissions:`requiredPermissions`,capabilities:`requiredPermissions`,requiresPermissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`,acl:`requiredPermissions`},guidance:{hidden:"`hidden` is not an action key, and hiding is not gating — `visible` and `disabled` are UI predicates that hide or grey a button, they do not stop a request. To actually gate invocation use `requiredPermissions` (ADR-0066 D4, enforced with a 403 on the platform action route). To declare an action with no UI surface at all, set `locations: []`.",exposed:"AI exposure lives under `ai` — write `ai: { exposed: true, description: … }`. The description is the LLM-facing contract and is REQUIRED (≥40 chars) whenever exposed.",requiresConfirmation:"the AI human-in-the-loop override lives under `ai` — write `ai: { requiresConfirmation: true }`. `confirmText` is the separate UI confirm prompt."}},{name:O.describe(`Machine name (lowercase snake_case)`),label:j.describe(`Display label`),objectName:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).optional().describe(`Target object this action belongs to. When set, the action is auto-merged into the object's actions array by defineStack().`),icon:t.z.string().optional().describe(`Icon name`),locations:t.z.array(un).optional().describe(`Locations where this action is visible`),component:t.z.enum([`action:button`,`action:icon`,`action:menu`,`action:group`]).optional().describe(`Visual component override`),type:cn.default(`script`).describe(`Action functionality type`),target:t.z.string().optional().describe("URL, Script Name, Flow ID, or API Endpoint. Supports ${param.X} and ${ctx.X} interpolation."),openIn:t.z.enum([`self`,`new-tab`]).optional().describe("For type:'url' — where to open `target`. 'new-tab' opens a new browser tab; 'self' navigates in place. When omitted, external/absolute URLs open in a new tab and relative URLs navigate in place. Static execution option — keep it OUT of `params` (which is user-input-collection only)."),body:en.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:v("`execute` was removed in @objectstack/spec 17 (#3855) — use `target`. Rename the key; the value (a handler / flow / URL ref) is unchanged. Run `os migrate meta --from 16` to rewrite it automatically."),params:t.z.array(sn).optional().describe(`Input parameters required from user`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`link`]).optional().describe(`Button visual variant for styling (primary = highlighted, danger = destructive, ghost = transparent)`),order:t.z.number().optional().describe("Sort order within a location group (lower = higher). Promotes/demotes an action toward the record_header primary button; stable, so actions without `order` keep their registration order."),confirmText:j.optional().describe(`Confirmation message before execution`),successMessage:j.optional().describe(`Success message to show after execution`),errorMessage:j.optional().describe(`Error message to show when the action fails (overrides the raw error).`),refreshAfter:t.z.boolean().default(!1).describe(`Refresh view after execution`),undoable:t.z.boolean().optional().describe(`Offer an Undo affordance after this single-record update action succeeds.`),resultDialog:T({surface:`this result dialog`,history:N,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:j.optional(),description:j.optional(),acknowledge:j.optional().describe(`Acknowledge button label, e.g. "I have saved this"`),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Default format for fields without their own format. Defaults to json when omitted.`),fields:t.z.array(T({surface:`this result dialog field`,history:N,aliases:{key:`path`,field:`path`,name:`path`,title:`label`,display:`format`,render:`format`}},{path:t.z.string().describe(`Dot path into result.data (e.g. "totpURI", "client.client_secret").`),label:j.optional(),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Per-field format override.`)})).optional().describe(`Which fields from result.data to render. Omit to dump full JSON.`)}).optional().describe(`Render API response in a one-shot reveal dialog (suppresses successMessage when set).`),visible:k.optional().describe(`Visibility predicate (CEL).`),requiresFeature:t.z.enum(nn).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:t.z.union([t.z.boolean(),k]).optional().describe(`Boolean or predicate (CEL) — action is disabled when TRUE.`),requiredPermissions:t.z.array(t.z.string()).optional().describe("[ADR-0066 D4] Capabilities required to invoke this action. Enforced with 403 on the platform action route (script/flow/modal + MCP) and mirrored as a UI hide; a `type: api` action pointed at a custom endpoint must re-check it there."),shortcut:v("`action.shortcut` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never triggered anything: no keydown listener feeds ActionEngine.getShortcuts(), and objectui's keyboard stack (useKeyboardShortcuts) is hand-registered and never consults action metadata. Delete the key. For a real shortcut, register the key in the Console keyboard stack and have its handler invoke the action by name."),bulkEnabled:v("`action.bulkEnabled` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — the multi-select toolbar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, never by this flag, so setting it changed nothing. Delete the key and declare the action in the view's `bulkActions` instead."),ai:fn.optional().describe(`AI exposure (opt-in). Set ai.exposed=true + ai.description to make this callable by agents.`),recordIdParam:t.z.string().optional().describe(`Body key to inject the row id into when running from a list_item context.`),recordIdField:t.z.string().optional().describe(`Row field whose value seeds recordIdParam. Defaults to "id".`),bodyShape:t.z.union([t.z.literal(`flat`),T({surface:`this body shape`,history:N,aliases:{key:`wrap`,under:`wrap`,nest:`wrap`,root:`wrap`}},{wrap:t.z.string()})]).optional().describe(`Body wrapping: flat (default) or { wrap: key } to nest user-collected params under a key.`),method:t.z.enum([`POST`,`PATCH`,`PUT`,`DELETE`]).optional().describe(`HTTP method for type:"api" actions. Defaults to POST.`),bodyExtra:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Constant body fields merged into the API request (applied last; overrides user params).`),mode:t.z.enum([`create`,`edit`,`delete`,`custom`]).optional().describe(`Semantic mode of the action.`),opensInNewTab:t.z.boolean().optional().describe(`Open the action result in a new tab. The renderer pre-opens the tab synchronously on click (popup-blocker-safe) and navigates it to the handler's redirectUrl.`),newTabUrl:t.z.string().optional().describe(`Direct new-tab URL template ({recordId} placeholder). When set with opensInNewTab, the renderer navigates the pre-opened tab here immediately — no action POST. The endpoint must enforce auth itself.`),aria:Ut.optional().describe(`ARIA accessibility attributes`),...D}),mn=n(()=>pn().refine(e=>!(ln.has(e.type)&&!e.target),{message:`Action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form'.`,path:[`target`]}).refine(e=>!(e.type===`script`&&!e.body&&!e.target),{message:"A 'script' action requires either an inline `body` (sandboxed L1/L2 handler) or a `target` (a registered bundle function name).",path:[`body`]}).refine(e=>!(e.type!==`script`&&e.body),{message:"`body` only runs for `type: 'script'` — a non-script action dispatches on `target` and silently ignores its body. To collect `params` and then run the body, use `type: 'script'`; to open a page/modal, drop the `body` and keep `type: 'modal'` with `target` naming the page.",path:[`body`]}).refine(e=>!(e.ai?.exposed===!0&&!e.ai.description),{message:`ai.description is required (≥40 chars) when ai.exposed is true.`,path:[`ai`,`description`]}).refine(e=>{let t=e.ai?.paramHints;if(!t)return!0;let n=new Set([`recordId`]);for(let t of e.params??[]){let e=t.name??t.field;e&&n.add(e)}return Object.keys(t).every(e=>n.has(e))},{message:`ai.paramHints keys must match a declared param name (or "recordId").`,path:[`ai`,`paramHints`]}).transform((e,t)=>an(e,t)));function hn(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e,n=t.type===`navigation`,r=t.target===void 0&&typeof t.to==`string`;if(!n&&!r&&!(`to`in t))return e;let i={...t};return n&&(i.type=`url`),r&&(i.target=t.to),delete i.to,i}n(()=>t.z.preprocess(hn,pn().pick({type:!0,name:!0,label:!0,target:!0,openIn:!0,method:!0,params:!0,confirmText:!0,successMessage:!0,errorMessage:!0,refreshAfter:!0,opensInNewTab:!0}).partial({name:!0,label:!0}).refine(e=>!(ln.has(e.type)&&!e.target),{message:"Inline action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form' (`to` is accepted as a legacy spelling).",path:[`target`]})));var gn=t.z.object({lock:lt.describe(`Lock policy — none | no-overlay | no-delete | full.`),reason:t.z.string().min(1).max(500).describe(`User-visible reason shown when the lock blocks an action.`),docsUrl:t.z.string().url().optional().describe(`Optional URL the Studio banner links to for more context.`)}).strict();function _n(e){let{visibleOn:t,visibility:n,...r}=e,i=r.visibleWhen===void 0?t===void 0?n:t:r.visibleWhen;return i===void 0?r:{...r,visibleWhen:i}}function vn(e){return/vis|conceal|hidden|show.?when/i.test(e)}var yn=e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=`Unrecognized key(s) on this view/page schema: ${t.map(e=>`\`${e}\``).join(`, `)}. Before ADR-0089 D3a these were dropped silently, shipping inert metadata; a mis-layered or stale key is now a loud parse error.`;return t.some(vn)?n+" If this is the conditional-visibility predicate, the canonical key is `visibleWhen` (ADR-0089) — `visibleOn` (view form) and `visibility` (page component) are still accepted as deprecated aliases.":n},bn=n(()=>t.z.enum([`bar`,`horizontal-bar`,`column`,`line`,`area`,`pie`,`donut`,`funnel`,`scatter`,`treemap`,`sankey`,`combo`,`gauge`,`solid-gauge`,`metric`,`kpi`,`bullet`,`radar`,`table`,`pivot`])),xn=n(()=>t.z.object({field:t.z.string().describe(`Data field key`),title:j.optional().describe(`Axis display title`),format:t.z.string().optional().describe(`Value format string (e.g., "$0,0.00")`),min:t.z.number().optional().describe(`Minimum value`),max:t.z.number().optional().describe(`Maximum value`),stepSize:t.z.number().optional().describe(`Step size for ticks`),showGridLines:t.z.boolean().default(!0),position:t.z.enum([`left`,`right`,`top`,`bottom`]).optional().describe(`Axis position`),logarithmic:t.z.boolean().default(!1)})),Sn=n(()=>t.z.object({name:t.z.string().describe(`Field name or series identifier`),label:j.optional().describe(`Series display label`),type:bn.optional().describe(`Override chart type for this series`),color:t.z.string().optional().describe(`Series color (hex/rgb/token)`),stack:t.z.string().optional().describe(`Stack identifier to group series`),yAxis:t.z.enum([`left`,`right`]).default(`left`).describe(`Bind to specific Y-Axis`),variant:t.z.enum([`primary`,`comparison`]).default(`primary`).optional().describe(`Series visual role`),dashArray:t.z.string().optional().describe(`SVG stroke-dasharray override`),opacity:t.z.number().min(0).max(1).optional().describe(`Series opacity override`)})),Cn=n(()=>t.z.object({type:t.z.enum([`line`,`region`]).default(`line`),axis:t.z.enum([`x`,`y`]).default(`y`),value:t.z.union([t.z.number(),t.z.string()]).describe(`Start value`),endValue:t.z.union([t.z.number(),t.z.string()]).optional().describe(`End value for regions`),color:t.z.string().optional(),label:j.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),wn=n(()=>t.z.object({tooltips:t.z.boolean().default(!0).describe(`Show the hover tooltip`),brush:t.z.boolean().default(!1).describe(`Show the range selector under the plot`)}));n(()=>t.z.object({type:bn,title:j.optional().describe(`Chart title`),subtitle:j.optional().describe(`Chart subtitle`),description:j.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:xn.optional().describe(`X-Axis configuration`),yAxis:t.z.array(xn).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(Sn).optional().describe(`Defined series configuration`),colors:t.z.union([t.z.array(t.z.string()),t.z.record(t.z.string(),t.z.string())]).optional().describe(`Color palette (string[]) or value→color map ({ value: color })`),height:t.z.number().optional().describe(`Fixed plot height in pixels (overrides the container default)`),showLegend:t.z.boolean().default(!0).describe(`Display legend`),showDataLabels:t.z.boolean().default(!1).describe(`Display data labels`),annotations:t.z.array(Cn).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:wn.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:Ut.optional().describe(`ARIA accessibility attributes`)}));var Tn=n(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),En=n(()=>t.z.union([t.z.string().describe(`Field to group by`),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:t.z.enum([`day`,`week`,`month`,`quarter`,`year`]).optional().describe(`Bucket date values into uniform periods`),alias:t.z.string().optional().describe("Alias for the projected group value (defaults to `field`) — this becomes the category column")})]));n(()=>t.z.object({field:t.z.string().optional().describe(`Field to aggregate — required for sum/avg/min/max, optional for count`),function:Tn.describe(`Aggregation function`),groupBy:En.describe(`Field the rows are grouped by — the chart category axis`)}).superRefine((e,t)=>{e.function!==`count`&&!e.field&&t.addIssue({code:`custom`,path:[`field`],message:`aggregate.function "${e.function}" needs a "field" to aggregate (only "count" may omit it).`})}).describe(`Inline aggregation for an object-bound chart`));var Dn=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable public sharing`),publicLink:t.z.string().optional().describe(`Generated public share URL`),password:t.z.string().optional().describe(`Password required to access shared link`),allowedDomains:t.z.array(t.z.string()).optional().describe(`Restrict access to specific email domains (e.g. ["example.com"])`),expiresAt:t.z.string().optional().describe(`Expiration date/time in ISO 8601 format`),allowAnonymous:t.z.boolean().optional().default(!1).describe(`Allow access without authentication`)}));n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable iframe embedding`),allowedOrigins:t.z.array(t.z.string()).optional().describe(`Allowed iframe parent origins (e.g. ["https://example.com"])`),width:t.z.string().optional().default(`100%`).describe(`Embed width (CSS value)`),height:t.z.string().optional().default(`600px`).describe(`Embed height (CSS value)`),showHeader:t.z.boolean().optional().default(!0).describe(`Show interface header in embed`),showNavigation:t.z.boolean().optional().default(!1).describe(`Show navigation in embed`),responsive:t.z.boolean().optional().default(!0).describe(`Enable responsive resizing`)}));var On=t.z.enum([`update`,`delete`,`custom`]),kn=t.z.enum([`perRecord`,`aggregate`]),An=n(()=>t.z.object({name:t.z.string().min(1).describe(`Param key — becomes params[name] in the patch / action params bag.`),label:t.z.string().optional().describe(`Field label in the dialog. Plain string: an authored def is not i18n-resolved (see module header).`),help:t.z.string().optional().describe("Help text under the field. (An ActionParam spells this `helpText` — known divergence, module header.)"),type:St.describe(`Field widget to render, from the standard field-type vocabulary (text/number/select/lookup/date/…).`),required:t.z.boolean().optional().describe(`Blocks the Confirm button until a value is present.`),default:t.z.unknown().optional().describe("Value applied when the dialog opens. (An ActionParam spells this `defaultValue`.)"),options:t.z.array(t.z.object({label:t.z.string().describe(`Option label (plain string — not i18n-resolved on this path).`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Stored value.`)}).passthrough()).optional().describe("Static options for select-style widgets. Each entry is `{ label, value }` plus any extra widget config — the entry is open (`.passthrough()`) because the renderer forwards unknown option keys to the field widget, which reads `color` / `icon` / `disabled` / `visibleWhen` beyond the declared pair."),object:O.optional().describe("Target object for a `lookup` widget. (An ActionParam spells this `reference`.)"),labelField:t.z.string().optional().describe("Related-object field used as the option label for a `lookup` widget (defaults to name/full_name/email/id)."),multiple:t.z.boolean().optional().describe(`Allow picking multiple values — the param value becomes an array and is written to the patch as-is.`),placeholder:t.z.string().optional().describe(`Placeholder text.`)}).passthrough()),jn=w({surface:`this bulk action definition`,knownKeys:[`name`,`label`,`icon`,`variant`,`operation`,`execution`,`patch`,`params`,`confirmText`,`confirmLabel`,`visible`,`maxRecords`,`batchSize`],aliases:{action:`name`,actionname:`name`,title:`label`,op:`operation`,mode:`execution`,confirm:`confirmText`,confirmmessage:`confirmText`,limit:`maxRecords`,max:`maxRecords`,batch:`batchSize`},guidance:{actionDef:"`actionDef` is attached by the renderer, not authored: `resolveBulkActions` looks the action up by `name` and inlines it. Writing it by hand smuggles an action definition past the action registry — no permission gate, no param contract, no lint. Declare the action normally and let this def name it.",bulkEnabled:"`action.bulkEnabled` was retired in spec 17: the selection bar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, which is this array. There is nothing to set.",recordIdParam:"`recordIdParam` belongs on the ACTION, not on the def that names it — a per-record bulk run reuses the action's own declaration, and an `execution: 'aggregate'` run carries the whole selection in `params._selectedIds` instead of a single record id."},history:"Until #4457 the whole array was `z.array(z.record(z.string(), z.any()))` — every key parsed, so a mis-spelled one shipped as a button that silently ran the DEFAULT behaviour (or none at all)."}),Mn=n(()=>t.z.object({name:O.describe(`Stable identifier — the audit-log action key, and (for an aggregate def) the name of the object action to dispatch.`),label:t.z.string().optional().describe("Button + dialog-header text. Plain string: an authored def is not i18n-resolved (declare a real action and name it in `bulkActions` to get localization)."),icon:t.z.string().optional().describe(`Lucide icon name (e.g. "user-check", "trash-2").`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`outline`]).optional().describe(`Visual treatment of the button.`),operation:On.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:kn.optional().describe("For `operation: 'custom'` — 'aggregate' dispatches the named action ONCE for the whole selection, carrying every id in `params._selectedIds` (objectui#3139). Required on a custom def: the per-record form is declared as `bulkActions: ['<name>']` instead."),patch:t.z.record(t.z.string(),t.z.unknown()).optional().describe("For `operation: 'update'` — static field values applied to every selected record, merged UNDER the user-supplied params so a fixed value can be declared without exposing it in the dialog."),params:t.z.array(An).optional().describe(`Inputs collected once before the run. Omit to skip the params step and go straight to confirm.`),confirmText:t.z.string().optional().describe(`Confirmation text shown above the affected-record summary.`),confirmLabel:t.z.string().optional().describe(`Custom Confirm button label (default: "Run").`),visible:k.optional().describe("Eligibility predicate (CEL), same shape as `action.visible`. Evaluated once PER SELECTED RECORD with that record bound: the button is offered when at least one passes, the run covers only those, and the rest are reported as skipped. A record-free predicate (`features.x`, `current_user.y`) therefore behaves as a plain button-level gate. Fail-closed — a predicate that faults excludes the record."),maxRecords:t.z.number().int().positive().optional().describe(`Selection size above which the run is blocked. Set it on defs whose server work is expensive — an aggregate def carries every selected id in one request.`),batchSize:t.z.number().int().positive().optional().describe(`Records per executor batch (default 200). Data-plane operations only — an aggregate run is a single call by definition.`)},{error:jn}).strict().superRefine((e,t)=>{e.operation===`custom`&&e.execution!==`aggregate`&&t.addIssue({code:`custom`,path:[`execution`],message:`Bulk action "${e.name}" declares \`operation: 'custom'\` without \`execution: 'aggregate'\`, which the renderer treats as a no-op \u2014 the button runs, reports success for every selected record, and does nothing. Pick the form you meant: to run the action ONCE PER record, drop this def and name the action in the view's \`bulkActions: ['${e.name}']\` (it is promoted with the action's label, params and \`visible\`); to run it ONCE for the whole selection, add \`execution: 'aggregate'\` (the handler reads \`params._selectedIds\`). For a mass field update or delete, use \`operation: 'update'\` / \`'delete'\` instead.`}),e.execution!==void 0&&e.operation!==`custom`&&t.addIssue({code:`custom`,path:[`execution`],message:`\`execution\` only applies to \`operation: 'custom'\` \u2014 a '${e.operation}' def is a data-plane mass mutation, always batched per record. Remove it, or switch the def to \`operation: 'custom'\` if you meant to dispatch an action.`}),e.patch!==void 0&&e.operation!==`update`&&t.addIssue({code:`custom`,path:[`patch`],message:`\`patch\` only applies to \`operation: 'update'\` \u2014 a '${e.operation}' def never writes fields, so these values are silently dropped. Use \`operation: 'update'\`, or move the constant into the action's own \`bodyExtra\`/\`params\` if this is a custom def.`}),e.params!==void 0&&e.operation===`delete`&&t.addIssue({code:`custom`,path:[`params`],message:"`params` on a `delete` def collects values the executor never reads — a bulk delete takes ids only. Remove them, or use `operation: 'update'` if the dialog is meant to write something."}),e.batchSize!==void 0&&e.execution===`aggregate`&&t.addIssue({code:`custom`,path:[`batchSize`],message:"`batchSize` does not apply to an aggregate def — the whole selection goes out in ONE call by definition, which is the point of `execution: 'aggregate'`. To bound how much a single call may carry, use `maxRecords`."})})),Nn=t.z.enum([`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`]),Pn=n(()=>t.z.enum([`GET`,`POST`,`PUT`,`PATCH`,`DELETE`])),Fn=n(()=>t.z.object({url:t.z.string().describe(`API endpoint URL`),method:Pn.optional().default(`GET`).describe(`HTTP method`),headers:t.z.record(t.z.string(),t.z.string()).optional().describe(`Custom HTTP headers`),params:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Query parameters`),body:t.z.unknown().optional().describe(`Request body for POST/PUT/PATCH`)}));n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable CORS`),origins:t.z.union([t.z.string(),t.z.array(t.z.string())]).default(`*`).describe(`Allowed origins (* for all)`),methods:t.z.array(Nn).optional().describe(`Allowed HTTP methods`),credentials:t.z.boolean().default(!1).describe(`Allow credentials (cookies, authorization headers)`),maxAge:t.z.number().int().optional().describe(`Preflight cache duration in seconds`)})),n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable rate limiting`),windowMs:t.z.number().int().default(6e4).describe(`Time window in milliseconds`),maxRequests:t.z.number().int().default(100).describe(`Max requests per window`)})),n(()=>t.z.object({path:t.z.string().describe(`URL path to serve from`),directory:t.z.string().describe(`Physical directory to serve`),cacheControl:t.z.string().optional().describe(`Cache-Control header value`)}));var P=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,In=n(()=>t.z.discriminatedUnion(`provider`,[t.z.object({provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),t.z.object({provider:t.z.literal(`api`),read:Fn.optional().describe(`Configuration for fetching data`),write:Fn.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),t.z.object({provider:t.z.literal(`value`),items:t.z.array(t.z.unknown()).describe(`Static data array`)}),t.z.object({provider:t.z.literal(`schema`),schemaId:t.z.string().describe(`Schema identifier — typically the metadata type name`),schema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Inline JSON Schema (Draft 2020-12). Optional when schemaId is resolvable.`)})])),Ln=[`equals`,`not_equals`,`contains`,`not_contains`,`starts_with`,`ends_with`,`greater_than`,`less_than`,`greater_than_or_equal`,`less_than_or_equal`,`in`,`not_in`,`is_empty`,`is_not_empty`,`is_null`,`is_not_null`,`before`,`after`,`between`],Rn={eq:`equals`,ne:`not_equals`,neq:`not_equals`,notequals:`not_equals`,notEquals:`not_equals`,notcontains:`not_contains`,notContains:`not_contains`,startswith:`starts_with`,startsWith:`starts_with`,endswith:`ends_with`,endsWith:`ends_with`,gt:`greater_than`,greaterthan:`greater_than`,greaterThan:`greater_than`,lt:`less_than`,lessthan:`less_than`,lessThan:`less_than`,gte:`greater_than_or_equal`,greaterorequal:`greater_than_or_equal`,greaterOrEqual:`greater_than_or_equal`,greaterThanOrEqual:`greater_than_or_equal`,lte:`less_than_or_equal`,lessorequal:`less_than_or_equal`,lessOrEqual:`less_than_or_equal`,lessThanOrEqual:`less_than_or_equal`,nin:`not_in`,notin:`not_in`,notIn:`not_in`,isempty:`is_empty`,isEmpty:`is_empty`,isnotempty:`is_not_empty`,isNotEmpty:`is_not_empty`,isnull:`is_null`,isNull:`is_null`,isnotnull:`is_not_null`,isNotNull:`is_not_null`};function zn(e){return typeof e!=`string`||Ln.includes(e)?e:Rn[e]??Rn[e.toLowerCase()]??e}var Bn=n(()=>T({surface:`this view filter rule`,history:P},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(zn,t.z.enum(Ln)).describe(`Filter operator`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean(),t.z.null(),t.z.array(t.z.union([t.z.string(),t.z.number()]))]).optional().describe(`Filter value`)}).describe(`View filter rule`)),Vn=n(()=>t.z.enum([`none`,`count`,`count_empty`,`count_filled`,`count_unique`,`percent_empty`,`percent_filled`,`sum`,`avg`,`min`,`max`]).describe(`Aggregation function for column footer summary`)),Hn=n(()=>T({surface:`this column summary configuration`,history:P},{type:Vn.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),Un=n(()=>T({surface:`this column prefix`,history:P},{field:t.z.string().describe(`Field whose value renders before the cell value`),type:t.z.enum([`badge`,`text`]).default(`text`).describe(`How the prefix value is rendered`)}).describe(`Compound-cell prefix configuration`)),Wn=n(()=>T({surface:`this list column`,history:P},{field:t.z.string().describe(`Field name (snake_case)`),label:j.optional().describe(`Display label override`),width:t.z.number().positive().optional().describe(`Column width in pixels`),align:t.z.enum([`left`,`center`,`right`]).optional().describe(`Text alignment`),hidden:t.z.boolean().optional().describe(`Hide column by default`),sortable:t.z.boolean().optional().describe(`Allow sorting by this column`),resizable:t.z.boolean().optional().describe(`Allow resizing this column`),wrap:t.z.boolean().optional().describe(`Allow text wrapping`),type:t.z.string().optional().describe(`Renderer type override (e.g., "currency", "date")`),pinned:t.z.enum([`left`,`right`]).optional().describe(`Pin/freeze column to left or right side`),summary:t.z.union([Vn,Hn]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:Un.optional().describe(`Field rendered inline before this cell value`),link:t.z.boolean().optional().describe(`Functions as the primary navigation link (triggers View navigation)`),action:t.z.string().optional().describe(`Registered Action ID to execute when clicked`)})),Gn=n(()=>T({surface:`this selection configuration`,history:P},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),Kn=n(()=>T({surface:`this pagination configuration`,history:P},{pageSize:t.z.number().int().positive().default(25).describe(`Number of records per page`),pageSizeOptions:t.z.array(t.z.number().int().positive()).optional().describe(`Available page size options`)})),qn=n(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),Jn=n(()=>T({surface:`this grouping field`,history:P},{field:t.z.string().describe(`Field name to group by`),order:t.z.enum([`asc`,`desc`]).default(`asc`).describe(`Group sort order`),collapsed:t.z.boolean().default(!1).describe(`Collapse groups by default`)})),Yn=n(()=>T({surface:`this grouping configuration`,history:P},{fields:t.z.array(Jn).min(1).describe(`Fields to group by (supports up to 3 levels)`)}).describe(`Record grouping configuration`)),F=n(()=>T({surface:`this gallery configuration`,history:P},{coverField:t.z.string().optional().describe(`Attachment/image field to display as card cover`),coverFit:t.z.enum([`cover`,`contain`]).default(`cover`).describe(`Image fit mode for card cover`),cardSize:t.z.enum([`small`,`medium`,`large`]).default(`medium`).describe(`Card size in gallery view`),titleField:t.z.string().optional().describe(`Field to display as card title`),visibleFields:t.z.array(t.z.string()).optional().describe(`Fields to display on card body`)}).describe(`Gallery/card view configuration`)),Xn=n(()=>T({surface:`this timeline configuration`,history:P},{startDateField:t.z.string().describe(`Field for timeline item start date`),endDateField:t.z.string().optional().describe(`Field for timeline item end date`),titleField:t.z.string().describe(`Field to display as timeline item title`),groupByField:t.z.string().optional().describe(`Field to group timeline rows`),colorField:t.z.string().optional().describe(`Field to determine item color`),scale:t.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).default(`week`).describe(`Default timeline scale`)}).describe(`Timeline view configuration`)),Zn=n(()=>T({surface:`this view sharing`,history:P},{type:t.z.enum([`personal`,`collaborative`]).default(`collaborative`).describe(`View ownership type`),lockedBy:t.z.string().optional().describe(`User who locked the view configuration`)}).describe(`View sharing and access configuration`)),Qn=n(()=>T({surface:`this row color configuration`,history:P},{field:t.z.string().describe(`Field to derive color from (typically a select/status field)`),colors:t.z.record(t.z.string(),t.z.string()).optional().describe(`Map of field value to color (hex/token)`)}).describe(`Row color configuration based on field values`)),$n=n(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),I=n(()=>T({surface:`this user actions configuration`,history:P},{sort:t.z.boolean().default(!0).describe(`Allow users to sort records`),search:t.z.boolean().default(!0).describe(`Allow users to search records`),filter:t.z.boolean().default(!0).describe(`Allow users to filter records`),refresh:t.z.boolean().default(!0).describe(`Allow users to reload the view data from the backend without a full page reload`),rowHeight:t.z.boolean().default(!0).describe(`Allow users to toggle row height/density`),addRecordForm:t.z.boolean().default(!1).describe(`Add records through a form instead of inline`),editInline:t.z.boolean().default(!1).describe(`Allow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in.`),buttons:t.z.array(t.z.string()).optional().describe(`Custom action button IDs to show in the toolbar`)}).describe(`User action toggles for the view toolbar`)),er=n(()=>T({surface:`this appearance configuration`,history:P},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array($n).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),tr=n(()=>T({surface:`this view tab`,history:P},{name:O.describe(`Tab identifier (snake_case)`),label:j.optional().describe(`Display label`),icon:t.z.string().optional().describe(`Tab icon name`),view:t.z.string().optional().describe(`Referenced list view name from listViews`),filter:t.z.array(Bn).optional().describe(`Tab-specific filter criteria`),order:t.z.number().int().min(0).optional().describe(`Tab display order`),pinned:t.z.boolean().default(!1).describe(`Pin tab (cannot be removed by users)`),isDefault:t.z.boolean().default(!1).describe(`Set as the default active tab`),visible:t.z.boolean().default(!0).describe(`Tab visibility`)}).describe(`Tab configuration for multi-tab view interface`)),nr=n(()=>T({surface:`this user filter field`,history:P},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:j.optional().describe(`Display label override (defaults to the field label)`),type:t.z.enum([`select`,`multi-select`,`boolean`,`date-range`,`text`]).optional().describe(`Filter control type. Omit to infer from the field definition`),options:t.z.array(t.z.object({value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Option value`),label:j.describe(`Option label`),color:t.z.string().optional().describe(`Option color token/hex`)})).optional().describe(`Static options. Omit to derive from the field definition (select options / lookup records)`),showCount:t.z.boolean().optional().describe(`Show per-option record counts`),defaultValues:t.z.array(t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Pre-selected values when the view loads`)}).describe(`Quick-filter field configuration`)),rr=n(()=>t.z.object({element:t.z.enum([`dropdown`,`tabs`,`toggle`]).default(`dropdown`).describe(`Filter control style: "dropdown" (per-field value selectors) or "tabs" (named presets). "toggle" is deprecated.`),fields:t.z.array(nr).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(tr).optional().describe(`Named filter presets rendered as tabs (tabs element). Reuses ViewTabSchema`),showAllRecords:t.z.boolean().optional().describe(`Show an "All records" tab before the presets (tabs element)`)}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),ir=n(()=>T({surface:`this add record configuration`,history:P},{enabled:t.z.boolean().default(!0).describe(`Show the add record entry point`),position:t.z.enum([`top`,`bottom`,`both`]).default(`bottom`).describe(`Position of the add record button`),mode:t.z.enum([`inline`,`form`,`modal`]).default(`inline`).describe(`How to add a new record`),formView:t.z.string().optional().describe(`Named form view to use when mode is "form" or "modal"`)}).describe(`Add record entry point configuration`)),ar=n(()=>T({surface:`this kanban configuration`,history:P},{groupByField:t.z.string().describe(`Field to group columns by (usually status/select)`),summarizeField:t.z.string().optional().describe(`Field to sum at top of column (e.g. amount)`),columns:t.z.array(t.z.string()).describe(`Fields to show on cards`)})),or=n(()=>T({surface:`this list chart configuration`,history:P},{chartType:bn.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:O.describe(`Dataset name to bind (ADR-0021)`),dimensions:t.z.array(t.z.string()).optional().describe(`Dimension names — X/group/split`),values:t.z.array(t.z.string()).min(1).describe(`Measure names — Y (at least one)`)}).describe(`List chart view configuration`)),sr=n(()=>T({surface:`this calendar configuration`,history:P},{startDateField:t.z.string().describe(`Field providing the event start date/time`),endDateField:t.z.string().optional().describe(`Field providing the event end date/time (defaults to a single-day event)`),titleField:t.z.string().describe(`Field displayed as the event title`),colorField:t.z.string().optional().describe(`Field whose value determines the event color`)})),cr=n(()=>T({surface:`this gantt quick filter`,history:P},{field:t.z.string().describe(`Record field / dot-path the dimension filters on`),label:t.z.string().optional().describe(`Trigger label (falls back to the field label)`),options:t.z.array(t.z.union([t.z.string(),t.z.object({value:t.z.union([t.z.string(),t.z.number()]),label:t.z.string().optional()})])).optional().describe(`Explicit option override for fixed enums`)})),lr=n(()=>T({surface:`this gantt configuration`,history:P},{startDateField:t.z.string().describe(`Field providing the task start date`),endDateField:t.z.string().describe(`Field providing the task end date`),titleField:t.z.string().describe(`Field displayed as the task title`),progressField:t.z.string().optional().describe(`Field providing the task completion percentage`),dependenciesField:t.z.string().optional().describe(`Field listing the task's predecessor (dependency) record ids`),colorField:t.z.string().optional().describe(`Field that drives the bar color`),parentField:t.z.string().optional().describe(`Field holding the parent task id (builds the summary → step tree)`),typeField:t.z.string().optional().describe(`Field whose value maps to task/summary/milestone`),baselineStartField:t.z.string().optional().describe(`Baseline (planned) start field`),baselineEndField:t.z.string().optional().describe(`Baseline (planned) end field`),groupByField:t.z.string().optional().describe(`Field to group leaf tasks by (synthesized summary rows)`),resourceView:t.z.boolean().optional().describe(`Render a per-resource workload histogram instead of the timeline`),assigneeField:t.z.string().optional().describe(`Resource field to bucket load by (resource view)`),effortField:t.z.string().optional().describe(`Per-task load units (resource view; default 1)`),capacity:t.z.number().optional().describe(`Per-resource capacity ceiling; loads above this flag overload`),tooltipFields:t.z.array(t.z.union([t.z.string(),t.z.object({field:t.z.string(),label:t.z.string().optional()})])).optional().describe(`Fields to surface in the hover tooltip, in display order`),quickFilters:t.z.array(cr).optional().describe(`Multi-select filter dropdowns rendered above the chart`),autoZoomToFilter:t.z.boolean().optional().describe(`When true (default), filtering zooms the range to the filtered tasks`)}).passthrough()),ur=n(()=>T({surface:`this tree configuration`,history:P},{parentField:t.z.string().optional().describe(`Single-parent pointer field (auto-detected from the object schema when omitted)`),labelField:t.z.string().optional().describe(`Field rendered indented in the first column (defaults to "name")`),fields:t.z.array(t.z.string()).optional().describe(`Additional fields rendered as flat columns alongside the label`),defaultExpandedDepth:t.z.number().int().min(0).optional().describe(`Initial expansion depth (0 = roots only; omit = expand all)`)}).passthrough()),dr=n(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),fr=n(()=>T({surface:`this navigation configuration`,history:P},{mode:dr.default(`page`),view:t.z.string().optional().describe(`Name of the form view to use for details (e.g. "summary_view", "edit_form")`),preventNavigation:t.z.boolean().default(!1).describe(`Disable standard navigation entirely`),openNewTab:t.z.boolean().default(!1).describe(`Force open in new tab (applies to page mode)`),size:t.z.enum([`auto`,`sm`,`md`,`lg`,`xl`,`full`]).default(`auto`).describe("[#2578] Overlay size bucket for drawer/modal detail: 'auto' (default — renderer derives from field count + viewport; AI writes nothing) or a coarse override sm/md/lg/xl/full. Prefer this over the pixel `width`; page mode ignores it."),width:t.z.union([t.z.string(),t.z.number()]).optional().describe('[DEPRECATED → size] Pixel/percent width of the drawer/modal (e.g. "600px"). A pixel width cannot be chosen at authoring time without knowing the client viewport — use the `size` bucket.')})),L=n(()=>T({surface:`this list view`,history:P},{name:O.optional().describe(`Internal view name (lowercase snake_case)`),label:j.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:In.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(Wn)]).describe(`Fields to display as columns`),filter:t.z.array(Bn).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(t.z.object({field:t.z.string(),order:t.z.enum([`asc`,`desc`])}))]).optional(),searchableFields:t.z.array(t.z.string()).optional().describe(`Fields enabled for search`),filterableFields:t.z.array(t.z.string()).optional().describe(`Legacy shorthand for userFilters.fields — bare field names enabled for end-user filtering. Prefer userFilters`),userFilters:rr.optional().describe(`End-user quick-filter bar: dropdown/toggle fields or tab presets. Omit to let the renderer derive filters from select/boolean fields`),resizable:t.z.boolean().optional().describe(`Enable column resizing`),striped:t.z.boolean().optional().describe(`Striped row styling`),bordered:t.z.boolean().optional().describe(`Show borders`),compactToolbar:t.z.boolean().optional().describe(`Collapse Group/Color/Density/Hide-fields into a single View settings popover`),selection:Gn.optional().describe(`Row selection configuration`),navigation:fr.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:Kn.optional().describe(`Pagination configuration`),kanban:ar.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:sr.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:lr.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:F.optional(),timeline:Xn.optional(),chart:or.optional(),tree:ur.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:j.optional().describe(`View description for documentation/tooltips`),sharing:Zn.optional().describe(`View sharing and access configuration`),rowHeight:qn.optional().describe(`Row height / density setting`),grouping:Yn.optional().describe(`Group records by one or more fields`),rowColor:Qn.optional().describe(`Color rows based on field value`),hiddenFields:t.z.array(t.z.string()).optional().describe(`Fields to hide in this specific view`),fieldOrder:t.z.array(t.z.string()).optional().describe(`Explicit field display order for this view`),rowActions:t.z.array(t.z.string()).optional().describe(`Actions available for individual row items`),bulkActions:t.z.array(t.z.string()).optional().describe(`Actions available when multiple rows are selected`),bulkActionDefs:t.z.array(Mn).optional().describe("Rich bulk action definitions (schema-driven, executed via BulkActionDialog). Use a def for a mass data-plane mutation ('update' with a `patch` / 'delete') that no action expresses, or for an `operation: 'custom'` + `execution: 'aggregate'` entry (objectui#3139) that dispatches the action it NAMES once for the whole selection — the renderer injects `params._selectedIds: string[]` (read that on the server, not `recordId`) so a single call can produce one aggregate artifact (zip of QR codes, merged PDF, batch print). Aggregate results are all-or-nothing: a handler that cannot cover the whole selection must reject, and per-row retry is replaced by re-running the action. `batchSize` does not apply (the call is never chunked); set `maxRecords` on defs whose server work is expensive. For the PER-RECORD dispatch use `bulkActions: ['<name>']` instead — the bare-string form, promoted with the action's own label, params and `visible`; a 'custom' def without `execution: 'aggregate'` has no dispatcher and is refused at parse time (#4457). Toolbar url/api actions can also interpolate the current selection via `${ctx.selection.ids}` / `${ctx.selection.count}`."),virtualScroll:t.z.boolean().optional().describe(`Enable virtual scrolling for large datasets`),conditionalFormatting:t.z.array(t.z.object({condition:k.describe(`Predicate (CEL) to evaluate.`),style:t.z.record(t.z.string(),t.z.string()).describe(`CSS styles to apply when condition is true`)})).optional().describe(`Conditional formatting rules for list rows`),inlineEdit:t.z.boolean().optional().describe(`Allow inline editing of records directly in the list view`),exportOptions:t.z.array(t.z.enum([`csv`,`xlsx`,`pdf`,`json`])).optional().describe(`Available export format options`),userActions:I.optional().describe(`User action toggles for the view toolbar`),appearance:er.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(tr).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:ir.optional().describe(`Add record entry point configuration`),showRecordCount:t.z.boolean().optional().describe(`Show record count at the bottom of the list`),allowPrinting:t.z.boolean().optional().describe(`Allow users to print the view`),emptyState:t.z.object({title:j.optional(),message:j.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:Ut.optional().describe(`ARIA accessibility attributes for the list view`),responsive:v("`view.responsive` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer ever read it; the grid is responsive by its own layout rules. Delete the key."),performance:v("`view.performance` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer or runtime read it; list-view performance tuning was never implemented. Delete the key.")})),pr=n(()=>t.z.object({field:t.z.string().describe(`Field name (snake_case)`),type:St.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(wt).optional().describe(`Options for select/multiselect/radio/checkboxes fields`),reference:t.z.string().optional().describe(`Target object name for lookup/master_detail fields`),maxLength:t.z.number().optional().describe(`Maximum character length (for text/textarea/email/url/phone)`),minLength:t.z.number().optional().describe(`Minimum character length`),min:t.z.number().optional().describe(`Minimum value (for number/currency/percent/slider)`),max:t.z.number().optional().describe(`Maximum value`),precision:t.z.number().optional().describe(`Total digits (for number/currency)`),scale:t.z.number().optional().describe(`Decimal places`),multiple:t.z.boolean().optional().describe(`Allow multiple values (for select/lookup/file/image)`),label:j.optional().describe(`Display label override`),placeholder:j.optional().describe(`Placeholder text`),helpText:j.optional().describe(`Help/hint text`),readonly:t.z.boolean().optional().describe(`Read-only override`),immutable:t.z.boolean().optional().describe(`Editable on create, locked once the record exists (e.g. machine names).`),required:t.z.boolean().optional().describe(`Required override`),hidden:t.z.boolean().optional().describe(`Hidden override`),colSpan:t.z.number().int().min(1).max(4).optional().describe("[legacy — prefer `span`] Absolute column span (1-4). Fragile when the column count is derived per surface (mobile 1 / modal 2 / page 3-4): a fixed span only lines up at the width the author imagined. The renderer clamps it to the current column count. Prefer `span`."),span:t.z.enum([`auto`,`full`]).default(`auto`).describe("Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count (wide widgets like textarea/richtext/json/file/subform take the whole row). 'full': whole row at any column count. Prefer this over the absolute `colSpan`."),widget:t.z.string().optional().describe(`Custom widget/component name (overrides type-based inference)`),language:t.z.string().optional().describe(`Code editor language (for type=code)`),keyField:t.z.object({field:t.z.string().default(`name`).describe(`Property name that holds the key inside each item (defaults to "name")`),label:j.optional().describe(`Display label for the key column`),placeholder:j.optional().describe(`Placeholder when entering a new key`),helpText:j.optional().describe(`Help text under the key input`),regex:t.z.string().optional().describe(`JS regex source string the key must match (no flags)`),immutable:t.z.boolean().default(!0).describe(`If true, the key is read-only after creation`)}).optional().describe(`Key column config for record-typed fields`),dependsOn:t.z.string().optional().describe(`Parent field name for cascading`),visibleWhen:k.optional().describe("Visibility predicate (CEL) — field shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms). e.g. P`record.priority == 'urgent'`"),visibleOn:k.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Normalized to `visibleWhen` at parse."),disclosure:t.z.enum([`inline`,`popover`]).optional().describe(`Composite rendering: inline bordered box (default) or a summary line + gear popover (progressive disclosure).`)},{error:yn})),R=n(()=>pr.extend({fields:t.z.array(t.z.lazy(()=>R)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(_n)),mr=n(()=>t.z.object({name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:j.optional(),description:t.z.string().optional().describe(`Optional description rendered under the section header.`),collapsible:t.z.boolean().default(!1),collapsed:t.z.boolean().default(!1),visibleWhen:k.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms)."),visibleOn:k.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Hides the whole section when false. Normalized to `visibleWhen` at parse."),columns:t.z.union([t.z.enum([`1`,`2`,`3`,`4`]),t.z.literal(1),t.z.literal(2),t.z.literal(3),t.z.literal(4)]).default(1).transform(e=>typeof e==`string`?parseInt(e):e),pane:t.z.enum([`primary`,`secondary`]).optional().describe(`Split pane this section renders in (split forms only; a parse error elsewhere). Omitted → first section 'primary', others 'secondary'.`),fields:t.z.array(t.z.union([t.z.string(),R]))},{error:yn}).strict().transform(_n)),hr=n(()=>T({surface:`this form button configuration`,history:P},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:j.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict()),gr=n(()=>T({surface:`this form view`,history:P},{type:t.z.enum([`simple`,`tabbed`,`wizard`,`split`,`drawer`,`modal`]).default(`simple`),layout:t.z.enum([`vertical`,`horizontal`,`inline`,`grid`]).optional().describe(`Field layout direction`),columns:t.z.number().int().min(1).optional().describe(`Number of columns for the form body`),title:t.z.string().optional().describe(`Form title`),description:t.z.string().optional().describe(`Form description`),defaultTab:t.z.string().optional().describe(`Initially active tab (tabbed forms)`),tabPosition:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Tab strip position (tabbed forms)`),allowSkip:t.z.boolean().optional().describe(`Allow skipping steps (wizard forms)`),showStepIndicator:t.z.boolean().optional().describe(`Show the step indicator (wizard forms)`),splitDirection:t.z.enum([`horizontal`,`vertical`]).optional().describe(`Split orientation (split forms)`),splitSize:t.z.number().optional().describe(`Primary split panel size, % (split forms)`),splitResizable:t.z.boolean().optional().describe(`Whether the split is resizable (split forms)`),drawerSide:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Drawer side (drawer forms)`),drawerWidth:t.z.string().optional().describe(`[DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it.`),modalSize:t.z.enum([`sm`,`default`,`lg`,`xl`,`full`]).optional().describe(`Modal size (modal forms)`),data:In.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(mr).optional(),groups:t.z.array(mr).optional(),subforms:t.z.array(t.z.object({childObject:t.z.string().describe(`Child object whose records are entered inline`),relationshipField:t.z.string().optional().describe(`FK on the child pointing back to the parent (auto-detected when omitted)`),columns:t.z.array(t.z.any()).optional().describe(`Editable grid columns (derived from the child object when omitted)`),amountField:t.z.string().optional().describe(`Numeric child column summed for the running total`),totalField:t.z.string().optional().describe(`Parent field to receive the rolled-up sum`),title:t.z.string().optional().describe(`Section title`),addLabel:t.z.string().optional().describe(`Add-row button label`),minRows:t.z.number().optional(),maxRows:t.z.number().optional()})).optional().describe(`Inline master-detail child collections`),defaultSort:v("`form.defaultSort` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — nothing read it: a related list inside a form sorts by its own list view's `sort`. Delete the key and set the sort on the related list view instead."),sharing:Dn.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.union([t.z.object({kind:t.z.literal(`thank-you`),title:t.z.string().optional(),message:t.z.string().optional()}),t.z.object({kind:t.z.literal(`redirect`),url:t.z.string(),delayMs:t.z.number().int().min(0).optional()}),t.z.object({kind:t.z.literal(`continue`)}),t.z.object({kind:t.z.literal(`next-record`)})]).optional().describe(`Post-submit behavior`),buttons:t.z.object({submit:hr.optional().describe(`Submit button`),cancel:hr.optional().describe(`Cancel button`),reset:hr.optional().describe(`Reset button`)}).strict().optional().describe(`Form action-button visibility & labels; folded onto the flat renderer props by ObjectUI ObjectForm (framework#1894 / #2998).`),defaults:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Initial field values for create-mode forms (folded into ObjectUI ObjectForm initial values; framework#1894 / #2998).`),aria:v("`form.aria` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no form renderer ever applied it, so declared ARIA attributes silently did not reach the DOM. Delete the key. The form renderer emits its own semantic markup; report gaps as renderer issues rather than per-view attribute overrides.")}).superRefine((e,t)=>{if(e.type!==`split`)for(let[n,r]of[[`sections`,e.sections],[`groups`,e.groups]])r?.forEach((r,i)=>{r?.pane!=null&&t.addIssue({code:`custom`,path:[n,i,`pane`],message:`\`pane\` places a section in a split pane and is only valid on \`type: 'split'\` form views (this form is '${e.type}'). Remove the key or change the form type.`})})})),z=n(()=>rr.omit({tabs:!0,showAllRecords:!0}).extend({element:t.z.enum([`dropdown`,`toggle`]).default(`dropdown`).describe('Filter control style on object views: "dropdown" (per-field value chips). "toggle" is deprecated. "tabs" is page-only — use `listViews` for named presets.')})),_r=n(()=>L.omit({userFilters:!0}).extend({userFilters:z.optional()})),vr=n(()=>T({surface:`this view container`,history:P,guidance:Object.fromEntries([`type`,`columns`,`data`,`viewKind`,`filters`,`sort`].map(e=>[e,`\`${e}\` belongs to a single VIEW, not to the container. Wrap it: \`defineView({ list: { type, data, columns, \u2026 } })\`, or name it \u2014 \`defineView({ listViews: { my_view: { \u2026 } } })\`. The container's own keys are \`list\`, \`form\`, \`listViews\`, \`formViews\`.`]))},{name:t.z.string().optional().describe(`Item name — supplied by the metadata door; for an object-scoped container it is the object name.`),label:j.optional().describe(`Human-readable label shown in metadata lists.`),object:t.z.string().optional().describe("Object this container binds to — how a stack-level `views: [...]` entry says which object its views belong to; read by `getViewsByObject()` / `GET /meta/view?object=`."),list:_r.optional(),form:gr.optional(),listViews:t.z.record(t.z.string(),_r).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),gr).optional().describe(`Additional named form views`),protection:gn.optional().describe(`Package author protection block — lock policy for this view.`),...D})),yr=t.z.string().regex(/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/,`View item name must be a dotted snake_case qualified name, e.g. "crm_lead.pipeline".`).describe("Globally-unique view id, `<object>.<viewKey>`."),br=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),xr=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function Sr(){return{name:yr,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:j.optional().describe(`Display label (supports i18n).`),isDefault:t.z.boolean().optional().describe(`Whether this is the object's default view in the switcher.`),order:t.z.number().int().optional().describe(`Sort order within the object's view switcher / left rail.`),scope:br.optional().describe("Identity layer (defaults to `package` for source-loaded views)."),owner:t.z.string().optional().describe("Owner user id — set when `scope` is `personal`."),hidden:t.z.boolean().optional().describe(`Hidden from the switcher (per-user / per-org declutter).`),protection:gn.optional().describe(`Package author protection block — lock policy for this view.`),...D}}var Cr=n(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({viewKind:t.z.literal(`list`),config:L.describe(`List-family view configuration.`),...Sr()}),t.z.object({viewKind:t.z.literal(`form`),config:gr.describe(`Form view configuration.`),...Sr()})]));function wr(){return{name:t.z.string().optional().describe(`Save name / qualified view id (stamped by the write path).`),object:t.z.string().optional().describe(`Bound object name (inherited from the shadowed entry — #2555).`),viewKind:xr.optional().describe(`View family (inherited from the shadowed entry — #2555).`),label:j.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:br.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:gn.optional(),...D,config:t.z.undefined().optional(),list:t.z.undefined().optional(),form:t.z.undefined().optional(),listViews:t.z.undefined().optional(),formViews:t.z.undefined().optional()}}function Tr(e){if(!e||typeof e!=`object`)return!1;let t=e;return!!(t.list||t.form||t.listViews&&typeof t.listViews==`object`&&Object.keys(t.listViews).length>0||t.formViews&&typeof t.formViews==`object`&&Object.keys(t.formViews).length>0)}n(()=>t.z.union([Cr,vr.refine(Tr,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."}),L.extend(wr()).strip(),gr.extend(wr()).strip()]));function Er(e){let{schemaId:t,...n}=e;return gr.parse({...n,data:{provider:`schema`,schemaId:t}})}var Dr=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),Or=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],kr={upsert:"declare ['create','update'] — `upsert` derives from create ∧ update",aggregate:"declare ['list'] — `aggregate` derives from list",history:"declare ['get'] with `enable.trackHistory: true` — `history` derives from get ∧ trackHistory",search:"declare ['list'] (with `searchable` not false) — `search` derives from list ∧ searchable",restore:"delete the value — `restore` never derives (`enable.trash` retired, #2377); it returns only with a real recycle bin (#3146, parked)",purge:"delete the value — `purge` never derives (`enable.trash` retired, #2377)",import:"declare ['create'] and/or ['update'] — `import` derives from create ∨ update (writeMode-precise at the gate)",export:"declare ['list'] — `export` derives from list"},Ar=[`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],jr=t.z.enum(Ar),Mr=new Set(Or),B=new Set;function Nr(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&Mr.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&Mr.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return B.has(i)||(B.add(i),(t?.warn??(e=>console.warn(e)))(`[spec] enable.apiMethods declares retired legacy value(s) [${n.join(`, `)}] \u2014 the ApiMethod enum is the six primitives get/list/create/update/delete/bulk (#3543). Legacy values are stripped at parse; their semantics are DERIVED from the primitives:
4
4
  `+n.map(e=>` \u2022 \`${e}\`: ${kr[e]}`).join(`
5
5
  `)+(r.length===0?"\n ⚠ After stripping, this whitelist is EMPTY — `[]` means DENY-ALL (fully closed API). Declare the underlying primitives if the object should stay reachable.":``)+`
6
6
  Codemod: node scripts/codemod/apimethods-legacy-to-primitives.mjs`)),r}var Pr={trash:"`enable.trash` was removed from @objectstack/spec in the 16.x line (#2377/#3207, ADR-0049) — it never had a runtime consumer: every delete has always been a hard delete, and a default-true flag promising a recycle bin was a false affordance (authors wrote `trash: false` believing they were opting out of a soft-delete that never ran). Delete the key. For recoverability use per-field `trackHistory` (audit trail) or a `lifecycle` policy; soft delete is parked at #3146 and, if built, returns as a live enforced flag (ADR-0049 prune-or-build). Run `os migrate meta --from 16` to rewrite it automatically.",mru:"`enable.mru` was removed from @objectstack/spec in the 16.x line (#2377/#3207, ADR-0049) — Most-Recently-Used tracking was never implemented; no reader existed, so the flag changed nothing. Delete the key. If MRU tracking is built it returns as a live enforced flag (ADR-0049 prune-or-build). Run `os migrate meta --from 16` to rewrite it automatically."},Fr=t.z.object({trackHistory:t.z.boolean().default(!1).describe(`Show the record History tab (audit-trail UI). Pair with per-field trackHistory to pick which field diffs are summarized; audit capture itself is always on for compliance`),searchable:t.z.boolean().default(!0).describe(`Index records for global search`),apiEnabled:t.z.boolean().default(!0).describe(`Expose object via automatic APIs`),apiMethods:t.z.preprocess(e=>Nr(e),t.z.array(Dr)).optional().describe(`Whitelist of allowed API operations (six primitives; undefined = all, [] = none)`),files:t.z.boolean().default(!1).describe(`Generic record Attachments panel (sys_attachment). Opt-in: true surfaces the panel and permits attachments targeting this object; otherwise creation is rejected. Field.file/Field.image are independent`),feeds:t.z.boolean().default(!0).describe(`Record comments/collaboration feed. Default on; explicit false hides the feed UI and rejects new comments for this object`),activities:t.z.boolean().default(!0).describe(`Record activity timeline (sys_activity mirror of CRUD). Default on; explicit false stops mirroring and hides the timeline`),clone:t.z.boolean().default(!0).describe(`Allow record deep cloning`)},{error:e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=t.map(e=>Pr[e]??`\`${e}\` is not an \`enable\` capability flag.`);return`Unrecognized key(s) on \`enable\`: ${t.map(e=>`\`${e}\``).join(`, `)}.
@@ -15,7 +15,7 @@ ${i.join(`
15
15
 
16
16
  Remove the unknown key(s), fix the typo, or move the logic to a supported mechanism.`)}var ai=new Set;function oi(e,t,n){if(n===`better-auth`||!t||typeof t!=`object`)return;let r=Object.entries(t).filter(([,e])=>e&&e.type===`password`&&e.ackPlaintextMasking!==!0).map(([e])=>e);if(r.length===0)return;let i=typeof e==`string`&&e.length>0?e:`<unnamed>`;ai.has(i)||(ai.add(i),console.warn(`ObjectSchema.create('${i}'): field(s) ${r.map(e=>`\`${e}\``).join(`, `)} use type 'password' on a non-auth object. The generic CRUD path stores a password field as plaintext at rest and masks it to \u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022 on read (ADR-0100) \u2014 it is NOT one-way hashed (that is owned by the auth subsystem, for its identity tables only). Use \`Field.secret(...)\` for reversible machine credentials, or model login credentials on the auth user object. If this is intended, the masking contract applies \u2014 affirm it with \`ackPlaintextMasking: true\` on the field to silence this warning.`))}function si(e,t,n){if(t!==`system-data`)return;let r=fi({managedBy:t,userActions:n});if(r.create||r.edit||r.delete)return;let i=typeof e==`string`&&e.length>0?e:`<unnamed>`;throw Error(`ObjectSchema.create('${i}'): \`managedBy: 'system-data'\` declares "platform-defined schema, admin/user-writable DATA", but this object's resolved affordances grant no create, edit or delete \u2014 so nothing about it is user-writable and the bucket name is false. Use \`managedBy: 'engine-owned'\` for rows a platform service owns end to end (written via \`isSystem\` / a service SYSTEM_CTX), or \`append-only\` for an immutable audit log. If the object IS user-writable, drop the \`userActions\` entries closing create/edit/delete \u2014 the \`system-data\` default is full CRUD, and \`userActions\` is for NARROWING only (#3355).`)}function ci(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e;return t.nameField==null&&typeof t.displayNameField==`string`?{...t,nameField:t.displayNameField}:e}function li(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e,n=t;if(Array.isArray(t.fieldGroups)){let e=!1,r=t.fieldGroups.map(t=>{if(!t||typeof t!=`object`||Array.isArray(t))return t;let n=t;if(n.collapse!=null)return t;let r;return typeof n.collapsible==`boolean`||typeof n.collapsed==`boolean`?r=n.collapsed===!0?`collapsed`:n.collapsible===!0?`expanded`:`none`:typeof n.defaultExpanded==`boolean`&&(r=n.defaultExpanded?`expanded`:`collapsed`),r===void 0?t:(e=!0,{...n,collapse:r})});e&&(n={...n,fieldGroups:r})}return n}var ui=n(()=>{let e=V.parse.bind(V),t=V.safeParse.bind(V);return Object.assign(V,{parse(t,n){return e(li(ci(t)),n)},safeParse(e,n){return t(li(ci(e)),n)},create:e=>{let t=e,n=Object.keys(V.shape),r=Object.keys(t).filter(e=>!n.includes(e));if(r.length>0)throw ii(t.name,r,n);oi(t.name,t.fields,t.managedBy),si(t.name,t.managedBy,t.userActions);let i={...t,label:t.label??ei(t.name)};return V.parse(i)}})}),di={platform:{create:!0,import:!0,edit:!0,delete:!0,exportCsv:!0},config:{create:!0,import:!1,edit:!0,delete:!0,exportCsv:!0},"system-data":{create:!0,import:!0,edit:!0,delete:!0,exportCsv:!0},"engine-owned":{create:!1,import:!1,edit:!1,delete:!1,exportCsv:!0},"append-only":{create:!1,import:!1,edit:!1,delete:!1,exportCsv:!0},"better-auth":{create:!1,import:!1,edit:!1,delete:!1,exportCsv:!0}};function fi(e){let t=di[e?.managedBy??`platform`]??di.platform,n=e?.userActions??{},r=pi(n.edit,t.edit),i=pi(n.delete,t.delete),a={create:n.create??t.create,import:n.import??t.import,edit:r.enabled,delete:i.enabled,exportCsv:n.exportCsv??t.exportCsv};return r.predicates&&(a.editPredicates=r.predicates),i.predicates&&(a.deletePredicates=i.predicates),a}function pi(e,t){if(e==null)return{enabled:t};if(typeof e==`boolean`)return{enabled:e};let n=e.enabled??t,r=e.visibleWhen,i=e.disabledWhen;if(r==null&&i==null)return{enabled:n};let a={};return r!=null&&(a.visibleWhen=r),i!=null&&(a.disabledWhen=i),{enabled:n,predicates:a}}var mi=t.z.enum([`own`,`extend`]),hi=n(()=>t.z.object({extend:t.z.string().describe(`Target object name (FQN) to extend`),fields:t.z.record(t.z.string(),Nt).optional().describe(`Fields to add/override`),label:t.z.string().optional().describe(`Override label for the extended object`),pluralLabel:t.z.string().optional().describe(`Override plural label for the extended object`),description:t.z.string().optional().describe(`Override description for the extended object`),validations:t.z.array(Vt).optional().describe(`Additional validation rules to merge into the target object`),indexes:t.z.array(Ir).optional().describe(`Additional indexes to merge into the target object`),priority:t.z.number().int().min(0).max(999).default(200).describe(`Merge priority (higher = applied later)`)}));function gi(e){return hi.parse(e)}var _i=[`get`,`list`,`create`,`update`,`delete`,`bulk`],vi=Ar,yi=new Set(_i),bi=new Set(Or);function xi(e){return yi.has(e)}function Si(e){return bi.has(e)}var Ci={upsert:{all:[`create`,`update`]},import:{any:[`create`,`update`]},export:{all:[`list`]},aggregate:{all:[`list`]},search:{all:[`list`],flag:e=>e.searchable!==!1},history:{all:[`get`],flag:e=>e.trackHistory===!0},restore:{all:[`delete`],flag:()=>!1},purge:{all:[`delete`],flag:()=>!1}},wi={get:`get`,query:`list`,find:`list`,list:`list`,create:`create`,update:`update`,delete:`delete`,batch:`bulk`,bulk:`bulk`,upsert:`upsert`,aggregate:`aggregate`,history:`history`,search:`search`,restore:`restore`,purge:`purge`,import:`import`,export:`export`};function Ti(e,t,n,r){let i=Ci[e];return i.flag&&!i.flag(n)||e===`export`&&!r?!1:i.all?i.all.every(e=>t.has(e)):i.any?i.any.some(e=>t.has(e)):!1}function Ei(e,t,n,r){let i=new Set;if(e===`deny-all`)return i;for(let e of t)i.add(e);for(let e of Or)Ti(e,t,n,r)&&i.add(e);return i}function Di(e,t){let n=t?.userExportAllowed!==!1,r=e??{},i=r.apiMethods;if(i==null){let e=new Set(_i);return{mode:`unrestricted`,primitives:e,operations:Ei(`unrestricted`,e,r,n),userExportAllowed:n}}let a=Array.isArray(i)?new Set(i.map(e=>String(e)).filter(xi)):new Set;return a.size===0?{mode:`deny-all`,primitives:new Set,operations:new Set,userExportAllowed:n}:{mode:`restricted`,primitives:a,operations:Ei(`restricted`,a,r,n),userExportAllowed:n}}function Oi(e,t,n){if(e.mode===`deny-all`)return!1;let r=e.mode===`unrestricted`;if(t===`bulk`&&n?.bulkChild)return!r&&!e.primitives.has(`bulk`)?!1:Oi(e,n.bulkChild,{writeMode:n.writeMode});if(xi(t))return r||e.primitives.has(t);if(Si(t)){if(t===`import`&&n?.writeMode&&!r){let t=n.writeMode;if(t===`insert`)return e.primitives.has(`create`);if(t===`update`)return e.primitives.has(`update`);if(t===`upsert`)return e.primitives.has(`create`)&&e.primitives.has(`update`)}return e.operations.has(t)}return!0}function ki(e){return Ar.filter(t=>e.operations.has(t))}var Ai={USER:`sys_user`},ji=new Set([`text`,`textarea`,`email`,`url`,`phone`,`password`,`secret`,`markdown`,`html`,`richtext`,`code`,`color`,`signature`,`qrcode`]),Mi=new Set([`number`,`currency`,`percent`,`rating`,`slider`,`progress`,`summary`]),Ni=new Set([`boolean`,`toggle`]),Pi=new Set([`date`]),Fi=new Set([`datetime`]),Ii=new Set([`time`]),Li=new Set([`select`,`radio`]),Ri=new Set([`multiselect`,`checkboxes`,`tags`]),zi=new Set([`lookup`,`master_detail`,`user`,`tree`]),Bi=new Map([[`user`,Ai.USER]]);function Vi(e){if(!e||typeof e!=`object`)return;let{type:t,reference:n}=e;if(!(typeof t!=`string`||!zi.has(t)))return typeof n==`string`&&n?n:Bi.get(t)}var Hi=new Set([`image`,`file`,`avatar`,`video`,`audio`]);function Ui(e){return typeof e==`string`&&/^[A-Za-z0-9_-]{1,64}$/.test(e)}var Wi=`__rawFileValues`,Gi=new Set([`json`,`composite`,`repeater`,`record`,`location`,`address`,`vector`]),Ki=new Set([`formula`,`summary`,`autonumber`]),qi=new Set([`select`,`radio`,`lookup`,`user`,`file`,`image`]);function Ji(e){return Ri.has(e.type)?!0:qi.has(e.type)&&e.multiple===!0}var Yi=n(()=>t.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,`expected YYYY-MM-DD (calendar day, not an instant)`)),Xi=n(()=>t.z.string().refine(e=>!Number.isNaN(Date.parse(e))&&(/[Zz]$/.test(e)||/[+-]\d{2}:?\d{2}$/.test(e.slice(10))),`expected an ISO-8601 instant with explicit zone (e.g. 2026-03-15T14:30:00.000Z)`)),Zi=n(()=>t.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d+)?)?(Z|[+-]([01]\d|2[0-3]):?[0-5]\d)?$/,`expected HH:MM or HH:MM:SS (wall-clock time of day)`)),Qi=n(()=>t.z.object({lat:t.z.number().min(-90).max(90).describe(`Latitude`),lng:t.z.number().min(-180).max(180).describe(`Longitude`),altitude:t.z.number().optional().describe(`Altitude in meters`),accuracy:t.z.number().optional().describe(`Accuracy in meters`)})),$i=Ot,ea=n(()=>t.z.looseObject({url:t.z.string(),name:t.z.string().optional(),size:t.z.number().optional(),mimeType:t.z.string().optional(),alt:t.z.string().optional(),duration:t.z.number().optional()})),ta=n(()=>t.z.string().regex(/^[A-Za-z0-9_-]{1,64}$/,`Expected an opaque sys_file id`)),na=n(()=>t.z.union([t.z.string().min(1),ea])),ra=/^\s*[[{]/,H=n(()=>t.z.string().min(1).refine(e=>!ra.test(e),{message:`Expected a record id, but the value is an embedded record object. A reference stores an opaque id; the expanded record is the READ shape ($expand produces it) and is never stored. Replace the value with the referenced record's id.`}));function ia(e){return Array.isArray(e.options)?e.options.map(e=>String(typeof e==`object`&&e?e.value:e)):[]}function aa(e,n=`stored`){let r=e.type,i=(()=>{if(ji.has(r))return t.z.string();if(Mi.has(r))return t.z.number().finite();if(Ni.has(r))return t.z.boolean();if(Pi.has(r))return Yi;if(Fi.has(r))return Xi;if(Ii.has(r))return Zi;if(Li.has(r)||Ri.has(r)){let n=ia(e);return n.length>0?t.z.enum(n):t.z.string()}return zi.has(r)?n===`expanded`?t.z.union([H,t.z.record(t.z.string(),t.z.unknown())]):H:Hi.has(r)?n===`expanded`?t.z.union([ta,ea]):ta:r===`location`?Qi:r===`address`?$i:r===`composite`||r===`record`?t.z.record(t.z.string(),t.z.unknown()):r===`repeater`?t.z.array(t.z.record(t.z.string(),t.z.unknown())):r===`vector`?t.z.array(t.z.number()):t.z.unknown()})();return Ji(e)?t.z.array(i):i}var oa=new Set([`true`,`t`,`yes`,`y`,`1`,`on`,`是`,`对`,`✓`,`√`]),sa=new Set([`false`,`f`,`no`,`n`,`0`,`off`,`否`,`错`,`✗`,`×`]),ca=new Set([...zi,`reference`]),la=new Set([`YYYY`,`YY`,`MM`,`DD`,`YYYYMMDD`]);function ua(e){let t=[];if(!e)return t;let n=/\{([^{}]*)\}/g,r=0,i,a=!1;for(;(i=n.exec(e))!==null;){i.index>r&&t.push({kind:`literal`,text:e.slice(r,i.index)});let o=i[1];/^0+$/.test(o)&&!a?(t.push({kind:`seq`,width:o.length}),a=!0):la.has(o)?t.push({kind:`date`,pattern:o}):/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)?t.push({kind:`field`,field:o}):t.push({kind:`literal`,text:i[0]}),r=n.lastIndex}return r<e.length&&t.push({kind:`literal`,text:e.slice(r)}),t}function da(e){return e.some(e=>e.kind===`date`||e.kind===`field`)}function fa(e,t=4){let n=e.find(e=>e.kind===`seq`);return n&&n.kind===`seq`?n.width:t}function pa(e){return e.filter(e=>e.kind===`field`).map(e=>e.field)}function ma(e,t){let n=[];for(let r of pa(e)){let e=t?t[r]:void 0;(e==null||e===``)&&!n.includes(r)&&n.push(r)}return n}function ha(e,t){let n,r,i;try{let a=new Intl.DateTimeFormat(`en-CA`,{timeZone:t||`UTC`,year:`numeric`,month:`2-digit`,day:`2-digit`}).formatToParts(e);n=a.find(e=>e.type===`year`)?.value??`0000`,r=a.find(e=>e.type===`month`)?.value??`01`,i=a.find(e=>e.type===`day`)?.value??`01`}catch{n=String(e.getUTCFullYear()).padStart(4,`0`),r=String(e.getUTCMonth()+1).padStart(2,`0`),i=String(e.getUTCDate()).padStart(2,`0`)}return{YYYY:n,YY:n.slice(-2),MM:r,DD:i}}function ga(e,t){switch(e){case`YYYY`:return t.YYYY;case`YY`:return t.YY;case`MM`:return t.MM;case`DD`:return t.DD;case`YYYYMMDD`:return`${t.YYYY}${t.MM}${t.DD}`;default:return``}}function _a(e){let{tokens:t,seq:n,record:r,now:i,timezone:a}=e,o=ha(i,a),s=``,c=``,l=null;for(let e of t){if(e.kind===`seq`){l=e.width;continue}let t=``;if(e.kind===`literal`)t=e.text;else if(e.kind===`date`)t=ga(e.pattern,o);else if(e.kind===`field`){let n=r?r[e.field]:void 0;t=n==null?``:String(n)}l===null?s+=t:c+=t}let ee=da(t)?s:``,u=l===null?`${s}${n}`:`${s}${String(n).padStart(l,`0`)}${c}`;return{prefix:s,suffix:c,scope:ee,value:u}}var va="A hook `object` target must name at least one object. An empty target is not \"no target\": until #4001 `''` and `[]` were widened to the wildcard `'*'`, registering the hook on EVERY object, and `['']` registered it on an object name nothing matches, so it could never fire. Name the object(s) — `object: 'account'` or `object: ['account', 'contact']` — or, if firing on every object really is the intent, write the wildcard explicitly: `object: '*'`.",ya=[`name`,`label`,`object`,`events`,`handler`,`body`,`priority`,`async`,`condition`,`description`,`retryPolicy`,`timeout`,`onError`],ba=[`maxRetries`,`backoffMs`],xa=w({surface:`this hook`,knownKeys:ya,aliases:{hookname:`name`,objectname:`object`,objects:`object`,event:`events`,fn:`handler`,callback:`handler`,order:`priority`,sequence:`priority`,background:`async`,isasync:`async`,when:`condition`,predicate:`condition`,retry:`retryPolicy`,timeoutms:`timeout`,errorpolicy:`onError`,onfailure:`onError`},guidance:{enabled:"`enabled` is not a hook key — a hook has no on/off switch. Gate it with `condition` (the hook is skipped when the predicate is false), or remove the hook.",active:"`active` is not a hook key — a hook has no on/off switch. Gate it with `condition`, or remove the hook."},history:`Until #4001 these were dropped silently — the hook still registered and ran.`}),Sa=w({surface:`this hook's retryPolicy`,knownKeys:ba,aliases:{retries:`maxRetries`,attempts:`maxRetries`,basedelayms:`backoffMs`,backoff:`backoffMs`,delayms:`backoffMs`},history:"Until #4001 these were dropped silently — the hook retried on the defaults rather than the policy that was written. Note a datasource retryPolicy spells its delay `baseDelayMs`; a hook spells it `backoffMs`."}),Ca=t.z.enum([`beforeFind`,`afterFind`,`beforeInsert`,`afterInsert`,`beforeUpdate`,`afterUpdate`,`beforeDelete`,`afterDelete`]),wa=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Hook unique name (snake_case)`),label:t.z.string().optional().describe(`Description of what this hook does`),object:t.z.union([t.z.string(),t.z.array(t.z.string())]).refine(e=>Array.isArray(e)?e.length>0&&e.every(e=>e.trim().length>0):e.trim().length>0,{error:va}).describe(`Target object(s)`),events:t.z.array(Ca).describe(`Lifecycle events`),handler:t.z.union([t.z.string(),t.z.custom(e=>typeof e==`function`,{message:`Expected function`})]).optional().describe("Handler function name (string, post-build) or inline function (pre-build) — DEPRECATED, prefer `body`"),body:en.optional().describe(`Hook body — expression (L1) or sandboxed JS (L2)`),priority:t.z.number().default(100).describe(`Execution priority`),async:t.z.boolean().default(!1).describe(`Run specifically as fire-and-forget`),condition:k.optional().describe('Predicate (CEL); hook runs only when TRUE. e.g. P`record.status == "closed" && record.amount > 1000`'),description:t.z.string().optional().describe(`Human-readable description of what this hook does`),retryPolicy:t.z.object({maxRetries:t.z.number().default(3).describe(`Maximum retry attempts on failure`),backoffMs:t.z.number().default(1e3).describe(`Backoff delay between retries in milliseconds`)},{error:Sa}).strict().optional().describe(`Retry policy for failed hook executions`),timeout:t.z.number().optional().describe(`Maximum execution time in milliseconds before the hook is aborted`),onError:t.z.enum([`abort`,`log`]).default(`abort`).describe(`Error handling strategy`),...D},{error:xa}).strict()),Ta=n(()=>t.z.object({id:t.z.string().optional().describe(`Unique execution ID for tracing`),object:t.z.string(),event:Ca,input:t.z.record(t.z.string(),t.z.unknown()).describe(`Mutable input parameters`),result:t.z.unknown().optional().describe(`Operation result (After hooks only)`),previous:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Record state before operation`),session:t.z.object({userId:t.z.string().optional(),actor:t.z.string().optional().describe(`Service-principal label for audit attribution when the caller is not a real user (e.g. svc:flow:<flowName>)`),organizationId:t.z.string().optional().describe(`Active organization ID (blessed developer-facing name)`),roles:t.z.array(t.z.string()).optional(),accessToken:t.z.string().optional(),isSystem:t.z.boolean().optional().describe(`True when the call was made with an elevated system context (engine self-writes)`),skipTriggers:t.z.boolean().optional().describe(`True when record-change automation (flow triggers) must be suppressed for this write — e.g. package seed replay. Lifecycle hooks still run.`),skipAutomations:t.z.boolean().optional().describe(`True when metadata-bound automation hooks must be suppressed for this write — e.g. data import with "run automations" unchecked, or import undo. Implies skipTriggers; code-registered system hooks (audit, security) still run.`)}).optional().describe(`Current session context`),provenance:t.z.object({flowRunId:t.z.string().optional().describe(`Id of the automation flow run performing this write, when it originates from a flow data node. Lets a hook recognize the run that OWNS state that run itself opened — the approvals record lock exempts the run holding the pending request (#3456).`),attributedUserId:t.z.string().optional().describe("The real human credited for a write whose authorization subject was the SYSTEM — e.g. the admin whose better-auth `update-member-role` call the identity adapter executes as `isSystem` (#4586). ATTRIBUTION ONLY: the audit writer records it as `sys_audit_log.user_id`; no security middleware reads it, and it never becomes the subject the write is authorized as.")}).optional().describe(`Server-stamped write provenance (never client-supplied, never an authorization input)`),transaction:t.z.unknown().optional().describe(`Database transaction handle`),ql:t.z.unknown().describe(`ObjectQL Engine Reference`),api:t.z.unknown().optional().describe(`Cross-object data access (ScopedContext)`),user:t.z.object({id:t.z.string().optional(),name:t.z.string().optional(),email:t.z.string().optional(),organizationId:t.z.string().optional().describe(`Active organization ID of the acting user (equals session.organizationId)`)}).optional().describe(`Current user info shortcut`)}));function Ea(e){return wa.parse(e)}var Da=`Until #4001 closed this shape these were dropped silently — the mapping still ran to completion and reported success, minus whatever the key was meant to control.`,Oa='`mapping.extractQuery` was removed in @objectstack/spec 17.0.0 (#4509, ADR-0049) — no exporter ever read a mapping artifact, so "Query to run for export only" promised an export path that does not exist. Delete the key. Exports run through the ordinary query API (`POST /api/v1/data/:object/query`); if a mapping-driven export is ever designed, this is where it plugs back in. Run `os migrate meta --from 16` to rewrite existing sources automatically.',ka="`mapping.errorPolicy` was removed in @objectstack/spec 17.0.0 (#4509, ADR-0049) — no import code ever read it, so `skip` / `abort` / `retry` selected between three behaviours that were all the same behaviour. Delete the key. Error handling on the import path belongs to the import REQUEST's own options, not to the stored mapping. Run `os migrate meta --from 16` to rewrite existing sources automatically.",Aa="`mapping.batchSize` was removed in @objectstack/spec 17.0.0 (#4509, ADR-0049) — no import code ever batched by it; the write path sizes its own batches. Delete the key. CAREFUL — do NOT \"fix\" this by relocating the value to a neighbouring `batchSize`: `bulkActionDef.batchSize`, `connector.batchSize`, `sync.batchSize`, `offline.batchSize`, the seed loader's and the NoSQL driver cursor's are all LIVE and enforced — but each is a DIFFERENT key on a different type sizing its own path, and none of them sizes a mapping import. Run `os migrate meta --from 16` to rewrite existing sources automatically.",ja={extractQuery:Oa,query:Oa,errorPolicy:ka,onError:ka,errorHandling:ka,errorMode:ka,skipErrors:ka,batchSize:Aa,batch:Aa,chunkSize:Aa},Ma=t.z.enum([`none`,`constant`,`lookup`,`split`,`join`,`javascript`,`map`]),Na=n(()=>T({surface:`this field mapping`,history:Da,aliases:{from:`source`,sourceField:`source`,column:`source`,header:`source`,to:`target`,targetField:`target`,field:`target`,type:`transform`,operation:`transform`,fn:`transform`,config:`params`,options:`params`,args:`params`}},{source:t.z.union([t.z.string(),t.z.array(t.z.string())]).describe(`Source column header(s)`),target:t.z.union([t.z.string(),t.z.array(t.z.string())]).describe(`Target object field(s)`),transform:Ma.default(`none`),params:T({surface:`this transform’s params`,history:Da,aliases:{default:`value`,defaultValue:`value`,constant:`value`,lookupObject:`object`,targetObject:`object`,match:`fromField`,matchOn:`fromField`,matchField:`fromField`,keyField:`fromField`,returnField:`toField`,valueField:`toField`,create:`autoCreate`,createIfMissing:`autoCreate`,upsert:`autoCreate`,map:`valueMap`,mapping:`valueMap`,values:`valueMap`,valueMapping:`valueMap`,delimiter:`separator`,splitOn:`separator`,joinWith:`separator`}},{value:t.z.unknown().optional(),object:t.z.string().optional(),fromField:t.z.string().optional(),toField:t.z.string().optional(),autoCreate:t.z.boolean().optional(),valueMap:t.z.record(t.z.string(),t.z.unknown()).optional(),separator:t.z.string().optional()}).optional()})),U=n(()=>T({surface:`this mapping`,history:Da,aliases:{object:`targetObject`,target:`targetObject`,to:`targetObject`,format:`sourceFormat`,source:`sourceFormat`,sourceType:`sourceFormat`,mappings:`fieldMapping`,fields:`fieldMapping`,columns:`fieldMapping`,fieldMappings:`fieldMapping`,key:`upsertKey`,matchOn:`upsertKey`,externalId:`upsertKey`,externalIdField:`upsertKey`},guidance:{dedupe:"deduplication is `mode: 'upsert'` plus `upsertKey: [<field>]` — there is no separate dedupe switch",...ja}},{name:O.describe(`Mapping unique name (lowercase snake_case)`),label:t.z.string().optional(),sourceFormat:t.z.enum([`csv`,`json`,`xml`,`sql`]).default(`csv`),targetObject:t.z.string().describe(`Target Object Name`),fieldMapping:t.z.array(Na),mode:t.z.enum([`insert`,`update`,`upsert`]).default(`insert`),upsertKey:t.z.array(t.z.string()).optional().describe(`Fields to match for upsert (e.g. email)`),...D}));function Pa(e){return U.parse(e)}var Fa=t.z.enum([`read`,`create`,`update`,`delete`,`transfer`,`restore`,`purge`,`export`]),Ia=t.z.enum([`PLATFORM_ADMIN`,`TENANT_ADMIN`,`MEMBER`,`EXTERNAL`]).describe(`ADR-0095 D2 posture rung — PLATFORM_ADMIN crosses the tenant wall where object posture permits; TENANT_ADMIN sees all rows in the org; MEMBER gets business RLS; EXTERNAL sees only explicitly shared rows.`),La=n(()=>t.z.object({kind:t.z.enum([`tenant_filter`,`owd_baseline`,`ownership`,`record_share`,`sharing_rule`,`team`,`territory`,`rls_policy`]).describe(`The row-visibility source kind evaluated for this record at this layer.`),name:t.z.string().describe(`Stable identifier of the concrete rule, share, or policy that was evaluated.`),grants:t.z.enum([`read`,`edit`,`full`]).optional().describe("Access level a sharing source grants on the record (authorable: read/edit; `full` appears only for legacy rows pending normalisation)."),via:t.z.string().optional().describe(`How the rule reached the principal — recipient group/position, ownership, or the matching criteria.`),predicate:t.z.unknown().optional().describe(`The row predicate this rule contributed, when it is filter-shaped (null = unrestricted).`),effect:t.z.enum([`admits`,`excludes`,`neutral`]).describe(`The rule's effect on THIS record: admits, excludes, or neutral.`)})),Ra=n(()=>t.z.object({outcome:t.z.enum([`admitted`,`excluded`,`not_evaluated`]).describe(`This layer's row-level outcome for the record: admitted, excluded, or not_evaluated (skipped/not row-scoped).`),rowFilter:t.z.unknown().optional().describe(`The effective row predicate this layer contributed for the record set (null = unrestricted, __deny_all__ = zero rows).`),matchesRecord:t.z.boolean().optional().describe(`Whether the specific record satisfies rowFilter — the judgement behind outcome.`),rules:t.z.array(La).default([]).describe(`Concrete rules, shares, or policies this layer evaluated against the record, in evaluation order.`),detail:t.z.string().optional().describe(`Human-readable, record-specific explanation of this layer's outcome.`)})),za=n(()=>t.z.object({layer:t.z.enum([`tenant_isolation`,`principal`,`required_permissions`,`object_crud`,`fls`,`owd_baseline`,`depth`,`sharing`,`vama_bypass`,`rls`]),kernelTier:t.z.enum([`layer_0_tenant`,`layer_1_business`]).optional().describe(`ADR-0095 kernel layer: layer_0_tenant = the always-first org wall; layer_1_business = business RLS/sharing/ownership.`),verdict:t.z.enum([`grants`,`denies`,`narrows`,`widens`,`neutral`,`not_applicable`]),detail:t.z.string(),contributors:t.z.array(t.z.object({kind:t.z.enum([`permission_set`,`position`,`system`]),name:t.z.string(),via:t.z.string().optional(),state:t.z.enum([`active`,`expired`]).optional()})).default([]),record:Ra.optional().describe(`Row-level determination for the specific record under explanation; set only for record-grained requests.`)}));n(()=>t.z.object({object:t.z.string(),operation:Fa,recordId:t.z.string().optional().describe(`Optional id of one concrete record to explain at row granularity; omitted = object-level (pre-C2) request.`),userId:t.z.string().optional()})),n(()=>t.z.object({allowed:t.z.boolean(),object:t.z.string(),operation:Fa,principal:t.z.object({userId:t.z.string().nullable(),positions:t.z.array(t.z.string()).default([]),permissionSets:t.z.array(t.z.string()).default([]),principalKind:t.z.enum([`human`,`agent`,`service`,`guest`,`system`]).optional(),onBehalfOf:t.z.object({userId:t.z.string()}).optional(),posture:Ia.optional()}),layers:t.z.array(za),readFilter:t.z.unknown().optional(),record:n(()=>t.z.object({recordId:t.z.string().describe(`The concrete record id this verdict is about (echoes the request recordId).`),visible:t.z.boolean().describe(`Whether the operation is permitted on this specific record after all layers.`),decidedBy:t.z.enum([`tenant_isolation`,`principal`,`required_permissions`,`object_crud`,`fls`,`owd_baseline`,`depth`,`sharing`,`vama_bypass`,`rls`]).optional().describe(`The pipeline layer that decided the record-level outcome (excluded it, or last admitted it).`)})).optional().describe(`Row-level verdict for the specific record; set only for record-grained requests.`)}));var Ba=n(()=>t.z.object({permissionSet:t.z.string(),object:t.z.string(),create:t.z.boolean(),read:t.z.boolean(),edit:t.z.boolean(),delete:t.z.boolean(),viewAllRecords:t.z.boolean(),modifyAllRecords:t.z.boolean(),readScope:t.z.string().optional(),writeScope:t.z.string().optional(),sharingModel:t.z.string().optional()}));n(()=>t.z.object({version:t.z.literal(1).default(1),entries:t.z.array(Ba).default([])}));var Va=n(()=>t.z.object({userId:t.z.string().optional(),actor:t.z.string().optional(),attributedUserId:t.z.string().optional(),email:t.z.string().optional(),tenantId:t.z.string().optional(),timezone:t.z.string().optional(),locale:t.z.string().optional(),currency:t.z.string().optional(),positions:t.z.array(t.z.string()).default([]),principalKind:t.z.enum([`human`,`agent`,`service`,`guest`,`system`]).optional(),audience:t.z.enum([`internal`,`external`]).optional(),posture:Ia.optional(),onBehalfOf:t.z.object({userId:t.z.string(),principalKind:t.z.enum([`human`,`agent`,`service`,`guest`,`system`]).optional()}).optional(),permissions:t.z.array(t.z.string()).default([]),systemPermissions:t.z.array(t.z.string()).optional(),tabPermissions:t.z.record(t.z.string(),t.z.enum([`visible`,`hidden`,`default_on`,`default_off`])).optional(),org_user_ids:t.z.array(t.z.string()).optional(),accessible_org_ids:t.z.array(t.z.string()).optional(),rlsMembership:t.z.record(t.z.string(),t.z.array(t.z.string())).optional(),isSystem:t.z.boolean().default(!1),flowRunId:t.z.string().optional(),skipTriggers:t.z.boolean().optional(),skipAutomations:t.z.boolean().optional(),seedReplay:t.z.boolean().optional(),skipStateMachine:t.z.boolean().optional(),preserveAudit:t.z.boolean().optional(),oauthScopes:t.z.array(t.z.string()).optional(),accessToken:t.z.string().optional(),transaction:t.z.unknown().optional(),traceId:t.z.string().optional()})),Ha=n(()=>t.z.union([t.z.record(t.z.string(),t.z.unknown()),d]).describe(`Data Engine query filter conditions`)),Ua=n(()=>t.z.union([t.z.record(t.z.string(),t.z.enum([`asc`,`desc`])),t.z.record(t.z.string(),t.z.union([t.z.literal(1),t.z.literal(-1)])),t.z.array(se)]).describe(`Sort order definition`)),W=n(()=>t.z.object({context:Va.partial().optional()})),Wa=n(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),d]).optional(),fields:t.z.array(pe).optional(),orderBy:t.z.array(se).optional(),limit:t.z.number().optional(),offset:t.z.number().optional(),top:t.z.number().optional(),cursor:v(he),search:y.optional(),searchFields:t.z.array(t.z.string()).optional(),expand:t.z.lazy(()=>t.z.record(t.z.string(),b)).optional(),distinct:v(ge)}).describe(`QueryAST-aligned query options for IDataEngine.find() operations`)),Ga=n(()=>W.extend({filter:Ha.optional(),select:t.z.array(t.z.string()).optional(),sort:Ua.optional(),limit:t.z.number().int().min(1).optional(),skip:t.z.number().int().min(0).optional(),top:t.z.number().int().min(1).optional(),populate:t.z.array(t.z.string()).optional()}).describe(`Query options for IDataEngine.find() operations`)),Ka=n(()=>W.extend({returning:t.z.boolean().default(!0).optional()}).describe(`Options for DataEngine.insert operations`)),qa=n(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),d]).optional(),upsert:t.z.boolean().default(!1).optional(),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.update operations`)),Ja=n(()=>t.z.object({object:t.z.string().describe(`Object the write targeted (resolved object name)`),fields:t.z.array(t.z.string()).describe(`Caller-supplied field names the engine removed from the write payload`),reason:t.z.enum([`readonly`,`readonly_when`]).describe(`Why the fields were dropped: static readonly (#2948) or a TRUE readonlyWhen predicate (#3042)`)}).describe(`A write-path strip event: caller-supplied fields legally dropped from the payload (#3407)`)),Ya=n(()=>W.extend({filter:Ha.optional(),upsert:t.z.boolean().default(!1).optional(),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.update operations`)),Xa=n(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),d]).optional(),multi:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.delete operations`)),Za=n(()=>W.extend({filter:Ha.optional(),multi:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.delete operations`)),Qa=n(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),d]).optional(),groupBy:t.z.array(t.z.string()).optional(),aggregations:t.z.array(de).optional(),having:d.optional().describe(`HAVING — filter over the aggregated rows (aggregation aliases + groupBy projections); applied engine-side after aggregation`),timezone:t.z.string().optional()}).describe(`QueryAST-aligned options for DataEngine.aggregate operations`)),$a=n(()=>W.extend({filter:Ha.optional(),groupBy:t.z.array(t.z.string()).optional(),aggregations:t.z.array(t.z.object({field:t.z.string(),method:t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`]),alias:t.z.string().optional()})).optional()}).describe(`Options for DataEngine.aggregate operations`)),eo=n(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),d]).optional()}).describe(`QueryAST-aligned options for DataEngine.count operations`)),to=n(()=>W.extend({filter:Ha.optional()}).describe(`Options for DataEngine.count operations`)),no=n(()=>t.z.object({find:t.z.function().input(t.z.tuple([t.z.string(),Wa.optional()])).output(t.z.promise(t.z.array(t.z.unknown()))),findOne:t.z.function().input(t.z.tuple([t.z.string(),Wa.optional()])).output(t.z.promise(t.z.unknown())),insert:t.z.function().input(t.z.tuple([t.z.string(),t.z.union([t.z.record(t.z.string(),t.z.unknown()),t.z.array(t.z.record(t.z.string(),t.z.unknown()))]),Ka.optional()])).output(t.z.promise(t.z.unknown())),update:t.z.function().input(t.z.tuple([t.z.string(),t.z.record(t.z.string(),t.z.unknown()),qa.optional()])).output(t.z.promise(t.z.unknown())),delete:t.z.function().input(t.z.tuple([t.z.string(),Xa.optional()])).output(t.z.promise(t.z.unknown())),count:t.z.function().input(t.z.tuple([t.z.string(),eo.optional()])).output(t.z.promise(t.z.number())),aggregate:t.z.function().input(t.z.tuple([t.z.string(),Qa])).output(t.z.promise(t.z.array(t.z.unknown())))}).describe(`Standard Data Engine Contract`)),ro=[{canonical:`where`,aliases:[`filter`]},{canonical:`fields`,aliases:[`select`]},{canonical:`orderBy`,aliases:[`sort`]},{canonical:`offset`,aliases:[`skip`]},{canonical:`expand`,aliases:[`populate`]},{canonical:`limit`,aliases:[`top`]}];function io(e,t,n){let r={};for(let i of t){let t=[i.canonical,...i.aliases],a=t.filter(t=>e[t]!=null);if(a.length>1&&new Set(a.map(t=>JSON.stringify(e[t]))).size>1){n({canonical:i.canonical,spellings:a});continue}if(a.length>0){let t=e[a[0]];e[i.canonical]=t,r[i.canonical]=a[0]}for(let n of t)n!==i.canonical&&delete e[n]}return r}var ao=ro.filter(e=>e.canonical===`where`);function oo(e){return{code:`custom`,path:[e.canonical],message:`Conflicting query parameters: ${e.spellings.map(e=>`'${e}'`).join(`, `)} are spellings of the same parameter (canonical '${e.canonical}') and were given different values. Send exactly one.`}}var G={filter:Ha.optional()};function K(e,t){let n={...e};return io(n,ao,e=>t.addIssue(oo(e))),n}function so(e,t){let n={...e};return io(n,ro,e=>t.addIssue(oo(e))),n.orderBy!==void 0&&n.orderBy!==null&&!Array.isArray(n.orderBy)&&(n.orderBy=Object.entries(n.orderBy).map(([e,t])=>({field:e,order:t===`asc`||t===1?`asc`:`desc`}))),Array.isArray(n.expand)&&(n.expand=Object.fromEntries(n.expand.map(e=>[e,{object:e}]))),n}var co=Wa.extend({...G,select:t.z.array(t.z.string()).optional(),sort:Ua.optional(),skip:t.z.number().int().min(0).optional(),populate:t.z.array(t.z.string()).optional()}).transform((e,t)=>so(e,t)),lo=n(()=>t.z.object({method:t.z.literal(`find`),object:t.z.string(),query:co.optional()})),uo=n(()=>t.z.object({method:t.z.literal(`findOne`),object:t.z.string(),query:co.optional()})),fo=n(()=>t.z.object({method:t.z.literal(`insert`),object:t.z.string(),data:t.z.union([t.z.record(t.z.string(),t.z.unknown()),t.z.array(t.z.record(t.z.string(),t.z.unknown()))]),options:Ka.optional()})),po=n(()=>t.z.object({method:t.z.literal(`update`),object:t.z.string(),data:t.z.record(t.z.string(),t.z.unknown()),id:t.z.union([t.z.string(),t.z.number()]).optional().describe(`ID for single update, or use where in options`),options:qa.extend(G).transform((e,t)=>K(e,t)).optional()})),mo=n(()=>t.z.object({method:t.z.literal(`delete`),object:t.z.string(),id:t.z.union([t.z.string(),t.z.number()]).optional().describe(`ID for single delete, or use where in options`),options:Xa.extend(G).transform((e,t)=>K(e,t)).optional()})),ho=n(()=>t.z.object({method:t.z.literal(`count`),object:t.z.string(),query:eo.extend(G).transform((e,t)=>K(e,t)).optional()})),go=n(()=>t.z.object({method:t.z.literal(`aggregate`),object:t.z.string(),query:Qa.extend(G).transform((e,t)=>K(e,t))})),_o=n(()=>t.z.object({method:t.z.literal(`execute`),command:t.z.unknown(),options:t.z.record(t.z.string(),t.z.unknown()).optional()})),vo=n(()=>t.z.object({method:t.z.literal(`vectorFind`),object:t.z.string(),vector:t.z.array(t.z.number()),where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),d]).optional(),fields:t.z.array(t.z.string()).optional(),limit:t.z.number().int().default(5).optional(),threshold:t.z.number().optional()})),yo=n(()=>t.z.discriminatedUnion(`method`,[lo,uo,fo,po,mo,ho,go,_o,vo]).describe(`Virtual ObjectQL Request Protocol`)),bo=t.z.enum([`asc`,`desc`]).describe(`Sort order direction`);n(()=>t.z.object({field:t.z.string().describe(`Field name to sort by`),order:bo.describe(`Sort direction`)}).describe(`Sort field and direction pair`)),t.z.enum([`insert`,`update`,`delete`,`upsert`]).describe(`Data mutation event types`);var xo=t.z.enum([`read_uncommitted`,`read_committed`,`repeatable_read`,`serializable`,`snapshot`]).describe(`Transaction isolation levels (snake_case standard)`),q=n(()=>t.z.object({transaction:t.z.unknown().optional().describe(`Transaction handle`),timeout:t.z.number().optional().describe(`Timeout in ms`),skipCache:t.z.boolean().optional().describe(`Bypass cache`),traceContext:t.z.record(t.z.string(),t.z.string()).optional().describe(`OpenTelemetry context or request ID`),tenantId:t.z.string().optional().describe(`Tenant Isolation identifier`),tenantIds:t.z.array(t.z.string()).optional().describe(`Union tenant access set (group posture): native read scoping widens to organization_id IN (...); inserts still stamp from tenantId`),timezone:t.z.string().optional().describe(`Business reference timezone (IANA) for date-dependent generation, e.g. autonumber date tokens`),preserveAudit:t.z.boolean().optional().describe(`Historical import: keep a supplied updated_at instead of force-stamping now (from ExecutionContext.preserveAudit)`),bypassTenantAudit:t.z.boolean().optional().describe(`Suppress the driver tenant-audit warning for a deliberately global write on a tenant-scoped object (diagnostics only — never changes what the write touches)`)})),J=(e,t)=>`\`DriverCapabilities.${e}\` was removed in @objectstack/spec 17.0.0 (#4634, ADR-0049 enforce-or-remove) \u2014 no code in any repository ever read it, so its value never changed which code path ran. ${t} Delete the key.`,So=n(()=>t.z.object({queryDateGranularity:t.z.record(le,t.z.boolean()).optional().describe(`Per-granularity native date bucketing (day/week/month/quarter/year). Missing keys fall back to in-memory bucketing.`),autonumber:t.z.boolean().optional().describe(`Driver natively generates persistent autonumber/sequence values`),batchSchemaSync:t.z.boolean().optional().describe(`Supports batched schema sync to reduce schema DDL round-trips (absence = false)`),create:v(J(`create`,"CRUD is not optional for a driver: `create`/`find`/`findOne`/`update`/`delete` are REQUIRED `IDataDriver` methods and the engine calls them unconditionally.")),read:v(J(`read`,"CRUD is not optional for a driver: reads go through the REQUIRED `find`/`findOne`/`count` methods, called unconditionally.")),update:v(J(`update`,"CRUD is not optional for a driver: `update`/`upsert` are REQUIRED `IDataDriver` methods, called unconditionally.")),delete:v(J(`delete`,"CRUD is not optional for a driver: `delete` is a REQUIRED `IDataDriver` method, called unconditionally.")),bulkCreate:v(J(`bulkCreate`,"The bulk methods (`bulkCreate`/`bulkUpdate`/`bulkDelete`) are REQUIRED `IDataDriver` methods and the engine calls them directly; wire-level batch capability is advertised by REST discovery from the live composition (#3298), never from this record.")),bulkUpdate:v(J(`bulkUpdate`,"The bulk methods are REQUIRED `IDataDriver` methods and the engine calls them directly; wire-level batch capability is advertised by REST discovery from the live composition (#3298), never from this record.")),bulkDelete:v(J(`bulkDelete`,"The bulk methods are REQUIRED `IDataDriver` methods and the engine calls them directly; wire-level batch capability is advertised by REST discovery from the live composition (#3298), never from this record.")),transactions:v(J(`transactions`,"Transaction use is gated on METHOD PRESENCE — `driver.beginTransaction` (`engine.transaction()`, ADR-0034 ambient transactions): a driver without the method gets the non-transactional fallback, whatever this bit claimed. Discovery's `transactionalBatch` capability is likewise derived from `engine.transaction` plus the mounted batch route, never from this bit.")),savepoints:v(J(`savepoints`,`No savepoint code path exists in the engine — a capability bit for a feature the platform does not call is a false affordance, not documentation.`)),isolationLevels:v(J(`isolationLevels`,"Isolation is requested per transaction via `beginTransaction({ isolationLevel })`; no planner ever consulted this list to decide anything.")),queryFilters:v(J(`queryFilters`,'`find()` receives the full QueryAST (`where`/`orderBy`/`limit`/`offset`) and MUST execute all of it — the "ObjectQL will filter in memory" fallback this bit\'s description promised was never built.')),querySorting:v(J(`querySorting`,'`find()` receives the full QueryAST and MUST execute all of it — the "ObjectQL will sort in memory" fallback this bit\'s description promised was never built.')),queryPagination:v(J(`queryPagination`,'`find()` receives the full QueryAST and MUST execute all of it — the "ObjectQL will paginate in memory" fallback this bit\'s description promised was never built.')),queryAggregations:v(J(`queryAggregations`,"Aggregate pushdown is decided by `typeof driver.aggregate === 'function'` plus `queryDateGranularity` (engine aggregate dispatch) — never by this bit.")),queryWindowFunctions:v(J(`queryWindowFunctions`,`ObjectQL never plans window functions through a driver, so there was nothing for the bit to switch on.`)),querySubqueries:v(J(`querySubqueries`,`ObjectQL never plans subqueries through a driver, so there was nothing for the bit to switch on.`)),queryCTE:v(J(`queryCTE`,`ObjectQL never plans Common Table Expressions through a driver, so there was nothing for the bit to switch on.`)),joins:v(J(`joins`,"Related data is resolved by the engine (lookup expansion over `find()`), not by driver-side JOIN planning — no code consulted the bit.")),fullTextSearch:v(J(`fullTextSearch`,"`$search` is compiled by the engine into an `$or` of `$contains` predicates over the searchable fields (ADR-0061) and removed from the AST before the driver sees it — no driver-side full-text path exists.")),jsonQuery:v(J(`jsonQuery`,`No engine path ever branched on driver-side JSON querying.`)),geospatialQuery:v(J(`geospatialQuery`,`No geospatial query path exists in the platform — declaring the bit advertised a capability nothing delivers.`)),streaming:v("`DriverCapabilities.streaming` was removed in @objectstack/spec 17.0.0 (#4634, ADR-0049 enforce-or-remove) — no code in any repository ever read it, and `findStream`, the only read this bit could describe, was itself removed in 17.0.0 (#4484): nothing ever called it, and two of its three implementations materialised the entire result set before yielding. The bit carried the same defect one level up (`SqlDriver` implemented `findStream` yet declared `streaming: false`; `InMemoryDriver` declared `true` over a full-table read) — which is what zero readers makes inevitable. Page large reads through `find()` with `limit`/`offset`. Delete the key."),jsonFields:v(J(`jsonFields`,"Field-type handling is negotiated per object at `syncSchema` time by the driver itself (e.g. `SqlDriver`'s per-object JSON/date column tracking); no engine path consulted the bit.")),arrayFields:v(J(`arrayFields`,"Field-type handling is negotiated per object at `syncSchema` time by the driver itself; no engine path consulted the bit.")),vectorSearch:v(J(`vectorSearch`,"No vector read path routes through `IDataDriver`. When one exists it should arrive WITH its caller and its capability bit together (the honest order under enforce-or-remove), not as a dangling boolean.")),schemaSync:v(J(`schemaSync`,"Schema sync is gated on METHOD PRESENCE — `typeof driver.syncSchema === 'function'` (engine and ObjectQL plugin init).")),migrations:v(J(`migrations`,`No migration engine ever consulted it.`)),indexes:v(J(`indexes`,"Declared indexes are materialised by the driver itself during schema sync (`SqlDriver.syncDeclaredIndexes`); no engine path consulted the bit.")),connectionPooling:v(J(`connectionPooling`,"Pooling is configured via `poolConfig` and owned by the driver; `getPoolStats` is duck-typed where monitoring wants it. Nothing consulted the bit.")),preparedStatements:v(J(`preparedStatements`,"Parameterised execution is an implementation detail of the driver (`execute(command, parameters)`); nothing consulted the bit.")),queryCache:v(J(`queryCache`,"No query-cache layer keyed off it exists; `DriverOptions.skipCache` is a per-call hint to the driver, not a switch on this bit."))})),Co=n(()=>t.z.object({name:t.z.string().describe(`Driver unique name`),version:t.z.string().describe(`Driver version`),supports:So,connect:t.z.function().input(t.z.tuple([])).output(t.z.promise(t.z.void())).describe(`Establish connection`),disconnect:t.z.function().input(t.z.tuple([])).output(t.z.promise(t.z.void())).describe(`Close connection`),checkHealth:t.z.function().input(t.z.tuple([])).output(t.z.promise(t.z.boolean())).describe(`Health check`),getPoolStats:t.z.function().input(t.z.tuple([])).output(t.z.object({total:t.z.number(),idle:t.z.number(),active:t.z.number(),waiting:t.z.number()}).optional()).optional().describe(`Get connection pool statistics`),execute:t.z.function().input(t.z.tuple([t.z.unknown(),t.z.array(t.z.unknown()).optional(),q.optional()])).output(t.z.promise(t.z.unknown())).describe(`Execute raw command`),find:t.z.function().input(t.z.tuple([t.z.string(),b,q.optional()])).output(t.z.promise(t.z.array(t.z.record(t.z.string(),t.z.unknown())))).describe(`Find records`),findOne:t.z.function().input(t.z.tuple([t.z.string(),b,q.optional()])).output(t.z.promise(t.z.record(t.z.string(),t.z.unknown()).nullable())).describe(`Find one record`),create:t.z.function().input(t.z.tuple([t.z.string(),t.z.record(t.z.string(),t.z.unknown()),q.optional()])).output(t.z.promise(t.z.record(t.z.string(),t.z.unknown()))).describe(`Create record`),update:t.z.function().input(t.z.tuple([t.z.string(),t.z.string().or(t.z.number()),t.z.record(t.z.string(),t.z.unknown()),q.optional()])).output(t.z.promise(t.z.record(t.z.string(),t.z.unknown()))).describe(`Update record`),upsert:t.z.function().input(t.z.tuple([t.z.string(),t.z.record(t.z.string(),t.z.unknown()),t.z.array(t.z.string()).optional(),q.optional()])).output(t.z.promise(t.z.record(t.z.string(),t.z.unknown()))).describe(`Upsert record`),delete:t.z.function().input(t.z.tuple([t.z.string(),t.z.string().or(t.z.number()),q.optional()])).output(t.z.promise(t.z.boolean())).describe(`Delete record`),count:t.z.function().input(t.z.tuple([t.z.string(),b.optional(),q.optional()])).output(t.z.promise(t.z.number())).describe(`Count records`),bulkCreate:t.z.function().input(t.z.tuple([t.z.string(),t.z.array(t.z.record(t.z.string(),t.z.unknown())),q.optional()])).output(t.z.promise(t.z.array(t.z.record(t.z.string(),t.z.unknown())))),bulkUpdate:t.z.function().input(t.z.tuple([t.z.string(),t.z.array(t.z.object({id:t.z.string().or(t.z.number()),data:t.z.record(t.z.string(),t.z.unknown())})),q.optional()])).output(t.z.promise(t.z.array(t.z.record(t.z.string(),t.z.unknown())))),bulkDelete:t.z.function().input(t.z.tuple([t.z.string(),t.z.array(t.z.string().or(t.z.number())),q.optional()])).output(t.z.promise(t.z.void())),updateMany:t.z.function().input(t.z.tuple([t.z.string(),b,t.z.record(t.z.string(),t.z.unknown()),q.optional()])).output(t.z.promise(t.z.number())).optional(),deleteMany:t.z.function().input(t.z.tuple([t.z.string(),b,q.optional()])).output(t.z.promise(t.z.number())).optional(),beginTransaction:t.z.function().input(t.z.tuple([t.z.object({isolationLevel:xo.optional()}).optional()])).output(t.z.promise(t.z.unknown())).describe(`Start transaction`),commit:t.z.function().input(t.z.tuple([t.z.unknown()])).output(t.z.promise(t.z.void())).describe(`Commit transaction`),rollback:t.z.function().input(t.z.tuple([t.z.unknown()])).output(t.z.promise(t.z.void())).describe(`Rollback transaction`),syncSchema:t.z.function().input(t.z.tuple([t.z.string(),t.z.unknown(),q.optional()])).output(t.z.promise(t.z.void())).describe(`Sync object schema to DB`),syncSchemasBatch:t.z.function().input(t.z.tuple([t.z.array(t.z.object({object:t.z.string(),schema:t.z.unknown()})),q.optional()])).output(t.z.promise(t.z.void())).optional().describe(`Batch sync multiple schemas in one round-trip`),dropTable:t.z.function().input(t.z.tuple([t.z.string(),q.optional()])).output(t.z.promise(t.z.void())),explain:t.z.function().input(t.z.tuple([t.z.string(),b,q.optional()])).output(t.z.promise(t.z.unknown())).optional()})),wo=n(()=>t.z.object({min:t.z.number().min(0).default(2).describe(`Minimum number of connections in pool`),max:t.z.number().min(1).default(10).describe(`Maximum number of connections in pool`),idleTimeoutMillis:t.z.number().min(0).default(3e4).describe(`Time in ms before idle connection is closed`),connectionTimeoutMillis:t.z.number().min(0).default(5e3).describe(`Time in ms to wait for available connection`)})),To=n(()=>t.z.object({name:t.z.string().describe(`Driver instance name`),type:t.z.enum([`sql`,`nosql`,`cache`,`search`,`graph`,`timeseries`]).describe(`Driver type category`),capabilities:So.describe(`Driver capability flags`),connectionString:t.z.string().optional().describe(`Database connection string (driver-specific format)`),poolConfig:wo.optional().describe(`Connection pool configuration`)})),Eo=n(()=>t.z.enum([`postgresql`,`mysql`,`sqlite`,`mssql`,`oracle`,`mariadb`])),Do=n(()=>t.z.object({text:t.z.string().describe(`SQL type for text fields (e.g., VARCHAR, TEXT)`),number:t.z.string().describe(`SQL type for number fields (e.g., NUMERIC, DECIMAL, INT)`),boolean:t.z.string().describe(`SQL type for boolean fields (e.g., BOOLEAN, BIT)`),date:t.z.string().describe(`SQL type for date fields (e.g., DATE)`),datetime:t.z.string().describe(`SQL type for datetime fields (e.g., TIMESTAMP, DATETIME)`),json:t.z.string().optional().describe(`SQL type for JSON fields (e.g., JSON, JSONB)`),uuid:t.z.string().optional().describe(`SQL type for UUID fields (e.g., UUID, CHAR(36))`),binary:t.z.string().optional().describe(`SQL type for binary fields (e.g., BLOB, BYTEA)`)})),Oo=n(()=>t.z.object({rejectUnauthorized:t.z.boolean().default(!0).describe(`Reject connections with invalid certificates`),ca:t.z.string().optional().describe(`CA certificate file path or content`),cert:t.z.string().optional().describe(`Client certificate file path or content`),key:t.z.string().optional().describe(`Client private key file path or content`)}).refine(e=>e.cert!==void 0==(e.key!==void 0),{message:`Client certificate (cert) and private key (key) must be provided together`})),ko=n(()=>To.extend({type:t.z.literal(`sql`).describe(`Driver type must be "sql"`),dialect:Eo.describe(`SQL database dialect`),dataTypeMapping:Do.describe(`SQL data type mapping configuration`),ssl:t.z.boolean().default(!1).describe(`Enable SSL/TLS connection`),sslConfig:Oo.optional().describe(`SSL/TLS configuration (required when ssl is true)`)}).refine(e=>!(e.ssl&&!e.sslConfig),{message:`sslConfig is required when ssl is true`})),Ao={text:`TEXT`,number:`REAL`,boolean:`INTEGER`,date:`TEXT`,datetime:`TEXT`,json:`TEXT`,uuid:`TEXT`,binary:`BLOB`},jo={supportsAddColumn:!0,supportsRenameColumn:!0,supportsDropColumn:!0,supportsModifyColumn:!1,supportsAddConstraint:!1,rebuildStrategy:`create_copy_drop_rename`},Mo=n(()=>t.z.enum([`mongodb`,`couchdb`,`dynamodb`,`cassandra`,`redis`,`elasticsearch`,`neo4j`,`orientdb`])),No=n(()=>t.z.enum([`find`,`findOne`,`insert`,`update`,`delete`,`aggregate`,`mapReduce`,`count`,`distinct`,`createIndex`,`dropIndex`])),Po=n(()=>t.z.enum([`all`,`quorum`,`one`,`local_quorum`,`each_quorum`,`eventual`])),Fo=n(()=>t.z.enum([`single`,`compound`,`unique`,`text`,`geospatial`,`hashed`,`ttl`,`sparse`])),Io=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable sharding`),shardKey:t.z.string().optional().describe(`Field to use as shard key`),shardingStrategy:t.z.enum([`hash`,`range`,`zone`]).optional().describe(`Sharding strategy`),numShards:t.z.number().int().positive().optional().describe(`Number of shards`)})),Lo=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable replication`),replicaSetName:t.z.string().optional().describe(`Replica set name`),replicas:t.z.number().int().positive().optional().describe(`Number of replicas`),readPreference:t.z.enum([`primary`,`primaryPreferred`,`secondary`,`secondaryPreferred`,`nearest`]).optional().describe(`Read preference for replica set`),writeConcern:t.z.enum([`majority`,`acknowledged`,`unacknowledged`]).optional().describe(`Write concern level`)})),Ro=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable schema validation`),validationLevel:t.z.enum([`strict`,`moderate`,`off`]).optional().describe(`Validation strictness`),validationAction:t.z.enum([`error`,`warn`]).optional().describe(`Action on validation failure`),jsonSchema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`JSON Schema for validation`)})),zo=n(()=>t.z.object({text:t.z.string().describe(`NoSQL type for text fields`),number:t.z.string().describe(`NoSQL type for number fields`),boolean:t.z.string().describe(`NoSQL type for boolean fields`),date:t.z.string().describe(`NoSQL type for date fields`),datetime:t.z.string().describe(`NoSQL type for datetime fields`),json:t.z.string().optional().describe(`NoSQL type for JSON/object fields`),uuid:t.z.string().optional().describe(`NoSQL type for UUID fields`),binary:t.z.string().optional().describe(`NoSQL type for binary fields`),array:t.z.string().optional().describe(`NoSQL type for array fields`),objectId:t.z.string().optional().describe(`NoSQL type for ObjectID fields (MongoDB)`),geopoint:t.z.string().optional().describe(`NoSQL type for geospatial point fields`)})),Bo=n(()=>To.extend({type:t.z.literal(`nosql`).describe(`Driver type must be "nosql"`),databaseType:Mo.describe(`Specific NoSQL database type`),dataTypeMapping:zo.describe(`NoSQL data type mapping configuration`),consistency:Po.optional().describe(`Consistency level for operations`),replication:Lo.optional().describe(`Replication configuration`),sharding:Io.optional().describe(`Sharding configuration`),schemaValidation:Ro.optional().describe(`Document schema validation`),region:t.z.string().optional().describe(`AWS region (for managed NoSQL services)`),accessKeyId:t.z.string().optional().describe(`AWS access key ID`),secretAccessKey:t.z.string().optional().describe(`AWS secret access key`),ttlField:t.z.string().optional().describe(`Field name for TTL (auto-deletion)`),maxDocumentSize:t.z.number().int().positive().optional().describe(`Maximum document size in bytes`),collectionPrefix:t.z.string().optional().describe(`Prefix for collection/table names`)})),Vo=n(()=>t.z.object({consistency:Po.optional().describe(`Consistency level override`),readFromSecondary:t.z.boolean().optional().describe(`Allow reading from secondary replicas`),projection:t.z.record(t.z.string(),t.z.union([t.z.literal(0),t.z.literal(1)])).optional().describe(`Field projection`),timeout:t.z.number().int().positive().optional().describe(`Query timeout (ms)`),useCursor:t.z.boolean().optional().describe(`Use cursor instead of loading all results`),batchSize:t.z.number().int().positive().optional().describe(`Cursor batch size`),profile:t.z.boolean().optional().describe(`Enable query profiling`),hint:t.z.string().optional().describe(`Index hint for query optimization`)})),Ho=n(()=>t.z.object({operator:t.z.string().describe(`Aggregation operator (e.g., $match, $group, $sort)`),options:t.z.record(t.z.string(),t.z.unknown()).describe(`Stage-specific options`)})),Y=n(()=>t.z.object({collection:t.z.string().describe(`Collection/table name`),stages:t.z.array(Ho).describe(`Aggregation pipeline stages`),options:Vo.optional().describe(`Query options`)})),Uo=n(()=>t.z.object({name:t.z.string().describe(`Index name`),type:Fo.describe(`Index type`),fields:t.z.array(t.z.object({field:t.z.string().describe(`Field name`),order:t.z.enum([`asc`,`desc`,`text`,`2dsphere`]).optional().describe(`Index order or type`)})).describe(`Fields to index`),unique:t.z.boolean().default(!1).describe(`Enforce uniqueness`),sparse:t.z.boolean().default(!1).describe(`Sparse index`),expireAfterSeconds:t.z.number().int().positive().optional().describe(`TTL in seconds`),partialFilterExpression:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Partial index filter`),background:t.z.boolean().default(!1).describe(`Create index in background`)})),X=n(()=>t.z.object({readConcern:t.z.enum([`local`,`majority`,`linearizable`,`snapshot`]).optional().describe(`Read concern level`),writeConcern:t.z.enum([`majority`,`acknowledged`,`unacknowledged`]).optional().describe(`Write concern level`),readPreference:t.z.enum([`primary`,`primaryPreferred`,`secondary`,`secondaryPreferred`,`nearest`]).optional().describe(`Read preference`),maxCommitTimeMS:t.z.number().int().positive().optional().describe(`Transaction commit timeout (ms)`)})),Wo=t.z.enum([`insert`,`update`,`upsert`,`replace`,`ignore`]),Go=n(()=>T({surface:`this seed`,history:"Until #4001 these were dropped silently — the seed still applied, on the defaults (`mode: upsert`, `externalId: name`) rather than what was written.",aliases:{objectname:`object`,target:`object`,data:`records`,rows:`records`,values:`records`,key:`externalId`,externalkey:`externalId`,naturalkey:`externalId`,strategy:`mode`,conflict:`mode`,environment:`env`,environments:`env`}},{object:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Target Object Name`),externalId:t.z.union([t.z.string(),t.z.array(t.z.string()).min(1)]).default(`name`).describe(`Field (or composite list of fields) matched for the uniqueness check`),mode:Wo.default(`upsert`).describe(`Conflict resolution strategy`),env:t.z.array(t.z.enum([`prod`,`dev`,`test`])).default([`prod`,`dev`,`test`]).describe(`Applicable environments`),records:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Data records`),...D}));function Ko(e,t){return Go.parse({...t,object:e.name})}var qo=Er({schemaId:`object`,type:`simple`,sections:[{name:`basics`,label:`Basics`,description:`Identity, labels, and taxonomy.`,columns:2,fields:[{field:`name`,type:`text`,required:!0,immutable:!0,colSpan:1,helpText:`snake_case unique identifier (immutable after creation)`},{field:`label`,type:`text`,colSpan:1,helpText:`Singular display name (e.g. "Account")`},{field:`pluralLabel`,type:`text`,colSpan:1,helpText:`Plural display name (e.g. "Accounts")`},{field:`icon`,type:`text`,colSpan:1,helpText:`Lucide icon name (e.g. "building", "users")`},{field:`description`,type:`textarea`,colSpan:2,helpText:`Developer documentation`},{field:`isSystem`,type:`boolean`,colSpan:1,helpText:`System object (protected from deletion; defaults sharing to public)`}]},{name:`fields`,label:`Fields`,description:`Define the data model — each entry becomes a column in the database table.`,fields:[{field:`fields`,type:`record`,required:!0,helpText:`Add the columns this object will store`,keyField:{field:`name`,label:`Name`,placeholder:`snake_case_identifier`,helpText:`snake_case machine name (used as column name and API key)`,regex:`^[a-z_][a-z0-9_]*$`,immutable:!0},fields:[{field:`label`,type:`text`,helpText:`Display label`},{field:`type`,type:`select`,required:!0,helpText:`Field type`,options:[{label:`Text`,value:`text`},{label:`Textarea`,value:`textarea`},{label:`Email`,value:`email`},{label:`URL`,value:`url`},{label:`Phone`,value:`phone`},{label:`Password`,value:`password`},{label:`Markdown`,value:`markdown`},{label:`HTML`,value:`html`},{label:`Rich Text`,value:`richtext`},{label:`Number`,value:`number`},{label:`Currency`,value:`currency`},{label:`Percent`,value:`percent`},{label:`Date`,value:`date`},{label:`Date & Time`,value:`datetime`},{label:`Time`,value:`time`},{label:`Boolean`,value:`boolean`},{label:`Toggle`,value:`toggle`},{label:`Select`,value:`select`},{label:`Multiselect`,value:`multiselect`},{label:`Radio`,value:`radio`},{label:`Checkboxes`,value:`checkboxes`},{label:`Lookup (reference)`,value:`lookup`},{label:`Master–Detail`,value:`master_detail`},{label:`Tree`,value:`tree`},{label:`Image`,value:`image`},{label:`File`,value:`file`},{label:`Avatar`,value:`avatar`},{label:`Video`,value:`video`},{label:`Audio`,value:`audio`},{label:`Formula (computed)`,value:`formula`},{label:`Summary (rollup)`,value:`summary`},{label:`Autonumber`,value:`autonumber`},{label:`Composite (embedded)`,value:`composite`},{label:`Repeater (embedded array)`,value:`repeater`},{label:`Record (keyed map)`,value:`record`},{label:`Location (GPS)`,value:`location`},{label:`Address`,value:`address`},{label:`Code`,value:`code`},{label:`JSON`,value:`json`},{label:`Color`,value:`color`},{label:`Rating`,value:`rating`},{label:`Slider`,value:`slider`},{label:`Signature`,value:`signature`},{label:`QR / Barcode`,value:`qrcode`},{label:`Progress`,value:`progress`},{label:`Tags`,value:`tags`},{label:`Vector embedding`,value:`vector`}]},{field:`description`,type:`textarea`,helpText:`Developer documentation for this column`},{field:`required`,type:`boolean`,helpText:`Must be set on every record`},{field:`unique`,type:`boolean`,helpText:`Disallow duplicate values`},{field:`readonly`,type:`boolean`,helpText:`Visible but never user-editable`},{field:`hidden`,type:`boolean`,helpText:`Hidden from default UI`},{field:`searchable`,type:`boolean`,helpText:`Include in full-text search`},{field:`sortable`,type:`boolean`,helpText:`Allow sorting on this column`},{field:`defaultValue`,type:`text`,helpText:`Default value for new records (JSON literal)`},{field:`maxLength`,type:`number`,helpText:`Max characters`,visibleWhen:`type in ['text','textarea','email','url','phone','password','markdown','html','richtext']`},{field:`minLength`,type:`number`,helpText:`Min characters`,visibleWhen:`type in ['text','textarea','email','url','phone','password','markdown','html','richtext']`},{field:`min`,type:`number`,helpText:`Minimum value`,visibleWhen:`type in ['number','currency','percent','rating','slider','progress']`},{field:`max`,type:`number`,helpText:`Maximum value`,visibleWhen:`type in ['number','currency','percent','rating','slider','progress']`},{field:`precision`,type:`number`,helpText:`Total digits`,visibleWhen:`type in ['number','currency','percent']`},{field:`scale`,type:`number`,helpText:`Decimal places`,visibleWhen:`type in ['number','currency','percent']`},{field:`options`,type:`repeater`,helpText:`Available choices`,visibleWhen:`type in ['select','multiselect','radio','checkboxes']`,fields:[{field:`label`,type:`text`,required:!0},{field:`value`,type:`text`,required:!0},{field:`color`,type:`color`},{field:`icon`,type:`text`,helpText:`Lucide icon name`},{field:`description`,type:`text`}]},{field:`reference`,type:`text`,helpText:`Target object name`,visibleWhen:`type in ['lookup','master_detail','tree']`},{field:`lookupFilters`,widget:`json`,helpText:`Filter rules applied to the picker ({field, operator, value})`,visibleWhen:`type in ['lookup','master_detail']`},{field:`deleteBehavior`,type:`select`,helpText:`What happens when the referenced record is deleted`,visibleWhen:`type in ['lookup','master_detail']`,options:[{label:`Set null`,value:`set_null`},{label:`Cascade (delete children)`,value:`cascade`},{label:`Restrict (block the delete)`,value:`restrict`}]},{field:`multiple`,type:`boolean`,helpText:`Allow selecting multiple records`,visibleWhen:`type in ['lookup']`},{field:`expression`,type:`code`,language:`expression`,helpText:`CEL formula expression`,visibleWhen:`type == 'formula'`},{field:`returnType`,type:`select`,helpText:`Result type for formulas`,visibleWhen:`type == 'formula'`,options:[{label:`Text`,value:`text`},{label:`Number`,value:`number`},{label:`Boolean`,value:`boolean`},{label:`Date`,value:`date`},{label:`Datetime`,value:`datetime`},{label:`Currency`,value:`currency`}]},{field:`summaryOperations`,type:`composite`,helpText:`Roll-up: which child object, which field, which aggregation`,visibleWhen:`type == 'summary'`,fields:[{field:`object`,type:`text`,required:!0,helpText:`Source child object name`},{field:`field`,type:`text`,required:!0,helpText:`Field on the child object to aggregate (ignored for count)`},{field:`function`,type:`select`,required:!0,helpText:`Aggregation function`,options:[{label:`Count`,value:`count`},{label:`Sum`,value:`sum`},{label:`Avg`,value:`avg`},{label:`Min`,value:`min`},{label:`Max`,value:`max`}]}]},{field:`autonumberFormat`,type:`text`,helpText:`e.g. "INV-{0000}"; date tokens {YYYY}/{MM}/{DD} and {field_name} interpolation supported`,visibleWhen:`type == 'autonumber'`},{field:`language`,type:`text`,helpText:`Editor language (e.g. sql, javascript)`,visibleWhen:`type == 'code'`},{field:`trackHistory`,type:`boolean`,helpText:`Summarize this field on the record activity timeline`},{field:`visibleWhen`,type:`code`,language:`expression`,helpText:`CEL predicate — field is shown only when TRUE`},{field:`readonlyWhen`,type:`code`,language:`expression`,helpText:`CEL predicate — field is read-only when TRUE (enforced server-side)`},{field:`requiredWhen`,type:`code`,language:`expression`,helpText:`CEL predicate — field is required when TRUE (enforced server-side)`}]}]},{name:`capabilities`,label:`Capabilities`,description:`System features and API exposure.`,collapsible:!0,collapsed:!0,fields:[{field:`enable`,type:`composite`,helpText:`Enable/disable system features`,fields:[{field:`trackHistory`,type:`boolean`},{field:`searchable`,type:`boolean`},{field:`apiEnabled`,type:`boolean`},{field:`files`,type:`boolean`},{field:`feeds`,type:`boolean`},{field:`activities`,type:`boolean`},{field:`clone`,type:`boolean`}]}]},{name:`advanced`,label:`Advanced`,description:`State machines, actions, and storage.`,collapsible:!0,collapsed:!0,fields:[{field:`datasource`,type:`text`,helpText:`Target datasource ID (default: "default")`},{field:`lifecycle`,type:`composite`,helpText:`Data lifecycle contract (ADR-0057): how long rows live and how space is reclaimed. Leave empty for permanent record semantics. Non-record classes require at least one bounding policy (retention, TTL, or rotation).`,fields:[{field:`class`,type:`select`,helpText:`Persistence contract for the rows of this object`,options:[{label:`Record (business truth — permanent)`,value:`record`},{label:`Audit (compliance ledger — retain → archive → delete)`,value:`audit`},{label:`Telemetry (high-frequency log — short retention)`,value:`telemetry`},{label:`Transient (ephemeral state — TTL expiry)`,value:`transient`},{label:`Event (bus messages — very short TTL)`,value:`event`}]},{field:`retention`,type:`composite`,helpText:`Age-based retention window`,fields:[{field:`maxAge`,type:`text`,helpText:`Rows older than this (by created_at) are reaped. Duration literal: h/d/w/y, e.g. "30d"`}]},{field:`ttl`,type:`composite`,helpText:`Per-row TTL expiry`,fields:[{field:`field`,type:`text`,helpText:`Timestamp field the TTL is measured from (e.g. expires_at)`},{field:`expireAfter`,type:`text`,helpText:`Rows expire this long after the field, e.g. "1d"`}]},{field:`storage`,type:`composite`,helpText:`Physical rotation for high-frequency telemetry (SQLite: O(1) shard DROP)`,fields:[{field:`strategy`,type:`select`,helpText:`Storage strategy`,options:[{label:`Rotation (time-shard + drop oldest)`,value:`rotation`}]},{field:`shards`,type:`number`,min:2,helpText:`Shards retained; total window = shards × unit`},{field:`unit`,type:`select`,helpText:`Time width of one shard`,options:[{label:`Day`,value:`day`},{label:`Week`,value:`week`},{label:`Month`,value:`month`}]}]},{field:`archive`,type:`composite`,helpText:`Cold-store hand-off (audit class). Rows are never hot-deleted before the archive copy succeeded.`,fields:[{field:`after`,type:`text`,helpText:`Archive rows older than this — must equal retention.maxAge`},{field:`to`,type:`text`,helpText:`Target datasource name for cold storage`},{field:`keep`,type:`text`,helpText:`How long the archive keeps rows (empty = forever), e.g. "7y"`}]},{field:`reclaim`,type:`boolean`,helpText:`Reclaim driver space after sweeps (default on for non-record classes)`}]}]}]}),Jo=Er({schemaId:`field`,type:`simple`,sections:[{name:`basics`,label:`Basics`,description:`Core field identity and constraints.`,columns:2,fields:[{field:`name`,required:!0,immutable:!0,colSpan:1,helpText:`Unique identifier (snake_case, immutable after creation)`},{field:`label`,required:!0,colSpan:1,helpText:`Display name for users`},{field:`type`,required:!0,colSpan:1,helpText:`Data type of this field`},{field:`group`,colSpan:1,helpText:`Group name for form layout`},{field:`description`,widget:`textarea`,colSpan:2,helpText:`Help text shown to users`},{field:`required`,colSpan:1,helpText:`User must provide a value`},{field:`unique`,colSpan:1,helpText:`No two records can have the same value`},{field:`multiple`,colSpan:1,helpText:`Allow multiple values (for select/lookup)`}]},{name:`configuration`,label:`Configuration`,description:`Field-type specific settings (visible blocks depend on the chosen type).`,fields:[{field:`defaultValue`,helpText:`Default value for new records`},{field:`minLength`,visibleWhen:`data.type == 'text' || data.type == 'textarea' || data.type == 'email'`,helpText:`Minimum character length`},{field:`maxLength`,visibleWhen:`data.type == 'text' || data.type == 'textarea' || data.type == 'email'`,helpText:`Maximum character length`},{field:`min`,visibleWhen:`data.type == 'number' || data.type == 'currency'`,helpText:`Minimum value`},{field:`max`,visibleWhen:`data.type == 'number' || data.type == 'currency'`,helpText:`Maximum value`},{field:`precision`,visibleWhen:`data.type == 'currency' || data.type == 'number'`,helpText:`Decimal places (e.g., 2 for $10.50)`},{field:`scale`,visibleWhen:`data.type == 'number'`,helpText:`Number of decimal digits`},{field:`options`,type:`repeater`,visibleWhen:`data.type == 'select' || data.type == 'multiselect'`,helpText:`Available options (label/value pairs)`},{field:`reference`,widget:`ref:object`,visibleWhen:`data.type == 'lookup' || data.type == 'master_detail'`,helpText:`Referenced object name`},{field:`deleteBehavior`,visibleWhen:`data.type == 'lookup' || data.type == 'master_detail'`,helpText:`What happens when referenced record is deleted`}]},{name:`formula`,label:`Formula & Computed`,description:`Calculated values and roll-up summaries.`,collapsible:!0,collapsed:!0,fields:[{field:`expression`,widget:`textarea`,helpText:`CEL expression to calculate this field (makes it read-only)`},{field:`summaryOperations`,type:`composite`,visibleWhen:`data.type == 'summary'`,helpText:`Roll-up summary configuration (for parent-child relationships)`,fields:[{field:`object`,widget:`ref:object`,required:!0,helpText:`Child object to aggregate`},{field:`function`,type:`select`,required:!0,options:[{label:`Count`,value:`count`},{label:`Sum`,value:`sum`},{label:`Min`,value:`min`},{label:`Max`,value:`max`},{label:`Average`,value:`avg`}],helpText:`Aggregation function`},{field:`field`,required:!0,helpText:`Child field to aggregate (ignored for count)`},{field:`relationshipField`,helpText:`Child FK back to this parent (auto-detected when omitted)`},{field:`filter`,widget:`filter-condition`,helpText:`Only child rows matching this predicate are aggregated (e.g. status == received)`}]}]},{name:`advanced`,label:`Advanced`,description:`Database, UI, audit, and security settings.`,collapsible:!0,collapsed:!0,columns:2,fields:[{field:`externalId`,colSpan:1,helpText:`Mark as external ID for upsert operations`},{field:`readonly`,colSpan:1,helpText:`Field is read-only in forms`},{field:`hidden`,colSpan:1,helpText:`Hide field from default UI views`},{field:`searchable`,colSpan:1,helpText:`Include in global search results`},{field:`sortable`,colSpan:1,helpText:`Allow sorting lists by this field`}]}]}),Yo=Er({schemaId:`hook`,type:`simple`,sections:[{label:`Identity`,description:`What this hook is and when it fires.`,columns:2,fields:[{field:`name`,type:`text`,required:!0,immutable:!0,colSpan:1,helpText:`snake_case identifier (immutable after creation)`},{field:`label`,type:`text`,colSpan:1},{field:`description`,type:`textarea`,colSpan:2},{field:`object`,type:`text`,required:!0,colSpan:1,helpText:`Target object name (or "*" for global)`},{field:`events`,type:`tags`,required:!0,colSpan:1,helpText:`Lifecycle events (e.g. beforeInsert, afterUpdate)`},{field:`priority`,type:`number`,colSpan:1,helpText:`Lower numbers run first`}]},{label:`Body`,description:`Inline expression or sandboxed JavaScript executed when the hook fires.`,fields:[{field:`body`,type:`composite`,helpText:`Either an L1 expression or an L2 sandboxed JS body`,fields:[{field:`language`,type:`select`,required:!0,helpText:`expression = pure formula; js = sandboxed JavaScript`,options:[{label:`Expression (L1)`,value:`expression`},{label:`JavaScript (L2 sandboxed)`,value:`js`}]},{field:`source`,type:`code`,language:`javascript`,required:!0,helpText:`Function body source — no top-level imports`},{field:`capabilities`,type:`tags`,helpText:`Allowed ctx APIs (api.read, api.write, crypto.uuid, log, …)`},{field:`timeoutMs`,type:`number`,helpText:`Per-invocation timeout (ms)`},{field:`memoryMb`,type:`number`,helpText:`Per-invocation memory cap (MB, max 256)`}]}]},{label:`Legacy handler`,description:`Function name reference — deprecated in favour of body.`,collapsible:!0,collapsed:!0,fields:[{field:`handler`,type:`text`,helpText:"Handler function name (deprecated — prefer `body`)"}]},{label:`Execution`,collapsible:!0,collapsed:!0,columns:2,fields:[{field:`async`,type:`boolean`,colSpan:1,helpText:`Run in background, do not block the transaction`},{field:`onError`,type:`select`,colSpan:1,options:[{label:`Abort`,value:`abort`},{label:`Log`,value:`log`}]},{field:`timeout`,type:`number`,colSpan:1,helpText:`Abort the hook after N milliseconds`},{field:`condition`,type:`code`,language:`javascript`,colSpan:2,helpText:`Optional formula — skip the hook when this evaluates to false`},{field:`retryPolicy`,type:`composite`,colSpan:2,helpText:`Retry on failure — most useful for async hooks`,fields:[{field:`maxRetries`,type:`number`,helpText:`Maximum retry attempts`},{field:`backoffMs`,type:`number`,helpText:`Delay between retries (ms)`}]}]}]}),Xo=n(()=>t.z.object({field:t.z.string().describe(`Source field name containing the reference value`),targetObject:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Target object name (snake_case)`),targetField:t.z.string().default(`name`).describe(`Field on target object used for matching`),fieldType:t.z.enum([`lookup`,`master_detail`,`user`]).describe(`Relationship field type`),multiple:t.z.boolean().optional().describe(`Field stores an array of references (multiple: true)`)}).describe(`Describes how a field reference is resolved during seed loading`)),Zo=n(()=>t.z.object({object:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Object name (snake_case)`),dependsOn:t.z.array(t.z.string()).describe(`Objects this object depends on`),references:t.z.array(Xo).describe(`Field-level reference details`)}).describe(`Object node in the seed data dependency graph`)),Qo=n(()=>t.z.object({nodes:t.z.array(Zo).describe(`All objects in the dependency graph`),insertOrder:t.z.array(t.z.string()).describe(`Topologically sorted insert order`),circularDependencies:t.z.array(t.z.array(t.z.string())).default([]).describe(`Circular dependency chains (e.g., [["a", "b", "a"]])`)}).describe(`Complete object dependency graph for seed data loading`)),$o=n(()=>t.z.object({sourceObject:t.z.string().describe(`Object with the broken reference`),field:t.z.string().describe(`Field name with unresolved reference`),targetObject:t.z.string().describe(`Target object searched for the reference`),targetField:t.z.string().describe(`ExternalId field used for matching`),attemptedValue:t.z.unknown().describe(`Value that failed to resolve`),recordIndex:t.z.number().int().min(0).describe(`Index of the record in the dataset`),message:t.z.string().describe(`Human-readable error description`)}).describe(`Actionable error for a failed reference resolution`)),es=t.z.object({user:t.z.object({id:t.z.string().min(1),role:t.z.string().optional(),email:t.z.string().optional()}).optional().describe(`Subject bound to os.user in seed CEL expressions`),org:t.z.object({id:t.z.string().min(1),tier:t.z.string().optional()}).optional().describe(`Organization bound to os.org in seed CEL expressions`)}).describe(`Identity context for resolving os.user / os.org in seed CEL values`),ts=n(()=>t.z.object({dryRun:t.z.boolean().default(!1).describe(`Validate references without writing data`),haltOnError:t.z.boolean().default(!1).describe(`Stop on first reference resolution error`),multiPass:t.z.boolean().default(!0).describe(`Enable multi-pass loading for circular dependencies`),defaultMode:Wo.default(`upsert`).describe(`Default conflict resolution strategy`),batchSize:t.z.number().int().min(1).default(1e3).describe(`Maximum records per batch insert/upsert`),transaction:t.z.boolean().default(!1).describe(`Wrap entire load in a transaction (all-or-nothing)`),env:t.z.enum([`prod`,`dev`,`test`]).optional().describe(`Only load datasets matching this environment`),organizationId:t.z.string().min(1).optional().describe(`Target organization id for per-tenant seed replay`),identity:es.optional().describe(`Identity bound to os.user / os.org when resolving CEL seed values`)}).describe(`Seed data loader configuration`)),ns=n(()=>t.z.object({object:t.z.string().describe(`Object that was loaded`),mode:Wo.describe(`Import mode used`),inserted:t.z.number().int().min(0).describe(`Records inserted`),updated:t.z.number().int().min(0).describe(`Records updated`),skipped:t.z.number().int().min(0).describe(`Records skipped`),errored:t.z.number().int().min(0).describe(`Records with errors`),total:t.z.number().int().min(0).describe(`Total records in dataset`),referencesResolved:t.z.number().int().min(0).describe(`References resolved via externalId`),referencesDeferred:t.z.number().int().min(0).describe(`References deferred to second pass`),referencesDropped:t.z.number().int().min(0).default(0).describe(`Reference fields dropped from records that were still written`),errors:t.z.array($o).default([]).describe(`Reference resolution errors`)}).describe(`Result of loading a single dataset`)),rs=n(()=>t.z.object({success:t.z.boolean().describe(`Overall success status`),dryRun:t.z.boolean().describe(`Whether this was a dry-run`),dependencyGraph:Qo.describe(`Object dependency graph`),results:t.z.array(ns).describe(`Per-object load results`),errors:t.z.array($o).describe(`All reference resolution errors`),summary:t.z.object({objectsProcessed:t.z.number().int().min(0).describe(`Total objects processed`),totalRecords:t.z.number().int().min(0).describe(`Total records across all objects`),totalInserted:t.z.number().int().min(0).describe(`Total records inserted`),totalUpdated:t.z.number().int().min(0).describe(`Total records updated`),totalSkipped:t.z.number().int().min(0).describe(`Total records skipped`),totalErrored:t.z.number().int().min(0).describe(`Total records with errors`),totalReferencesResolved:t.z.number().int().min(0).describe(`Total references resolved`),totalReferencesDeferred:t.z.number().int().min(0).describe(`Total references deferred`),totalReferencesDropped:t.z.number().int().min(0).default(0).describe(`Total reference fields dropped from written records`),circularDependencyCount:t.z.number().int().min(0).describe(`Circular dependency chains detected`),durationMs:t.z.number().min(0).describe(`Load duration in milliseconds`)}).describe(`Summary statistics`)}).describe(`Complete seed loader result`)),is=n(()=>t.z.object({seeds:t.z.array(Go).min(1).describe(`Seeds to load`),config:ts.default(()=>ts.parse({})).describe(`Loader configuration`)}).describe(`Seed loader request with datasets and configuration`)),as=n(()=>t.z.object({versionNumber:t.z.number().describe(`Version number`),createdAt:t.z.number().describe(`Creation timestamp`),createdBy:t.z.string().describe(`Creator user ID`),size:t.z.number().describe(`File size in bytes`),checksum:t.z.string().describe(`File checksum`),downloadUrl:t.z.string().url().describe(`Download URL`),isLatest:t.z.boolean().optional().default(!1).describe(`Is latest version`)})),os=n(()=>t.z.object({id:t.z.string().describe(`Template ID`),name:t.z.string().describe(`Template name`),description:t.z.string().optional().describe(`Template description`),fileUrl:t.z.string().url().describe(`Template file URL`),fileType:t.z.string().describe(`File MIME type`),placeholders:t.z.array(t.z.object({key:t.z.string().describe(`Placeholder key`),label:t.z.string().describe(`Placeholder label`),type:t.z.enum([`text`,`number`,`date`,`image`]).describe(`Placeholder type`),required:t.z.boolean().optional().default(!1).describe(`Is required`)})).describe(`Template placeholders`)})),ss=n(()=>t.z.object({provider:t.z.enum([`docusign`,`adobe-sign`,`hellosign`,`custom`]).describe(`E-signature provider`),enabled:t.z.boolean().optional().default(!1).describe(`E-signature enabled`),signers:t.z.array(t.z.object({email:t.z.string().email().describe(`Signer email`),name:t.z.string().describe(`Signer name`),role:t.z.string().describe(`Signer role`),order:t.z.number().describe(`Signing order`)})).describe(`Document signers`),expirationDays:t.z.number().optional().default(30).describe(`Expiration days`),reminderDays:t.z.number().optional().default(7).describe(`Reminder interval days`)})),cs=n(()=>t.z.object({id:t.z.string().describe(`Document ID`),name:t.z.string().describe(`Document name`),description:t.z.string().optional().describe(`Document description`),fileType:t.z.string().describe(`File MIME type`),fileSize:t.z.number().describe(`File size in bytes`),category:t.z.string().optional().describe(`Document category`),tags:t.z.array(t.z.string()).optional().describe(`Document tags`),versioning:t.z.object({enabled:t.z.boolean().describe(`Versioning enabled`),versions:t.z.array(as).describe(`Version history`),majorVersion:t.z.number().describe(`Major version`),minorVersion:t.z.number().describe(`Minor version`)}).optional().describe(`Version control`),template:os.optional().describe(`Document template`),eSignature:ss.optional().describe(`E-signature config`),access:t.z.object({isPublic:t.z.boolean().optional().default(!1).describe(`Public access`),sharedWith:t.z.array(t.z.string()).optional().describe(`Shared with`),expiresAt:t.z.number().optional().describe(`Access expiration`)}).optional().describe(`Access control`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Custom metadata`)})),ls=n(()=>t.z.discriminatedUnion(`type`,[t.z.object({type:t.z.literal(`constant`),value:t.z.unknown().describe(`Constant value to use`)}).describe(`Set a constant value`),t.z.object({type:t.z.literal(`cast`),targetType:t.z.enum([`string`,`number`,`boolean`,`date`]).describe(`Target data type`)}).describe(`Cast to a specific data type`),t.z.object({type:t.z.literal(`lookup`),table:t.z.string().describe(`Lookup table name`),keyField:t.z.string().describe(`Field to match on`),valueField:t.z.string().describe(`Field to retrieve`)}).describe(`Lookup value from another table`),t.z.object({type:t.z.literal(`javascript`),expression:k.describe(`JS expression (dialect="js" recommended). e.g. value.toUpperCase()`)}).describe(`Custom JavaScript transformation`),t.z.object({type:t.z.literal(`map`),mappings:t.z.record(t.z.string(),t.z.unknown()).describe(`Value mappings (e.g., {"Active": "active"})`)}).describe(`Map values using a dictionary`)])),us=n(()=>t.z.object({source:t.z.string().describe(`Source field name`),target:t.z.string().describe(`Target field name`),transform:ls.optional().describe(`Transformation to apply`),defaultValue:t.z.unknown().optional().describe(`Default if source is null/undefined`)})),ds=n(()=>t.z.object({id:t.z.string().describe(`Data source ID`),name:t.z.string().describe(`Data source name`),type:t.z.enum([`odata`,`rest-api`,`graphql`,`custom`]).describe(`Protocol type`),endpoint:t.z.string().url().describe(`API endpoint URL`),authentication:t.z.object({type:t.z.enum([`oauth2`,`api-key`,`basic`,`none`]).describe(`Auth type`),config:t.z.record(t.z.string(),t.z.unknown()).describe(`Auth configuration`)}).describe(`Authentication`)})),fs=n(()=>us.extend({type:t.z.string().optional().describe(`Field type`),readonly:t.z.boolean().optional().default(!0).describe(`Read-only field`)})),ps=n(()=>t.z.object({fieldName:t.z.string().describe(`Field name`),dataSource:ds.describe(`External data source`),query:t.z.object({endpoint:t.z.string().describe(`Query endpoint path`),method:t.z.enum([`GET`,`POST`]).optional().default(`GET`).describe(`HTTP method`),parameters:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Query parameters`)}).describe(`Query configuration`),fieldMappings:t.z.array(fs).describe(`Field mappings`),caching:t.z.object({enabled:t.z.boolean().optional().default(!0).describe(`Cache enabled`),ttl:t.z.number().optional().default(300).describe(`Cache TTL (seconds)`),strategy:t.z.enum([`lru`,`lfu`,`ttl`]).optional().default(`ttl`).describe(`Cache strategy`)}).optional().describe(`Caching configuration`),fallback:t.z.object({enabled:t.z.boolean().optional().default(!0).describe(`Fallback enabled`),defaultValue:t.z.unknown().optional().describe(`Default fallback value`),showError:t.z.boolean().optional().default(!0).describe(`Show error to user`)}).optional().describe(`Fallback configuration`),rateLimit:t.z.object({requestsPerSecond:t.z.number().describe(`Requests per second limit`),burstSize:t.z.number().optional().describe(`Burst size`)}).optional().describe(`Rate limiting`),retry:t.z.object({maxRetries:t.z.number().min(0).default(3).describe(`Maximum retry attempts`),initialDelayMs:t.z.number().default(1e3).describe(`Initial retry delay in milliseconds`),maxDelayMs:t.z.number().default(3e4).describe(`Maximum retry delay in milliseconds`),backoffMultiplier:t.z.number().default(2).describe(`Exponential backoff multiplier`),retryableStatusCodes:t.z.array(t.z.number()).default([429,500,502,503,504]).describe(`HTTP status codes that are retryable`)}).optional().describe(`Retry configuration with exponential backoff`),transform:t.z.object({request:t.z.object({headers:t.z.record(t.z.string(),t.z.string()).optional().describe(`Additional request headers`),queryParams:t.z.record(t.z.string(),t.z.string()).optional().describe(`Additional query parameters`)}).optional().describe(`Request transformation`),response:t.z.object({dataPath:t.z.string().optional().describe(`JSONPath to extract data (e.g., "$.data.results")`),totalPath:t.z.string().optional().describe(`JSONPath to extract total count (e.g., "$.meta.total")`)}).optional().describe(`Response transformation`)}).optional().describe(`Request/response transformation pipeline`),pagination:t.z.object({type:t.z.enum([`offset`,`cursor`,`page`]).default(`offset`).describe(`Pagination type`),pageSize:t.z.number().default(100).describe(`Items per page`),maxPages:t.z.number().optional().describe(`Maximum number of pages to fetch`)}).optional().describe(`Pagination configuration for external data`)})),ms=t.z.enum([`off`,`safe`]).describe(`Dev-only non-destructive schema self-heal (#2186)`),hs="`schemaMode` is a datasource-level key, not driver config. Write it next to `driver` (`schemaMode: 'external'`) — the connection service now carries it down to the driver, so the copy inside `config` is gone rather than duplicated.",gs="`readOnly` is not driver config, and there is no datasource key that makes a connection read-only. For a FEDERATED datasource use `external.allowWrites: false`, which the ObjectQL engine enforces before every write. For a managed (local) datasource there is currently no read-only gate — grant the connection SELECT-only at the database instead, which is a real boundary rather than an application-layer flag (#4584).",_s=t.z.boolean().describe("Enable TLS. Certificates go in the datasource-level `ssl` block."),Z="Certificates and verification live in the datasource-level `ssl` block, not in driver config: `ssl: { enabled: true, rejectUnauthorized: false, ca: … }` next to `driver`. Inside `config`, `ssl` is the on/off shorthand only.",vs={target:`draft-2020-12`,io:`input`,unrepresentable:`any`};function ys(e){let n;return()=>(n===void 0&&(n=t.z.toJSONSchema(e,vs)),n)}var bs=n(()=>t.z.object({load:t.z.function().describe(`Load persisted data on startup. Returns Promise<Record<string, any[]> | null>`),save:t.z.function().describe(`Save data to persistent storage. Accepts Record<string, any[]>, returns Promise<void>`),flush:t.z.function().describe(`Flush pending writes and ensure data is persisted. Returns Promise<void>`)}).describe(`Custom persistence adapter interface`)),xs=n(()=>t.z.enum([`file`,`local`,`auto`]).describe(`Persistence backend type`)),Ss=n(()=>t.z.object({type:t.z.literal(`file`),path:t.z.string().optional().describe(`File path to persist data`),autoSaveInterval:t.z.number().min(100).default(2e3).describe(`Auto-save interval in ms`)}).describe(`File-system persistence configuration`)),Cs=n(()=>t.z.object({type:t.z.literal(`local`),key:t.z.string().optional().describe(`localStorage key for persisted data`)}).describe(`localStorage persistence configuration`)),Q=n(()=>t.z.object({adapter:bs}).describe(`Custom adapter persistence configuration`)),ws=n(()=>t.z.object({type:t.z.literal(`auto`),path:t.z.string().optional().describe(`File path override for Node.js environments`),autoSaveInterval:t.z.number().min(100).optional().describe(`Auto-save interval override for Node.js environments`),key:t.z.string().optional().describe(`localStorage key override for browser environments`)}).describe(`Auto-detect persistence configuration`)),Ts=n(()=>t.z.union([xs,Ss,Cs,ws,Q]).describe(`Persistence configuration for the memory driver`)),Es=w({surface:`this memory datasource's config`,knownKeys:[`initialData`,`strictMode`,`persistence`],aliases:{data:`initialData`,seed:`initialData`,seeddata:`initialData`,strict:`strictMode`,persist:`persistence`,persistent:`persistence`},guidance:{indexes:"`indexes` was declared but never read: the memory driver keeps no indexes — every read is a linear Mingo scan — so it changed nothing. Drop it, or move the datasource to a driver that indexes (`sqlite` / `postgres`), where object-level `indexes` apply.",maxRecordsPerObject:"`maxRecordsPerObject` was declared but never read: the memory driver evicts nothing, so a bound here was never enforced and the store grew unbounded regardless. Drop it and bound the data you load, or use a driver with real storage limits.",filename:"`filename` is a sqlite key. For a memory datasource that survives restarts set `persistence: 'file'` (the file is scoped per datasource); for a real file-backed SQL database set `driver: 'sqlite'`.",schemaMode:hs,readOnly:gs},history:"Until #4410 nothing validated `datasource.config` at all — an unrecognised key was accepted in silence and the store came up on the driver defaults instead."}),Ds=n(()=>t.z.object({initialData:t.z.record(t.z.string(),t.z.array(t.z.record(t.z.string(),t.z.unknown()))).optional().describe(`Pre-populated data keyed by object name`),strictMode:t.z.boolean().default(!1).describe(`Throw on missing records instead of returning null`),persistence:Ts.or(t.z.literal(!1)).default(!1).describe(`Persistence configuration (opt-in; defaults to pure in-memory)`)},{error:Es}).strict().describe(`Memory Driver Connection Configuration`)),Os=ys(Ds),ks={id:`memory`,label:`In-Memory`,description:`High-performance in-memory driver powered by Mingo (MongoDB-compatible query engine). Supports filtering, aggregation pipelines, sorting, projection.`,icon:`memory`,get configSchema(){return Os()}},As=w({surface:`this mongo datasource's config`,knownKeys:[`url`,`host`,`port`,`database`,`username`,`password`,`authSource`,`options`],aliases:{uri:`url`,connectionstring:`url`,dsn:`url`,hostname:`host`,server:`host`,dbname:`database`,db:`database`,user:`username`,passwd:`password`,pwd:`password`,authdb:`authSource`,authdatabase:`authSource`,replicaset:`options`},guidance:{pool:"`pool` is not driver config — connection pooling is configured once for every driver in the datasource's own `pool` block, which the factory maps onto the Mongo client's `minPoolSize`/`maxPoolSize`. Move it next to `driver`.",schemaMode:hs,readOnly:gs,ssl:"`ssl` is not a top-level mongo key. TLS is a connection-string concern here: put it in `url` (`?tls=true`) or in the `options` passthrough the Mongo client reads."},history:"Until #4410 nothing validated `datasource.config` at all — an unrecognised connection key was accepted in silence and the datasource then connected to mongodb://localhost:27017 rather than failing."}),js=n(()=>t.z.object({url:t.z.string().optional().describe(`Connection URI (supersedes the discrete fields)`).meta({title:`Connection URI`}),database:t.z.string().min(1).optional().describe(`Database name`).meta({title:`Database`}),host:t.z.string().default(`localhost`).describe(`Host address`).meta({title:`Host`}),port:t.z.number().int().default(27017).describe(`Port number`).meta({title:`Port`}),username:t.z.string().optional().describe(`Authentication user`).meta({title:`User`}),password:t.z.string().optional().describe(`Authentication password (prefer external.credentialsRef)`).meta({title:`Password`,format:`password`}),authSource:t.z.string().optional().describe(`Authentication database`).meta({title:`Auth source`}),options:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Extra MongoClient options (replicaSet, tls, timeouts, …)`)},{error:As}).strict().describe(`MongoDB Connection Configuration`).superRefine((e,t)=>{!e.url&&!e.database&&t.addIssue({code:`custom`,path:[`database`],message:"A mongo datasource needs a connection target: set `database` (with `host`/`port`) or a full `url`. Neither was given, so the connection would fall back to mongodb://localhost:27017 with no database selected."})})),Ms=ys(js),Ns={id:`mongo`,label:`MongoDB`,description:`Official MongoDB Driver for ObjectStack. Supports rich queries, aggregation, and atomic updates.`,icon:`database`,get configSchema(){return Ms()}},Ps=w({surface:`this mysql datasource's config`,knownKeys:[`url`,`host`,`port`,`database`,`username`,`password`,`ssl`,`autoMigrate`],aliases:{hostname:`host`,server:`host`,dbname:`database`,db:`database`,schema:`database`,user:`username`,passwd:`password`,pwd:`password`,connectionstring:`url`,dsn:`url`,uri:`url`,sslmode:`ssl`,tls:`ssl`,usessl:`ssl`},guidance:{pool:"`pool` is not driver config — connection pooling is configured once for every driver in the datasource's own `pool` block. Move it next to `driver`.",schemaMode:hs,readOnly:gs,ca:Z,cert:Z,key:Z,rejectUnauthorized:Z,charset:"`charset` is not honoured: the factory builds the mysql2 connection from the keys listed here only. Put it in the `url` as a query parameter (`?charset=utf8mb4`) so the client actually receives it."},history:"Until #4410 nothing validated `datasource.config` at all — an unrecognised connection key was accepted in silence and the datasource then connected on the client defaults (localhost:3306) rather than failing."}),Fs=n(()=>t.z.object({url:t.z.string().optional().describe(`Connection URI (supersedes the discrete fields)`).meta({title:`Connection URL`}),host:t.z.string().default(`localhost`).describe(`Host address`).meta({title:`Host`}),port:t.z.number().int().default(3306).describe(`Port number`).meta({title:`Port`}),database:t.z.string().optional().describe(`Database name`).meta({title:`Database`}),username:t.z.string().optional().describe(`Authentication user`).meta({title:`User`}),password:t.z.string().optional().describe(`Authentication password (prefer external.credentialsRef)`).meta({title:`Password`,format:`password`}),ssl:_s.optional().meta({title:`Use SSL/TLS`}),autoMigrate:ms.optional()},{error:Ps}).strict().describe(`MySQL / MariaDB connection configuration`).superRefine((e,t)=>{!e.url&&!e.database&&t.addIssue({code:`custom`,path:[`database`],message:"A mysql datasource needs a connection target: set `database` (with `host`/`port`) or a full `url`. Neither was given, so the connection would fall back to the client defaults and silently open a different database than the one intended."})})),Is=ys(Fs),Ls=[`url`,`host`,`port`,`database`,`username`,`password`,`ssl`,`schema`,`applicationName`,`statementTimeout`,`autoMigrate`],Rs=(e,t)=>`\`${e}\` is not driver config \u2014 connection pooling is configured once for every driver in the datasource's own \`pool\` block. Move it to \`pool: { ${t}: \u2026 }\`. (It was declared here and read by nothing until #4410.)`,zs=w({surface:`this postgres datasource's config`,knownKeys:Ls,aliases:{hostname:`host`,server:`host`,dbname:`database`,db:`database`,user:`username`,passwd:`password`,pwd:`password`,connectionstring:`url`,dsn:`url`,uri:`url`,searchpath:`schema`,applicationname:`applicationName`,statementtimeout:`statementTimeout`,sslmode:`ssl`,tls:`ssl`,usessl:`ssl`},guidance:{pool:Rs(`pool`,`max`),min:Rs(`min`,`min`),max:Rs(`max`,`max`),idleTimeoutMillis:Rs(`idleTimeoutMillis`,`idleTimeoutMillis`),connectionTimeoutMillis:Rs(`connectionTimeoutMillis`,`connectionTimeoutMillis`),schemaMode:hs,readOnly:gs,ca:Z,cert:Z,key:Z,rejectUnauthorized:Z},history:"Until #4410 nothing validated `datasource.config` at all — an unrecognised connection key was accepted in silence and the datasource then connected on the client defaults (localhost:5432), which is #4001's original bug one level down."}),Bs=n(()=>t.z.object({url:t.z.string().optional().describe(`Connection URI (supersedes the discrete fields)`).meta({title:`Connection URL`}),host:t.z.string().default(`localhost`).describe(`Host address`).meta({title:`Host`}),port:t.z.number().int().default(5432).describe(`Port number`).meta({title:`Port`}),database:t.z.string().optional().describe(`Database name`).meta({title:`Database`}),username:t.z.string().optional().describe(`Authentication user`).meta({title:`User`}),password:t.z.string().optional().describe(`Authentication password (prefer external.credentialsRef)`).meta({title:`Password`,format:`password`}),ssl:_s.optional().meta({title:`Use SSL/TLS`}),schema:t.z.string().default(`public`).describe(`Default schema (knex searchPath)`).meta({title:`Schema`}),applicationName:t.z.string().optional().describe(`Postgres application_name`).meta({title:`Application name`}),statementTimeout:t.z.number().int().positive().optional().describe(`Abort statements running longer than this (ms)`).meta({title:`Statement timeout (ms)`}),autoMigrate:ms.optional()},{error:zs}).strict().describe(`PostgreSQL connection configuration`).superRefine((e,t)=>{!e.url&&!e.database&&t.addIssue({code:`custom`,path:[`database`],message:"A postgres datasource needs a connection target: set `database` (with `host`/`port`) or a full `url`. Neither was given, so the connection would fall back to the client defaults and silently open a different database than the one intended."})})),Vs=ys(Bs),Hs=[`filename`,`autoMigrate`],Us={file:`filename`,filepath:`filename`,path:`filename`,database:`filename`,db:`filename`,url:`filename`,connectionstring:`filename`},Ws="Until #4410 nothing validated `datasource.config` at all — a misspelled `filename` was accepted in silence and the database silently became an ephemeral `:memory:` one, so the data was gone on the next boot with nothing having reported a problem.",Gs="`memory` is not a sqlite key. An ephemeral database is `filename: ':memory:'`; for the mingo in-memory engine (a different driver entirely) set `driver: 'memory'`.",Ks=w({surface:`this sqlite datasource's config`,knownKeys:Hs,aliases:Us,guidance:{schemaMode:hs,readOnly:gs,memory:Gs,persist:"`persist` is a `sqlite-wasm` key — the native sqlite driver writes through on every statement and has nothing to schedule. Set `driver: 'sqlite-wasm'` to use it."},history:Ws}),qs=n(()=>t.z.object({filename:t.z.string().default(`:memory:`).describe(`Database file path, or ":memory:" for an ephemeral database`).meta({title:`Filename`}),autoMigrate:ms.optional()},{error:Ks}).strict().describe(`SQLite connection configuration`)),Js=ys(qs),Ys=t.z.union([t.z.literal(`on-disconnect`),t.z.literal(`on-write`),t.z.string().regex(/^debounced:\d+$/,"Expected `debounced:<milliseconds>`")]).describe(`When to flush a file-backed wasm database to disk`),Xs=w({surface:`this sqlite-wasm datasource's config`,knownKeys:[`filename`,`persist`],aliases:Us,guidance:{schemaMode:hs,readOnly:gs,memory:Gs,autoMigrate:"`autoMigrate` is honoured by the native sqlite / postgres / mysql drivers only — the wasm driver is constructed without it, so writing it here would change nothing."},history:Ws}),Zs=n(()=>t.z.object({filename:t.z.string().default(`:memory:`).describe(`Database file path, or ":memory:" for an ephemeral database`).meta({title:`Filename`}),persist:Ys.optional().meta({title:`Persist mode`})},{error:Xs}).strict().describe(`SQLite (WASM) connection configuration`)),Qs=ys(Zs),$s=[`memory`,`sqlite`,`sqlite-wasm`,`postgres`,`mysql`,`mongo`],ec={memory:`memory`,inmemory:`memory`,"in-memory":`memory`,mingo:`memory`,sqlite:`sqlite`,sqlite3:`sqlite`,"better-sqlite3":`sqlite`,"sqlite-wasm":`sqlite-wasm`,"wasm-sqlite":`sqlite-wasm`,postgres:`postgres`,postgresql:`postgres`,pg:`postgres`,mysql:`mysql`,mysql2:`mysql`,mariadb:`mysql`,mongo:`mongo`,mongodb:`mongo`};function tc(e){if(typeof e==`string`)return ec[e.trim().toLowerCase()]}var nc={memory:Ds,sqlite:qs,"sqlite-wasm":Zs,postgres:Bs,mysql:Fs,mongo:js};function rc(e){let t=tc(e);return t?nc[t]:void 0}var ic={memory:Os,sqlite:Js,"sqlite-wasm":Qs,postgres:Vs,mysql:Is,mongo:Ms};function ac(e){return ic[e]()}function oc(e,t){let n=rc(e);if(!n)return{known:!1};let r=n.safeParse(t??{});return r.success?{known:!0,issues:[]}:{known:!0,issues:r.error.issues.map(e=>({path:[...e.path],message:e.message}))}}var sc=[`id`,`label`,`description`,`icon`,`configSchema`],cc=[`allowedSchemas`,`allowWrites`,`validation`,`credentialsRef`,`queryTimeoutMs`],lc=[`onMismatch`,`checkOnBoot`,`checkIntervalMs`],uc=[`name`,`label`,`driver`,`config`,`pool`,`ssl`,`description`,`active`,`autoConnect`,`schemaMode`,`external`,`origin`],dc=[`min`,`max`,`idleTimeoutMillis`,`connectionTimeoutMillis`],fc=[`enabled`,`rejectUnauthorized`,`ca`,`cert`,`key`],pc="`datasource.capabilities` was removed in @objectstack/spec 17.0.0 (#4583, ADR-0049) — all eleven flags were declared, strict-guarded and read by nobody. ",mc={capabilities:pc+"Pushdown is decided by the runtime driver's own `supports.*` object, not by datasource metadata, so declaring a capability here never changed which engine path ran. Delete the block. If you wrote `readOnly: true`, read its note below — it did NOT make anything read-only. Run `os migrate meta --from 16` to rewrite it automatically.",readOnly:pc+"`readOnly` in particular NEVER made a datasource read-only: no write path consulted it, so a datasource labelled a read replica accepted writes exactly like any other. The one enforced datasource-wide write gate is `external.allowWrites: false`, and it applies ONLY to a federated datasource (`schemaMode` other than `managed`) — for a managed datasource there is currently no read-only gate at all, so delete the key rather than trusting it. Tracked in #4584."},hc={retryPolicy:'`datasource.retryPolicy` was removed in @objectstack/spec 17.0.0 (#4583, ADR-0049) — no connect or query path ever retried on it. Connection failure is handled by the boot policy in the datasource connection service (degraded boot, or `bootCritical` fail-fast), which does not retry on a schedule. Delete the block. CAREFUL — do NOT "fix" this by renaming keys: `hook.retryPolicy` and `job.retryPolicy` ARE enforced, but they are a DIFFERENT key on a different type and spell the delay `backoffMs`, not `baseDelayMs`. Moving these values onto a hook or a job only makes sense if you actually want that hook or job retried. Run `os migrate meta --from 16` to remove it.',healthCheck:'`datasource.healthCheck` was removed in @objectstack/spec 17.0.0 (#4583, ADR-0049) — no health-check loop ever read it, so `enabled: true` scheduled nothing and the two timeouts bounded nothing. Connection liveness is probed ON DEMAND through the driver handle (`ping()` / `checkHealth()`), which the datasource admin service calls for "Test connection". The only recurring datasource timer is `external.validation.checkIntervalMs`, which checks SCHEMA DRIFT — a different concern, not a liveness probe. Delete the block. Run `os migrate meta --from 16` to remove it.',externalLabel:"`external.label` was removed in @objectstack/spec 17.0.0 (#4583, ADR-0049) — nothing read the federation block's own label. Use the datasource's TOP-LEVEL `label`, which is what Setup → Datasources actually renders. Run `os migrate meta --from 16` to remove it.",externalRequirePermission:"`external.requirePermission` was removed in @objectstack/spec 17.0.0 (#4583, ADR-0049) — no authorization check ever consulted it, so a permission named here gated nothing. Access to a federated datasource's data is governed by the ordinary object permission sets and RLS, exactly as for a managed datasource. Naming a permission that is never required is the false-compliance shape ADR-0049 exists to remove — grant or withhold the object permissions instead. Run `os migrate meta --from 16` to remove it."},gc=(e,t=e)=>`\`${e}\` is a driver connection detail \u2014 it belongs inside \`config\`, not at the top level. Move it to \`config: { ${t}: \u2026 }\`, which is parsed against your driver's config contract (\`PostgresConfigSchema\` / \`MysqlConfigSchema\` / \`SqliteConfigSchema\` / \`MongoConfigSchema\` / \`MemoryConfigSchema\`, exported from \`@objectstack/spec/data\`).`,_c=w({surface:`this driver definition`,knownKeys:sc,aliases:{name:`id`,driver:`id`,title:`label`,config:`configSchema`,schema:`configSchema`},guidance:{capabilities:mc.capabilities,capability:mc.capabilities},history:`Until #4001 these were dropped silently — the driver still registered.`}),vc=w({surface:`this datasource's external settings`,knownKeys:cc,aliases:{schemas:`allowedSchemas`,allowedschema:`allowedSchemas`,writable:`allowWrites`,allowwrite:`allowWrites`,credentials:`credentialsRef`,secretref:`credentialsRef`,timeoutms:`queryTimeoutMs`,querytimeout:`queryTimeoutMs`},guidance:{label:hc.externalLabel,requirePermission:hc.externalRequirePermission,permission:hc.externalRequirePermission,password:'`password` must never be inlined. Put the secret in the secrets store and reference it with `credentialsRef` (e.g. `credentialsRef: "secret:warehouse/password"`).',readOnly:"`readOnly` is not an external-settings key. Use `allowWrites: false` here — it is the enforced datasource-wide write gate (checked by the ObjectQL engine before any write to a federated datasource)."},history:`Until #4001 these were dropped silently — federation ran on the defaults instead.`}),yc=w({surface:`this datasource's external validation policy`,knownKeys:lc,aliases:{onmismatch:`onMismatch`,mismatch:`onMismatch`,checkonboot:`checkOnBoot`,validateonboot:`checkOnBoot`,interval:`checkIntervalMs`,checkinterval:`checkIntervalMs`},history:`Until #4001 these were dropped silently — drift checking ran on the defaults (fail on mismatch, check at boot) regardless of what was written.`}),bc="`datasource.readReplicas` was removed in @objectstack/spec 17.0.0 (#4468, ADR-0049) — it described replica connections nothing ever opened: no driver reads the key, and no query path separates reads from writes, so every statement always went to the primary. Delete the key. There is no read-replica routing to migrate to — if your database fronts its replicas behind one endpoint (pgpool, ProxySQL, an RDS reader endpoint), point `config` at that endpoint, which is the only read-scaling path that works today. Run `os migrate meta --from 16` to rewrite it automatically.",xc=w({surface:`this datasource`,knownKeys:uc,aliases:{type:`driver`,connection:`config`,connectionconfig:`config`,options:`config`,enabled:`active`,pooling:`pool`,mode:`schemaMode`,schema_mode:`schemaMode`,federation:`external`,tls:`ssl`},guidance:{host:gc(`host`),port:gc(`port`),database:gc(`database`),user:gc(`user`,`username`),username:gc(`username`),filename:gc(`filename`),url:gc(`url`),connectionString:gc(`connectionString`,`url`),password:"`password` must never be inlined on a datasource. Interpolate it from the environment inside `config`, or for an external datasource reference the secrets store via `external.credentialsRef`.",readReplicas:bc,replicas:bc,capabilities:mc.capabilities,readOnly:mc.readOnly,retryPolicy:hc.retryPolicy,retry:hc.retryPolicy,healthCheck:hc.healthCheck,healthcheck:hc.healthCheck},history:`Until #4001 these were dropped silently — a connection key written one level too high left the datasource connecting on driver defaults rather than failing.`}),Sc=w({surface:`this datasource's pool config`,knownKeys:dc,aliases:{minimum:`min`,maximum:`max`,minconnections:`min`,maxconnections:`max`,idletimeout:`idleTimeoutMillis`,idletimeoutms:`idleTimeoutMillis`,connectiontimeout:`connectionTimeoutMillis`,connectiontimeoutms:`connectionTimeoutMillis`,acquiretimeoutmillis:`connectionTimeoutMillis`},history:"Until #4001 these were dropped silently — the pool ran on its defaults (min 0, max 10) no matter what was written. Note both timeouts end in `Millis`, not `Ms`."}),Cc=w({surface:`this datasource's ssl config`,knownKeys:fc,aliases:{active:`enabled`,ssl:`enabled`,tls:`enabled`,rejectunauthorised:`rejectUnauthorized`,cacert:`ca`,certificate:`cert`,clientcert:`cert`,privatekey:`key`,clientkey:`key`},guidance:{insecure:"`insecure` is not an ssl key. To accept a self-signed certificate set `rejectUnauthorized: false` — deliberately, and never against a production database."},history:`Until #4001 these were dropped silently — which meant a TLS setting that never took effect looked identical to one that did.`}),wc=t.z.string().describe(`Underlying driver identifier`),Tc=n(()=>t.z.object({id:t.z.string().describe(`Unique driver identifier (e.g. "postgres")`),label:t.z.string().describe(`Display label (e.g. "PostgreSQL")`),description:t.z.string().optional(),icon:t.z.string().optional(),configSchema:t.z.record(t.z.string(),t.z.unknown()).describe(`JSON Schema for connection configuration`)},{error:_c}).strict()),Ec=t.z.enum([`managed`,`external`,`validate-only`]).describe(`Schema ownership mode`),Dc=t.z.object({allowedSchemas:t.z.array(t.z.string()).optional().describe(`Whitelist of remote schemas/databases that may be exposed.`),allowWrites:t.z.boolean().default(!1).describe(`Global write gate. Individual objects must also opt in via object.external.writable.`),validation:t.z.object({onMismatch:t.z.enum([`fail`,`warn`,`ignore`]).default(`fail`).describe(`What to do when a federated object diverges from the remote table.`),checkOnBoot:t.z.boolean().default(!0).describe(`Validate federated objects against the remote schema at boot.`),checkIntervalMs:t.z.number().optional().describe(`Optional background drift-check interval in milliseconds.`)},{error:yc}).strict().default({onMismatch:`fail`,checkOnBoot:!0}).describe(`Boot/drift validation policy`),credentialsRef:t.z.string().optional().describe(`Reference into the secrets store; never inline credentials.`),queryTimeoutMs:t.z.number().default(3e4).describe(`Hard cap on per-query execution time.`)},{error:vc}).strict().describe(`External datasource federation settings (schemaMode != "managed")`);function Oc(e,t,n,r){let i=oc(t,n);if(i.known)for(let t of i.issues)e.addIssue({code:`custom`,path:[...r,...t.path],message:t.message})}var kc=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique datasource identifier`),label:t.z.string().optional().describe(`Display label`),driver:wc.describe(`Underlying driver type`),config:t.z.record(t.z.string(),t.z.unknown()).describe(`Driver specific configuration`),pool:t.z.object({min:t.z.number().default(0).describe(`Minimum connections`),max:t.z.number().default(10).describe(`Maximum connections`),idleTimeoutMillis:t.z.number().default(3e4).describe(`Idle timeout`),connectionTimeoutMillis:t.z.number().default(3e3).describe(`Connection establishment timeout`)},{error:Sc}).strict().optional().describe(`Connection pool settings`),ssl:t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable SSL/TLS for database connection`),rejectUnauthorized:t.z.boolean().default(!0).describe(`Reject connections with invalid/self-signed certificates`),ca:t.z.string().optional().describe(`CA certificate (PEM format or path to file)`),cert:t.z.string().optional().describe(`Client certificate (PEM format or path to file)`),key:t.z.string().optional().describe(`Client private key (PEM format or path to file)`)},{error:Cc}).strict().optional().describe(`SSL/TLS configuration for secure database connections`),description:t.z.string().optional().describe(`Internal description`),active:t.z.boolean().default(!0).describe(`Is datasource enabled`),autoConnect:t.z.boolean().default(!1).describe(`Force a live driver connection at boot even when managed + unrouted (ADR-0062 D2).`),schemaMode:Ec.default(`managed`),external:Dc.optional(),origin:t.z.enum([`code`,`runtime`]).default(`code`).describe(`Datasource provenance (server-managed, read-only)`),...D},{error:xc}).strict().superRefine((e,t)=>{Oc(t,e.driver,e.config,[`config`]),e.schemaMode!==`managed`&&!e.external&&t.addIssue({code:`custom`,path:[`external`],message:`schemaMode='${e.schemaMode}' requires 'external' settings.`}),e.schemaMode===`managed`&&e.external&&t.addIssue({code:`custom`,path:[`external`],message:`'external' settings only apply when schemaMode != 'managed'.`})}));function Ac(e){return kc.parse(e)}var jc={postgres:{int2:`integer`,int4:`integer`,int8:`bigint`,serial:`integer`,bigserial:`bigint`,float4:`float`,float8:`float`,numeric:`decimal`,bool:`boolean`,timestamptz:`datetime`,timestamp:`datetime`,timetz:`time`,jsonb:`json`,json:`json`,uuid:`uuid`,bytea:`binary`,bpchar:`text`,citext:`text`,vector:`vector`},mysql:{tinyint:`integer`,smallint:`integer`,mediumint:`integer`,int:`integer`,bigint:`bigint`,double:`float`,real:`float`,decimal:`decimal`,datetime:`datetime`,timestamp:`datetime`,tinytext:`text`,mediumtext:`text`,longtext:`text`,json:`json`,blob:`binary`,longblob:`binary`,enum:`enum`},sqlite:{integer:`integer`,int:`integer`,real:`float`,numeric:`decimal`,text:`text`,blob:`binary`},snowflake:{number:`decimal`,int:`integer`,integer:`integer`,bigint:`bigint`,float:`float`,double:`float`,string:`text`,varchar:`text`,variant:`json`,object:`json`,array:`array`,boolean:`boolean`,timestamp_ntz:`datetime`,timestamp_tz:`datetime`,timestamp_ltz:`datetime`,binary:`binary`},bigquery:{int64:`bigint`,float64:`float`,numeric:`decimal`,bignumeric:`decimal`,string:`text`,bytes:`binary`,bool:`boolean`,boolean:`boolean`,timestamp:`datetime`,datetime:`datetime`,struct:`json`,json:`json`,array:`array`,record:`json`},mongo:{objectid:`text`,string:`text`,double:`float`,int:`integer`,long:`bigint`,decimal:`decimal`,bool:`boolean`,boolean:`boolean`,date:`datetime`,object:`json`,array:`array`,bindata:`binary`}},Mc={text:`text`,varchar:`text`,char:`text`,character:`text`,string:`text`,"character varying":`text`,nvarchar:`text`,nchar:`text`,clob:`text`,integer:`integer`,int:`integer`,smallint:`integer`,tinyint:`integer`,bigint:`bigint`,decimal:`decimal`,numeric:`decimal`,number:`decimal`,money:`decimal`,float:`float`,double:`float`,"double precision":`float`,real:`float`,boolean:`boolean`,bool:`boolean`,bit:`boolean`,date:`date`,time:`time`,datetime:`datetime`,timestamp:`datetime`,json:`json`,jsonb:`json`,uuid:`uuid`,guid:`uuid`,binary:`binary`,varbinary:`binary`,blob:`binary`,bytes:`binary`,enum:`enum`,array:`array`,vector:`vector`},Nc={text:{suggested:`text`,exact:[`text`,`textarea`,`email`,`url`,`phone`,`markdown`,`html`,`richtext`,`code`,`select`,`color`],lossy:[]},integer:{suggested:`number`,exact:[`number`,`autonumber`,`rating`,`percent`],lossy:[`currency`,`boolean`]},bigint:{suggested:`number`,exact:[`number`,`autonumber`],lossy:[`currency`]},decimal:{suggested:`number`,exact:[`number`,`currency`,`percent`],lossy:[`rating`]},float:{suggested:`number`,exact:[`number`,`currency`,`percent`,`slider`],lossy:[]},boolean:{suggested:`boolean`,exact:[`boolean`,`toggle`],lossy:[]},date:{suggested:`date`,exact:[`date`],lossy:[`datetime`]},time:{suggested:`time`,exact:[`time`],lossy:[]},datetime:{suggested:`datetime`,exact:[`datetime`],lossy:[`date`]},json:{suggested:`json`,exact:[`json`,`composite`,`repeater`,`record`,`location`,`address`,`tags`,`multiselect`],lossy:[`text`]},uuid:{suggested:`text`,exact:[`text`,`lookup`,`master_detail`,`user`],lossy:[]},binary:{suggested:`file`,exact:[`file`,`image`,`signature`],lossy:[`text`]},enum:{suggested:`select`,exact:[`select`,`radio`,`text`],lossy:[]},array:{suggested:`multiselect`,exact:[`multiselect`,`checkboxes`,`tags`,`json`],lossy:[`text`]},vector:{suggested:`vector`,exact:[`vector`],lossy:[`json`]},unknown:{suggested:`text`,exact:[],lossy:[`text`,`json`]}};function Pc(e,t){if(!e)return`unknown`;let n=e.trim().toLowerCase();if(n.endsWith(`[]`)||n.startsWith(`_`))return`array`;let r=n.indexOf(`(`);r!==-1&&(n=n.slice(0,r).trim());for(let e of[` without time zone`,` with time zone`,` unsigned`,` signed`])if(n.endsWith(e)){n=n.slice(0,n.length-e.length).trim();break}let i=t?jc[t]:void 0;return i&&i[n]?i[n]:Mc[n]?Mc[n]:`unknown`}function Fc(e,t){let n=Pc(e,t);if(n!==`unknown`)return Nc[n].suggested}function Ic(e,t,n){let r=Nc[Pc(e,n)];return r.exact.includes(t)?!0:r.lossy.includes(t)?`lossy`:!1}var Lc=t.z.object({name:t.z.string().describe(`Remote column name`),sqlType:t.z.string().describe(`Raw remote SQL type (e.g. "numeric(10,2)")`),nullable:t.z.boolean().describe(`Whether the remote column is nullable`),primaryKey:t.z.boolean().default(!1).describe(`Part of the remote primary key`),suggestedFieldType:t.z.string().optional().describe(`ObjectStack field type suggested by the type-compat matrix`)}),Rc=t.z.object({remoteSchema:t.z.string().optional().describe(`Remote schema/database qualifier`),remoteName:t.z.string().describe(`Remote table/view name`),columns:t.z.array(Lc).describe(`Remote columns`),indexes:t.z.array(t.z.object({name:t.z.string(),columns:t.z.array(t.z.string()),unique:t.z.boolean()})).optional().describe(`Remote indexes, when introspectable`),rowCountEstimate:t.z.number().optional().describe(`Approximate row count`)}),zc=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe("Catalog id, conventionally `<datasource>_catalog`."),datasource:t.z.string().describe(`Datasource.name this catalog snapshots.`),snapshotAt:t.z.string().datetime().describe(`When the snapshot was taken (ISO 8601).`),dialect:t.z.string().optional().describe(`Remote SQL dialect, when known.`),tables:t.z.array(Rc).describe(`Snapshotted remote tables.`)})),Bc=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`number`,`string`,`boolean`]),Vc=t.z.enum([`string`,`number`,`boolean`,`time`,`geo`]),Hc=t.z.enum([`second`,`minute`,`hour`,`day`,`week`,`month`,`quarter`,`year`]),Uc=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique metric ID`),label:t.z.string().describe(`Human readable label`),description:t.z.string().optional(),type:Bc,sql:t.z.string().describe(`SQL expression or field reference`),filters:t.z.array(t.z.object({sql:t.z.string()})).optional(),format:t.z.string().optional()})),Wc=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique dimension ID`),label:t.z.string().describe(`Human readable label`),description:t.z.string().optional(),type:Vc,sql:t.z.string().describe(`SQL expression or column reference`),granularities:t.z.array(Hc).optional()})),Gc=n(()=>t.z.object({name:t.z.string().describe(`Target cube name`),relationship:t.z.enum([`one_to_one`,`one_to_many`,`many_to_one`]).default(`many_to_one`),sql:t.z.string().describe(`Join condition (ON clause)`)})),Kc=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Cube name (snake_case)`),title:t.z.string().optional(),description:t.z.string().optional(),sql:t.z.string().describe(`Base SQL statement or Table Name`),measures:t.z.record(t.z.string(),Uc).describe(`Quantitative metrics`),dimensions:t.z.record(t.z.string(),Wc).describe(`Qualitative attributes`),joins:t.z.record(t.z.string(),Gc).optional(),refreshKey:t.z.object({every:t.z.string().optional(),sql:t.z.string().optional()}).optional(),public:t.z.boolean().default(!1)})),qc=n(()=>t.z.object({cube:t.z.string().optional().describe(`Target cube name (optional when provided externally, e.g. in API request wrapper)`),measures:t.z.array(t.z.string()).describe(`List of metrics to calculate`),dimensions:t.z.array(t.z.string()).optional().describe(`List of dimensions to group by`),where:d.optional().describe(`Filtering criteria (canonical Query DSL FilterCondition)`),timeDimensions:t.z.array(t.z.object({dimension:t.z.string(),granularity:Hc.optional(),dateRange:t.z.union([t.z.string(),t.z.array(t.z.string())]).optional()})).optional(),order:t.z.record(t.z.string(),t.z.enum([`asc`,`desc`])).optional(),limit:t.z.number().optional(),offset:t.z.number().optional(),timezone:t.z.string().optional()}));function Jc(e){return Kc.parse(e)}var Yc=new Set([`number`,`currency`,`percent`]);function Xc(e){return e===`percent`?`avg`:`sum`}function Zc(e,t){return!(t!==`percent`||e!==`sum`&&e!==`count_distinct`)}function Qc(e){return e===`count`||e===`count_distinct`||e===`sum`?0:void 0}function $c(e){if(e?.type===`percent`)return typeof e.max==`number`&&e.max>1?`whole`:`fraction`}var el=new Set(`date.datetime.time.number.currency.percent.boolean.toggle.file.image.avatar.video.audio.attachment.signature.qrcode.json.code.composite.repeater.record.address.vector.geolocation.location.select.multiselect.multi_select.radio.checkboxes.checkbox.tags.color.rating.slider.progress.lookup.master_detail.tree.user.autonumber.password.secret.phone`.split(`.`)),tl=new Set([`text`,`textarea`,`email`,`url`,`markdown`,`html`,`richtext`]),nl=tl;function rl(e){if(!e)return!1;let t=e.type;return t?t===`formula`?(e.returnType??e.valueType)===`text`:!el.has(t)&&tl.has(t):!1}var il=new Set([`name`,`title`,`subject`,`label`,`full_name`,`display_name`]),al=[`_name`,`_title`],ol=[`name_`];function sl(e){return il.has(e.toLowerCase())}function cl(e){let t=e.toLowerCase();return il.has(t)?!1:al.some(e=>t.endsWith(e))||ol.some(e=>t.startsWith(e))}function ll(e){if(!e)return;let t=Object.keys(e);for(let n of[`name`,`title`,`subject`,`label`,`full_name`,`display_name`])for(let r of t)if(r.toLowerCase()===n&&rl(e[r]))return r;for(let n of t)if(cl(n)&&rl(e[n]))return n;for(let n of t)if(!sl(n)&&rl(e[n]))return n}function ul(e){return e?(e.nameField??e.displayNameField)||ll(e.fields):void 0}function dl(e){return e==null||typeof e==`string`&&e.trim()===``}function fl(e,t,n){let r=t??{},i=n?.viewTitleField??ul(e),a=i?r[i]:void 0;return dl(a)?`Record #${r.id??r._id??``}`.trimEnd():String(a)}function pl(e,t){let n=ul(e);if(n)return e.nameField===n?e:{...e,nameField:n};if(t?.synthesize===!1)return e;let r={...e.fields??{}};return r.name||={type:`text`,label:`Name`,required:!0},{...e,fields:r,nameField:`name`}}function ml(e){if(!e)return{status:`none`};let t=e.nameField??e.displayNameField;if(t)return{status:e.fields&&Object.prototype.hasOwnProperty.call(e.fields,t)?`explicit`:`synthesized`,field:t};let n=ll(e.fields);return n?{status:`derived`,field:n}:{status:`none`}}var hl=new Set([`text`,`email`,`phone`,`url`,`autonumber`,`textarea`,`markdown`]),gl=new Set([`select`,`status`]),_l=new Set([`id`,`_id`,`created`,`modified`,`created_at`,`updated_at`,`created_by`,`updated_by`,`owner_id`,`organization_id`,`space`,`company_id`]),vl=new Set([`json`,`object`,`grid`,`image`,`file`,`avatar`,`vector`,`location`,`geometry`,`secret`,`password`,`encrypted`,`boolean`,`lookup`,`master_detail`]);function yl(e,t){let n=Object.keys(e).filter(t=>{if(_l.has(t))return!1;let n=e[t];if(!n||n.hidden)return!1;let r=n.type;return!r||vl.has(r)?!1:hl.has(r)||gl.has(r)}),r=e=>!!e&&n.includes(e),i=r(t)?t:r(`name`)?`name`:r(`title`)?`title`:void 0;return i?[i,...n.filter(e=>e!==i)]:n}function bl(e){let t=e.fields||{},n=e.searchableFields?.filter(e=>t[e]);return n&&n.length>0?{allowed:n,source:`declared`}:{allowed:yl(t,e.displayField),source:`auto`}}function xl(e){let{allowed:t}=bl(e),n=typeof e.requestedFields==`string`?e.requestedFields.split(`,`).map(e=>e.trim()).filter(Boolean):e.requestedFields;if(n&&n.length>0){let e=new Set(t),r=n.filter(t=>e.has(t));if(r.length>0)return r}return t}var Sl=Object.freeze([`created_at`,`created_by`,`updated_at`,`updated_by`]),Cl=new Set([...Sl,`organization_id`,`tenant_id`,`is_deleted`,`deleted_at`]);function wl(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e;if(typeof t.key!=`string`||t.key.length===0)return null;let n=`none`;return t.collapse===`expanded`||t.collapse===`collapsed`||t.collapse===`none`?n=t.collapse:typeof t.collapsible==`boolean`||typeof t.collapsed==`boolean`?n=t.collapsed===!0?`collapsed`:t.collapsible===!0?`expanded`:`none`:typeof t.defaultExpanded==`boolean`&&(n=t.defaultExpanded?`expanded`:`collapsed`),{key:t.key,label:typeof t.label==`string`?t.label:void 0,icon:typeof t.icon==`string`?t.icon:void 0,description:typeof t.description==`string`?t.description:void 0,collapse:n}}function Tl(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=(Array.isArray(t.fieldGroups)?t.fieldGroups:[]).map(wl).filter(e=>e!==null);if(n.length===0)return null;let r=new Set(n.map(e=>e.key)),i=t.fields&&typeof t.fields==`object`&&!Array.isArray(t.fields)?t.fields:{},a=new Map;for(let e of n)a.set(e.key,[]);let o=[],s=!1;for(let[e,t]of Object.entries(i)){if(t?.hidden===!0)continue;let n=typeof t?.group==`string`&&r.has(t.group)?t.group:null;n?(a.get(n).push(e),s=!0):Cl.has(e)||o.push(e)}if(!s)return null;let c=[];for(let e of n){let t=a.get(e.key);t.length!==0&&c.push({key:e.key,label:e.label??e.key,...e.icon===void 0?{}:{icon:e.icon},...e.description===void 0?{}:{description:e.description},collapse:e.collapse,fields:t})}return o.length>0&&c.push({collapse:`none`,fields:o}),c.length>0?c:null}var El=12;function Dl(e){if(!e||typeof e!=`object`||Array.isArray(e))return 0;let t=e.fields;if(!t||typeof t!=`object`||Array.isArray(t))return 0;let n=0;for(let[e,r]of Object.entries(t))r?.hidden!==!0&&(Cl.has(e)||n++);return n}function Ol(e,t={}){if(t.viewport===`mobile`)return`page`;let n=t.pageThreshold??El;return Dl(e)>=n?`page`:`drawer`}function kl(e,t,n={}){let r=Ol(e,n);return t===`view`?{container:r===`page`?`route`:`overlay`,surface:r,size:`auto`}:r===`page`?{container:`overlay`,surface:`modal`,size:`full`}:{container:`overlay`,surface:r,size:`auto`}}var Al=t.z.enum([`comment`,`field_change`,`task`,`event`,`email`,`call`,`note`,`file`,`record_create`,`record_delete`,`approval`,`sharing`,`system`]),jl=t.z.enum([`all`,`comments_only`,`changes_only`,`tasks_only`]);e.ALL_OPERATORS=oe,e.API_METHOD_DERIVATION=Ci,e.API_METHOD_ORDER=vi,e.API_OPERATION_ORDER=Ar,e.API_PRIMITIVES=_i,e.AUDIT_PROVENANCE_FIELDS=Sl,e.AddressSchema=Ot,e.AddressValueSchema=$i,e.AggregationFunction=ce,e.AggregationMetricType=Bc,e.AggregationNodeSchema=de,e.AggregationPipelineSchema=Y,e.AggregationStageSchema=Ho,e.AnalyticsQuerySchema=qc,e.ApiMethod=Dr,e.ApiOperationSchema=jr,e.AutoPersistenceConfigSchema=ws,e.BOOLEAN_VALUE_TYPES=Ni,e.BUILTIN_DRIVER_IDS=$s,e.BaseEngineOptionsSchema=W,e.CALENDAR_DATE_TYPES=Pi,e.CLOCK_TIME_TYPES=Ii,e.COMPUTED_VALUE_TYPES=Ki,e.CONTEXT_TOKENS=He,e.CONTEXT_TOKEN_DESCRIPTIONS=qe,e.CONTEXT_TOKEN_SUGGESTIONS=Je,e.CONTEXT_TOKEN_WRAPPED_RE=We,e.CalendarDateValueSchema=Yi,e.ClockTimeValueSchema=Zi,e.ComparisonOperatorSchema=a,e.ConditionalValidationSchema=Ht,e.ConsistencyLevelSchema=Po,e.ContextTokenPlaceholderSchema=Ke,e.ContextTokenSchema=Ge,e.CrossFieldValidationSchema=zt,e.CubeJoinSchema=Gc,e.CubeSchema=Kc,e.CurrencyConfigSchema=Et,e.CurrencyValueSchema=Dt,e.CustomPersistenceConfigSchema=Q,e.DATA_ACTION_TO_API_OPERATION=wi,e.DATE_MACRO_ALIAS_TOKENS=Ae,e.DATE_MACRO_DESCRIPTIONS=Re,e.DATE_MACRO_INSTANT_TOKENS=Oe,e.DATE_MACRO_PARAM_RE=C,e.DATE_MACRO_PERIOD_TOKENS=ke,e.DATE_MACRO_TOKENS=je,e.DATE_MACRO_UNITS=Me,e.DATE_MACRO_WRAPPED_RE=Ie,e.DEFAULT_VALUE_TOKENS=$e,e.DEFAULT_VALUE_TOKEN_CURRENT_USER=Qe,e.DEFAULT_VALUE_TOKEN_DESCRIPTIONS=et,e.DEFAULT_VALUE_TOKEN_NOW=Ze,e.DRIVER_CONFIG_SCHEMAS=nc,e.DRIVER_ID_ALIASES=ec,e.DataEngineAggregateOptionsSchema=$a,e.DataEngineAggregateRequestSchema=go,e.DataEngineContractSchema=no,e.DataEngineCountOptionsSchema=to,e.DataEngineCountRequestSchema=ho,e.DataEngineDeleteOptionsSchema=Za,e.DataEngineDeleteRequestSchema=mo,e.DataEngineExecuteRequestSchema=_o,e.DataEngineFilterSchema=Ha,e.DataEngineFindOneRequestSchema=uo,e.DataEngineFindRequestSchema=lo,e.DataEngineInsertOptionsSchema=Ka,e.DataEngineInsertRequestSchema=fo,e.DataEngineQueryOptionsSchema=Ga,e.DataEngineRequestSchema=yo,e.DataEngineSortSchema=Ua,e.DataEngineUpdateOptionsSchema=Ya,e.DataEngineUpdateRequestSchema=po,e.DataEngineVectorFindRequestSchema=vo,e.DataTypeMappingSchema=Do,e.DatasourceSchema=kc,e.DateGranularity=le,e.DateMacroPlaceholderSchema=Le,e.DateMacroTokenSchema=Fe,e.DimensionSchema=Wc,e.DimensionType=Vc,e.DocumentSchema=cs,e.DocumentSchemaValidationSchema=Ro,e.DocumentTemplateSchema=os,e.DocumentVersionSchema=as,e.DriverCapabilitiesSchema=So,e.DriverConfigSchema=To,e.DriverDefinitionSchema=Tc,e.DriverInterfaceSchema=Co,e.DriverOptionsSchema=q,e.DriverSslToggleSchema=_s,e.DriverType=wc,e.DroppedFieldsEventSchema=Ja,e.ESignatureConfigSchema=ss,e.EngineAggregateOptionsSchema=Qa,e.EngineCountOptionsSchema=eo,e.EngineDeleteOptionsSchema=Xa,e.EngineQueryOptionsSchema=Wa,e.EngineUpdateOptionsSchema=qa,e.EqualityOperatorSchema=i,e.ExpressionBodySchema=$t,e.ExternalCatalogSchema=zc,e.ExternalColumnSchema=Lc,e.ExternalDataSourceSchema=ds,e.ExternalDatasourceSettingsSchema=Dc,e.ExternalFieldMappingSchema=fs,e.ExternalLookupSchema=ps,e.ExternalTableSchema=Rc,e.FIELD_GROUP_SYSTEM_FIELDS=Cl,e.FIELD_KEY_GUIDANCE=gt,e.FILE_REFERENCE_TYPES=Hi,e.FILTER_LOGIC_CASES=ye,e.FILTER_LOGIC_ROWS=x,e.FILTER_OPERATORS=_,e.FeedFilterMode=jl,e.FeedItemType=Al,e.Field=Pt,e.FieldNodeSchema=pe,e.FieldOperatorsSchema=u,e.FieldReferenceSchema=r,e.FieldSchema=Nt,e.FieldType=St,e.FileLikeValueSchema=na,e.FilePersistenceConfigSchema=Ss,e.FileReferenceIdValueSchema=ta,e.FileValueSchema=ea,e.FilterConditionSchema=d,e.FormatValidationSchema=Rt,e.FullTextSearchSchema=y,e.GroupByNodeSchema=ue,e.HookBodyCapability=qt,e.HookBodySchema=en,e.HookContextSchema=Ta,e.HookEvent=Ca,e.HookSchema=wa,e.IMPORT_BOOLEAN_FALSE_TOKENS=sa,e.IMPORT_BOOLEAN_TRUE_TOKENS=oa,e.IMPORT_REFERENCE_TYPES=ca,e.INSTANT_TYPES=Fi,e.ImportFieldMappingSchema=Na,e.IndexSchema=Ir,e.InstantValueSchema=Xi,e.JSONValidationSchema=Bt,e.LEGACY_API_METHODS=Or,e.LEGACY_API_METHOD_GUIDANCE=kr,e.LIFECYCLE_DURATION_REGEX=Gr,e.LOGICAL_OPERATORS=ae,e.LifecycleClassSchema=Wr,e.LifecycleSchema=qr,e.LocalStoragePersistenceConfigSchema=Cs,e.LocationCoordinatesSchema=Tt,e.LocationValueSchema=Qi,e.MEASURE_FIELD_TYPES=Yc,e.MULTI_CAPABLE_TYPES=qi,e.MULTI_OPTION_TYPES=Ri,e.MappingSchema=U,e.MemoryConfigSchema=Ds,e.MemoryDriverSpec=ks,e.MemoryPersistenceConfigSchema=Ts,e.MetricSchema=Uc,e.MongoConfigSchema=js,e.MongoDriverSpec=Ns,e.MysqlConfigSchema=Fs,e.NUMERIC_VALUE_TYPES=Mi,e.NoSQLDataTypeMappingSchema=zo,e.NoSQLDatabaseTypeSchema=Mo,e.NoSQLDriverConfigSchema=Bo,e.NoSQLIndexSchema=Uo,e.NoSQLIndexTypeSchema=Fo,e.NoSQLOperationTypeSchema=No,e.NoSQLQueryOptionsSchema=Vo,e.NoSQLTransactionOptionsSchema=X,e.NormalizedFilterSchema=f,e.OBJECT_KEY_GUIDANCE=_t,e.ObjectAccessConfigSchema=Vr,e.ObjectCapabilities=Fr,e.ObjectDependencyGraphSchema=Qo,e.ObjectDependencyNodeSchema=Zo,e.ObjectExtensionSchema=hi,e.ObjectExternalBindingSchema=Yr,e.ObjectFieldGroupSchema=Jr,e.ObjectOwnershipEnum=mi,e.ObjectRequiredPermissionsSchema=Ur,e.ObjectSchema=ui,e.PAGINATION_ALL_IDS=De,e.PAGINATION_CASES=Te,e.PAGINATION_ROWS=we,e.PAGINATION_UNORDERED_CASES=Ee,e.PerOperationRequiredPermissionsSchema=Hr,e.PersistenceAdapterSchema=bs,e.PersistenceTypeSchema=xs,e.PoolConfigSchema=wo,e.PostgresConfigSchema=Bs,e.QUERY_CURSOR_REMOVED=he,e.QUERY_DISTINCT_REMOVED=ge,e.QueryFilterSchema=te,e.QuerySchema=b,e.RAW_FILE_VALUES_CONTEXT_KEY=Wi,e.READ_ONLY_BELONGS_ON_DATASOURCE=gs,e.RECORD_SURFACE_PAGE_THRESHOLD=El,e.REFERENCE_VALUE_TYPES=zi,e.RPC_QUERY_ALIAS_SLOTS=ro,e.RangeOperatorSchema=c,e.ReferenceIdValueSchema=H,e.ReferenceResolutionErrorSchema=$o,e.ReferenceResolutionSchema=Xo,e.ReplicationConfigSchema=Lo,e.RowCrudActionOverrideSchema=Xr,e.SCHEMA_MODE_BELONGS_ON_DATASOURCE=hs,e.SEARCHABLE_ENUM_TYPES=gl,e.SEARCHABLE_TEXTUAL_TYPES=hl,e.SEARCH_AUTO_EXCLUDED_FIELDS=_l,e.SEARCH_AUTO_EXCLUDED_TYPES=vl,e.SINGLE_OPTION_TYPES=Li,e.SQLDialectSchema=Eo,e.SQLDriverConfigSchema=ko,e.SQLiteAlterTableLimitations=jo,e.SQLiteDataTypeMappingDefaults=Ao,e.SSLConfigSchema=Oo,e.SSL_DETAIL_BELONGS_ON_DATASOURCE=Z,e.STACK_KEY_GUIDANCE=vt,e.STACK_RUNTIME_MEMBERS=yt,e.STRING_VALUE_TYPES=ji,e.STRUCTURED_JSON_TYPES=Gi,e.SchemaModeSchema=Ec,e.ScriptBodySchema=M,e.ScriptValidationSchema=It,e.SeedIdentitySchema=es,e.SeedLoadResultSchema=ns,e.SeedLoaderConfigSchema=ts,e.SeedLoaderRequestSchema=is,e.SeedLoaderResultSchema=rs,e.SeedMode=Wo,e.SeedSchema=Go,e.SelectOptionSchema=wt,e.SetOperatorSchema=s,e.ShardingConfigSchema=Io,e.SortNodeSchema=se,e.SpecialOperatorSchema=ee,e.SqlAutoMigrateSchema=ms,e.SqliteConfigSchema=qs,e.SqliteWasmConfigSchema=Zs,e.SqliteWasmPersistModeSchema=Ys,e.StateMachineValidationSchema=Lt,e.StringOperatorSchema=l,e.TEMPORAL_CASES=Se,e.TEMPORAL_NOW=be,e.TEMPORAL_ROWS=xe,e.TEMPORAL_TIME_CASES=Ce,e.TEMPORAL_TIME_ROWS=S,e.TITLE_ELIGIBLE=nl,e.TITLE_ELIGIBLE_TYPES=tl,e.TITLE_INELIGIBLE_TYPES=el,e.TenancyConfigSchema=zr,e.TimeUpdateInterval=Hc,e.TransformType=Ma,e.UniqueScopeSchema=kt,e.VALID_AST_OPERATORS=m,e.ValidationRuleSchema=Vt,e.canonicalAstOperator=h,e.canonicalizeSqlType=Pc,e.classifyFilterToken=Xe,e.countAuthorableFields=Dl,e.defaultAggregateFor=Xc,e.defineCube=Jc,e.defineDatasource=Ac,e.defineHook=Ea,e.defineMapping=Pa,e.defineObjectExtension=gi,e.defineSeed=Ko,e.deriveFieldGroupLayout=Tl,e.deriveRecordFlowSurface=kl,e.deriveRecordSurface=Ol,e.driverConfigJsonSchema=ys,e.effectiveOperationsArray=ki,e.emptyGroupValueFor=Qc,e.fieldForm=Jo,e.foldQueryAliasSlots=io,e.formatUnknownAuthoringKey=xt,e.getDriverConfigJsonSchemaById=ac,e.getDriverConfigSchema=rc,e.getMemoryConfigJsonSchema=Os,e.getMongoConfigJsonSchema=Ms,e.getMysqlConfigJsonSchema=Is,e.getPostgresConfigJsonSchema=Vs,e.getSqliteConfigJsonSchema=Js,e.getSqliteWasmConfigJsonSchema=Qs,e.hasDynamicTokens=da,e.hookForm=Yo,e.isApiOperationAllowed=Oi,e.isApiPrimitive=xi,e.isAppResolvedDefaultToken=it,e.isCompatible=Ic,e.isContextToken=Ue,e.isCurrentUserDefaultToken=nt,e.isDateMacroToken=Ne,e.isFileIdToken=Ui,e.isFilterAST=g,e.isGlobalUnique=At,e.isIncoherentAggregate=Zc,e.isKnownFilterToken=Ye,e.isLegacyApiMethod=Si,e.isMultiValueField=Ji,e.isNowDefaultToken=tt,e.isPlainRecord=A,e.isRuntimeDefaultToken=rt,e.isTenancyDisabled=Br,e.isTitleEligible=rl,e.isUniqueDeclared=jt,e.lintAuthoredRecordKeys=bt,e.missingFieldValues=ma,e.nextUtcCalendarDay=ze,e.objectForm=qo,e.objectTitleCompleteness=ml,e.parseAutonumberFormat=ua,e.parseDateMacroParam=Pe,e.parseFilterAST=ie,e.percentScaleOf=$c,e.provisionPrimary=pl,e.referenceTargetOf=Vi,e.referencedFields=pa,e.renderAutonumber=_a,e.resolveCrudAffordances=fi,e.resolveDisplayField=ul,e.resolveDriverId=tc,e.resolveEffectiveApiMethods=Di,e.resolveRecordDisplayName=fl,e.resolveSearchFieldResolution=bl,e.resolveSearchFields=xl,e.sequenceWidth=fa,e.stripLegacyApiMethods=Nr,e.suggestFieldTypeForSqlType=Fc,e.utcInstantMs=Be,e.validateDriverConfig=oc,e.valueSchemaFor=aa})),c=e((e=>{var t=o();function n(e){if(typeof process<`u`&&{}.OS_EAGER_SCHEMAS===`1`)return e();let t,n=()=>(t===void 0&&(t=e()),t),r=function(){},i,a=e=>{let t=e._zod;if(!t||typeof t.processJSONSchema!=`function`)return t;let n=t.processJSONSchema;return Object.create(t,{processJSONSchema:{enumerable:!0,value:(t,r,i)=>{let a=t?.seen;if(a&&typeof a.get==`function`){let t=a.get(o);t!==void 0&&!a.has(e)&&a.set(e,t)}return n(t,r,i)}}})},o=new Proxy(r,{get(e,t){let r=n();if(t===`_zod`)return i??=a(r),i;let o=r[t];return typeof o==`function`?o.bind(r):o},set(e,t,r){let i=n();return i[t]=r,!0},has(e,t){return t in n()},ownKeys(){return Reflect.ownKeys(n())},getOwnPropertyDescriptor(e,t){return Reflect.getOwnPropertyDescriptor(n(),t)},getPrototypeOf(){return Reflect.getPrototypeOf(n())}});return o}var r=n(()=>t.z.object({$field:t.z.string().describe(`Field Reference/Column Name`)}));n(()=>t.z.object({$eq:t.z.any().optional(),$ne:t.z.any().optional()})),n(()=>t.z.object({$gt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$gte:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lte:t.z.union([t.z.number(),t.z.date(),r]).optional()})),n(()=>t.z.object({$in:t.z.array(t.z.any()).optional(),$nin:t.z.array(t.z.any()).optional()})),n(()=>t.z.object({$between:t.z.tuple([t.z.union([t.z.number(),t.z.date(),r]),t.z.union([t.z.number(),t.z.date(),r])]).optional()})),n(()=>t.z.object({$contains:t.z.string().optional(),$notContains:t.z.string().optional(),$startsWith:t.z.string().optional(),$endsWith:t.z.string().optional()})),n(()=>t.z.object({$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()}));var i=n(()=>t.z.object({$eq:t.z.any().optional(),$ne:t.z.any().optional(),$gt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$gte:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lt:t.z.union([t.z.number(),t.z.date(),r]).optional(),$lte:t.z.union([t.z.number(),t.z.date(),r]).optional(),$in:t.z.array(t.z.any()).optional(),$nin:t.z.array(t.z.any()).optional(),$between:t.z.tuple([t.z.union([t.z.number(),t.z.date(),r]),t.z.union([t.z.number(),t.z.date(),r])]).optional(),$contains:t.z.string().optional(),$notContains:t.z.string().optional(),$startsWith:t.z.string().optional(),$endsWith:t.z.string().optional(),$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),a=t.z.lazy(()=>t.z.record(t.z.string(),t.z.unknown()).and(t.z.object({$and:t.z.array(a).optional(),$or:t.z.array(a).optional(),$not:a.optional()})));n(()=>t.z.object({where:a.optional()}));var s=t.z.lazy(()=>t.z.object({$and:t.z.array(t.z.union([t.z.record(t.z.string(),i),s])).optional(),$or:t.z.array(t.z.union([t.z.record(t.z.string(),i),s])).optional(),$not:t.z.union([t.z.record(t.z.string(),i),s]).optional()}));new Set(Object.keys({"=":`$eq`,"==":`$eq`,equals:`$eq`,eq:`$eq`,"!=":`$ne`,"<>":`$ne`,ne:`$ne`,neq:`$ne`,not_equals:`$ne`,notequals:`$ne`,">":`$gt`,gt:`$gt`,greater_than:`$gt`,greaterthan:`$gt`,">=":`$gte`,gte:`$gte`,greater_than_or_equal:`$gte`,greaterthanorequal:`$gte`,greaterorequal:`$gte`,"<":`$lt`,lt:`$lt`,less_than:`$lt`,lessthan:`$lt`,"<=":`$lte`,lte:`$lte`,less_than_or_equal:`$lte`,lessthanorequal:`$lte`,lessorequal:`$lte`,before:`$lt`,after:`$gt`,in:`$in`,nin:`$nin`,not_in:`$nin`,notin:`$nin`,contains:`$contains`,notcontains:`$notContains`,not_contains:`$notContains`,like:`$contains`,startswith:`$startsWith`,starts_with:`$startsWith`,endswith:`$endsWith`,ends_with:`$endsWith`,between:`$between`,is_null:`$null`,is_not_null:`$null`,isnull:`$null`,isnotnull:`$null`,is_empty:`$null`,is_not_empty:`$null`,isempty:`$null`,isnotempty:`$null`}));function c(e){return t.z.never({error:()=>e}).optional().describe(`[REMOVED] ${e}`)}var l=n(()=>t.z.object({field:t.z.string(),order:t.z.enum([`asc`,`desc`]).default(`asc`)})),ee=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`array_agg`,`string_agg`]),u=t.z.enum([`day`,`week`,`month`,`quarter`,`year`]),d=n(()=>t.z.union([t.z.string(),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:u.optional().describe(`Bucket date values into uniform periods (day/week/month/quarter/year)`),alias:t.z.string().optional().describe(`Alias for the projected group value`)})])),te=n(()=>t.z.object({function:ee.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (optional for COUNT(*))`),alias:t.z.string().describe(`Result column alias`),distinct:t.z.boolean().optional().describe(`Apply DISTINCT before aggregation`),filter:a.optional().describe("[EXPERIMENTAL — not enforced] Per-aggregation filter (SQL FILTER (WHERE …)). Neither the SQL builders nor the in-memory fallback applies it (#4286); filter the whole query with `where` instead.")})),f="A `fields[]` entry is a field name (string). The nested-select object form `{ field, fields, alias }` was removed in @objectstack/spec 17 (#4196, ADR-0049) — nothing ever produced it and nothing ever read `.fields`/`.alias`: every consumer on this path treats the list as `string[]`, so the object form was dropped by the SQL and memory drivers, projected as a column literally named \"[object Object]\" by MongoDB, and refused as an unknown field by the REST ingress. Select related records with `expand` — `expand: { owner: { object: 'user', fields: ['name'] } }` — or name a single related column with a dotted path (`fields: ['owner.name']`). `alias` has no replacement here; an aliased projection is an `aggregations` or `windowFunctions` entry, which carry their own `alias`.",p=t.z.string({error:e=>e.code===`invalid_type`&&typeof e.input==`object`&&e.input!==null&&!Array.isArray(e.input)?f:void 0}),m="`query.joins` was removed in @objectstack/spec 17 (#4286, ADR-0049) — no engine or driver ever read it: a query carrying `joins` behaved exactly as if the key were absent, while its name squatted on the reserved REST parameter set. Delete the key. Related records are read through `expand` — `expand: { owner: { object: 'user', fields: ['name'] } }` — which the engine resolves via batch $in queries, and a single related column is a dotted `fields` path (`fields: ['owner.name']`).",ne='`query.cursor` was removed in @objectstack/spec 17 (#4286, ADR-0049) — no driver ever implemented keyset pagination, so the cursor was accepted and ignored and every page came back identical (a caller looping "until hasMore is false" never terminates). Delete the key; `QueryBuilder.cursor()` was removed with it. Express the keyset as an ordinary `where` predicate on your sort key — `where: { created_at: { $gt: last.created_at } }` with the matching `orderBy` — which every driver executes with canonicalised comparands. A first-class cursor, if ever built, will be a response-minted opaque token, not this caller-built record.',h="`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.",g="`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`.",re=n(()=>t.z.object({query:t.z.string().describe(`Search query text`),fields:t.z.array(t.z.string()).optional().describe(`Fields to search in (if not specified, searches all text fields)`),fuzzy:t.z.boolean().optional().default(!1).describe("[EXPERIMENTAL — not enforced] Fuzzy matching (tolerate typos). The ADR-0061 expansion reads only `query` + `fields`; no executor receives this flag (#4286)."),operator:t.z.enum([`and`,`or`]).optional().default(`or`).describe(`[EXPERIMENTAL — not enforced] Logical operator between terms. The ADR-0061 expansion applies its own term semantics; no executor receives this flag (#4286).`),boost:t.z.record(t.z.string(),t.z.number()).optional().describe(`[EXPERIMENTAL — not enforced] Field-specific relevance boosting (field name -> boost factor). No executor scores results (#4286).`),minScore:t.z.number().optional().describe(`[EXPERIMENTAL — not enforced] Minimum relevance score threshold. No executor scores results (#4286).`),language:t.z.string().optional().describe(`[EXPERIMENTAL — not enforced] Language for text analysis (e.g., "en", "zh", "es"). No executor selects an analyzer (#4286).`),highlight:t.z.boolean().optional().default(!1).describe(`[EXPERIMENTAL — not enforced] Search result highlighting. No executor emits highlights (#4286).`)})),ie=t.z.object({object:t.z.string().describe(`Object name (e.g. account)`),fields:t.z.array(p).optional().describe("Fields to retrieve — field names, optionally dotted to reach through a relationship (`owner.name`). Related *records* are selected with `expand`, not from inside this list."),where:a.optional().describe(`Filtering criteria (WHERE)`),search:t.z.union([t.z.string(),re]).optional().describe(`Full-text search — the query text (canonical, ADR-0061 D1), or a structured FullTextSearch configuration`),searchFields:t.z.array(t.z.string()).optional().describe(`Narrow the search to these fields (server-intersected with the allowed searchable set — can only narrow, never widen; ADR-0061 D1)`),orderBy:t.z.array(l).optional().describe(`Sorting instructions (ORDER BY)`),limit:t.z.number().optional().describe(`Max records to return (LIMIT)`),offset:t.z.number().optional().describe(`Records to skip (OFFSET)`),top:t.z.number().optional().describe(`Alias for limit (OData compatibility)`),cursor:c(ne),joins:c(m),aggregations:t.z.array(te).optional().describe(`Aggregation functions`),groupBy:t.z.array(d).optional().describe("GROUP BY targets (strings or `{field, dateGranularity?}` objects for date bucketing)"),having:a.optional().describe(`HAVING — filter over the AGGREGATED rows (aggregation aliases + groupBy projections); applied engine-side after aggregation`),windowFunctions:c(g),distinct:c(h)}),_=n(()=>ie.extend({expand:t.z.lazy(()=>t.z.record(t.z.string(),_)).optional().describe("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.")})),ae=t.z.enum([`validation`,`authentication`,`authorization`,`not_found`,`conflict`,`rate_limit`,`server`,`external`,`maintenance`]),oe=t.z.enum(`VALIDATION_ERROR.INVALID_FIELD.MISSING_REQUIRED_FIELD.INVALID_FORMAT.VALUE_TOO_LONG.VALUE_TOO_SHORT.VALUE_OUT_OF_RANGE.INVALID_REFERENCE.DUPLICATE_VALUE.INVALID_QUERY.INVALID_FILTER.INVALID_SORT.MAX_RECORDS_EXCEEDED.UNAUTHENTICATED.INVALID_CREDENTIALS.EXPIRED_TOKEN.INVALID_TOKEN.SESSION_EXPIRED.MFA_REQUIRED.EMAIL_NOT_VERIFIED.PERMISSION_DENIED.INSUFFICIENT_PRIVILEGES.FIELD_NOT_ACCESSIBLE.RECORD_NOT_ACCESSIBLE.LICENSE_REQUIRED.IP_RESTRICTED.TIME_RESTRICTED.RESOURCE_NOT_FOUND.OBJECT_NOT_FOUND.RECORD_NOT_FOUND.FIELD_NOT_FOUND.ENDPOINT_NOT_FOUND.RESOURCE_CONFLICT.CONCURRENT_MODIFICATION.DELETE_RESTRICTED.DUPLICATE_RECORD.LOCK_CONFLICT.METHOD_NOT_ALLOWED.PRECONDITION_REQUIRED.RATE_LIMIT_EXCEEDED.QUOTA_EXCEEDED.CONCURRENT_LIMIT_EXCEEDED.INTERNAL_ERROR.DATABASE_ERROR.TIMEOUT.SERVICE_UNAVAILABLE.NOT_IMPLEMENTED.EXTERNAL_SERVICE_ERROR.INTEGRATION_ERROR.WEBHOOK_DELIVERY_FAILED.BATCH_PARTIAL_FAILURE.BATCH_COMPLETE_FAILURE.TRANSACTION_FAILED`.split(`.`)),v={validation:400,authentication:401,authorization:403,not_found:404,conflict:409,rate_limit:429,server:500,external:502,maintenance:503},se={400:`VALIDATION_ERROR`,401:`UNAUTHENTICATED`,403:`PERMISSION_DENIED`,404:`RESOURCE_NOT_FOUND`,405:`METHOD_NOT_ALLOWED`,409:`RESOURCE_CONFLICT`,428:`PRECONDITION_REQUIRED`,429:`RATE_LIMIT_EXCEEDED`,500:`INTERNAL_ERROR`,501:`NOT_IMPLEMENTED`,502:`EXTERNAL_SERVICE_ERROR`,503:`SERVICE_UNAVAILABLE`,504:`TIMEOUT`};function ce(e){return se[e]??(e>=500?`INTERNAL_ERROR`:`VALIDATION_ERROR`)}var le=t.z.enum([`no_retry`,`retry_immediate`,`retry_backoff`,`retry_after`]),ue=t.z.enum(`required.invalid_type.invalid_shape.unknown_field.invalid_boolean.invalid_number.invalid_date.invalid_time.invalid_email.invalid_url.invalid_phone.invalid_json.invalid_format.min_length.max_length.min_value.max_value.min_items.max_items.invalid_option.invalid_value.reference_not_found.reference_ambiguous.rule_violation.json_schema_violation.invalid_initial_state.invalid_transition`.split(`.`)),de=n(()=>t.z.object({field:t.z.string().describe(`Field path (supports dot notation)`),code:ue.describe(`Which constraint the value violated (field-level catalog, ADR-0114)`),message:t.z.string().describe(`Human-readable error message, rendered in the caller’s locale`),label:t.z.string().optional().describe(`Field display label in the caller’s locale`),value:t.z.unknown().optional().describe(`The invalid value that was provided`),constraint:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`The constraint that was violated, as discrete values (e.g. { maxLength: 512, actual: 3000 })`)})),fe=n(()=>t.z.object({code:oe.describe(`Machine-readable error code`),message:t.z.string().describe(`Human-readable error message`),category:ae.optional().describe(`Error category`),httpStatus:t.z.number().optional().describe(`HTTP status code`),retryable:t.z.boolean().default(!1).describe(`Whether the request can be retried`),retryStrategy:le.optional().describe(`Recommended retry strategy`),retryAfter:t.z.number().optional().describe(`Seconds to wait before retrying`),details:t.z.unknown().optional().describe(`Additional error context`),fields:t.z.array(de).optional().describe(`One entry per offending value`),fieldErrors:c("`EnhancedApiError.fieldErrors` was renamed to `fields` in @objectstack/spec 17 (ADR-0114 D4, #3977) — the array is unchanged, only the property name. Every producer already emitted `fields`; `fieldErrors` was declared and never emitted, so a reader keying on it was reading a field no server sent."),timestamp:t.z.string().datetime().optional().describe(`When the error occurred`),requestId:t.z.string().optional().describe(`Request ID for tracking`),traceId:t.z.string().optional().describe(`Distributed trace ID`),documentation:t.z.string().url().optional().describe(`URL to error documentation`),helpText:t.z.string().optional().describe(`Suggested actions to resolve the error`)})),pe=n(()=>t.z.object({success:t.z.literal(!1).describe(`Always false for error responses`),error:fe.describe(`Error details`),meta:t.z.object({timestamp:t.z.string().datetime().optional(),requestId:t.z.string().optional(),traceId:t.z.string().optional()}).optional().describe(`Response metadata`)})),me={"@objectstack/rest":`ALREADY_REVERTED.AMBIGUOUS_MATCH.ANALYTICS_QUERY_FAILED.APPROVAL_ACTIONS_FAILED.APPROVAL_RECALL_FAILED.APPROVAL_REQUEST_GET_FAILED.APPROVAL_REQUEST_LIST_FAILED.BATCH_NOT_ATOMIC.BATCH_TOO_LARGE.BATCH_UNRESOLVED_REF.BLANK_MATCH_KEY.CONCURRENT_UPDATE.CONFLICTING_MAPPING.DATASET_INVALID.DELEGABLE_SCOPE_FAILED.DUPLICATE_REQUEST.EMAIL_SEND_FAILED.ERR_BULK_RESULT_MISMATCH.ERR_DATASOURCE_UNAVAILABLE.EXPLAIN_FAILED.EXPORT_NOT_PERMITTED.EXTERNAL_DATASOURCE_ERROR.EXTERNAL_IMPORT_ERROR.FORBIDDEN.FORM_NOT_FOUND.FORM_RESOLVE_FAILED.IMPORT_JOB_CREATE_FAILED.IMPORT_ROW_FAILED.INTERNAL.INVALID_REQUEST.INVALID_STATE.LOOKUP_NOT_PUBLIC.LOOKUP_TARGET_MISSING.MAPPING_FORMAT_MISMATCH.MAPPING_FORMAT_UNSUPPORTED.MAPPING_NOT_FOUND.MAPPING_TARGET_MISMATCH.NOT_FOUND.NOT_UNDOABLE.NO_MATCH.OBJECT_API_DISABLED.OBJECT_API_METHOD_NOT_ALLOWED.OPENAPI_UNAVAILABLE.PACKAGE_DELETE_FAILED.PACKAGE_DELETE_PARTIAL.PACKAGE_MANIFEST_INVALID.PACKAGE_PUBLISH_FAILED.PAYLOAD_TOO_LARGE.PROJECT_NOT_FOUND.PROJECT_PROVISIONING.PROJECT_PROVISIONING_FAILED.REPORTS_LIST_FAILED.REPORT_DELETE_FAILED.REPORT_GET_FAILED.REPORT_NOT_FOUND.REPORT_RUN_FAILED.REPORT_SAVE_FAILED.REPORT_SCHEDULE_FAILED.REQUEST_NOT_FOUND.RESUME_FAILED.RESUME_TARGET_LOST.RULE_DEFINE_FAILED.RULE_DELETE_FAILED.RULE_EVALUATE_FAILED.RULE_GET_FAILED.RULE_LIST_FAILED.RULE_NOT_FOUND.SCHEDULES_LIST_FAILED.SCHEDULE_DELETE_FAILED.SHARES_LIST_FAILED.SHARE_GRANT_FAILED.SHARE_REVOKE_FAILED.SUGGESTION_CONFIRM_FAILED.SUGGESTION_DISMISS_FAILED.SUGGESTION_LIST_FAILED.SUMMARY_RECOMPUTE_FAILED.UNAUTHORIZED.UNIQUE_VIOLATION.UNSUPPORTED_TRANSFORM.VALIDATION_FAILED`.split(`.`),"@objectstack/runtime":[`EXPIRED_OR_REVOKED`,`INVALID_OR_EXPIRED`,`NEEDS_PASSWORD`,`PROJECT_MEMBERSHIP_REQUIRED`,`RECORD_GONE`,`ROUTE_NOT_FOUND`,`SIGN_IN_REQUIRED`,`UNSUPPORTED`,`VALIDATION_FAILED`,`WRONG_PASSWORD`],"@objectstack/service-storage":[`ATTACHMENT_DELETE_DENIED`,`ATTACHMENT_DOWNLOAD_DENIED`,`ATTACHMENT_PARENT_ACCESS`,`AUTH_REQUIRED`,`ERR_FILE_CONSTRAINT`,`ERR_FILE_REFERENCE_COPY`,`FILE_DOWNLOAD_DENIED`,`FILE_NOT_FOUND`,`INTERNAL`,`INVALID_REQUEST`,`INVALID_RESUME_TOKEN`,`UPLOAD_SESSION_NOT_FOUND`],"@objectstack/service-i18n":[`INTERNAL`,`INVALID_REQUEST`],"@objectstack/plugin-auth":`ACCOUNT_LOCKED.ASYNC_NOT_SUPPORTED.AUTH_CONFIG_ERROR.CREATE_FAILED.DOMAIN_VERIFICATION_DISABLED.DOMAIN_VERIFICATION_FAILED.EMAIL_SERVICE_REQUIRED.ENV_ACCESS_DENIED.INVALID_EMAIL.INVALID_PHONE.INVITE_EMAIL_FAILED.INVITE_REQUIRES_EMAIL.INVALID_REQUEST.INVITE_SMS_FAILED.IP_NOT_ALLOWED.LAST_LOCAL_CREDENTIAL.NO_IDENTITY.NO_PENDING_VERIFICATION.PASSWORD_ALREADY_SET.PASSWORD_EXPIRED.PASSWORD_POLICY_VIOLATION.PASSWORD_REUSE.OAUTH_REGISTER_FAILED.PHONE_NOT_ENABLED.SAML_REGISTER_FAILED.SSO_REGISTER_FAILED.SSO_REGISTER_FORBIDDEN.USER_ALREADY_EXISTS.VALIDATION_FAILED`.split(`.`),"@objectstack/plugin-sharing":[`AUDIENCE_NOT_ALLOWED`,`EXPIRED_OR_REVOKED`,`EXPIRY_IN_PAST`,`EXPIRY_TOO_LONG`,`FORBIDDEN`,`INTERNAL`,`INVALID_EXPIRY`,`INVALID_OR_EXPIRED`,`NEEDS_PASSWORD`,`NOT_FOUND`,`PERMISSION_NOT_ALLOWED`,`RECORD_GONE`,`SHARING_NOT_ENABLED`,`SIGN_IN_REQUIRED`,`UNSUPPORTED`,`VALIDATION_FAILED`,`WRONG_PASSWORD`],"@objectstack/metadata-protocol":[`BATCH_ABORTED`,`CLONE_DISABLED`,`COMMIT_NOT_FOUND`,`CONCURRENT_UPDATE`,`DESTRUCTIVE_CHANGE`,`INVALID_METADATA`,`INVALID_REQUEST`,`ITEM_LOCKED`,`METADATA_CONFLICT`,`NAMESPACE_PREFIX`,`NO_DRAFT`,`NOT_ATTEMPTED`,`NOT_CREATABLE`,`NOT_OVERRIDABLE`,`OVERLAY_PERSISTENCE_FAILED`,`ROLLED_BACK`,`UNSUPPORTED_QUERY_PARAM`,`VALIDATION_FAILED`,`VERSION_NOT_FOUND`,`VERSION_NOT_RESTORABLE`,`WRITABLE_PACKAGE_REQUIRED`],"@objectstack/metadata-core":[`METADATA_BRANCH`,`METADATA_CONFLICT`,`METADATA_NOT_FOUND`,`METADATA_SCHEMA_INVALID`,`OS_PROTOCOL_INCOMPATIBLE`],"@objectstack/objectql":[`ERR_BULK_RESULT_MISMATCH`,`ERR_DATASOURCE_UNAVAILABLE`,`ERR_DRIVER_CONNECT`,`ERR_SUMMARY_RECOMPUTE`,`VALIDATION_FAILED`],"@objectstack/core":[`ERR_BULK_RESULT_MISMATCH`,`FILTER_TOKEN_UNKNOWN`,`FILTER_TOKEN_UNRESOLVED`],"@objectstack/hono":[`AUTH_CONFIG_ERROR`],"@objectstack/service-messaging":[`DELIVERY_NOT_ELIGIBLE`],"@objectstack/trigger-api":[`ENQUEUE_FAILED`,`INVALID_SIGNATURE`],"@objectstack/cloud-connection":[`CLOUD_FETCH_FAILED`,`CLOUD_UNCONFIGURED`,`DEVICE_CODE_FAILED`,`DRIVER_UNAVAILABLE`,`ENVIRONMENT_BIND_FAILED`,`ENVIRONMENT_NOT_FOUND`,`INVALID_REQUEST`,`MANIFEST_CONFLICT`,`MARKETPLACE_PROXY_FAILED`,`MARKETPLACE_STORAGE_FAILED`,`MARKETPLACE_UNAVAILABLE`,`NOTHING_TO_PURGE`,`PLUGIN_INSTALL_FAILED`,`PLUGIN_MANIFEST_INVALID`,`PLUGIN_REGISTER_FAILED`,`RESEED_NO_ROWS`,`RESEED_SKIPPED`],"@objectstack/service-settings":[`INTERNAL`,`SETTINGS_ACTION_FAILED`,`SETTINGS_FORBIDDEN`,`SETTINGS_LOCKED`,`SETTINGS_UNKNOWN_KEY`,`SETTINGS_UNKNOWN_NAMESPACE`,`SETTINGS_VALIDATION`,`UNKNOWN_KEY`,`UNKNOWN_NAMESPACE`],"@objectstack/service-automation":[`AUTOMATION_UNSCOPED_RUN_DATA_ACCESS`,`EXECUTION_ERROR`,`INVALID_SIGNAL`,`NODE_FAILURE`,`NO_EXECUTOR`,`RESUME_IN_PROGRESS`,`RUN_NOT_FOUND`,`STORE_UNAVAILABLE`],"@objectstack/service-analytics":[`CUBE_NOT_FOUND`,`RAW_SQL_UNSUPPORTED`],"@objectstack/service-datasource":[`DATASOURCE_ADMIN_ERROR`,`EXTERNAL_DATASOURCE_ERROR`],"@objectstack/plugin-audit":[`FEEDS_DISABLED`,`FILES_DISABLED`],"@objectstack/plugin-approvals":[`FORBIDDEN`,`RECORD_LOCKED`],"@objectstack/plugin-security":[`SUGGESTION_NOT_FOUND`,`SUGGESTION_STATE`],"@objectstack/spec":[`CONNECTOR_UPSTREAM_UNAVAILABLE`,`EXTERNAL_SCHEMA_MISMATCH`,`EXTERNAL_SCHEMA_MODE_VIOLATION`,`EXTERNAL_WRITE_FORBIDDEN`],"@objectstack/driver-mongodb":[`MONGODB_MULTI_TENANT_UNSUPPORTED`]},he=Object.freeze([...new Set(Object.values(me).flat())].sort()),ge=t.z.enum([...oe.options,...he]),_e=n(()=>t.z.object({code:ge.describe(`Error code (e.g. VALIDATION_ERROR; StandardErrorCode ∪ ERROR_CODE_LEDGER)`),message:t.z.string().describe(`Readable error message`),category:t.z.string().optional().describe(`Error category (e.g. validation, authorization)`),httpStatus:t.z.number().int().optional().describe(`HTTP status of the response carrying this error`),details:t.z.unknown().optional().describe(`Additional error context (e.g. field validation errors)`),requestId:t.z.string().optional().describe(`Request ID for tracking`)})),y=n(()=>t.z.object({success:t.z.boolean().describe(`Operation success status`),error:_e.optional().describe(`Error details if success is false`),meta:t.z.object({timestamp:t.z.string(),duration:t.z.number().optional(),requestId:t.z.string().optional(),traceId:t.z.string().optional()}).optional().describe(`Response metadata`)})),ve=new Set([`success`,`data`,`error`,`meta`]);function b(e){if(typeof e!=`object`||!e||Array.isArray(e))return[`body is ${Array.isArray(e)?`an array`:String(e===null?`null`:typeof e)}, not an envelope object`];let t=e,n=[];if(typeof t.success!=`boolean`)n.push(`success is ${t.success===void 0?`missing`:`\`${typeof t.success}\``}, must be a boolean`);else if(t.success)t.data===void 0&&n.push("success body carries no `data`"),t.error!==void 0&&n.push("success body carries an `error`");else{let e=t.error;if(e===void 0||typeof e!=`object`||!e)n.push(`failure body's \`error\` is ${e===void 0?`missing`:`a ${typeof e}`}, must be an object`);else{let t=e;typeof t.code!=`string`&&n.push(`error.code is missing or not a string`),typeof t.message!=`string`&&n.push(`error.message is missing or not a string`)}}for(let e of Object.keys(t))ve.has(e)||n.push(`stray top-level key \`${e}\` \u2014 the payload belongs under \`data\``);return n}var x=n(()=>t.z.record(t.z.string(),t.z.unknown()).describe(`Key-value map of record data`)),ye=n(()=>t.z.object({data:x.describe(`Record data to insert`)})),be=n(()=>t.z.object({data:x.describe(`Partial record data to update`)})),xe=n(()=>t.z.object({records:t.z.array(x).describe(`Array of records to process`),allOrNone:t.z.boolean().default(!0).describe(`If true, rollback entire transaction on any failure`)})),Se=n(()=>t.z.intersection(_,t.z.object({format:t.z.enum([`csv`,`json`,`xlsx`]).default(`csv`)}))),S=n(()=>y.extend({data:x.describe(`The requested or modified record`)})),Ce=n(()=>y.extend({data:t.z.array(x).describe(`Array of matching records`),pagination:t.z.object({total:t.z.number().optional().describe(`Total matching records count`),limit:t.z.number().optional().describe(`Page size`),offset:t.z.number().optional().describe(`Page offset`),cursor:t.z.string().optional().describe(`Cursor for next page`),nextCursor:t.z.string().optional().describe(`Next cursor for pagination`),hasMore:t.z.boolean().describe(`Are there more pages?`)}).describe(`Pagination info`)})),we=n(()=>t.z.object({id:t.z.string().describe(`Record ID`)})),Te=n(()=>t.z.object({id:t.z.string().optional().describe(`Record ID if processed`),success:t.z.boolean(),errors:t.z.array(_e).optional(),index:t.z.number().optional().describe(`Index in original request`),data:t.z.unknown().optional().describe(`Result data (e.g. created record)`)})),Ee=n(()=>y.extend({data:t.z.array(Te).describe(`Results for each item in the batch`)})),De=n(()=>y.extend({id:t.z.string().describe(`ID of the deleted record`)})),Oe={create:{input:ye,output:S},delete:{input:we,output:De},get:{input:we,output:S},update:{input:be,output:S},list:{input:_,output:Ce},bulkCreate:{input:xe,output:Ee},bulkUpdate:{input:xe,output:Ee},bulkUpsert:{input:xe,output:Ee},bulkDelete:{input:t.z.object({ids:t.z.array(t.z.string())}),output:Ee}},ke=n(()=>t.z.object({maxBatchSize:t.z.number().int().default(100).describe(`Maximum number of keys per batch load`),batchScheduleFn:t.z.enum([`microtask`,`timeout`,`manual`]).default(`microtask`).describe(`Scheduling strategy for collecting batch keys`),cacheEnabled:t.z.boolean().default(!0).describe(`Enable per-request result caching`),cacheKeyFn:t.z.string().optional().describe(`Name or identifier of the cache key function`),cacheTtl:t.z.number().min(0).optional().describe(`Cache time-to-live in seconds (0 = no expiration)`),coalesceRequests:t.z.boolean().default(!0).describe(`Deduplicate identical requests within a batch window`),maxConcurrency:t.z.number().int().optional().describe(`Maximum parallel batch requests`)})),Ae=n(()=>t.z.object({strategy:t.z.enum([`dataloader`,`windowed`,`prefetch`]).describe(`Batch loading strategy type`),windowMs:t.z.number().optional().describe(`Collection window duration in milliseconds (for windowed strategy)`),prefetchDepth:t.z.number().int().optional().describe(`Depth of relation prefetching (for prefetch strategy)`),associationLoading:t.z.enum([`lazy`,`eager`,`batch`]).default(`batch`).describe(`How to load related associations`)})),je=n(()=>t.z.object({preventNPlusOne:t.z.boolean().describe(`Enable N+1 query detection and prevention`),dataLoader:ke.optional().describe(`DataLoader batch loading configuration`),batchStrategy:Ae.optional().describe(`Batch loading strategy configuration`),maxQueryDepth:t.z.number().int().describe(`Maximum depth for nested relation queries`),queryComplexityLimit:t.z.number().optional().describe(`Maximum allowed query complexity score`),enableQueryPlan:t.z.boolean().default(!1).describe(`Log query execution plans for debugging`)})),C=t.z.enum([`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`]),Me=n(()=>t.z.enum([`GET`,`POST`,`PUT`,`PATCH`,`DELETE`])),Ne=n(()=>t.z.object({url:t.z.string().describe(`API endpoint URL`),method:Me.optional().default(`GET`).describe(`HTTP method`),headers:t.z.record(t.z.string(),t.z.string()).optional().describe(`Custom HTTP headers`),params:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Query parameters`),body:t.z.unknown().optional().describe(`Request body for POST/PUT/PATCH`)})),Pe=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable CORS`),origins:t.z.union([t.z.string(),t.z.array(t.z.string())]).default(`*`).describe(`Allowed origins (* for all)`),methods:t.z.array(C).optional().describe(`Allowed HTTP methods`),credentials:t.z.boolean().default(!1).describe(`Allow credentials (cookies, authorization headers)`),maxAge:t.z.number().int().optional().describe(`Preflight cache duration in seconds`)})),Fe=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable rate limiting`),windowMs:t.z.number().int().default(6e4).describe(`Time window in milliseconds`),maxRequests:t.z.number().int().default(100).describe(`Max requests per window`)})),Ie=n(()=>t.z.object({path:t.z.string().describe(`URL path to serve from`),directory:t.z.string().describe(`Physical directory to serve`),cacheControl:t.z.string().optional().describe(`Cache-Control header value`)})),Le=n(()=>t.z.object({source:t.z.string().describe(`Source field/path`),target:t.z.string().describe(`Target field/path`),transform:t.z.string().optional().describe(`Transformation function name`)})),Re=t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique endpoint ID`),path:t.z.string().regex(/^\//).describe(`URL Path (e.g. /api/v1/customers)`),method:C.describe(`HTTP Method`),summary:t.z.string().optional(),description:t.z.string().optional(),type:t.z.enum([`flow`,`script`,`object_operation`,`proxy`]).describe(`Implementation type`),target:t.z.string().describe(`Target Flow ID, Script Name, or Proxy URL`),objectParams:t.z.object({object:t.z.string().optional(),operation:t.z.enum([`find`,`get`,`create`,`update`,`delete`]).optional()}).optional().describe(`For object_operation type`),inputMapping:t.z.array(Le).optional().describe(`Map Request Body to Internal Params`),outputMapping:t.z.array(Le).optional().describe(`Map Internal Result to Response Body`),authRequired:t.z.boolean().default(!0).describe(`Require authentication`),rateLimit:Fe.optional().describe(`Rate limiting policy`),cacheTtl:t.z.number().optional().describe(`Response cache TTL in seconds`)}),ze=Object.assign(Re,{create:e=>e}),Be=t.z.enum([`available`,`registered`,`unavailable`,`degraded`,`stub`]).describe(`available = fully operational, registered = route declared but handler unverified, unavailable = not installed, degraded = partial, stub = placeholder that returns 501`),Ve=n(()=>t.z.object({enabled:t.z.boolean(),status:Be,handlerReady:t.z.boolean().optional().describe(`Whether the HTTP handler is confirmed to be mounted. Omitted = readiness unknown/unverified; true = handler mounted; false = handler missing or stub (likely 501).`),route:t.z.string().optional().describe(`e.g. /api/v1/analytics`),provider:t.z.string().optional().describe(`e.g. "objectql", "plugin-redis", "driver-memory"`),version:t.z.string().optional().describe(`Semantic version of the service implementation (e.g. "3.0.6")`),message:t.z.string().optional().describe(`e.g. "Install plugin-workflow to enable"`),rateLimit:t.z.object({requestsPerMinute:t.z.number().int().optional().describe(`Maximum requests per minute`),requestsPerHour:t.z.number().int().optional().describe(`Maximum requests per hour`),burstLimit:t.z.number().int().optional().describe(`Maximum burst request count`),retryAfterMs:t.z.number().int().optional().describe(`Suggested retry-after delay in milliseconds when rate-limited`)}).optional().describe(`Rate limit and quota info for this service`)})),He=`__serviceInfo`,Ue=n(()=>t.z.object({status:t.z.enum([`stub`,`degraded`]).describe(`stub = placeholder or dev fake (do not use for real work); degraded = functional fallback with reduced capability`),handlerReady:t.z.boolean().optional().describe(`Whether the HTTP handler genuinely serves requests. Defaults: false for stub, true for degraded.`),message:t.z.string().optional().describe(`Human-readable explanation, e.g. what to install for the full implementation`)}));function We(e){if(!e||typeof e!=`object`)return;let t=e[He];if(t&&typeof t==`object`&&(t.status===`stub`||t.status===`degraded`))return{status:t.status,handlerReady:typeof t.handlerReady==`boolean`?t.handlerReady:t.status===`degraded`,...typeof t.message==`string`?{message:t.message}:{}}}var Ge=n(()=>t.z.object({data:t.z.string().describe(`e.g. /api/v1/data`),metadata:t.z.string().describe(`e.g. /api/v1/meta`),discovery:t.z.string().optional().describe(`e.g. /api/v1/discovery`),ui:t.z.string().optional().describe(`e.g. /api/v1/ui`),auth:t.z.string().optional().describe(`e.g. /api/v1/auth`),automation:t.z.string().optional().describe(`e.g. /api/v1/automation`),storage:t.z.string().optional().describe(`e.g. /api/v1/storage`),analytics:t.z.string().optional().describe(`e.g. /api/v1/analytics`),packages:t.z.string().optional().describe(`e.g. /api/v1/packages`),approvals:t.z.string().optional().describe(`e.g. /api/v1/approvals`),realtime:t.z.string().optional().describe(`e.g. /api/v1/realtime`),notifications:t.z.string().optional().describe(`e.g. /api/v1/notifications`),ai:t.z.string().optional().describe(`e.g. /api/v1/ai`),i18n:t.z.string().optional().describe(`e.g. /api/v1/i18n`)})),Ke=n(()=>t.z.object({name:t.z.string(),version:t.z.string(),environment:t.z.enum([`production`,`sandbox`,`development`]),routes:Ge,locale:t.z.object({default:t.z.string(),supported:t.z.array(t.z.string()),timezone:t.z.string()}),services:t.z.record(t.z.string(),Ve).describe(`Per-service availability map keyed by CoreServiceName`),capabilities:t.z.record(t.z.string(),t.z.object({enabled:t.z.boolean().describe(`Whether this capability is available`),features:t.z.record(t.z.string(),t.z.boolean()).optional().describe(`Sub-feature flags within this capability`),description:t.z.string().optional().describe(`Human-readable capability description`)})).optional().describe(`Hierarchical capability descriptors for frontend intelligent adaptation`),schemaDiscovery:t.z.object({openapi:t.z.string().optional().describe(`URL to OpenAPI (Swagger) specification (e.g., "/api/v1/openapi.json")`),jsonSchema:t.z.string().optional().describe(`URL to JSON Schema definitions`)}).optional().describe(`Schema discovery endpoints for API toolchain integration`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Custom metadata key-value pairs for extensibility`)})),qe=n(()=>t.z.object({comments:t.z.boolean().describe("Whether the backend supports record comments / chatter (the `sys_comment` object served via the data API)"),automation:t.z.boolean().describe(`Whether the backend supports Automation CRUD (flows, triggers)`),cron:t.z.boolean().describe(`Whether the backend supports cron scheduling`),search:t.z.boolean().describe(`Whether the backend supports full-text search`),export:t.z.boolean().describe(`Whether the backend supports async export`),chunkedUpload:t.z.boolean().describe(`Whether the backend supports chunked (multipart) uploads`),transactionalBatch:t.z.boolean().describe(`Whether the backend exposes the atomic cross-object batch endpoint (POST {basePath}/batch, #1604/ADR-0034): all ops commit or roll back together in one transaction. Lets clients skip non-atomic client-side simulation instead of runtime-probing 404/405/501. True ⟺ the /batch route is mounted AND the runtime can honour a transaction.`)}).describe(`Well-known capability flags for frontend intelligent adaptation`)),Je=n(()=>t.z.object({route:t.z.string().describe(`Route path pattern`),method:C.describe(`HTTP method (GET, POST, etc.)`),service:t.z.string().describe(`Target service name`),declared:t.z.boolean().describe(`Whether the route is declared in discovery/metadata`),handlerRegistered:t.z.boolean().describe(`Whether the HTTP handler is registered`),healthStatus:t.z.enum([`pass`,`fail`,`missing`,`skip`]).describe(`pass = handler responds, fail = 501/503, missing = no handler (404), skip = not checked`),message:t.z.string().optional().describe(`Diagnostic message`)})),Ye=n(()=>t.z.object({timestamp:t.z.string().describe(`ISO 8601 timestamp of report generation`),adapter:t.z.string().describe(`Adapter or runtime that produced this report`),totalDeclared:t.z.number().int().describe(`Total routes declared in discovery`),totalRegistered:t.z.number().int().describe(`Routes with confirmed handler`),totalMissing:t.z.number().int().describe(`Routes missing a handler`),routes:t.z.array(Je).describe(`Per-route health entries`)})),Xe=t.z.enum(`metadata.object.created,metadata.object.updated,metadata.object.deleted,metadata.field.created,metadata.field.updated,metadata.field.deleted,metadata.view.created,metadata.view.updated,metadata.view.deleted,metadata.app.created,metadata.app.updated,metadata.app.deleted,metadata.agent.created,metadata.agent.updated,metadata.agent.deleted,metadata.tool.created,metadata.tool.updated,metadata.tool.deleted,metadata.flow.created,metadata.flow.updated,metadata.flow.deleted,metadata.action.created,metadata.action.updated,metadata.action.deleted,metadata.workflow.created,metadata.workflow.updated,metadata.workflow.deleted,metadata.dashboard.created,metadata.dashboard.updated,metadata.dashboard.deleted,metadata.report.created,metadata.report.updated,metadata.report.deleted,metadata.role.created,metadata.role.updated,metadata.role.deleted,metadata.permission.created,metadata.permission.updated,metadata.permission.deleted`.split(`,`)),Ze=t.z.enum([`data.record.created`,`data.record.updated`,`data.record.deleted`]),Qe=t.z.enum([`data.records.updated`,`data.records.deleted`]),$e=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:Xe.describe(`Event type`),metadataType:t.z.string().describe(`Metadata type (object, view, agent, etc.)`),name:t.z.string().describe(`Metadata item name`),packageId:t.z.string().optional().describe(`Package ID`),definition:t.z.unknown().optional().describe(`Full definition (create/update only)`),userId:t.z.string().optional().describe(`User who triggered the event`),timestamp:t.z.string().datetime().describe(`Event timestamp`)})),et=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:Ze.describe(`Event type`),object:t.z.string().describe(`Object name`),recordId:t.z.string().describe(`Record ID`),changes:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Changed fields`),before:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Before state`),after:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`After state`),userId:t.z.string().optional().describe(`User who triggered the event`),timestamp:t.z.string().datetime().describe(`Event timestamp`)})),tt=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:Qe.describe(`Event type`),object:t.z.string().describe(`Object name`),matched:t.z.number().int().nonnegative().describe(`Number of records affected`),userId:t.z.string().optional().describe(`User who triggered the event`),timestamp:t.z.string().datetime().describe(`Event timestamp`)})),nt=t.z.enum([`online`,`away`,`busy`,`offline`]),rt=t.z.enum([`created`,`updated`,`deleted`]),it=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),status:nt.describe(`Current presence status`),lastSeen:t.z.string().datetime().describe(`ISO 8601 datetime of last activity`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Custom presence data (e.g., current page, custom status)`)})),at=t.z.enum([`websocket`,`sse`,`polling`]),ot=t.z.enum([`record.created`,`record.updated`,`record.deleted`,`field.changed`]).describe(`Realtime event type (not yet enforced — the runtime emits data.record.* event names instead, and field.changed is never emitted; see #3197)`),st=n(()=>t.z.object({type:ot.describe(`Type of event to subscribe to`),object:t.z.string().optional().describe(`Object name to subscribe to`),filters:t.z.unknown().optional().describe(`Filter conditions`)})),w=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique subscription identifier`),events:t.z.array(st).describe(`Array of events to subscribe to`),transport:at.describe(`Transport protocol to use`),channel:t.z.string().optional().describe(`Optional channel name for grouping subscriptions`)})),ct=n(()=>it),T=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:t.z.string().describe(`Event type (e.g., record.created, record.updated)`),object:t.z.string().optional().describe(`Object name the event relates to`),action:rt.optional().describe(`Action performed`),payload:t.z.record(t.z.string(),t.z.unknown()).describe(`Event payload data`),timestamp:t.z.string().datetime().describe(`ISO 8601 datetime when event occurred`),userId:t.z.string().optional().describe(`User who triggered the event`),sessionId:t.z.string().optional().describe(`Session identifier`)})),lt=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable realtime synchronization`),transport:at.default(`websocket`).describe(`Transport protocol`),subscriptions:t.z.array(w).optional().describe(`Default subscriptions`)}).passthrough()),ut=n(()=>t.z.string().min(2,{message:`System identifier must be at least 2 characters`}).regex(/^[a-z][a-z0-9_.]*$/,{message:`System identifier must be lowercase, starting with a letter, and may contain letters, numbers, underscores, or dots (e.g., "user_profile" or "order.created")`}).describe(`System identifier (lowercase with underscores or dots)`)),E=n(()=>t.z.string().min(2,{message:`Identifier must be at least 2 characters`}).regex(/^[a-z][a-z0-9_]*$/,{message:`Identifier must be lowercase snake_case, starting with a letter, and may contain only letters, numbers, and underscores (e.g., "user_profile")`}).describe(`Snake case identifier (lowercase with underscores only)`)),D=n(()=>t.z.string().min(3,{message:`Event name must be at least 3 characters`}).regex(/^[a-z][a-z0-9_.]*$/,{message:`Event name must be lowercase with dots for namespacing (e.g., "user.created", "order.paid")`}).describe(`Event name (lowercase with dot notation for namespacing)`)),dt=t.z.enum([`subscribe`,`unsubscribe`,`event`,`ping`,`pong`,`ack`,`error`,`presence`,`cursor`,`edit`]),O=n(()=>t.z.string().min(1).regex(/^[a-z*][a-z0-9_.*]*$/,{message:`Event pattern must be lowercase and may contain letters, numbers, underscores, dots, or wildcards (e.g., "record.*", "*.created", "user.login")`}).describe(`Event pattern (supports wildcards like "record.*" or "*.created")`)),ft=n(()=>t.z.object({subscriptionId:t.z.string().uuid().describe(`Unique subscription identifier`),events:t.z.array(O).describe(`Event patterns to subscribe to (supports wildcards, e.g., "record.*", "user.created")`),objects:t.z.array(t.z.string()).optional().describe(`Object names to filter events by (e.g., ["account", "contact"])`),filters:t.z.unknown().optional().describe(`Filter conditions for event payloads (not yet enforced — the runtime filters by object name and event type only)`),channels:t.z.array(t.z.string()).optional().describe(`Channel names for scoped subscriptions`)})),pt=n(()=>t.z.object({subscriptionId:t.z.string().uuid().describe(`Subscription ID to unsubscribe from`)})),mt=nt,k=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),sessionId:t.z.string().uuid().describe(`Unique session identifier`),status:mt.describe(`Current presence status`),lastSeen:t.z.string().datetime().describe(`ISO 8601 datetime of last activity`),currentLocation:t.z.string().optional().describe(`Current page/route user is viewing`),device:t.z.enum([`desktop`,`mobile`,`tablet`,`other`]).optional().describe(`Device type`),customStatus:t.z.string().optional().describe(`Custom user status message`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional custom presence data`)})),ht=n(()=>t.z.object({status:mt.optional().describe(`Updated presence status`),currentLocation:t.z.string().optional().describe(`Updated current location`),customStatus:t.z.string().optional().describe(`Updated custom status message`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Updated metadata`)})),gt=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),sessionId:t.z.string().uuid().describe(`Session identifier`),documentId:t.z.string().describe(`Document identifier being edited`),position:t.z.object({line:t.z.number().int().nonnegative().describe(`Line number (0-indexed)`),column:t.z.number().int().nonnegative().describe(`Column number (0-indexed)`)}).optional().describe(`Cursor position in document`),selection:t.z.object({start:t.z.object({line:t.z.number().int().nonnegative(),column:t.z.number().int().nonnegative()}),end:t.z.object({line:t.z.number().int().nonnegative(),column:t.z.number().int().nonnegative()})}).optional().describe(`Selection range (if text is selected)`),color:t.z.string().optional().describe(`Cursor color for visual representation`),userName:t.z.string().optional().describe(`Display name of user`),lastUpdate:t.z.string().datetime().describe(`ISO 8601 datetime of last cursor update`)})),_t=t.z.enum([`insert`,`delete`,`replace`]),vt=n(()=>t.z.object({operationId:t.z.string().uuid().describe(`Unique operation identifier`),documentId:t.z.string().describe(`Document identifier`),userId:t.z.string().describe(`User who performed the edit`),sessionId:t.z.string().uuid().describe(`Session identifier`),type:_t.describe(`Type of edit operation`),position:t.z.object({line:t.z.number().int().nonnegative().describe(`Line number (0-indexed)`),column:t.z.number().int().nonnegative().describe(`Column number (0-indexed)`)}).describe(`Starting position of the operation`),endPosition:t.z.object({line:t.z.number().int().nonnegative(),column:t.z.number().int().nonnegative()}).optional().describe(`Ending position (for delete/replace operations)`),content:t.z.string().optional().describe(`Content to insert/replace`),version:t.z.number().int().nonnegative().describe(`Document version before this operation`),timestamp:t.z.string().datetime().describe(`ISO 8601 datetime when operation was created`),baseOperationId:t.z.string().uuid().optional().describe(`Previous operation ID this builds upon (for OT)`)})),yt=n(()=>t.z.object({documentId:t.z.string().describe(`Document identifier`),version:t.z.number().int().nonnegative().describe(`Current document version`),content:t.z.string().describe(`Current document content`),lastModified:t.z.string().datetime().describe(`ISO 8601 datetime of last modification`),activeSessions:t.z.array(t.z.string().uuid()).describe(`Active editing session IDs`),checksum:t.z.string().optional().describe(`Content checksum for integrity verification`)})),A=t.z.object({messageId:t.z.string().uuid().describe(`Unique message identifier`),type:dt.describe(`Message type`),timestamp:t.z.string().datetime().describe(`ISO 8601 datetime when message was sent`)}),bt=n(()=>A.extend({type:t.z.literal(`subscribe`),subscription:ft.describe(`Subscription configuration`)})),xt=n(()=>A.extend({type:t.z.literal(`unsubscribe`),request:pt.describe(`Unsubscribe request`)})),St=n(()=>A.extend({type:t.z.literal(`event`),subscriptionId:t.z.string().uuid().describe(`Subscription ID this event belongs to`),eventName:D.describe(`Event name`),object:t.z.string().optional().describe(`Object name the event relates to`),payload:t.z.unknown().describe(`Event payload data`),userId:t.z.string().optional().describe(`User who triggered the event`)})),Ct=n(()=>A.extend({type:t.z.literal(`presence`),presence:k.describe(`Presence state`)})),wt=n(()=>A.extend({type:t.z.literal(`cursor`),cursor:gt.describe(`Cursor position`)})),Tt=n(()=>A.extend({type:t.z.literal(`edit`),operation:vt.describe(`Edit operation`)})),Et=n(()=>A.extend({type:t.z.literal(`ack`),ackMessageId:t.z.string().uuid().describe(`ID of the message being acknowledged`),success:t.z.boolean().describe(`Whether the operation was successful`),error:t.z.string().optional().describe(`Error message if operation failed`)})),Dt=n(()=>A.extend({type:t.z.literal(`error`),code:t.z.string().describe(`Error code`),message:t.z.string().describe(`Error message`),details:t.z.unknown().optional().describe(`Additional error details`)})),Ot=n(()=>A.extend({type:t.z.literal(`ping`)})),kt=n(()=>A.extend({type:t.z.literal(`pong`),pingMessageId:t.z.string().uuid().optional().describe(`ID of ping message being responded to`)})),At=n(()=>t.z.discriminatedUnion(`type`,[bt,xt,St,Ct,wt,Tt,Et,Dt,Ot,kt])),jt=n(()=>t.z.object({url:t.z.string().url().describe(`WebSocket server URL`),protocols:t.z.array(t.z.string()).optional().describe(`WebSocket sub-protocols`),reconnect:t.z.boolean().optional().default(!0).describe(`Enable automatic reconnection`),reconnectInterval:t.z.number().int().positive().optional().default(1e3).describe(`Reconnection interval in milliseconds`),maxReconnectAttempts:t.z.number().int().positive().optional().default(5).describe(`Maximum reconnection attempts`),pingInterval:t.z.number().int().positive().optional().default(3e4).describe(`Ping interval in milliseconds`),timeout:t.z.number().int().positive().optional().default(5e3).describe(`Message timeout in milliseconds`),headers:t.z.record(t.z.string(),t.z.string()).optional().describe(`Custom headers for WebSocket handshake`)})),Mt=n(()=>t.z.object({type:t.z.enum([`subscribe`,`unsubscribe`,`data-change`,`presence-update`,`cursor-update`,`error`]).describe(`Event type`),channel:t.z.string().describe(`Channel identifier (e.g., "record.account.123", "user.456")`),payload:t.z.unknown().describe(`Event payload data`),timestamp:t.z.number().describe(`Unix timestamp in milliseconds`)})),Nt=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),userName:t.z.string().describe(`User display name`),status:t.z.enum([`online`,`away`,`offline`]).describe(`User presence status`),lastSeen:t.z.number().describe(`Unix timestamp of last activity in milliseconds`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional presence metadata (e.g., current page, custom status)`)})),Pt=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),recordId:t.z.string().describe(`Record identifier being edited`),fieldName:t.z.string().describe(`Field name being edited`),position:t.z.number().describe(`Cursor position (character offset from start)`),selection:t.z.object({start:t.z.number().describe(`Selection start position`),end:t.z.number().describe(`Selection end position`)}).optional().describe(`Text selection range (if text is selected)`)})),Ft=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable WebSocket server`),path:t.z.string().default(`/ws`).describe(`WebSocket endpoint path`),heartbeatInterval:t.z.number().default(3e4).describe(`Heartbeat interval in milliseconds`),reconnectAttempts:t.z.number().default(5).describe(`Maximum reconnection attempts for clients`),presence:t.z.boolean().default(!1).describe(`Enable presence tracking`),cursorSharing:t.z.boolean().default(!1).describe(`Enable collaborative cursor sharing`)})),It=t.z.enum([`system`,`api`,`auth`,`static`,`webhook`,`plugin`]),Lt=n(()=>t.z.object({method:C,path:t.z.string().describe(`URL Path pattern`),category:It.default(`api`),handler:t.z.string().describe(`Unique handler identifier`),summary:t.z.string().optional().describe(`OpenAPI summary`),description:t.z.string().optional().describe(`OpenAPI description`),public:t.z.boolean().default(!1).describe(`Is publicly accessible`),permissions:t.z.array(t.z.string()).optional().describe(`Required permissions`),timeout:t.z.number().int().optional().describe(`Execution timeout in ms`),rateLimit:t.z.string().optional().describe(`Rate limit policy name`)})),Rt=n(()=>t.z.object({basePath:t.z.string().default(`/api`).describe(`Global API prefix`),mounts:t.z.object({data:t.z.string().default(`/data`).describe(`Data Protocol (CRUD)`),metadata:t.z.string().default(`/meta`).describe(`Metadata Protocol (Schemas)`),auth:t.z.string().default(`/auth`).describe(`Auth Protocol`),automation:t.z.string().default(`/automation`).describe(`Automation Protocol`),storage:t.z.string().default(`/storage`).describe(`Storage Protocol`),analytics:t.z.string().default(`/analytics`).describe(`Analytics Protocol`),ui:t.z.string().default(`/ui`).describe(`UI Metadata Protocol (Views, Layouts)`),realtime:t.z.string().default(`/realtime`).describe(`Realtime/WebSocket Protocol`),notifications:t.z.string().default(`/notifications`).describe(`Notification Protocol`),ai:t.z.string().default(`/ai`).describe(`AI Engine Protocol (NLQ, Chat, Suggest)`),i18n:t.z.string().default(`/i18n`).describe(`Internationalization Protocol`),packages:t.z.string().default(`/packages`).describe(`Package Management Protocol`)}).default({data:`/data`,metadata:`/meta`,auth:`/auth`,automation:`/automation`,storage:`/storage`,analytics:`/analytics`,ui:`/ui`,realtime:`/realtime`,notifications:`/notifications`,ai:`/ai`,i18n:`/i18n`,packages:`/packages`}),cors:Pe.optional(),staticMounts:t.z.array(Ie).optional()})),zt=n(()=>t.z.object({$select:t.z.union([t.z.string(),t.z.array(t.z.string())]).optional().describe(`Fields to select`),$filter:t.z.string().optional().describe(`Filter expression (OData filter syntax)`),$orderby:t.z.union([t.z.string(),t.z.array(t.z.string())]).optional().describe(`Sort order`),$top:t.z.number().int().min(0).optional().describe(`Max results to return`),$skip:t.z.number().int().min(0).optional().describe(`Results to skip`),$expand:t.z.union([t.z.string(),t.z.array(t.z.string())]).optional().describe(`Navigation properties to expand (reference fields: lookup/master_detail/user/tree)`),$count:t.z.boolean().optional().describe(`Include total count`),$search:t.z.string().optional().describe(`Search expression`),$format:t.z.enum([`json`,`xml`,`atom`]).optional().describe(`Response format`),$apply:t.z.string().optional().describe(`Aggregation expression`)})),Bt=n(()=>t.z.enum(`contains.startswith.endswith.length.indexof.substring.tolower.toupper.trim.concat.year.month.day.hour.minute.second.date.time.now.maxdatetime.mindatetime.round.floor.ceiling.cast.isof.any.all`.split(`.`))),Vt=n(()=>t.z.object({"@odata.context":t.z.string().url().optional().describe(`Metadata context URL`),"@odata.count":t.z.number().int().optional().describe(`Total results count`),"@odata.nextLink":t.z.string().url().optional().describe(`Next page URL`),value:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Results array`)})),Ht=n(()=>t.z.object({error:t.z.object({code:t.z.string().describe(`Error code`),message:t.z.string().describe(`Error message`),target:t.z.string().optional().describe(`Error target`),details:t.z.array(t.z.object({code:t.z.string(),message:t.z.string(),target:t.z.string().optional()})).optional().describe(`Error details`),innererror:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Inner error details`)})})),j=n(()=>t.z.object({namespace:t.z.string().describe(`Service namespace`),entityTypes:t.z.array(t.z.object({name:t.z.string().describe(`Entity type name`),key:t.z.array(t.z.string()).describe(`Key fields`),properties:t.z.array(t.z.object({name:t.z.string(),type:t.z.string().describe(`OData type (Edm.String, Edm.Int32, etc.)`),nullable:t.z.boolean().default(!0)})),navigationProperties:t.z.array(t.z.object({name:t.z.string(),type:t.z.string(),partner:t.z.string().optional()})).optional()})).describe(`Entity types`),entitySets:t.z.array(t.z.object({name:t.z.string().describe(`Entity set name`),entityType:t.z.string().describe(`Entity type`)})).describe(`Entity sets`)})),Ut={buildUrl:(e,t)=>{let n=new URLSearchParams;t.$select&&n.append(`$select`,Array.isArray(t.$select)?t.$select.join(`,`):t.$select),t.$filter&&n.append(`$filter`,t.$filter),t.$orderby&&n.append(`$orderby`,Array.isArray(t.$orderby)?t.$orderby.join(`,`):t.$orderby),t.$top!==void 0&&n.append(`$top`,t.$top.toString()),t.$skip!==void 0&&n.append(`$skip`,t.$skip.toString()),t.$expand&&n.append(`$expand`,Array.isArray(t.$expand)?t.$expand.join(`,`):t.$expand),t.$count!==void 0&&n.append(`$count`,t.$count.toString()),t.$search&&n.append(`$search`,t.$search),t.$format&&n.append(`$format`,t.$format),t.$apply&&n.append(`$apply`,t.$apply);let r=n.toString();return r?`${e}?${r}`:e},filter:{eq:(e,t)=>`${e} eq ${typeof t==`string`?`'${t}'`:t}`,ne:(e,t)=>`${e} ne ${typeof t==`string`?`'${t}'`:t}`,gt:(e,t)=>`${e} gt ${t}`,lt:(e,t)=>`${e} lt ${t}`,contains:(e,t)=>`contains(${e}, '${t}')`,and:(...e)=>e.join(` and `),or:(...e)=>e.join(` or `)}},Wt=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable OData API`),path:t.z.string().default(`/odata`).describe(`OData endpoint path`),metadata:j.optional().describe(`OData metadata configuration`)}).passthrough()),Gt=t.z.enum([`read`,`create`,`update`,`delete`,`transfer`,`restore`,`purge`,`export`]),Kt=t.z.enum([`PLATFORM_ADMIN`,`TENANT_ADMIN`,`MEMBER`,`EXTERNAL`]).describe(`ADR-0095 D2 posture rung — PLATFORM_ADMIN crosses the tenant wall where object posture permits; TENANT_ADMIN sees all rows in the org; MEMBER gets business RLS; EXTERNAL sees only explicitly shared rows.`),qt=n(()=>t.z.object({kind:t.z.enum([`tenant_filter`,`owd_baseline`,`ownership`,`record_share`,`sharing_rule`,`team`,`territory`,`rls_policy`]).describe(`The row-visibility source kind evaluated for this record at this layer.`),name:t.z.string().describe(`Stable identifier of the concrete rule, share, or policy that was evaluated.`),grants:t.z.enum([`read`,`edit`,`full`]).optional().describe("Access level a sharing source grants on the record (authorable: read/edit; `full` appears only for legacy rows pending normalisation)."),via:t.z.string().optional().describe(`How the rule reached the principal — recipient group/position, ownership, or the matching criteria.`),predicate:t.z.unknown().optional().describe(`The row predicate this rule contributed, when it is filter-shaped (null = unrestricted).`),effect:t.z.enum([`admits`,`excludes`,`neutral`]).describe(`The rule's effect on THIS record: admits, excludes, or neutral.`)})),Jt=n(()=>t.z.object({outcome:t.z.enum([`admitted`,`excluded`,`not_evaluated`]).describe(`This layer's row-level outcome for the record: admitted, excluded, or not_evaluated (skipped/not row-scoped).`),rowFilter:t.z.unknown().optional().describe(`The effective row predicate this layer contributed for the record set (null = unrestricted, __deny_all__ = zero rows).`),matchesRecord:t.z.boolean().optional().describe(`Whether the specific record satisfies rowFilter — the judgement behind outcome.`),rules:t.z.array(qt).default([]).describe(`Concrete rules, shares, or policies this layer evaluated against the record, in evaluation order.`),detail:t.z.string().optional().describe(`Human-readable, record-specific explanation of this layer's outcome.`)})),Yt=n(()=>t.z.object({layer:t.z.enum([`tenant_isolation`,`principal`,`required_permissions`,`object_crud`,`fls`,`owd_baseline`,`depth`,`sharing`,`vama_bypass`,`rls`]),kernelTier:t.z.enum([`layer_0_tenant`,`layer_1_business`]).optional().describe(`ADR-0095 kernel layer: layer_0_tenant = the always-first org wall; layer_1_business = business RLS/sharing/ownership.`),verdict:t.z.enum([`grants`,`denies`,`narrows`,`widens`,`neutral`,`not_applicable`]),detail:t.z.string(),contributors:t.z.array(t.z.object({kind:t.z.enum([`permission_set`,`position`,`system`]),name:t.z.string(),via:t.z.string().optional(),state:t.z.enum([`active`,`expired`]).optional()})).default([]),record:Jt.optional().describe(`Row-level determination for the specific record under explanation; set only for record-grained requests.`)}));n(()=>t.z.object({object:t.z.string(),operation:Gt,recordId:t.z.string().optional().describe(`Optional id of one concrete record to explain at row granularity; omitted = object-level (pre-C2) request.`),userId:t.z.string().optional()})),n(()=>t.z.object({allowed:t.z.boolean(),object:t.z.string(),operation:Gt,principal:t.z.object({userId:t.z.string().nullable(),positions:t.z.array(t.z.string()).default([]),permissionSets:t.z.array(t.z.string()).default([]),principalKind:t.z.enum([`human`,`agent`,`service`,`guest`,`system`]).optional(),onBehalfOf:t.z.object({userId:t.z.string()}).optional(),posture:Kt.optional()}),layers:t.z.array(Yt),readFilter:t.z.unknown().optional(),record:n(()=>t.z.object({recordId:t.z.string().describe(`The concrete record id this verdict is about (echoes the request recordId).`),visible:t.z.boolean().describe(`Whether the operation is permitted on this specific record after all layers.`),decidedBy:t.z.enum([`tenant_isolation`,`principal`,`required_permissions`,`object_crud`,`fls`,`owd_baseline`,`depth`,`sharing`,`vama_bypass`,`rls`]).optional().describe(`The pipeline layer that decided the record-level outcome (excluded it, or last admitted it).`)})).optional().describe(`Row-level verdict for the specific record; set only for record-grained requests.`)}));var Xt=n(()=>t.z.object({permissionSet:t.z.string(),object:t.z.string(),create:t.z.boolean(),read:t.z.boolean(),edit:t.z.boolean(),delete:t.z.boolean(),viewAllRecords:t.z.boolean(),modifyAllRecords:t.z.boolean(),readScope:t.z.string().optional(),writeScope:t.z.string().optional(),sharingModel:t.z.string().optional()}));n(()=>t.z.object({version:t.z.literal(1).default(1),entries:t.z.array(Xt).default([])}));var Zt=n(()=>t.z.object({userId:t.z.string().optional(),actor:t.z.string().optional(),attributedUserId:t.z.string().optional(),email:t.z.string().optional(),tenantId:t.z.string().optional(),timezone:t.z.string().optional(),locale:t.z.string().optional(),currency:t.z.string().optional(),positions:t.z.array(t.z.string()).default([]),principalKind:t.z.enum([`human`,`agent`,`service`,`guest`,`system`]).optional(),audience:t.z.enum([`internal`,`external`]).optional(),posture:Kt.optional(),onBehalfOf:t.z.object({userId:t.z.string(),principalKind:t.z.enum([`human`,`agent`,`service`,`guest`,`system`]).optional()}).optional(),permissions:t.z.array(t.z.string()).default([]),systemPermissions:t.z.array(t.z.string()).optional(),tabPermissions:t.z.record(t.z.string(),t.z.enum([`visible`,`hidden`,`default_on`,`default_off`])).optional(),org_user_ids:t.z.array(t.z.string()).optional(),accessible_org_ids:t.z.array(t.z.string()).optional(),rlsMembership:t.z.record(t.z.string(),t.z.array(t.z.string())).optional(),isSystem:t.z.boolean().default(!1),flowRunId:t.z.string().optional(),skipTriggers:t.z.boolean().optional(),skipAutomations:t.z.boolean().optional(),seedReplay:t.z.boolean().optional(),skipStateMachine:t.z.boolean().optional(),preserveAudit:t.z.boolean().optional(),oauthScopes:t.z.array(t.z.string()).optional(),accessToken:t.z.string().optional(),transaction:t.z.unknown().optional(),traceId:t.z.string().optional()})),Qt=n(()=>t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).describe(`Data Engine query filter conditions`)),$t=n(()=>t.z.union([t.z.record(t.z.string(),t.z.enum([`asc`,`desc`])),t.z.record(t.z.string(),t.z.union([t.z.literal(1),t.z.literal(-1)])),t.z.array(l)]).describe(`Sort order definition`)),M=n(()=>t.z.object({context:Zt.partial().optional()})),en=n(()=>M.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).optional(),fields:t.z.array(p).optional(),orderBy:t.z.array(l).optional(),limit:t.z.number().optional(),offset:t.z.number().optional(),top:t.z.number().optional(),cursor:c(ne),search:re.optional(),searchFields:t.z.array(t.z.string()).optional(),expand:t.z.lazy(()=>t.z.record(t.z.string(),_)).optional(),distinct:c(h)}).describe(`QueryAST-aligned query options for IDataEngine.find() operations`));n(()=>M.extend({filter:Qt.optional(),select:t.z.array(t.z.string()).optional(),sort:$t.optional(),limit:t.z.number().int().min(1).optional(),skip:t.z.number().int().min(0).optional(),top:t.z.number().int().min(1).optional(),populate:t.z.array(t.z.string()).optional()}).describe(`Query options for IDataEngine.find() operations`));var tn=n(()=>M.extend({returning:t.z.boolean().default(!0).optional()}).describe(`Options for DataEngine.insert operations`)),nn=n(()=>M.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).optional(),upsert:t.z.boolean().default(!1).optional(),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.update operations`)),rn=n(()=>t.z.object({object:t.z.string().describe(`Object the write targeted (resolved object name)`),fields:t.z.array(t.z.string()).describe(`Caller-supplied field names the engine removed from the write payload`),reason:t.z.enum([`readonly`,`readonly_when`]).describe(`Why the fields were dropped: static readonly (#2948) or a TRUE readonlyWhen predicate (#3042)`)}).describe(`A write-path strip event: caller-supplied fields legally dropped from the payload (#3407)`));n(()=>M.extend({filter:Qt.optional(),upsert:t.z.boolean().default(!1).optional(),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.update operations`));var an=n(()=>M.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).optional(),multi:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.delete operations`));n(()=>M.extend({filter:Qt.optional(),multi:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.delete operations`));var on=n(()=>M.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).optional(),groupBy:t.z.array(t.z.string()).optional(),aggregations:t.z.array(te).optional(),having:a.optional().describe(`HAVING — filter over the aggregated rows (aggregation aliases + groupBy projections); applied engine-side after aggregation`),timezone:t.z.string().optional()}).describe(`QueryAST-aligned options for DataEngine.aggregate operations`));n(()=>M.extend({filter:Qt.optional(),groupBy:t.z.array(t.z.string()).optional(),aggregations:t.z.array(t.z.object({field:t.z.string(),method:t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`]),alias:t.z.string().optional()})).optional()}).describe(`Options for DataEngine.aggregate operations`));var sn=n(()=>M.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).optional()}).describe(`QueryAST-aligned options for DataEngine.count operations`));n(()=>M.extend({filter:Qt.optional()}).describe(`Options for DataEngine.count operations`)),n(()=>t.z.object({find:t.z.function().input(t.z.tuple([t.z.string(),en.optional()])).output(t.z.promise(t.z.array(t.z.unknown()))),findOne:t.z.function().input(t.z.tuple([t.z.string(),en.optional()])).output(t.z.promise(t.z.unknown())),insert:t.z.function().input(t.z.tuple([t.z.string(),t.z.union([t.z.record(t.z.string(),t.z.unknown()),t.z.array(t.z.record(t.z.string(),t.z.unknown()))]),tn.optional()])).output(t.z.promise(t.z.unknown())),update:t.z.function().input(t.z.tuple([t.z.string(),t.z.record(t.z.string(),t.z.unknown()),nn.optional()])).output(t.z.promise(t.z.unknown())),delete:t.z.function().input(t.z.tuple([t.z.string(),an.optional()])).output(t.z.promise(t.z.unknown())),count:t.z.function().input(t.z.tuple([t.z.string(),sn.optional()])).output(t.z.promise(t.z.number())),aggregate:t.z.function().input(t.z.tuple([t.z.string(),on])).output(t.z.promise(t.z.array(t.z.unknown())))}).describe(`Standard Data Engine Contract`));var cn=[{canonical:`where`,aliases:[`filter`]},{canonical:`fields`,aliases:[`select`]},{canonical:`orderBy`,aliases:[`sort`]},{canonical:`offset`,aliases:[`skip`]},{canonical:`expand`,aliases:[`populate`]},{canonical:`limit`,aliases:[`top`]}];function ln(e,t,n){let r={};for(let i of t){let t=[i.canonical,...i.aliases],a=t.filter(t=>e[t]!=null);if(a.length>1&&new Set(a.map(t=>JSON.stringify(e[t]))).size>1){n({canonical:i.canonical,spellings:a});continue}if(a.length>0){let t=e[a[0]];e[i.canonical]=t,r[i.canonical]=a[0]}for(let n of t)n!==i.canonical&&delete e[n]}return r}var un=cn.filter(e=>e.canonical===`where`);function dn(e){return{code:`custom`,path:[e.canonical],message:`Conflicting query parameters: ${e.spellings.map(e=>`'${e}'`).join(`, `)} are spellings of the same parameter (canonical '${e.canonical}') and were given different values. Send exactly one.`}}var N={filter:Qt.optional()};function fn(e,t){let n={...e};return ln(n,un,e=>t.addIssue(dn(e))),n}function pn(e,t){let n={...e};return ln(n,cn,e=>t.addIssue(dn(e))),n.orderBy!==void 0&&n.orderBy!==null&&!Array.isArray(n.orderBy)&&(n.orderBy=Object.entries(n.orderBy).map(([e,t])=>({field:e,order:t===`asc`||t===1?`asc`:`desc`}))),Array.isArray(n.expand)&&(n.expand=Object.fromEntries(n.expand.map(e=>[e,{object:e}]))),n}var mn=en.extend({...N,select:t.z.array(t.z.string()).optional(),sort:$t.optional(),skip:t.z.number().int().min(0).optional(),populate:t.z.array(t.z.string()).optional()}).transform((e,t)=>pn(e,t)),hn=n(()=>t.z.object({method:t.z.literal(`find`),object:t.z.string(),query:mn.optional()})),gn=n(()=>t.z.object({method:t.z.literal(`findOne`),object:t.z.string(),query:mn.optional()})),_n=n(()=>t.z.object({method:t.z.literal(`insert`),object:t.z.string(),data:t.z.union([t.z.record(t.z.string(),t.z.unknown()),t.z.array(t.z.record(t.z.string(),t.z.unknown()))]),options:tn.optional()})),vn=n(()=>t.z.object({method:t.z.literal(`update`),object:t.z.string(),data:t.z.record(t.z.string(),t.z.unknown()),id:t.z.union([t.z.string(),t.z.number()]).optional().describe(`ID for single update, or use where in options`),options:nn.extend(N).transform((e,t)=>fn(e,t)).optional()})),yn=n(()=>t.z.object({method:t.z.literal(`delete`),object:t.z.string(),id:t.z.union([t.z.string(),t.z.number()]).optional().describe(`ID for single delete, or use where in options`),options:an.extend(N).transform((e,t)=>fn(e,t)).optional()})),bn=n(()=>t.z.object({method:t.z.literal(`count`),object:t.z.string(),query:sn.extend(N).transform((e,t)=>fn(e,t)).optional()})),xn=n(()=>t.z.object({method:t.z.literal(`aggregate`),object:t.z.string(),query:on.extend(N).transform((e,t)=>fn(e,t))})),Sn=n(()=>t.z.object({method:t.z.literal(`execute`),command:t.z.unknown(),options:t.z.record(t.z.string(),t.z.unknown()).optional()})),Cn=n(()=>t.z.object({method:t.z.literal(`vectorFind`),object:t.z.string(),vector:t.z.array(t.z.number()),where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).optional(),fields:t.z.array(t.z.string()).optional(),limit:t.z.number().int().default(5).optional(),threshold:t.z.number().optional()}));n(()=>t.z.discriminatedUnion(`method`,[hn,gn,_n,vn,yn,bn,xn,Sn,Cn]).describe(`Virtual ObjectQL Request Protocol`));var wn=t.z.enum([`create`,`update`,`upsert`,`delete`]),Tn=n(()=>t.z.object({id:t.z.string().optional().describe(`Record ID (required for update/delete)`),data:x.optional().describe(`Record data (required for create/update/upsert)`),externalId:t.z.string().optional().describe(`External ID for upsert matching`)})),En=n(()=>t.z.object({atomic:t.z.boolean().optional().default(!1).describe("Opt-in all-or-nothing. When explicitly true the whole batch runs inside ONE engine transaction: the first failure rolls back every prior write, and the response reports zero successes — each row carries `errors[0].code` ROLLED_BACK (written, then undone), the causal row its own error, and rows never reached NOT_ATTEMPTED. A runtime that cannot roll back REFUSES the request (501 NOT_IMPLEMENTED) rather than silently degrading to best-effort — probe `capabilities.transactionalBatch` on /discovery first. Takes precedence over continueOnError. Default false: sequential best-effort."),returnRecords:t.z.boolean().optional().default(!1).describe(`If true, return full record data in response`),continueOnError:t.z.boolean().optional().default(!1).describe(`If true (and atomic=false), continue processing remaining records after errors`),validateOnly:c('`options.validateOnly` was removed from BatchOptions in @objectstack/spec (#4052). It was never implemented: the batch surfaces persisted regardless, so a "dry-run" would have silently executed. There is no dry-run today — drop the key. If you need to preview a batch without writing, open an issue so it can be designed (no-commit cascade / constraint semantics) and reintroduced as a flag that actually holds.')})),Dn=n(()=>t.z.object({operation:wn.describe(`Type of batch operation`),records:t.z.array(Tn).describe(`Array of records to process (server caps the count — see batch.maxBatchSize)`),options:En.optional().describe(`Batch operation options`)})),On=n(()=>t.z.object({id:t.z.string().describe(`Record ID`),data:x.describe(`Fields to update`)})),kn=n(()=>t.z.object({records:t.z.array(On).describe(`Array of records to update (server caps the count — see batch.maxBatchSize)`),options:En.optional().describe(`Update options`)})),An=n(()=>t.z.object({id:t.z.string().optional().describe(`Record ID if operation succeeded`),success:t.z.boolean().describe(`Whether this record was processed successfully`),errors:t.z.array(_e).optional().describe("Array of errors if operation failed. Branch on `errors[0].code` — an atomic batch that rolled back marks rows that were written then undone with code ROLLED_BACK and rows never reached with NOT_ATTEMPTED, while the causal row keeps its own error (#4793)."),data:x.optional().describe(`Full record data (if returnRecords=true)`),index:t.z.number().optional().describe(`Index of the record in the request array`),droppedFields:t.z.array(rn).optional().describe("Write-observability (#3407/#3431/#3455): caller-supplied fields LEGALLY stripped from THIS row before it was written — static `readonly` (#2948) / TRUE `readonlyWhen` (#3042) on update, or the #3043 create-ingress strip. Per-row because a batch can drop different fields on different rows (`readonlyWhen` is record-state-dependent). Present ONLY when ≥1 field was dropped for this row; the row still succeeded (success unchanged). A single response header cannot express per-row drops, so this body field is the canonical bulk channel — REST does not emit `X-ObjectStack-Dropped-Fields` for batches. Optional — omit-when-empty keeps the shape backward-compatible.")})),jn=n(()=>y.extend({operation:wn.optional().describe(`Operation type that was performed`),total:t.z.number().describe(`Total number of records in the batch`),succeeded:t.z.number().describe(`Number of records that succeeded`),failed:t.z.number().describe(`Number of records that failed`),results:t.z.array(An).describe(`Detailed results for each record`)})),Mn=n(()=>t.z.object({ids:t.z.array(t.z.string()).describe(`Array of record IDs to delete (server caps the count — see batch.maxBatchSize)`),options:En.optional().describe(`Delete options`)})),Nn={batchOperation:{input:Dn,output:jn},updateMany:{input:kn,output:jn},deleteMany:{input:Mn,output:jn}},Pn=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable batch operations`),maxRecordsPerBatch:t.z.number().int().min(1).max(1e3).default(200).describe(`Maximum records per batch`),defaultOptions:En.optional().describe(`Default batch options`)}).passthrough()),Fn=n(()=>t.z.object({object:t.z.string().min(1).describe(`Target object (table) name`),action:t.z.enum([`create`,`update`,`delete`]).optional().default(`create`).describe(`Operation to perform (default: create)`),id:t.z.string().optional().describe(`Target record id — required for update and delete`),data:x.optional().describe(`Record payload for create/update; a value may be { $ref: <opIndex> } to reference an earlier op's created id`)})),P=n(()=>t.z.object({operations:t.z.array(Fn).max(1e3).describe(`Ordered operations executed in one transaction`),atomic:t.z.boolean().optional().default(!0).describe(`Always true — the cross-object batch is all-or-nothing`)})),In=n(()=>rn.extend({index:t.z.number().int().min(0).describe("Index of the operation in the request `operations` array")}).describe(`A cross-object batch strip event: dropped fields plus the operation index`)),Ln=n(()=>t.z.object({results:t.z.array(t.z.unknown()).describe(`Per-operation result, index-aligned with the request operations`),droppedFields:t.z.array(In).optional().describe("Write-observability (#3407/#3431/#3455/#3794): caller-supplied fields the engine LEGALLY stripped from an operation before it was written — static `readonly` (#2948) or a TRUE `readonlyWhen` predicate (#3042). This endpoint is the console record form's save path (master-detail writes parent + children in one transaction), so without it the ONE surface where a user edits a `readonlyWhen` field reported plain success while the value never landed. Each event carries the `index` of its operation. Present ONLY when ≥1 field was dropped; the batch still committed without them (results/success semantics unchanged). Optional — omit-when-empty keeps the shape backward-compatible.")})),Rn=t.z.enum([`public`,`private`,`no-cache`,`no-store`,`must-revalidate`,`max-age`]),zn=n(()=>t.z.object({directives:t.z.array(Rn).describe(`Cache control directives`),maxAge:t.z.number().optional().describe(`Maximum cache age in seconds`),staleWhileRevalidate:t.z.number().optional().describe(`Allow serving stale content while revalidating (seconds)`),staleIfError:t.z.number().optional().describe(`Allow serving stale content on error (seconds)`)})),Bn=n(()=>t.z.object({value:t.z.string().describe(`ETag value (hash or version identifier)`),weak:t.z.boolean().optional().default(!1).describe(`Whether this is a weak ETag`)})),Vn=n(()=>t.z.object({ifNoneMatch:t.z.string().optional().describe(`ETag value for conditional request (If-None-Match header)`),ifModifiedSince:t.z.string().datetime().optional().describe(`Timestamp for conditional request (If-Modified-Since header)`),cacheControl:zn.optional().describe(`Client cache control preferences`)})),Hn=n(()=>t.z.object({data:t.z.unknown().optional().describe(`Metadata payload (omitted for 304 Not Modified)`),etag:Bn.optional().describe(`ETag for this resource version`),lastModified:t.z.string().datetime().optional().describe(`Last modification timestamp`),cacheControl:zn.optional().describe(`Cache control directives`),notModified:t.z.boolean().optional().default(!1).describe(`True if resource has not been modified (304 response)`),version:t.z.string().optional().describe(`Metadata version identifier`)})),Un=t.z.enum([`all`,`object`,`field`,`permission`,`layout`,`custom`]),Wn=n(()=>t.z.object({target:Un.describe(`What to invalidate`),identifiers:t.z.array(t.z.string()).optional().describe(`Specific resources to invalidate (e.g., object names)`),cascade:t.z.boolean().optional().default(!1).describe(`If true, invalidate dependent resources`),pattern:t.z.string().optional().describe(`Pattern for custom invalidation (supports wildcards)`)})),Gn=n(()=>t.z.object({success:t.z.boolean().describe(`Whether invalidation succeeded`),invalidated:t.z.number().describe(`Number of cache entries invalidated`),targets:t.z.array(t.z.string()).optional().describe(`List of invalidated resources`)})),Kn={getCached:{input:Vn,output:Hn},invalidate:{input:Wn,output:Gn}},qn=t.z.enum([`none`,`no-overlay`,`no-delete`,`full`]),Jn=t.z.enum([`artifact`,`package`,`env-forced`]),Yn=t.z.enum([`package`,`org`,`env-forced`]),F={_lock:qn.optional().describe(`Item-level lock — controls overlay & delete (ADR-0010).`),_lockReason:t.z.string().max(500).optional().describe(`Human-readable reason shown when a write is refused by _lock.`),_lockSource:Jn.optional().describe(`Layer that set _lock (artifact | package | env-forced).`),_provenance:Yn.optional().describe(`Origin of the item (package | org | env-forced).`),_packageId:t.z.string().optional().describe(`Owning package machine id.`),_packageVersion:t.z.string().optional().describe(`Owning package version.`),_lockDocsUrl:t.z.string().optional().describe(`Optional documentation link surfaced next to _lockReason.`)},Xn=t.z.object({lock:qn.describe(`Lock policy — none | no-overlay | no-delete | full.`),reason:t.z.string().min(1).max(500).describe(`User-visible reason shown when the lock blocks an action.`),docsUrl:t.z.string().url().optional().describe(`Optional URL the Studio banner links to for more context.`)}).strict(),Zn=t.z.enum([`cel`,`cron`,`template`]),Qn=t.z.object({rationale:t.z.string().optional(),generatedBy:t.z.string().optional()}),$n=t.z.object({dialect:Zn,source:t.z.string().min(1).optional(),ast:t.z.unknown().optional(),meta:Qn.optional()}).refine(e=>e.source!==void 0||e.ast!==void 0,{message:"Expression requires at least one of `source` or `ast`"}),I=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cel`,source:e})),$n]),er=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cron`,source:e})),$n]),tr=t.z.union([t.z.string().min(1).transform(e=>({dialect:`template`,source:e})),$n]),nr=Object.freeze({referenceFilter:{to:`lookupFilters`},cascadeDelete:{to:`deleteBehavior`},formula:{to:`expression`},displayFormat:{to:`autonumberFormat`},summaryType:{to:`summaryOperations`},summaryField:{to:`summaryOperations`},index:{why:"field-level index flags built no index and were removed in the 16.x line (#2377, ADR-0049) — declare the index in the object's `indexes[]` instead."},indexed:{why:"never a FieldSchema key; a field-level index flag built no index (#2377). Declare the index in the object's `indexes[]`."},immutable:{why:"never a FieldSchema key. Use the `readonlyWhen` predicate to lock a field after creation."},filterable:{why:"never a FieldSchema key — every declared column is filterable. `sortable` and `searchable` are the real knobs."},placeholder:{why:"never a FieldSchema key. Author hint text through `inlineHelpText` or `description`."},startingNumber:{why:"never a FieldSchema key. An autonumber counter resets per rendered prefix, which `autonumberFormat` itself determines."},validation:{why:"field-level predicates are not a FieldSchema key — author a `validation` metadata item on the object, which carries its own message."},errorMessage:{why:"pairs with the `validation` key that never existed; a `validation` metadata item carries its own message."},audit:{why:"the `auditTrail` family was pruned in 2026-06 as dead in both layers. Use `trackHistory` for the activity timeline."},auditTrail:{why:"pruned in 2026-06 as dead in both layers. Use `trackHistory` for the activity timeline."},pii:{why:"the `dataQuality` governance family was pruned in 2026-06 as dead in both layers — it enforced nothing."},dataQuality:{why:`pruned in 2026-06 as dead in both layers (#3726) — it enforced nothing.`},encrypted:{why:"the `encryptionConfig` family was pruned in 2026-06: it implied at-rest protection that never happened. The real channel is `type: 'secret'`."},encryptionConfig:{why:"pruned in 2026-06 — it implied at-rest protection that never happened. The real channel is `type: 'secret'`."},maskingRule:{why:`pruned in 2026-06 as dead in both layers — masking was never applied.`},cached:{why:`computed-field caching was pruned in 2026-06 (#3733); nothing read it.`}}),rr=t.z.enum(`text.textarea.email.url.phone.password.secret.markdown.html.richtext.number.currency.percent.date.datetime.time.boolean.toggle.select.multiselect.radio.checkboxes.lookup.master_detail.tree.user.image.file.avatar.video.audio.formula.summary.autonumber.composite.repeater.record.location.address.code.json.color.rating.slider.signature.qrcode.progress.tags.vector`.split(`.`)),ir=`Until #4001 closed this shape these were dropped silently — the field was still created, minus whatever the key was meant to constrain, protect or compute.`,ar=n(()=>R({surface:`this select option`,history:ir,aliases:{text:`label`,name:`label`,title:`label`,key:`value`,id:`value`,isDefault:`default`,selected:`default`,colour:`color`,visible:`visibleWhen`,showWhen:`visibleWhen`}},{label:t.z.string().describe(`Display label (human-readable, any case allowed)`),value:ut.describe(`Stored value (lowercase machine identifier)`),color:t.z.string().optional().describe(`Color code for badges/charts`),default:t.z.boolean().optional().describe(`Is default option`),visibleWhen:I.optional().describe("Per-option visibility predicate (CEL) — option is offered only when TRUE (else omitted). Same env as field visibleWhen (record + current_user). e.g. P`record.country == 'cn'` or P`'admin' in current_user.positions`")}));n(()=>t.z.object({latitude:t.z.number().min(-90).max(90).describe(`Latitude coordinate`),longitude:t.z.number().min(-180).max(180).describe(`Longitude coordinate`),altitude:t.z.number().optional().describe(`Altitude in meters`),accuracy:t.z.number().optional().describe(`Accuracy in meters`)}));var or=n(()=>R({surface:`this currency configuration`,history:ir,aliases:{decimals:`precision`,scale:`precision`,mode:`currencyMode`,currency:`defaultCurrency`,code:`defaultCurrency`,isoCode:`defaultCurrency`}},{precision:t.z.number().int().min(0).max(10).default(2).describe(`Decimal precision (default: 2)`),currencyMode:t.z.enum([`dynamic`,`fixed`]).default(`dynamic`).describe(`Currency mode: dynamic (user selectable) or fixed (single currency)`),defaultCurrency:t.z.string().length(3).default(`CNY`).describe(`Default or fixed currency code (ISO 4217, e.g., USD, CNY, EUR)`)}));n(()=>t.z.object({value:t.z.number().describe(`Monetary amount`),currency:t.z.string().length(3).describe(`Currency code (ISO 4217)`)})),n(()=>t.z.object({street:t.z.string().optional().describe(`Street address`),city:t.z.string().optional().describe(`City name`),state:t.z.string().optional().describe(`State/Province`),postalCode:t.z.string().optional().describe(`Postal/ZIP code`),country:t.z.string().optional().describe(`Country name or code`),countryCode:t.z.string().optional().describe(`ISO country code (e.g., US, GB)`),formatted:t.z.string().optional().describe(`Formatted address string`)}));var sr=n(()=>t.z.union([t.z.boolean(),t.z.literal(`global`)]));function cr(){let e={},t={};for(let[n,r]of Object.entries(nr))r.to?e[n]=r.to:r.why&&(t[n]=r.why);return{aliases:e,guidance:t}}var lr=n(()=>R({surface:`this field`,history:ir,aliases:{...cr().aliases,fieldName:`name`,key:`name`,column:`name`,dataType:`type`,fieldType:`type`,title:`label`,displayName:`label`,help:`inlineHelpText`,helpText:`inlineHelpText`,hint:`inlineHelpText`,tooltip:`inlineHelpText`,default:`defaultValue`,initialValue:`defaultValue`,isRequired:`required`,mandatory:`required`,notNull:`required`,isUnique:`unique`,values:`options`,choices:`options`,picklist:`options`,selectOptions:`options`,relatedTo:`reference`,referenceTo:`reference`,target:`reference`,targetObject:`reference`,lookupObject:`reference`,onDelete:`deleteBehavior`,deleteRule:`deleteBehavior`,cascade:`deleteBehavior`,formula:`expression`,calculation:`expression`,compute:`expression`,rollup:`summaryOperations`,rollUp:`summaryOperations`,summary:`summaryOperations`,aggregate:`summaryOperations`,length:`maxLength`,size:`maxLength`,decimals:`scale`,decimalPlaces:`scale`,digits:`precision`,isReadonly:`readonly`,disabled:`readonly`,isHidden:`hidden`,invisible:`hidden`,section:`group`,category:`group`,fieldset:`group`,component:`widget`,renderer:`widget`,control:`widget`,mimeTypes:`accept`,allowedTypes:`accept`,fileTypes:`accept`,maxFileSize:`maxSize`,maxBytes:`maxSize`,trackChanges:`trackHistory`,feedTracked:`trackHistory`,permissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`},guidance:{...cr().guidance,columnName:"`columnName` was removed in the 16.x line (#2377) — the SQL driver hardcodes the physical column to the field key, so a custom name was ignored. External/federated objects map physical columns with `external.columnMap` (ADR-0062 D7).",referenceFilters:"`referenceFilters` (string[]) was removed in the 16.x line (#2377) — the lookup picker only ever read the structured form. Use `lookupFilters: [{ field, operator, value }]`.",storageNotNull:"physical column constraints live under `storage` — write `storage: { notNull: true }` (ADR-0113). `required` is the WRITE contract and deliberately does not imply the column constraint.",tracked:"`tracked` is not a field key — per-field timeline tracking is `trackHistory: true` (ADR-0052 §5b)."}},{name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Machine name (snake_case)`).optional(),label:t.z.string().optional().describe(`Human readable label`),type:rr.describe(`Field Data Type`),description:t.z.string().optional().describe(`Tooltip/Help text`),format:t.z.string().optional().describe(`Format string (e.g. email, phone)`),required:t.z.boolean().default(!1).describe("Write-time contract (ADR-0113): an insert must provide a non-null value, and an update may not null it out. NOT a column constraint — the physical NOT NULL is a separate explicit opt-in (`storage.notNull`), so tightening this on a deployed object is safe: existing null rows stay readable, and editable as long as the write does not touch this field."),storage:t.z.object({notNull:t.z.boolean().optional().describe("Emit a physical NOT NULL on the column (ADR-0113). Absent = the column stays nullable even under `required: true` — the write contract is enforced at the engine, the only sanctioned write path, not by the database. Declaring this over existing null rows is a destructive migration gated by the schema-drift ceremony. Incompatible with `requiredWhen` (a conditional contract cannot be an unconditional column constraint).")}).strict().optional().describe(`Physical storage constraints (ADR-0113). Owns the DDL the write contract deliberately does not imply. Absent = no storage-level constraint requested.`),searchable:t.z.boolean().default(!1).describe(`Is searchable`),multiple:t.z.boolean().default(!1).describe(`Allow multiple values (Stores as Array/JSON). Applicable for select, lookup, file, image.`),unique:sr.default(!1).describe(`Unique constraint. true = unique within the tenant (composite with the tenant column on tenant-scoped objects); 'global' = unique platform-wide across all tenants`),defaultValue:t.z.unknown().optional().describe(`Default value`),maxLength:t.z.number().optional().describe(`Max character length`),minLength:t.z.number().optional().describe(`Min character length`),precision:t.z.number().optional().describe(`Total digits`),scale:t.z.number().optional().describe(`Decimal places`),min:t.z.number().optional().describe(`Minimum value`),max:t.z.number().optional().describe(`Maximum value`),accept:t.z.array(t.z.string()).optional().describe(`Permitted upload types for media fields, as MIME types or extensions (e.g. ["image/*", ".pdf"]). Offered to the file picker AND enforced on write.`),maxSize:t.z.number().int().positive().optional().describe(`Maximum permitted file size in BYTES for media fields. Enforced on write against the stored file size, not just checked in the browser.`),options:t.z.array(ar).optional().describe(`Static options for select/multiselect`),reference:t.z.string().optional().describe(`Target object name (snake_case) for lookup/master_detail fields. Required for relationship types. Used by $expand to resolve foreign key IDs into full objects.`),deleteBehavior:t.z.enum([`set_null`,`cascade`,`restrict`]).optional().default(`set_null`).describe(`What happens if referenced record is deleted`),inlineEdit:t.z.union([t.z.boolean(),t.z.enum([`grid`,`form`])]).optional().describe(`Edit these child records inline within the parent's form (atomic master-detail). true = auto-pick grid/form by child shape; 'grid' = editable line-item grid; 'form' = list + per-row full form.`),inlineTitle:t.z.string().optional().describe(`Title for the inline master-detail grid`),inlineColumns:t.z.array(t.z.any()).optional().describe(`Explicit columns for the inline grid (derived from the child object when omitted)`),inlineAmountField:t.z.string().optional().describe(`Numeric child field summed for the inline grid total`),relatedList:t.z.union([t.z.boolean(),t.z.literal(`primary`)]).optional().describe(`Show this child collection as a related list on the parent's detail page (read-side mirror of inlineEdit). false = suppress; true/absent = shown (stacked under the shared "Related" tab); 'primary' = core relationship, promoted to its own tab. Prominence intent, not a layout switch (ADR-0085).`),relatedListTitle:t.z.string().optional().describe(`Title for the detail-page related list`),relatedListColumns:t.z.array(t.z.any()).optional().describe(`Explicit columns for the detail-page related list (derived from the child object when omitted)`),displayField:t.z.string().optional().describe(`Field shown as each candidate's label in the picker/popover (defaults to the referenced object's name/title).`),descriptionField:t.z.string().optional().describe(`Secondary field shown under the label in the quick-select popover.`),lookupColumns:t.z.array(t.z.union([t.z.string(),R({surface:`this lookup column`,history:ir,aliases:{name:`field`,fieldName:`field`,key:`field`,title:`label`,header:`label`,size:`width`}},{field:t.z.string(),label:t.z.string().optional(),width:t.z.string().optional(),type:t.z.string().optional()})])).optional().describe(`Explicit columns for the record-picker table; auto-derived from the referenced object when omitted.`),lookupPageSize:t.z.number().int().positive().optional().describe(`Rows per page in the record-picker dialog (default 10).`),lookupFilters:t.z.array(R({surface:`this lookup filter`,history:ir,aliases:{name:`field`,fieldName:`field`,op:`operator`,comparator:`operator`,condition:`operator`},guidance:{$in:"the operator vocabulary here is flat, not Mongo-style — write `{ field, operator: 'in', value: [...] }`",values:"a multi-value filter puts the array in `value` with `operator: 'in'`"}},{field:t.z.string(),operator:t.z.enum([`eq`,`ne`,`gt`,`lt`,`gte`,`lte`,`contains`,`in`,`notIn`]),value:t.z.any()})).optional().describe(`Base filters restricting which records are selectable (e.g. only active). The structured, picker-honoured lookup filter.`),dependsOn:t.z.array(t.z.union([t.z.string(),R({surface:`this dependsOn entry`,history:ir,aliases:{name:`field`,fieldName:`field`,local:`field`,remote:`param`,remoteField:`param`,key:`param`}},{field:t.z.string(),param:t.z.string().optional()})])).optional().describe("Declares that this field's available values depend on the value of other field(s) on the same record — the form gates the field until they are set and re-evaluates as they change. For `lookup`/`master_detail` it scopes the candidate query (string = same local/remote key; {field,param} when the remote filter key differs — the {field,param} form is lookup-only). For `select`/`multiselect`/`radio` the actual per-option rule lives in each option's `visibleWhen`; list the referenced fields here (string form) so the option list gates and refreshes with the parent."),allowCreate:t.z.boolean().optional().describe(`Allow inline quick-create from the record picker: when no match exists the user can create a record from the typed text (optimistic dataSource.create with the display field). Best for simple objects whose only required field is the display field.`),expression:I.optional().describe("Formula expression (CEL). e.g. F`record.amount * 0.1`"),returnType:t.z.enum([`number`,`text`,`boolean`,`date`]).optional().describe(`Inferred value type of a formula field (number/text/boolean/date)`),summaryOperations:R({surface:`this roll-up summary`,history:ir,aliases:{child:`object`,childObject:`object`,from:`object`,source:`object`,aggregate:`function`,operation:`function`,op:`function`,aggregation:`function`,summaryField:`field`,targetField:`field`,foreignKey:`relationshipField`,fk:`relationshipField`,via:`relationshipField`,parentField:`relationshipField`,where:`filter`,criteria:`filter`,condition:`filter`}},{object:t.z.string().describe(`Source child object name for roll-up`),field:t.z.string().describe(`Field on child object to aggregate (ignored for count)`),function:t.z.enum([`count`,`sum`,`min`,`max`,`avg`]).describe(`Aggregation function to apply`),relationshipField:t.z.string().optional().describe(`FK field on the child pointing back to this parent. Auto-detected from the child's lookup/master_detail field referencing this object when omitted; set explicitly only when the child has more than one such reference.`),filter:a.optional().describe("Predicate restricting which child rows are aggregated (a query `where` FilterCondition, e.g. { status: 'received' } or { type: { $in: ['signup','trial'] } }). Omit to aggregate all children. Lets one child object feed multiple filtered roll-ups.")}).optional().describe(`Roll-up summary definition. The engine recomputes the value when child records are inserted/updated/deleted.`),language:t.z.string().optional().describe(`Programming language for syntax highlighting (e.g., javascript, python, sql)`),step:t.z.number().optional().describe(`Step increment for slider (default: 1)`),currencyConfig:or.optional().describe(`Configuration for currency field type`),dimensions:t.z.number().int().min(1).max(1e4).optional().describe(`Vector dimensionality (e.g., 1536 for OpenAI embeddings)`),trackHistory:t.z.boolean().optional().describe(`Render this field's value changes as human-readable entries on the record activity timeline (ADR-0052 §5b). Opt-in per field.`),group:t.z.string().optional().describe(`Field group name for organizing fields in forms and layouts (e.g., "contact_info", "billing", "system")`),visibleWhen:I.optional().describe("Predicate (CEL) — field is shown only when TRUE (else hidden). e.g. P`record.type == 'invoice'`"),readonlyWhen:I.optional().describe("Predicate (CEL) — field is read-only when TRUE. e.g. P`record.status == 'paid'`"),requiredWhen:I.optional().describe("Predicate (CEL) — field is required when TRUE. The only slot; the `conditionalRequired` alias was removed in protocol 17 (#3855)."),conditionalRequired:c("`conditionalRequired` was removed in @objectstack/spec 17 (#3855) — use `requiredWhen`. Rename the key; the value (a CEL predicate) is unchanged. Run `os migrate meta --from 16` to rewrite it automatically."),widget:t.z.string().optional().describe('Form widget override — names a registered field component (resolved as `field:<widget>`) to render this field instead of the `type` default. Degrades to the `type` renderer when unregistered. e.g. "object-ref", "filter-condition", "recipient-picker".'),hidden:t.z.boolean().default(!1).describe(`Hidden from default UI`),readonly:t.z.boolean().default(!1).describe('Read-only — never editable in forms, AND server-enforced on BOTH write paths: a non-system write to this field is silently dropped from the payload on UPDATE (#2948/#3003) and on INSERT (#3043; a create can no longer directly seed e.g. `approval_status: "approved"`), symmetric with `readonlyWhen`. A stripped INSERT field still falls back to its `defaultValue`. Exempt from the strip: `isSystem` writes (seed replay, migration), and an opt-in "historical" import (`preserveAudit`, #3493) — which admits a whitelist (the audit/timestamp family plus author-declared business `readonly` fields). A normal (non-system) import is NOT system-context and still strips.'),requiredPermissions:t.z.array(t.z.string()).optional().describe(`[ADR-0066 D3] Capabilities required to read/edit this field (mask on read, deny on write; AND-gate).`),ackPlaintextMasking:t.z.boolean().optional().describe("[ADR-0100] Affirm a generic `password` field's plaintext-at-rest / masked-on-read contract is intended, silencing the author-time warning (#3420). No effect on non-password fields."),system:t.z.boolean().optional().describe(`Auto-injected system/audit field (e.g. created_at, updated_by, organization_id). Tools that surface system fields separately from author-declared business fields should branch on this flag.`),sortable:t.z.boolean().optional().default(!0).describe(`Whether field is sortable in list views`),inlineHelpText:t.z.string().optional().describe(`Help text displayed below the field in forms`),autonumberFormat:t.z.string().optional().describe(`Auto-number format: literal text + {0000} counter, {YYYY}/{MM}/{DD}/{YYYYMMDD} date tokens (business tz), and {field_name} interpolation. Counter resets per rendered prefix (e.g. AD{YYYYMMDD}{0000} resets daily).`),externalId:t.z.boolean().default(!1).describe(`Is external ID for upsert operations`),...F}).superRefine((e,t)=>{e.storage?.notNull===!0&&e.requiredWhen!==void 0&&t.addIssue({code:`custom`,path:[`storage`,`notNull`],message:"`storage.notNull` cannot be combined with `requiredWhen` (ADR-0113): when the condition is false the write contract permits null, but the column would refuse it. Use `required: true` + `storage.notNull` for an unconditional constraint, or `requiredWhen` alone for a conditional write contract (the column stays nullable)."})}));function ur(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array(r+1),a=Array(r+1);for(let e=0;e<=r;e++)i[e]=e;for(let o=1;o<=n;o++){a[0]=o;for(let n=1;n<=r;n++){let r=e[o-1]===t[n-1]?0:1;a[n]=Math.min(i[n]+1,a[n-1]+1,i[n-1]+r)}[i,a]=[a,i]}return i[r]}function dr(e,t,n=3,r=3){let i=e.toLowerCase().replace(/[-\s]/g,`_`);return t.map(e=>({value:e,distance:ur(i,e)})).filter(e=>e.distance<=n&&e.distance>0).sort((e,t)=>e.distance-t.distance).slice(0,r).map(e=>e.value)}var fr=e=>e.toLowerCase().replace(/[_\-\s]/g,``);function L(e){let{surface:t,knownKeys:n,guidance:r={},history:i}=e,a={};for(let[t,n]of Object.entries(e.aliases??{}))a[fr(t)]=n;return e=>{if(e.code!==`unrecognized_keys`)return;let o=e.keys??[],s=[],c=[];for(let e of o){let t=r[e];if(t){c.push(t);continue}let i=Math.max(2,Math.floor(e.length/3)),o=a[fr(e)]??dr(e,n,i,1)[0];o&&o!==e&&s.push(`\`${e}\` \u2192 \`${o}\``)}let l=`Unrecognized key(s) on ${t}: ${o.map(e=>`\`${e}\``).join(`, `)}. ${i}`;return s.length&&(l+=` Did you mean ${s.join(`, `)}?`),c.length&&(l+=`
17
17
  ${c.map(e=>` \u2022 ${e}`).join(`
18
- `)}`),l}}function pr(e,t=0){if(t>6)return!1;let n=e._zod?.def;if(!n?.type)return!1;if(n.type===`never`)return!0;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`readonly`:case`nonoptional`:case`catch`:return pr(n.innerType,t+1);default:return!1}}function R(e,n){let{surface:r,history:i,aliases:a,guidance:o,extraKeys:s=[]}=e,c;return t.z.object(n,{error:e=>(c??=L({surface:r,knownKeys:[...Object.keys(n).filter(e=>!pr(n[e])),...s],history:i,aliases:a,guidance:o}))(e)}).strict()}function mr(e){let{visibleOn:t,visibility:n,...r}=e,i=r.visibleWhen===void 0?t===void 0?n:t:r.visibleWhen;return i===void 0?r:{...r,visibleWhen:i}}function hr(e){return/vis|conceal|hidden|show.?when/i.test(e)}var gr=e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=`Unrecognized key(s) on this view/page schema: ${t.map(e=>`\`${e}\``).join(`, `)}. Before ADR-0089 D3a these were dropped silently, shipping inert metadata; a mis-layered or stale key is now a loud parse error.`;return t.some(hr)?n+" If this is the conditional-visibility predicate, the canonical key is `visibleWhen` (ADR-0089) — `visibleOn` (view form) and `visibility` (page component) are still accepted as deprecated aliases.":n};n(()=>t.z.object({key:t.z.string().describe(`Translation key (e.g., "views.task_list.label")`),defaultValue:t.z.string().optional().describe(`Fallback value when translation key is not found`),params:t.z.record(t.z.string(),t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Interpolation parameters (e.g., { count: 5 })`)}));var z=n(()=>t.z.string().describe(`Display label (plain string; i18n keys are auto-generated by the framework)`)),_r=n(()=>t.z.object({ariaLabel:z.optional().describe(`Accessible label for screen readers (WAI-ARIA aria-label)`),ariaDescribedBy:t.z.string().optional().describe(`ID of element providing additional description (WAI-ARIA aria-describedby)`),role:t.z.string().optional().describe(`WAI-ARIA role attribute (e.g., "dialog", "navigation", "alert")`)}).describe(`ARIA accessibility attributes`));n(()=>t.z.object({key:t.z.string().describe(`Translation key`),zero:t.z.string().optional().describe(`Zero form (e.g., "No items")`),one:t.z.string().optional().describe(`Singular form (e.g., "{count} item")`),two:t.z.string().optional().describe(`Dual form (e.g., "{count} items" for exactly 2)`),few:t.z.string().optional().describe(`Few form (e.g., for 2-4 in some languages)`),many:t.z.string().optional().describe(`Many form (e.g., for 5+ in some languages)`),other:t.z.string().describe(`Default plural form (e.g., "{count} items")`)}).describe(`ICU plural rules for a translation key`));var vr=n(()=>t.z.object({style:t.z.enum([`decimal`,`currency`,`percent`,`unit`]).default(`decimal`).describe(`Number formatting style`),currency:t.z.string().optional().describe(`ISO 4217 currency code (e.g., "USD", "EUR")`),unit:t.z.string().optional().describe(`Unit for unit formatting (e.g., "kilometer", "liter")`),minimumFractionDigits:t.z.number().optional().describe(`Minimum number of fraction digits`),maximumFractionDigits:t.z.number().optional().describe(`Maximum number of fraction digits`),useGrouping:t.z.boolean().optional().describe(`Whether to use grouping separators (e.g., 1,000)`)}).describe(`Number formatting rules`)),yr=n(()=>t.z.object({dateStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Date display style`),timeStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Time display style`),timeZone:t.z.string().optional().describe(`IANA time zone (e.g., "America/New_York")`),hour12:t.z.boolean().optional().describe(`Use 12-hour format`)}).describe(`Date/time formatting rules`));n(()=>t.z.object({code:t.z.string().describe(`BCP 47 language code (e.g., "en-US", "zh-CN")`),fallbackChain:t.z.array(t.z.string()).optional().describe(`Fallback language codes in priority order (e.g., ["zh-TW", "en"])`),direction:t.z.enum([`ltr`,`rtl`]).default(`ltr`).describe(`Text direction: left-to-right or right-to-left`),numberFormat:vr.optional().describe(`Default number formatting rules`),dateFormat:yr.optional().describe(`Default date/time formatting rules`)}).describe(`Locale configuration`));var br=n(()=>t.z.enum([`bar`,`horizontal-bar`,`column`,`line`,`area`,`pie`,`donut`,`funnel`,`scatter`,`treemap`,`sankey`,`combo`,`gauge`,`solid-gauge`,`metric`,`kpi`,`bullet`,`radar`,`table`,`pivot`])),xr=n(()=>t.z.object({field:t.z.string().describe(`Data field key`),title:z.optional().describe(`Axis display title`),format:t.z.string().optional().describe(`Value format string (e.g., "$0,0.00")`),min:t.z.number().optional().describe(`Minimum value`),max:t.z.number().optional().describe(`Maximum value`),stepSize:t.z.number().optional().describe(`Step size for ticks`),showGridLines:t.z.boolean().default(!0),position:t.z.enum([`left`,`right`,`top`,`bottom`]).optional().describe(`Axis position`),logarithmic:t.z.boolean().default(!1)})),Sr=n(()=>t.z.object({name:t.z.string().describe(`Field name or series identifier`),label:z.optional().describe(`Series display label`),type:br.optional().describe(`Override chart type for this series`),color:t.z.string().optional().describe(`Series color (hex/rgb/token)`),stack:t.z.string().optional().describe(`Stack identifier to group series`),yAxis:t.z.enum([`left`,`right`]).default(`left`).describe(`Bind to specific Y-Axis`),variant:t.z.enum([`primary`,`comparison`]).default(`primary`).optional().describe(`Series visual role`),dashArray:t.z.string().optional().describe(`SVG stroke-dasharray override`),opacity:t.z.number().min(0).max(1).optional().describe(`Series opacity override`)})),Cr=n(()=>t.z.object({type:t.z.enum([`line`,`region`]).default(`line`),axis:t.z.enum([`x`,`y`]).default(`y`),value:t.z.union([t.z.number(),t.z.string()]).describe(`Start value`),endValue:t.z.union([t.z.number(),t.z.string()]).optional().describe(`End value for regions`),color:t.z.string().optional(),label:z.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),wr=n(()=>t.z.object({tooltips:t.z.boolean().default(!0).describe(`Show the hover tooltip`),brush:t.z.boolean().default(!1).describe(`Show the range selector under the plot`)}));n(()=>t.z.object({type:br,title:z.optional().describe(`Chart title`),subtitle:z.optional().describe(`Chart subtitle`),description:z.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:xr.optional().describe(`X-Axis configuration`),yAxis:t.z.array(xr).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(Sr).optional().describe(`Defined series configuration`),colors:t.z.union([t.z.array(t.z.string()),t.z.record(t.z.string(),t.z.string())]).optional().describe(`Color palette (string[]) or value→color map ({ value: color })`),height:t.z.number().optional().describe(`Fixed plot height in pixels (overrides the container default)`),showLegend:t.z.boolean().default(!0).describe(`Display legend`),showDataLabels:t.z.boolean().default(!1).describe(`Display data labels`),annotations:t.z.array(Cr).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:wr.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:_r.optional().describe(`ARIA accessibility attributes`)}));var Tr=n(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),Er=n(()=>t.z.union([t.z.string().describe(`Field to group by`),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:t.z.enum([`day`,`week`,`month`,`quarter`,`year`]).optional().describe(`Bucket date values into uniform periods`),alias:t.z.string().optional().describe("Alias for the projected group value (defaults to `field`) — this becomes the category column")})]));n(()=>t.z.object({field:t.z.string().optional().describe(`Field to aggregate — required for sum/avg/min/max, optional for count`),function:Tr.describe(`Aggregation function`),groupBy:Er.describe(`Field the rows are grouped by — the chart category axis`)}).superRefine((e,t)=>{e.function!==`count`&&!e.field&&t.addIssue({code:`custom`,path:[`field`],message:`aggregate.function "${e.function}" needs a "field" to aggregate (only "count" may omit it).`})}).describe(`Inline aggregation for an object-bound chart`));var Dr=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable public sharing`),publicLink:t.z.string().optional().describe(`Generated public share URL`),password:t.z.string().optional().describe(`Password required to access shared link`),allowedDomains:t.z.array(t.z.string()).optional().describe(`Restrict access to specific email domains (e.g. ["example.com"])`),expiresAt:t.z.string().optional().describe(`Expiration date/time in ISO 8601 format`),allowAnonymous:t.z.boolean().optional().default(!1).describe(`Allow access without authentication`)}));n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable iframe embedding`),allowedOrigins:t.z.array(t.z.string()).optional().describe(`Allowed iframe parent origins (e.g. ["https://example.com"])`),width:t.z.string().optional().default(`100%`).describe(`Embed width (CSS value)`),height:t.z.string().optional().default(`600px`).describe(`Embed height (CSS value)`),showHeader:t.z.boolean().optional().default(!0).describe(`Show interface header in embed`),showNavigation:t.z.boolean().optional().default(!1).describe(`Show navigation in embed`),responsive:t.z.boolean().optional().default(!0).describe(`Enable responsive resizing`)}));var Or=t.z.enum([`update`,`delete`,`custom`]),kr=t.z.enum([`perRecord`,`aggregate`]),Ar=n(()=>t.z.object({name:t.z.string().min(1).describe(`Param key — becomes params[name] in the patch / action params bag.`),label:t.z.string().optional().describe(`Field label in the dialog. Plain string: an authored def is not i18n-resolved (see module header).`),help:t.z.string().optional().describe("Help text under the field. (An ActionParam spells this `helpText` — known divergence, module header.)"),type:rr.describe(`Field widget to render, from the standard field-type vocabulary (text/number/select/lookup/date/…).`),required:t.z.boolean().optional().describe(`Blocks the Confirm button until a value is present.`),default:t.z.unknown().optional().describe("Value applied when the dialog opens. (An ActionParam spells this `defaultValue`.)"),options:t.z.array(t.z.object({label:t.z.string().describe(`Option label (plain string — not i18n-resolved on this path).`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Stored value.`)})).optional().describe(`Static options for select-style widgets.`),object:E.optional().describe("Target object for a `lookup` widget. (An ActionParam spells this `reference`.)"),labelField:t.z.string().optional().describe("Related-object field used as the option label for a `lookup` widget (defaults to name/full_name/email/id)."),multiple:t.z.boolean().optional().describe(`Allow picking multiple values — the param value becomes an array and is written to the patch as-is.`),placeholder:t.z.string().optional().describe(`Placeholder text.`)}).passthrough()),jr=L({surface:`this bulk action definition`,knownKeys:[`name`,`label`,`icon`,`variant`,`operation`,`execution`,`patch`,`params`,`confirmText`,`confirmLabel`,`visible`,`maxRecords`,`batchSize`],aliases:{action:`name`,actionname:`name`,title:`label`,op:`operation`,mode:`execution`,confirm:`confirmText`,confirmmessage:`confirmText`,limit:`maxRecords`,max:`maxRecords`,batch:`batchSize`},guidance:{actionDef:"`actionDef` is attached by the renderer, not authored: `resolveBulkActions` looks the action up by `name` and inlines it. Writing it by hand smuggles an action definition past the action registry — no permission gate, no param contract, no lint. Declare the action normally and let this def name it.",bulkEnabled:"`action.bulkEnabled` was retired in spec 17: the selection bar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, which is this array. There is nothing to set.",recordIdParam:"`recordIdParam` belongs on the ACTION, not on the def that names it — a per-record bulk run reuses the action's own declaration, and an `execution: 'aggregate'` run carries the whole selection in `params._selectedIds` instead of a single record id."},history:"Until #4457 the whole array was `z.array(z.record(z.string(), z.any()))` — every key parsed, so a mis-spelled one shipped as a button that silently ran the DEFAULT behaviour (or none at all)."}),Mr=n(()=>t.z.object({name:E.describe(`Stable identifier — the audit-log action key, and (for an aggregate def) the name of the object action to dispatch.`),label:t.z.string().optional().describe("Button + dialog-header text. Plain string: an authored def is not i18n-resolved (declare a real action and name it in `bulkActions` to get localization)."),icon:t.z.string().optional().describe(`Lucide icon name (e.g. "user-check", "trash-2").`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`outline`]).optional().describe(`Visual treatment of the button.`),operation:Or.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:kr.optional().describe("For `operation: 'custom'` — 'aggregate' dispatches the named action ONCE for the whole selection, carrying every id in `params._selectedIds` (objectui#3139). Required on a custom def: the per-record form is declared as `bulkActions: ['<name>']` instead."),patch:t.z.record(t.z.string(),t.z.unknown()).optional().describe("For `operation: 'update'` — static field values applied to every selected record, merged UNDER the user-supplied params so a fixed value can be declared without exposing it in the dialog."),params:t.z.array(Ar).optional().describe(`Inputs collected once before the run. Omit to skip the params step and go straight to confirm.`),confirmText:t.z.string().optional().describe(`Confirmation text shown above the affected-record summary.`),confirmLabel:t.z.string().optional().describe(`Custom Confirm button label (default: "Run").`),visible:I.optional().describe("Eligibility predicate (CEL), same shape as `action.visible`. Evaluated once PER SELECTED RECORD with that record bound: the button is offered when at least one passes, the run covers only those, and the rest are reported as skipped. A record-free predicate (`features.x`, `current_user.y`) therefore behaves as a plain button-level gate. Fail-closed — a predicate that faults excludes the record."),maxRecords:t.z.number().int().positive().optional().describe(`Selection size above which the run is blocked. Set it on defs whose server work is expensive — an aggregate def carries every selected id in one request.`),batchSize:t.z.number().int().positive().optional().describe(`Records per executor batch (default 200). Data-plane operations only — an aggregate run is a single call by definition.`)},{error:jr}).strict().superRefine((e,t)=>{e.operation===`custom`&&e.execution!==`aggregate`&&t.addIssue({code:`custom`,path:[`execution`],message:`Bulk action "${e.name}" declares \`operation: 'custom'\` without \`execution: 'aggregate'\`, which the renderer treats as a no-op \u2014 the button runs, reports success for every selected record, and does nothing. Pick the form you meant: to run the action ONCE PER record, drop this def and name the action in the view's \`bulkActions: ['${e.name}']\` (it is promoted with the action's label, params and \`visible\`); to run it ONCE for the whole selection, add \`execution: 'aggregate'\` (the handler reads \`params._selectedIds\`). For a mass field update or delete, use \`operation: 'update'\` / \`'delete'\` instead.`}),e.execution!==void 0&&e.operation!==`custom`&&t.addIssue({code:`custom`,path:[`execution`],message:`\`execution\` only applies to \`operation: 'custom'\` \u2014 a '${e.operation}' def is a data-plane mass mutation, always batched per record. Remove it, or switch the def to \`operation: 'custom'\` if you meant to dispatch an action.`}),e.patch!==void 0&&e.operation!==`update`&&t.addIssue({code:`custom`,path:[`patch`],message:`\`patch\` only applies to \`operation: 'update'\` \u2014 a '${e.operation}' def never writes fields, so these values are silently dropped. Use \`operation: 'update'\`, or move the constant into the action's own \`bodyExtra\`/\`params\` if this is a custom def.`}),e.params!==void 0&&e.operation===`delete`&&t.addIssue({code:`custom`,path:[`params`],message:"`params` on a `delete` def collects values the executor never reads — a bulk delete takes ids only. Remove them, or use `operation: 'update'` if the dialog is meant to write something."}),e.batchSize!==void 0&&e.execution===`aggregate`&&t.addIssue({code:`custom`,path:[`batchSize`],message:"`batchSize` does not apply to an aggregate def — the whole selection goes out in ONE call by definition, which is the point of `execution: 'aggregate'`. To bound how much a single call may carry, use `maxRecords`."})})),B=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,Nr=n(()=>t.z.discriminatedUnion(`provider`,[t.z.object({provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),t.z.object({provider:t.z.literal(`api`),read:Ne.optional().describe(`Configuration for fetching data`),write:Ne.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),t.z.object({provider:t.z.literal(`value`),items:t.z.array(t.z.unknown()).describe(`Static data array`)}),t.z.object({provider:t.z.literal(`schema`),schemaId:t.z.string().describe(`Schema identifier — typically the metadata type name`),schema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Inline JSON Schema (Draft 2020-12). Optional when schemaId is resolvable.`)})])),Pr=[`equals`,`not_equals`,`contains`,`not_contains`,`starts_with`,`ends_with`,`greater_than`,`less_than`,`greater_than_or_equal`,`less_than_or_equal`,`in`,`not_in`,`is_empty`,`is_not_empty`,`is_null`,`is_not_null`,`before`,`after`,`between`],Fr={eq:`equals`,ne:`not_equals`,neq:`not_equals`,notequals:`not_equals`,notEquals:`not_equals`,notcontains:`not_contains`,notContains:`not_contains`,startswith:`starts_with`,startsWith:`starts_with`,endswith:`ends_with`,endsWith:`ends_with`,gt:`greater_than`,greaterthan:`greater_than`,greaterThan:`greater_than`,lt:`less_than`,lessthan:`less_than`,lessThan:`less_than`,gte:`greater_than_or_equal`,greaterorequal:`greater_than_or_equal`,greaterOrEqual:`greater_than_or_equal`,greaterThanOrEqual:`greater_than_or_equal`,lte:`less_than_or_equal`,lessorequal:`less_than_or_equal`,lessOrEqual:`less_than_or_equal`,lessThanOrEqual:`less_than_or_equal`,nin:`not_in`,notin:`not_in`,notIn:`not_in`,isempty:`is_empty`,isEmpty:`is_empty`,isnotempty:`is_not_empty`,isNotEmpty:`is_not_empty`,isnull:`is_null`,isNull:`is_null`,isnotnull:`is_not_null`,isNotNull:`is_not_null`};function Ir(e){return typeof e!=`string`||Pr.includes(e)?e:Fr[e]??Fr[e.toLowerCase()]??e}var Lr=n(()=>R({surface:`this view filter rule`,history:B},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(Ir,t.z.enum(Pr)).describe(`Filter operator`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean(),t.z.null(),t.z.array(t.z.union([t.z.string(),t.z.number()]))]).optional().describe(`Filter value`)}).describe(`View filter rule`)),Rr=n(()=>t.z.enum([`none`,`count`,`count_empty`,`count_filled`,`count_unique`,`percent_empty`,`percent_filled`,`sum`,`avg`,`min`,`max`]).describe(`Aggregation function for column footer summary`)),zr=n(()=>R({surface:`this column summary configuration`,history:B},{type:Rr.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),Br=n(()=>R({surface:`this column prefix`,history:B},{field:t.z.string().describe(`Field whose value renders before the cell value`),type:t.z.enum([`badge`,`text`]).default(`text`).describe(`How the prefix value is rendered`)}).describe(`Compound-cell prefix configuration`)),Vr=n(()=>R({surface:`this list column`,history:B},{field:t.z.string().describe(`Field name (snake_case)`),label:z.optional().describe(`Display label override`),width:t.z.number().positive().optional().describe(`Column width in pixels`),align:t.z.enum([`left`,`center`,`right`]).optional().describe(`Text alignment`),hidden:t.z.boolean().optional().describe(`Hide column by default`),sortable:t.z.boolean().optional().describe(`Allow sorting by this column`),resizable:t.z.boolean().optional().describe(`Allow resizing this column`),wrap:t.z.boolean().optional().describe(`Allow text wrapping`),type:t.z.string().optional().describe(`Renderer type override (e.g., "currency", "date")`),pinned:t.z.enum([`left`,`right`]).optional().describe(`Pin/freeze column to left or right side`),summary:t.z.union([Rr,zr]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:Br.optional().describe(`Field rendered inline before this cell value`),link:t.z.boolean().optional().describe(`Functions as the primary navigation link (triggers View navigation)`),action:t.z.string().optional().describe(`Registered Action ID to execute when clicked`)})),Hr=n(()=>R({surface:`this selection configuration`,history:B},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),Ur=n(()=>R({surface:`this pagination configuration`,history:B},{pageSize:t.z.number().int().positive().default(25).describe(`Number of records per page`),pageSizeOptions:t.z.array(t.z.number().int().positive()).optional().describe(`Available page size options`)})),Wr=n(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),Gr=n(()=>R({surface:`this grouping field`,history:B},{field:t.z.string().describe(`Field name to group by`),order:t.z.enum([`asc`,`desc`]).default(`asc`).describe(`Group sort order`),collapsed:t.z.boolean().default(!1).describe(`Collapse groups by default`)})),Kr=n(()=>R({surface:`this grouping configuration`,history:B},{fields:t.z.array(Gr).min(1).describe(`Fields to group by (supports up to 3 levels)`)}).describe(`Record grouping configuration`)),qr=n(()=>R({surface:`this gallery configuration`,history:B},{coverField:t.z.string().optional().describe(`Attachment/image field to display as card cover`),coverFit:t.z.enum([`cover`,`contain`]).default(`cover`).describe(`Image fit mode for card cover`),cardSize:t.z.enum([`small`,`medium`,`large`]).default(`medium`).describe(`Card size in gallery view`),titleField:t.z.string().optional().describe(`Field to display as card title`),visibleFields:t.z.array(t.z.string()).optional().describe(`Fields to display on card body`)}).describe(`Gallery/card view configuration`)),Jr=n(()=>R({surface:`this timeline configuration`,history:B},{startDateField:t.z.string().describe(`Field for timeline item start date`),endDateField:t.z.string().optional().describe(`Field for timeline item end date`),titleField:t.z.string().describe(`Field to display as timeline item title`),groupByField:t.z.string().optional().describe(`Field to group timeline rows`),colorField:t.z.string().optional().describe(`Field to determine item color`),scale:t.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).default(`week`).describe(`Default timeline scale`)}).describe(`Timeline view configuration`)),Yr=n(()=>R({surface:`this view sharing`,history:B},{type:t.z.enum([`personal`,`collaborative`]).default(`collaborative`).describe(`View ownership type`),lockedBy:t.z.string().optional().describe(`User who locked the view configuration`)}).describe(`View sharing and access configuration`)),Xr=n(()=>R({surface:`this row color configuration`,history:B},{field:t.z.string().describe(`Field to derive color from (typically a select/status field)`),colors:t.z.record(t.z.string(),t.z.string()).optional().describe(`Map of field value to color (hex/token)`)}).describe(`Row color configuration based on field values`)),Zr=n(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),Qr=n(()=>R({surface:`this user actions configuration`,history:B},{sort:t.z.boolean().default(!0).describe(`Allow users to sort records`),search:t.z.boolean().default(!0).describe(`Allow users to search records`),filter:t.z.boolean().default(!0).describe(`Allow users to filter records`),refresh:t.z.boolean().default(!0).describe(`Allow users to reload the view data from the backend without a full page reload`),rowHeight:t.z.boolean().default(!0).describe(`Allow users to toggle row height/density`),addRecordForm:t.z.boolean().default(!1).describe(`Add records through a form instead of inline`),editInline:t.z.boolean().default(!1).describe(`Allow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in.`),buttons:t.z.array(t.z.string()).optional().describe(`Custom action button IDs to show in the toolbar`)}).describe(`User action toggles for the view toolbar`)),$r=n(()=>R({surface:`this appearance configuration`,history:B},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array(Zr).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),V=n(()=>R({surface:`this view tab`,history:B},{name:E.describe(`Tab identifier (snake_case)`),label:z.optional().describe(`Display label`),icon:t.z.string().optional().describe(`Tab icon name`),view:t.z.string().optional().describe(`Referenced list view name from listViews`),filter:t.z.array(Lr).optional().describe(`Tab-specific filter criteria`),order:t.z.number().int().min(0).optional().describe(`Tab display order`),pinned:t.z.boolean().default(!1).describe(`Pin tab (cannot be removed by users)`),isDefault:t.z.boolean().default(!1).describe(`Set as the default active tab`),visible:t.z.boolean().default(!0).describe(`Tab visibility`)}).describe(`Tab configuration for multi-tab view interface`)),ei=n(()=>R({surface:`this user filter field`,history:B},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:z.optional().describe(`Display label override (defaults to the field label)`),type:t.z.enum([`select`,`multi-select`,`boolean`,`date-range`,`text`]).optional().describe(`Filter control type. Omit to infer from the field definition`),options:t.z.array(t.z.object({value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Option value`),label:z.describe(`Option label`),color:t.z.string().optional().describe(`Option color token/hex`)})).optional().describe(`Static options. Omit to derive from the field definition (select options / lookup records)`),showCount:t.z.boolean().optional().describe(`Show per-option record counts`),defaultValues:t.z.array(t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Pre-selected values when the view loads`)}).describe(`Quick-filter field configuration`)),ti=n(()=>t.z.object({element:t.z.enum([`dropdown`,`tabs`,`toggle`]).default(`dropdown`).describe(`Filter control style: "dropdown" (per-field value selectors) or "tabs" (named presets). "toggle" is deprecated.`),fields:t.z.array(ei).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(V).optional().describe(`Named filter presets rendered as tabs (tabs element). Reuses ViewTabSchema`),showAllRecords:t.z.boolean().optional().describe(`Show an "All records" tab before the presets (tabs element)`)}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),ni=n(()=>R({surface:`this add record configuration`,history:B},{enabled:t.z.boolean().default(!0).describe(`Show the add record entry point`),position:t.z.enum([`top`,`bottom`,`both`]).default(`bottom`).describe(`Position of the add record button`),mode:t.z.enum([`inline`,`form`,`modal`]).default(`inline`).describe(`How to add a new record`),formView:t.z.string().optional().describe(`Named form view to use when mode is "form" or "modal"`)}).describe(`Add record entry point configuration`)),ri=n(()=>R({surface:`this kanban configuration`,history:B},{groupByField:t.z.string().describe(`Field to group columns by (usually status/select)`),summarizeField:t.z.string().optional().describe(`Field to sum at top of column (e.g. amount)`),columns:t.z.array(t.z.string()).describe(`Fields to show on cards`)})),ii=n(()=>R({surface:`this list chart configuration`,history:B},{chartType:br.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:E.describe(`Dataset name to bind (ADR-0021)`),dimensions:t.z.array(t.z.string()).optional().describe(`Dimension names — X/group/split`),values:t.z.array(t.z.string()).min(1).describe(`Measure names — Y (at least one)`)}).describe(`List chart view configuration`)),ai=n(()=>R({surface:`this calendar configuration`,history:B},{startDateField:t.z.string().describe(`Field providing the event start date/time`),endDateField:t.z.string().optional().describe(`Field providing the event end date/time (defaults to a single-day event)`),titleField:t.z.string().describe(`Field displayed as the event title`),colorField:t.z.string().optional().describe(`Field whose value determines the event color`)})),oi=n(()=>R({surface:`this gantt quick filter`,history:B},{field:t.z.string().describe(`Record field / dot-path the dimension filters on`),label:t.z.string().optional().describe(`Trigger label (falls back to the field label)`),options:t.z.array(t.z.union([t.z.string(),t.z.object({value:t.z.union([t.z.string(),t.z.number()]),label:t.z.string().optional()})])).optional().describe(`Explicit option override for fixed enums`)})),si=n(()=>R({surface:`this gantt configuration`,history:B},{startDateField:t.z.string().describe(`Field providing the task start date`),endDateField:t.z.string().describe(`Field providing the task end date`),titleField:t.z.string().describe(`Field displayed as the task title`),progressField:t.z.string().optional().describe(`Field providing the task completion percentage`),dependenciesField:t.z.string().optional().describe(`Field listing the task's predecessor (dependency) record ids`),colorField:t.z.string().optional().describe(`Field that drives the bar color`),parentField:t.z.string().optional().describe(`Field holding the parent task id (builds the summary → step tree)`),typeField:t.z.string().optional().describe(`Field whose value maps to task/summary/milestone`),baselineStartField:t.z.string().optional().describe(`Baseline (planned) start field`),baselineEndField:t.z.string().optional().describe(`Baseline (planned) end field`),groupByField:t.z.string().optional().describe(`Field to group leaf tasks by (synthesized summary rows)`),resourceView:t.z.boolean().optional().describe(`Render a per-resource workload histogram instead of the timeline`),assigneeField:t.z.string().optional().describe(`Resource field to bucket load by (resource view)`),effortField:t.z.string().optional().describe(`Per-task load units (resource view; default 1)`),capacity:t.z.number().optional().describe(`Per-resource capacity ceiling; loads above this flag overload`),tooltipFields:t.z.array(t.z.union([t.z.string(),t.z.object({field:t.z.string(),label:t.z.string().optional()})])).optional().describe(`Fields to surface in the hover tooltip, in display order`),quickFilters:t.z.array(oi).optional().describe(`Multi-select filter dropdowns rendered above the chart`),autoZoomToFilter:t.z.boolean().optional().describe(`When true (default), filtering zooms the range to the filtered tasks`)}).passthrough()),ci=n(()=>R({surface:`this tree configuration`,history:B},{parentField:t.z.string().optional().describe(`Single-parent pointer field (auto-detected from the object schema when omitted)`),labelField:t.z.string().optional().describe(`Field rendered indented in the first column (defaults to "name")`),fields:t.z.array(t.z.string()).optional().describe(`Additional fields rendered as flat columns alongside the label`),defaultExpandedDepth:t.z.number().int().min(0).optional().describe(`Initial expansion depth (0 = roots only; omit = expand all)`)}).passthrough()),li=n(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),ui=n(()=>R({surface:`this navigation configuration`,history:B},{mode:li.default(`page`),view:t.z.string().optional().describe(`Name of the form view to use for details (e.g. "summary_view", "edit_form")`),preventNavigation:t.z.boolean().default(!1).describe(`Disable standard navigation entirely`),openNewTab:t.z.boolean().default(!1).describe(`Force open in new tab (applies to page mode)`),size:t.z.enum([`auto`,`sm`,`md`,`lg`,`xl`,`full`]).default(`auto`).describe("[#2578] Overlay size bucket for drawer/modal detail: 'auto' (default — renderer derives from field count + viewport; AI writes nothing) or a coarse override sm/md/lg/xl/full. Prefer this over the pixel `width`; page mode ignores it."),width:t.z.union([t.z.string(),t.z.number()]).optional().describe('[DEPRECATED → size] Pixel/percent width of the drawer/modal (e.g. "600px"). A pixel width cannot be chosen at authoring time without knowing the client viewport — use the `size` bucket.')})),di=n(()=>R({surface:`this list view`,history:B},{name:E.optional().describe(`Internal view name (lowercase snake_case)`),label:z.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:Nr.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(Vr)]).describe(`Fields to display as columns`),filter:t.z.array(Lr).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(t.z.object({field:t.z.string(),order:t.z.enum([`asc`,`desc`])}))]).optional(),searchableFields:t.z.array(t.z.string()).optional().describe(`Fields enabled for search`),filterableFields:t.z.array(t.z.string()).optional().describe(`Legacy shorthand for userFilters.fields — bare field names enabled for end-user filtering. Prefer userFilters`),userFilters:ti.optional().describe(`End-user quick-filter bar: dropdown/toggle fields or tab presets. Omit to let the renderer derive filters from select/boolean fields`),resizable:t.z.boolean().optional().describe(`Enable column resizing`),striped:t.z.boolean().optional().describe(`Striped row styling`),bordered:t.z.boolean().optional().describe(`Show borders`),compactToolbar:t.z.boolean().optional().describe(`Collapse Group/Color/Density/Hide-fields into a single View settings popover`),selection:Hr.optional().describe(`Row selection configuration`),navigation:ui.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:Ur.optional().describe(`Pagination configuration`),kanban:ri.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:ai.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:si.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:qr.optional(),timeline:Jr.optional(),chart:ii.optional(),tree:ci.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:z.optional().describe(`View description for documentation/tooltips`),sharing:Yr.optional().describe(`View sharing and access configuration`),rowHeight:Wr.optional().describe(`Row height / density setting`),grouping:Kr.optional().describe(`Group records by one or more fields`),rowColor:Xr.optional().describe(`Color rows based on field value`),hiddenFields:t.z.array(t.z.string()).optional().describe(`Fields to hide in this specific view`),fieldOrder:t.z.array(t.z.string()).optional().describe(`Explicit field display order for this view`),rowActions:t.z.array(t.z.string()).optional().describe(`Actions available for individual row items`),bulkActions:t.z.array(t.z.string()).optional().describe(`Actions available when multiple rows are selected`),bulkActionDefs:t.z.array(Mr).optional().describe("Rich bulk action definitions (schema-driven, executed via BulkActionDialog). Use a def for a mass data-plane mutation ('update' with a `patch` / 'delete') that no action expresses, or for an `operation: 'custom'` + `execution: 'aggregate'` entry (objectui#3139) that dispatches the action it NAMES once for the whole selection — the renderer injects `params._selectedIds: string[]` (read that on the server, not `recordId`) so a single call can produce one aggregate artifact (zip of QR codes, merged PDF, batch print). Aggregate results are all-or-nothing: a handler that cannot cover the whole selection must reject, and per-row retry is replaced by re-running the action. `batchSize` does not apply (the call is never chunked); set `maxRecords` on defs whose server work is expensive. For the PER-RECORD dispatch use `bulkActions: ['<name>']` instead — the bare-string form, promoted with the action's own label, params and `visible`; a 'custom' def without `execution: 'aggregate'` has no dispatcher and is refused at parse time (#4457). Toolbar url/api actions can also interpolate the current selection via `${ctx.selection.ids}` / `${ctx.selection.count}`."),virtualScroll:t.z.boolean().optional().describe(`Enable virtual scrolling for large datasets`),conditionalFormatting:t.z.array(t.z.object({condition:I.describe(`Predicate (CEL) to evaluate.`),style:t.z.record(t.z.string(),t.z.string()).describe(`CSS styles to apply when condition is true`)})).optional().describe(`Conditional formatting rules for list rows`),inlineEdit:t.z.boolean().optional().describe(`Allow inline editing of records directly in the list view`),exportOptions:t.z.array(t.z.enum([`csv`,`xlsx`,`pdf`,`json`])).optional().describe(`Available export format options`),userActions:Qr.optional().describe(`User action toggles for the view toolbar`),appearance:$r.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(V).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:ni.optional().describe(`Add record entry point configuration`),showRecordCount:t.z.boolean().optional().describe(`Show record count at the bottom of the list`),allowPrinting:t.z.boolean().optional().describe(`Allow users to print the view`),emptyState:t.z.object({title:z.optional(),message:z.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:_r.optional().describe(`ARIA accessibility attributes for the list view`),responsive:c("`view.responsive` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer ever read it; the grid is responsive by its own layout rules. Delete the key."),performance:c("`view.performance` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer or runtime read it; list-view performance tuning was never implemented. Delete the key.")})),fi=n(()=>t.z.object({field:t.z.string().describe(`Field name (snake_case)`),type:rr.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(ar).optional().describe(`Options for select/multiselect/radio/checkboxes fields`),reference:t.z.string().optional().describe(`Target object name for lookup/master_detail fields`),maxLength:t.z.number().optional().describe(`Maximum character length (for text/textarea/email/url/phone)`),minLength:t.z.number().optional().describe(`Minimum character length`),min:t.z.number().optional().describe(`Minimum value (for number/currency/percent/slider)`),max:t.z.number().optional().describe(`Maximum value`),precision:t.z.number().optional().describe(`Total digits (for number/currency)`),scale:t.z.number().optional().describe(`Decimal places`),multiple:t.z.boolean().optional().describe(`Allow multiple values (for select/lookup/file/image)`),label:z.optional().describe(`Display label override`),placeholder:z.optional().describe(`Placeholder text`),helpText:z.optional().describe(`Help/hint text`),readonly:t.z.boolean().optional().describe(`Read-only override`),immutable:t.z.boolean().optional().describe(`Editable on create, locked once the record exists (e.g. machine names).`),required:t.z.boolean().optional().describe(`Required override`),hidden:t.z.boolean().optional().describe(`Hidden override`),colSpan:t.z.number().int().min(1).max(4).optional().describe("[legacy — prefer `span`] Absolute column span (1-4). Fragile when the column count is derived per surface (mobile 1 / modal 2 / page 3-4): a fixed span only lines up at the width the author imagined. The renderer clamps it to the current column count. Prefer `span`."),span:t.z.enum([`auto`,`full`]).default(`auto`).describe("Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count (wide widgets like textarea/richtext/json/file/subform take the whole row). 'full': whole row at any column count. Prefer this over the absolute `colSpan`."),widget:t.z.string().optional().describe(`Custom widget/component name (overrides type-based inference)`),language:t.z.string().optional().describe(`Code editor language (for type=code)`),keyField:t.z.object({field:t.z.string().default(`name`).describe(`Property name that holds the key inside each item (defaults to "name")`),label:z.optional().describe(`Display label for the key column`),placeholder:z.optional().describe(`Placeholder when entering a new key`),helpText:z.optional().describe(`Help text under the key input`),regex:t.z.string().optional().describe(`JS regex source string the key must match (no flags)`),immutable:t.z.boolean().default(!0).describe(`If true, the key is read-only after creation`)}).optional().describe(`Key column config for record-typed fields`),dependsOn:t.z.string().optional().describe(`Parent field name for cascading`),visibleWhen:I.optional().describe("Visibility predicate (CEL) — field shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms). e.g. P`record.priority == 'urgent'`"),visibleOn:I.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Normalized to `visibleWhen` at parse."),disclosure:t.z.enum([`inline`,`popover`]).optional().describe(`Composite rendering: inline bordered box (default) or a summary line + gear popover (progressive disclosure).`)},{error:gr})),pi=n(()=>fi.extend({fields:t.z.array(t.z.lazy(()=>pi)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(mr)),mi=n(()=>t.z.object({name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:z.optional(),description:t.z.string().optional().describe(`Optional description rendered under the section header.`),collapsible:t.z.boolean().default(!1),collapsed:t.z.boolean().default(!1),visibleWhen:I.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms)."),visibleOn:I.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Hides the whole section when false. Normalized to `visibleWhen` at parse."),columns:t.z.union([t.z.enum([`1`,`2`,`3`,`4`]),t.z.literal(1),t.z.literal(2),t.z.literal(3),t.z.literal(4)]).default(1).transform(e=>typeof e==`string`?parseInt(e):e),pane:t.z.enum([`primary`,`secondary`]).optional().describe(`Split pane this section renders in (split forms only; a parse error elsewhere). Omitted → first section 'primary', others 'secondary'.`),fields:t.z.array(t.z.union([t.z.string(),pi]))},{error:gr}).strict().transform(mr)),hi=n(()=>R({surface:`this form button configuration`,history:B},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:z.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict()),gi=n(()=>R({surface:`this form view`,history:B},{type:t.z.enum([`simple`,`tabbed`,`wizard`,`split`,`drawer`,`modal`]).default(`simple`),layout:t.z.enum([`vertical`,`horizontal`,`inline`,`grid`]).optional().describe(`Field layout direction`),columns:t.z.number().int().min(1).optional().describe(`Number of columns for the form body`),title:t.z.string().optional().describe(`Form title`),description:t.z.string().optional().describe(`Form description`),defaultTab:t.z.string().optional().describe(`Initially active tab (tabbed forms)`),tabPosition:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Tab strip position (tabbed forms)`),allowSkip:t.z.boolean().optional().describe(`Allow skipping steps (wizard forms)`),showStepIndicator:t.z.boolean().optional().describe(`Show the step indicator (wizard forms)`),splitDirection:t.z.enum([`horizontal`,`vertical`]).optional().describe(`Split orientation (split forms)`),splitSize:t.z.number().optional().describe(`Primary split panel size, % (split forms)`),splitResizable:t.z.boolean().optional().describe(`Whether the split is resizable (split forms)`),drawerSide:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Drawer side (drawer forms)`),drawerWidth:t.z.string().optional().describe(`[DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it.`),modalSize:t.z.enum([`sm`,`default`,`lg`,`xl`,`full`]).optional().describe(`Modal size (modal forms)`),data:Nr.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(mi).optional(),groups:t.z.array(mi).optional(),subforms:t.z.array(t.z.object({childObject:t.z.string().describe(`Child object whose records are entered inline`),relationshipField:t.z.string().optional().describe(`FK on the child pointing back to the parent (auto-detected when omitted)`),columns:t.z.array(t.z.any()).optional().describe(`Editable grid columns (derived from the child object when omitted)`),amountField:t.z.string().optional().describe(`Numeric child column summed for the running total`),totalField:t.z.string().optional().describe(`Parent field to receive the rolled-up sum`),title:t.z.string().optional().describe(`Section title`),addLabel:t.z.string().optional().describe(`Add-row button label`),minRows:t.z.number().optional(),maxRows:t.z.number().optional()})).optional().describe(`Inline master-detail child collections`),defaultSort:c("`form.defaultSort` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — nothing read it: a related list inside a form sorts by its own list view's `sort`. Delete the key and set the sort on the related list view instead."),sharing:Dr.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.union([t.z.object({kind:t.z.literal(`thank-you`),title:t.z.string().optional(),message:t.z.string().optional()}),t.z.object({kind:t.z.literal(`redirect`),url:t.z.string(),delayMs:t.z.number().int().min(0).optional()}),t.z.object({kind:t.z.literal(`continue`)}),t.z.object({kind:t.z.literal(`next-record`)})]).optional().describe(`Post-submit behavior`),buttons:t.z.object({submit:hi.optional().describe(`Submit button`),cancel:hi.optional().describe(`Cancel button`),reset:hi.optional().describe(`Reset button`)}).strict().optional().describe(`Form action-button visibility & labels; folded onto the flat renderer props by ObjectUI ObjectForm (framework#1894 / #2998).`),defaults:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Initial field values for create-mode forms (folded into ObjectUI ObjectForm initial values; framework#1894 / #2998).`),aria:c("`form.aria` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no form renderer ever applied it, so declared ARIA attributes silently did not reach the DOM. Delete the key. The form renderer emits its own semantic markup; report gaps as renderer issues rather than per-view attribute overrides.")}).superRefine((e,t)=>{if(e.type!==`split`)for(let[n,r]of[[`sections`,e.sections],[`groups`,e.groups]])r?.forEach((r,i)=>{r?.pane!=null&&t.addIssue({code:`custom`,path:[n,i,`pane`],message:`\`pane\` places a section in a split pane and is only valid on \`type: 'split'\` form views (this form is '${e.type}'). Remove the key or change the form type.`})})})),_i=n(()=>ti.omit({tabs:!0,showAllRecords:!0}).extend({element:t.z.enum([`dropdown`,`toggle`]).default(`dropdown`).describe('Filter control style on object views: "dropdown" (per-field value chips). "toggle" is deprecated. "tabs" is page-only — use `listViews` for named presets.')})),vi=n(()=>di.omit({userFilters:!0}).extend({userFilters:_i.optional()})),yi=n(()=>R({surface:`this view container`,history:B,guidance:Object.fromEntries([`type`,`columns`,`data`,`viewKind`,`filters`,`sort`].map(e=>[e,`\`${e}\` belongs to a single VIEW, not to the container. Wrap it: \`defineView({ list: { type, data, columns, \u2026 } })\`, or name it \u2014 \`defineView({ listViews: { my_view: { \u2026 } } })\`. The container's own keys are \`list\`, \`form\`, \`listViews\`, \`formViews\`.`]))},{name:t.z.string().optional().describe(`Item name — supplied by the metadata door; for an object-scoped container it is the object name.`),label:z.optional().describe(`Human-readable label shown in metadata lists.`),object:t.z.string().optional().describe("Object this container binds to — how a stack-level `views: [...]` entry says which object its views belong to; read by `getViewsByObject()` / `GET /meta/view?object=`."),list:vi.optional(),form:gi.optional(),listViews:t.z.record(t.z.string(),vi).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),gi).optional().describe(`Additional named form views`),protection:Xn.optional().describe(`Package author protection block — lock policy for this view.`),...F})),bi=t.z.string().regex(/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/,`View item name must be a dotted snake_case qualified name, e.g. "crm_lead.pipeline".`).describe("Globally-unique view id, `<object>.<viewKey>`."),xi=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),Si=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function Ci(){return{name:bi,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:z.optional().describe(`Display label (supports i18n).`),isDefault:t.z.boolean().optional().describe(`Whether this is the object's default view in the switcher.`),order:t.z.number().int().optional().describe(`Sort order within the object's view switcher / left rail.`),scope:xi.optional().describe("Identity layer (defaults to `package` for source-loaded views)."),owner:t.z.string().optional().describe("Owner user id — set when `scope` is `personal`."),hidden:t.z.boolean().optional().describe(`Hidden from the switcher (per-user / per-org declutter).`),protection:Xn.optional().describe(`Package author protection block — lock policy for this view.`),...F}}var wi=n(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({viewKind:t.z.literal(`list`),config:di.describe(`List-family view configuration.`),...Ci()}),t.z.object({viewKind:t.z.literal(`form`),config:gi.describe(`Form view configuration.`),...Ci()})]));function Ti(){return{name:t.z.string().optional().describe(`Save name / qualified view id (stamped by the write path).`),object:t.z.string().optional().describe(`Bound object name (inherited from the shadowed entry — #2555).`),viewKind:Si.optional().describe(`View family (inherited from the shadowed entry — #2555).`),label:z.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:xi.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:Xn.optional(),...F,config:t.z.undefined().optional(),list:t.z.undefined().optional(),form:t.z.undefined().optional(),listViews:t.z.undefined().optional(),formViews:t.z.undefined().optional()}}function Ei(e){if(!e||typeof e!=`object`)return!1;let t=e;return!!(t.list||t.form||t.listViews&&typeof t.listViews==`object`&&Object.keys(t.listViews).length>0||t.formViews&&typeof t.formViews==`object`&&Object.keys(t.formViews).length>0)}n(()=>t.z.union([wi,yi.refine(Ei,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."}),di.extend(Ti()).strip(),gi.extend(Ti()).strip()]));var Di=t.z.enum([`select`,`insert`,`update`,`delete`,`all`]),Oi=L({surface:`this RLS policy`,knownKeys:[`name`,`label`,`description`,`object`,`operation`,`using`,`check`,`positions`,`enabled`,`tags`],aliases:{roles:`positions`,role:`positions`,withcheck:`check`,condition:`using`,filter:`using`,where:`using`},history:`Until #4001 these were dropped silently — the policy still parsed, so a row-level restriction the author wrote was never compiled into the filter.`}),ki=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Policy unique identifier (snake_case)`),label:t.z.string().optional().describe(`Human-readable policy label`),description:t.z.string().optional().describe(`Policy description and business justification`),object:t.z.string().describe(`Target object name`),operation:Di.describe(`Database operation this policy applies to`),using:t.z.string().optional().describe("Filter condition for SELECT/UPDATE/DELETE. One of the four compiler-supported forms: `field = current_user.<prop>`, `field = 'literal'`, `field IN (current_user.<array>)`, or `1 = 1`. Optional for INSERT-only policies."),check:t.z.string().optional().describe(`Validation condition for INSERT/UPDATE (defaults to USING clause if not specified - enforced at application level)`),positions:t.z.array(t.z.string()).optional().describe(`Positions this policy applies to (omit for all)`),enabled:t.z.boolean().default(!0).describe(`Whether this policy is active`),priority:c("`rowLevelSecurity[].priority` was removed in @objectstack/spec 17.0.0 (#3896 security audit). It never had an effect and could not: applicable policies OR-combine (most permissive wins), so there is no conflict to order. Delete the key — policy outcomes are unchanged."),tags:t.z.array(t.z.string()).optional().describe(`Policy categorization tags`)},{error:Oi}).strict().superRefine((e,n)=>{!e.using&&!e.check&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`At least one of "using" or "check" must be specified. For SELECT/UPDATE/DELETE operations, provide "using". For INSERT operations, provide "check".`})}));n(()=>t.z.object({id:t.z.string().describe(`User ID`),email:t.z.string().email().optional().describe(`User email`),tenantId:t.z.string().optional().describe(`Tenant/Organization ID`),positions:t.z.array(t.z.string()).optional().describe(`Positions held by the user`),department:t.z.string().optional().describe(`User department`),attributes:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional custom user attributes`)})),n(()=>t.z.object({policyName:t.z.string().describe(`Policy name`),granted:t.z.boolean().describe(`Whether access was granted`),durationMs:t.z.number().optional().describe(`Evaluation duration in milliseconds`),error:t.z.string().optional().describe(`Error message if evaluation failed`),usingResult:t.z.boolean().optional().describe(`USING clause evaluation result`),checkResult:t.z.boolean().optional().describe(`CHECK clause evaluation result`)}));var Ai={name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique rule name (snake_case)`),label:t.z.string().optional().describe(`Human-readable label for the rule listing`),description:t.z.string().optional().describe(`Administrative notes explaining the business reason`),active:t.z.boolean().default(!0),events:t.z.array(t.z.enum([`insert`,`update`])).default([`insert`,`update`]).describe("Write contexts the rule runs on. `delete` is intentionally absent — the evaluator only runs on the insert/update write path; guard deletions with a `beforeDelete` lifecycle hook"),priority:t.z.number().int().min(0).max(9999).default(100).describe(`Execution priority (lower runs first, default: 100)`),tags:t.z.array(t.z.string()).optional().describe(`Categorization tags (e.g., "compliance", "billing")`),severity:t.z.enum([`error`,`warning`,`info`]).default(`error`),message:t.z.string().describe(`Error message to display to the user`),...F},ji=n(()=>R({surface:`this script validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`,predicate:`condition`,rule:`condition`}},{...Ai,type:t.z.literal(`script`),condition:I.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),Mi=n(()=>R({surface:`this state-machine validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{states:`transitions`,statefield:`field`,from:`transitions`,initial:`initialStates`,initialstate:`initialStates`}},{...Ai,type:t.z.literal(`state_machine`),field:t.z.string().describe(`State field (e.g. status)`),transitions:t.z.record(t.z.string(),t.z.array(t.z.string())).describe(`Map of { OldState: [AllowedNewStates] }`),initialStates:t.z.array(t.z.string()).optional().describe("States a record may be CREATED in. When set, an INSERT whose state field carries a value outside this list is rejected (server-enforced) — the FSM entry point. `transitions` only governs UPDATE, and a `select` field permits ANY declared option as an initial value, so without this a record could be born mid-flow (e.g. created already `approved`). Omit to keep the legacy behavior (no initial-state check on insert). #3165.")})),Ni=n(()=>R({surface:`this format validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{pattern:`regex`,fieldname:`field`}},{...Ai,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),Pi=n(()=>R({surface:`this cross-field validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`}},{...Ai,type:t.z.literal(`cross_field`),condition:I.describe("Predicate (CEL) comparing fields. e.g. P`record.end_date > record.start_date`"),fields:t.z.array(t.z.string()).describe(`Fields involved. Only fields[0] is read (labels which field the violation attaches to); the rest are advisory. Shares script’s evaluation path.`)})),Fi=n(()=>R({surface:`this JSON-schema validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{jsonschema:`schema`,fieldname:`field`}},{...Ai,type:t.z.literal(`json_schema`),field:t.z.string().describe(`JSON field to validate`),schema:t.z.record(t.z.string(),t.z.unknown()).describe(`JSON Schema object definition`)})),Ii=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[ji,Mi,Ni,Pi,Fi,Li])),Li=n(()=>R({surface:`this conditional validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{if:`when`,condition:`when`,match:`when`,else:`otherwise`}},{...Ai,type:t.z.literal(`conditional`),when:I.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:Ii.describe(`Validation rule to apply when condition is true`),otherwise:Ii.optional().describe(`Validation rule to apply when condition is false`)})),Ri='`crypto.hash` was removed from `HookBodyCapability` in @objectstack/spec 17 (#4391, ADR-0049 enforce-or-remove) — the sandbox never implemented it. `installCtx` wired only `ctx.crypto.randomUUID`, so `ctx.crypto.hash(...)` threw inside the VM on every call the token ever "granted", while the build-time extractor inferred the token from that very call and let `os build` pass. Delete the capability from `capabilities` AND delete the `ctx.crypto.hash(...)` call it was declared for — the call has never returned a value, so nothing that works today depends on it. There is no replacement inside the sandbox: hash in the host (a Connector recipe, or an engine-side hook) instead. If you need hashing in a body, reopen it through the capability admission process — implementation first, the declaration lands with the implementation. Run `os migrate meta --from 16` to rewrite it automatically.',zi=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?Ri:void 0}),Bi=[`language`,`source`],Vi=[`language`,`source`,`capabilities`,`timeoutMs`,`memoryMb`],Hi='is an L2 key — it only applies to `language: "js"`. An expression body is a pure formula: it performs no IO, so it has nothing to grant and no sandbox to bound.',Ui=L({surface:`this expression (L1) hook body`,knownKeys:Bi,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${Hi}`,timeoutMs:`\`timeoutMs\` ${Hi}`,memoryMb:`\`memoryMb\` ${Hi}`},history:`Until #4001 these were dropped silently.`}),Wi=L({surface:`this sandboxed JS (L2) hook body`,knownKeys:Vi,aliases:{capability:`capabilities`,caps:`capabilities`,permissions:`capabilities`,timeout:`timeoutMs`,timeoutms:`timeoutMs`,memory:`memoryMb`,memorymb:`memoryMb`,code:`source`,script:`source`,body:`source`},history:`Until #4001 these were dropped silently — the body still ran, just not under the limits or grants that were written.`}),Gi=t.z.object({language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)},{error:Ui}).strict().describe(`L1 expression body — pure formula, no IO`),Ki=t.z.object({language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(zi).default([]).describe(`Granted capability tokens`),timeoutMs:t.z.number().int().positive().max(3e4).optional().describe(`Per-invocation timeout (ms)`),memoryMb:t.z.number().int().positive().max(256).optional().describe(`Per-invocation memory cap (MB)`)},{error:Wi}).strict().describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),qi=t.z.discriminatedUnion(`language`,[Gi,Ki]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),Ji={twoFactor:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.enable_two_factor`,`sys_user.actions.disable_two_factor`,`sys_user.actions.generate_backup_codes`,`sys_two_factor.actions.enable_two_factor`,`sys_two_factor.actions.disable_two_factor`,`sys_two_factor.actions.regenerate_backup_codes`],notes:`Login-surface 2FA challenge is server-driven remediation (ADR-0069), so the flag is intentionally unread by objectui LoginForm.`},passkeys:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no passkey UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},magicLink:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no magic-link UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},organization:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_user.actions.invite_user`,`sys_member.actions.add_member`,`sys_member.actions.update_member_role`,`sys_member.actions.remove_member`,`sys_member.actions.transfer_ownership`,`sys_invitation.actions.invite_user`,`sys_invitation.actions.cancel_invitation`,`sys_invitation.actions.resend_invitation`,`sys_team.actions.create_team`,`sys_team.actions.update_team`,`sys_team.actions.remove_team`,`sys_team_member.actions.add_team_member`,`sys_team_member.actions.remove_team_member`],notes:`Org CAPABILITY gate, not multi-org (ADR-0081 D1).`},multiOrgEnabled:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_organization.actions.create_organization`,`sys_organization.actions.update_organization`,`sys_organization.actions.delete_organization`,`sys_organization.actions.set_active_organization`,`sys_organization.actions.leave_organization`,`sys_organization.actions.change_slug`],notes:"Reflects ACTUAL multi-tenancy capability (the tenancy posture enforces an organization wall — `group` or `isolated`, ADR-0093 D4 / ADR-0105 D1), not just the requested posture."},degradedTenancy:{surface:`status`,semantics:`opt-in`,exempt:{reason:`Operator status banner (ADR-0093 D5) — signals degraded tenant isolation, not an input capability gate.`}},oidcProvider:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_oauth_application.actions.create_oauth_application`,`sys_oauth_application.actions.delete_oauth_application`,`sys_oauth_application.actions.disable_oauth_application`,`sys_oauth_application.actions.enable_oauth_application`,`sys_oauth_application.actions.rotate_client_secret`],notes:`Default-ON: the embedded OIDC authorization server follows the default-on MCP surface (resolveOidcProviderEnabled). Login surface consumes the socialProviders[] array (per-provider enabled), not this flag.`},sso:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Deliberately ungated on the CRUD surface: the served value is refined to "usable" (≥1 provider configured) via isSsoUsable() at /auth/config, so gating sys_sso_provider registration actions on it would deadlock first-provider setup. Login consumption verified: objectui LoginForm gates the "Sign in with SSO" button.`}},ssoEnforced:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: objectui LoginForm hides the password form and self-registration (break-glass link remains). No spec input to gate.`}},deviceAuthorization:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input (sys_device_code declares no actions). Known gap: objectui DeviceAuthPage hits the device-auth endpoints without checking this flag (absent from its client type) — tracked in objectui#2513 (#2874 P2②).`}},admin:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user`,`sys_user.actions.ban_user`,`sys_user.actions.unban_user`,`sys_user.actions.unlock_user`,`sys_user.actions.set_user_password`,`sys_user.actions.set_user_role`,`sys_user.actions.impersonate_user`],notes:`SCIM forces the admin plugin (and this flag) on — ADR-0071.`},phoneNumber:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user.params.phoneNumber`],notes:`The original #2871 fix. Also read by objectui LoginForm for the phone+password sign-in mode.`},phoneNumberOtp:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: gates the "sign in with verification code" link (LoginForm) and the phone branch of forgot-password. Only advertised when SMS is actually deliverable (#2780).`}}},Yi=Object.keys(Ji);function Xi(e){return`features.${e} ${Ji[e].semantics===`opt-in`?`== true`:`!= false`}`}function Zi(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=Xi(n),a=r.visible;return a===void 0?{...r,visible:{dialect:`cel`,source:i}}:a.dialect!==`cel`||typeof a.source!=`string`?(t.addIssue({code:`custom`,path:[`requiresFeature`],message:"`requiresFeature` composes only with a CEL `visible` carrying a `source` string; this expression is AST-only or non-CEL — write the combined predicate by hand."}),r):{...r,visible:{...a,source:`(${a.source}) && ${i}`}}}var Qi=L({surface:`this action param`,knownKeys:[`name`,`field`,`objectOverride`,`label`,`type`,`required`,`options`,`placeholder`,`helpText`,`defaultValue`,`multiple`,`accept`,`maxSize`,`reference`,`defaultFromRow`,`visible`,`requiresFeature`],aliases:{referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},history:`Until #3405 these were dropped silently — the param still parsed, so a mis-spelled config shipped as a control that quietly ignored it.`}),$i=n(()=>t.z.object({name:t.z.string().optional(),field:E.optional(),objectOverride:E.optional(),label:z.optional(),type:rr.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(t.z.object({label:z,value:t.z.string()})).optional(),placeholder:t.z.string().optional(),helpText:t.z.string().optional(),defaultValue:t.z.unknown().optional(),multiple:t.z.boolean().optional().describe(`Allow multiple values (array value shape); mirrors FieldSchema.multiple.`),accept:t.z.array(t.z.string()).optional().describe(`Accepted upload types (MIME types / extensions) for file/image params.`),maxSize:t.z.number().int().positive().optional().describe(`Max upload size in bytes for file/image params.`),reference:E.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:I.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(Yi).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")},{error:Qi}).strict().refine(e=>!!e.name||!!e.field,{message:`ActionParam requires either "name" or "field"`}).refine(e=>!(!e.field&&(e.type===`lookup`||e.type===`master_detail`)&&!e.reference),{path:[`reference`],message:`ActionParam with type "lookup"/"master_detail" requires "reference" (the target object) when declared inline — without it the param dialog degrades to a raw record-id text input. Set \`reference: '<object>'\`, or use a field-backed param (\`{ field: '<lookup_field>' }\`) to inherit it.`}).transform((e,t)=>Zi(e,t))),ea=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),ta=new Set(ea.options.filter(e=>e!==`script`)),na=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`,`global_nav`]),ra=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),H=`Until #4001 closed this shape these were dropped silently — the action still registered and still ran, without whatever the key was meant to configure or gate.`,ia=R({surface:`this action's AI exposure block`,history:H,aliases:{enabled:`exposed`,enable:`exposed`,aiEnabled:`exposed`,expose:`exposed`,visible:`exposed`,prompt:`description`,toolDescription:`description`,summary:`description`,type:`category`,kind:`category`,toolCategory:`category`,hints:`paramHints`,parameterHints:`paramHints`,params:`paramHints`,returns:`outputSchema`,responseSchema:`outputSchema`,output:`outputSchema`,confirm:`requiresConfirmation`,requireConfirmation:`requiresConfirmation`,hitl:`requiresConfirmation`,humanInTheLoop:`requiresConfirmation`},guidance:{permissions:"AI invocation is not gated by a key here — an agent reaches this action only if a surface-compatible SKILL declares it (ADR-0064), and who may talk to that agent is gated by the agent's `access` / `permissions` (enforced at the chat route since #1884). For a human-approval step on the call itself, use `requiresConfirmation: true`.",approval:"there is no approval workflow key here — `requiresConfirmation: true` forces a human-in-the-loop gate on the AI call. A multi-step business approval is an `approval` metadata item, not an action field."}},{exposed:t.z.boolean().default(!1).describe("Expose this action to AI agents. Requires `description` when true."),description:t.z.string().min(40).optional().describe(`LLM-facing description (≥40 chars). Required when exposed.`),category:ra.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),R({surface:`this AI parameter hint`,history:H,aliases:{desc:`description`,hint:`description`,values:`enum`,options:`enum`,choices:`enum`,allowed:`enum`,example:`examples`,sample:`examples`}},{description:t.z.string().optional(),enum:t.z.array(t.z.union([t.z.string(),t.z.number()])).optional(),examples:t.z.array(t.z.unknown()).optional()})).optional().describe(`Per-parameter AI hints keyed by param name.`),outputSchema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`JSON Schema for the action return value.`),requiresConfirmation:t.z.boolean().optional().describe(`Override HITL confirmation for AI invocations.`)}),aa=()=>R({surface:`this action`,history:H,aliases:{title:`label`,displayName:`label`,text:`label`,object:`objectName`,entity:`objectName`,actionType:`type`,url:`target`,endpoint:`target`,path:`target`,href:`target`,parameters:`params`,args:`params`,inputs:`params`,fields:`params`,confirm:`confirmText`,confirmation:`confirmText`,confirmMessage:`confirmText`,success:`successMessage`,successText:`successMessage`,toast:`successMessage`,visibleWhen:`visible`,showWhen:`visible`,disabledWhen:`disabled`,style:`variant`,color:`variant`,appearance:`variant`,placement:`locations`,location:`locations`,position:`locations`,verb:`method`,httpMethod:`method`,body:`bodyExtra`,payload:`bodyExtra`,llm:`ai`,tool:`ai`,dialog:`resultDialog`,result:`resultDialog`,refresh:`refreshAfter`,reload:`refreshAfter`,permissions:`requiredPermissions`,capabilities:`requiredPermissions`,requiresPermissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`,acl:`requiredPermissions`},guidance:{hidden:"`hidden` is not an action key, and hiding is not gating — `visible` and `disabled` are UI predicates that hide or grey a button, they do not stop a request. To actually gate invocation use `requiredPermissions` (ADR-0066 D4, enforced with a 403 on the platform action route). To declare an action with no UI surface at all, set `locations: []`.",exposed:"AI exposure lives under `ai` — write `ai: { exposed: true, description: … }`. The description is the LLM-facing contract and is REQUIRED (≥40 chars) whenever exposed.",requiresConfirmation:"the AI human-in-the-loop override lives under `ai` — write `ai: { requiresConfirmation: true }`. `confirmText` is the separate UI confirm prompt."}},{name:E.describe(`Machine name (lowercase snake_case)`),label:z.describe(`Display label`),objectName:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).optional().describe(`Target object this action belongs to. When set, the action is auto-merged into the object's actions array by defineStack().`),icon:t.z.string().optional().describe(`Icon name`),locations:t.z.array(na).optional().describe(`Locations where this action is visible`),component:t.z.enum([`action:button`,`action:icon`,`action:menu`,`action:group`]).optional().describe(`Visual component override`),type:ea.default(`script`).describe(`Action functionality type`),target:t.z.string().optional().describe("URL, Script Name, Flow ID, or API Endpoint. Supports ${param.X} and ${ctx.X} interpolation."),openIn:t.z.enum([`self`,`new-tab`]).optional().describe("For type:'url' — where to open `target`. 'new-tab' opens a new browser tab; 'self' navigates in place. When omitted, external/absolute URLs open in a new tab and relative URLs navigate in place. Static execution option — keep it OUT of `params` (which is user-input-collection only)."),body:qi.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:c("`execute` was removed in @objectstack/spec 17 (#3855) — use `target`. Rename the key; the value (a handler / flow / URL ref) is unchanged. Run `os migrate meta --from 16` to rewrite it automatically."),params:t.z.array($i).optional().describe(`Input parameters required from user`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`link`]).optional().describe(`Button visual variant for styling (primary = highlighted, danger = destructive, ghost = transparent)`),order:t.z.number().optional().describe("Sort order within a location group (lower = higher). Promotes/demotes an action toward the record_header primary button; stable, so actions without `order` keep their registration order."),confirmText:z.optional().describe(`Confirmation message before execution`),successMessage:z.optional().describe(`Success message to show after execution`),errorMessage:z.optional().describe(`Error message to show when the action fails (overrides the raw error).`),refreshAfter:t.z.boolean().default(!1).describe(`Refresh view after execution`),undoable:t.z.boolean().optional().describe(`Offer an Undo affordance after this single-record update action succeeds.`),resultDialog:R({surface:`this result dialog`,history:H,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:z.optional(),description:z.optional(),acknowledge:z.optional().describe(`Acknowledge button label, e.g. "I have saved this"`),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Default format for fields without their own format. Defaults to json when omitted.`),fields:t.z.array(R({surface:`this result dialog field`,history:H,aliases:{key:`path`,field:`path`,name:`path`,title:`label`,display:`format`,render:`format`}},{path:t.z.string().describe(`Dot path into result.data (e.g. "totpURI", "client.client_secret").`),label:z.optional(),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Per-field format override.`)})).optional().describe(`Which fields from result.data to render. Omit to dump full JSON.`)}).optional().describe(`Render API response in a one-shot reveal dialog (suppresses successMessage when set).`),visible:I.optional().describe(`Visibility predicate (CEL).`),requiresFeature:t.z.enum(Yi).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:t.z.union([t.z.boolean(),I]).optional().describe(`Boolean or predicate (CEL) — action is disabled when TRUE.`),requiredPermissions:t.z.array(t.z.string()).optional().describe("[ADR-0066 D4] Capabilities required to invoke this action. Enforced with 403 on the platform action route (script/flow/modal + MCP) and mirrored as a UI hide; a `type: api` action pointed at a custom endpoint must re-check it there."),shortcut:c("`action.shortcut` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never triggered anything: no keydown listener feeds ActionEngine.getShortcuts(), and objectui's keyboard stack (useKeyboardShortcuts) is hand-registered and never consults action metadata. Delete the key. For a real shortcut, register the key in the Console keyboard stack and have its handler invoke the action by name."),bulkEnabled:c("`action.bulkEnabled` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — the multi-select toolbar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, never by this flag, so setting it changed nothing. Delete the key and declare the action in the view's `bulkActions` instead."),ai:ia.optional().describe(`AI exposure (opt-in). Set ai.exposed=true + ai.description to make this callable by agents.`),recordIdParam:t.z.string().optional().describe(`Body key to inject the row id into when running from a list_item context.`),recordIdField:t.z.string().optional().describe(`Row field whose value seeds recordIdParam. Defaults to "id".`),bodyShape:t.z.union([t.z.literal(`flat`),R({surface:`this body shape`,history:H,aliases:{key:`wrap`,under:`wrap`,nest:`wrap`,root:`wrap`}},{wrap:t.z.string()})]).optional().describe(`Body wrapping: flat (default) or { wrap: key } to nest user-collected params under a key.`),method:t.z.enum([`POST`,`PATCH`,`PUT`,`DELETE`]).optional().describe(`HTTP method for type:"api" actions. Defaults to POST.`),bodyExtra:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Constant body fields merged into the API request (applied last; overrides user params).`),mode:t.z.enum([`create`,`edit`,`delete`,`custom`]).optional().describe(`Semantic mode of the action.`),opensInNewTab:t.z.boolean().optional().describe(`Open the action result in a new tab. The renderer pre-opens the tab synchronously on click (popup-blocker-safe) and navigates it to the handler's redirectUrl.`),newTabUrl:t.z.string().optional().describe(`Direct new-tab URL template ({recordId} placeholder). When set with opensInNewTab, the renderer navigates the pre-opened tab here immediately — no action POST. The endpoint must enforce auth itself.`),aria:_r.optional().describe(`ARIA accessibility attributes`),...F}),oa=n(()=>aa().refine(e=>!(ta.has(e.type)&&!e.target),{message:`Action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form'.`,path:[`target`]}).refine(e=>!(e.type===`script`&&!e.body&&!e.target),{message:"A 'script' action requires either an inline `body` (sandboxed L1/L2 handler) or a `target` (a registered bundle function name).",path:[`body`]}).refine(e=>!(e.type!==`script`&&e.body),{message:"`body` only runs for `type: 'script'` — a non-script action dispatches on `target` and silently ignores its body. To collect `params` and then run the body, use `type: 'script'`; to open a page/modal, drop the `body` and keep `type: 'modal'` with `target` naming the page.",path:[`body`]}).refine(e=>!(e.ai?.exposed===!0&&!e.ai.description),{message:`ai.description is required (≥40 chars) when ai.exposed is true.`,path:[`ai`,`description`]}).refine(e=>{let t=e.ai?.paramHints;if(!t)return!0;let n=new Set([`recordId`]);for(let t of e.params??[]){let e=t.name??t.field;e&&n.add(e)}return Object.keys(t).every(e=>n.has(e))},{message:`ai.paramHints keys must match a declared param name (or "recordId").`,path:[`ai`,`paramHints`]}).transform((e,t)=>Zi(e,t)));function sa(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e,n=t.type===`navigation`,r=t.target===void 0&&typeof t.to==`string`;if(!n&&!r&&!(`to`in t))return e;let i={...t};return n&&(i.type=`url`),r&&(i.target=t.to),delete i.to,i}n(()=>t.z.preprocess(sa,aa().pick({type:!0,name:!0,label:!0,target:!0,openIn:!0,method:!0,params:!0,confirmText:!0,successMessage:!0,errorMessage:!0,refreshAfter:!0,opensInNewTab:!0}).partial({name:!0,label:!0}).refine(e=>!(ta.has(e.type)&&!e.target),{message:"Inline action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form' (`to` is accepted as a legacy spelling).",path:[`target`]})));var ca=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),la=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],ua={upsert:"declare ['create','update'] — `upsert` derives from create ∧ update",aggregate:"declare ['list'] — `aggregate` derives from list",history:"declare ['get'] with `enable.trackHistory: true` — `history` derives from get ∧ trackHistory",search:"declare ['list'] (with `searchable` not false) — `search` derives from list ∧ searchable",restore:"delete the value — `restore` never derives (`enable.trash` retired, #2377); it returns only with a real recycle bin (#3146, parked)",purge:"delete the value — `purge` never derives (`enable.trash` retired, #2377)",import:"declare ['create'] and/or ['update'] — `import` derives from create ∨ update (writeMode-precise at the gate)",export:"declare ['list'] — `export` derives from list"},da=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`]),fa=new Set(la),pa=new Set;function ma(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&fa.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&fa.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return pa.has(i)||(pa.add(i),(e=>console.warn(e))(`[spec] enable.apiMethods declares retired legacy value(s) [${n.join(`, `)}] \u2014 the ApiMethod enum is the six primitives get/list/create/update/delete/bulk (#3543). Legacy values are stripped at parse; their semantics are DERIVED from the primitives:
18
+ `)}`),l}}function pr(e,t=0){if(t>6)return!1;let n=e._zod?.def;if(!n?.type)return!1;if(n.type===`never`)return!0;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`readonly`:case`nonoptional`:case`catch`:return pr(n.innerType,t+1);default:return!1}}function R(e,n){let{surface:r,history:i,aliases:a,guidance:o,extraKeys:s=[]}=e,c;return t.z.object(n,{error:e=>(c??=L({surface:r,knownKeys:[...Object.keys(n).filter(e=>!pr(n[e])),...s],history:i,aliases:a,guidance:o}))(e)}).strict()}function mr(e){let{visibleOn:t,visibility:n,...r}=e,i=r.visibleWhen===void 0?t===void 0?n:t:r.visibleWhen;return i===void 0?r:{...r,visibleWhen:i}}function hr(e){return/vis|conceal|hidden|show.?when/i.test(e)}var gr=e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=`Unrecognized key(s) on this view/page schema: ${t.map(e=>`\`${e}\``).join(`, `)}. Before ADR-0089 D3a these were dropped silently, shipping inert metadata; a mis-layered or stale key is now a loud parse error.`;return t.some(hr)?n+" If this is the conditional-visibility predicate, the canonical key is `visibleWhen` (ADR-0089) — `visibleOn` (view form) and `visibility` (page component) are still accepted as deprecated aliases.":n};n(()=>t.z.object({key:t.z.string().describe(`Translation key (e.g., "views.task_list.label")`),defaultValue:t.z.string().optional().describe(`Fallback value when translation key is not found`),params:t.z.record(t.z.string(),t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Interpolation parameters (e.g., { count: 5 })`)}));var z=n(()=>t.z.string().describe(`Display label (plain string; i18n keys are auto-generated by the framework)`)),_r=n(()=>t.z.object({ariaLabel:z.optional().describe(`Accessible label for screen readers (WAI-ARIA aria-label)`),ariaDescribedBy:t.z.string().optional().describe(`ID of element providing additional description (WAI-ARIA aria-describedby)`),role:t.z.string().optional().describe(`WAI-ARIA role attribute (e.g., "dialog", "navigation", "alert")`)}).describe(`ARIA accessibility attributes`));n(()=>t.z.object({key:t.z.string().describe(`Translation key`),zero:t.z.string().optional().describe(`Zero form (e.g., "No items")`),one:t.z.string().optional().describe(`Singular form (e.g., "{count} item")`),two:t.z.string().optional().describe(`Dual form (e.g., "{count} items" for exactly 2)`),few:t.z.string().optional().describe(`Few form (e.g., for 2-4 in some languages)`),many:t.z.string().optional().describe(`Many form (e.g., for 5+ in some languages)`),other:t.z.string().describe(`Default plural form (e.g., "{count} items")`)}).describe(`ICU plural rules for a translation key`));var vr=n(()=>t.z.object({style:t.z.enum([`decimal`,`currency`,`percent`,`unit`]).default(`decimal`).describe(`Number formatting style`),currency:t.z.string().optional().describe(`ISO 4217 currency code (e.g., "USD", "EUR")`),unit:t.z.string().optional().describe(`Unit for unit formatting (e.g., "kilometer", "liter")`),minimumFractionDigits:t.z.number().optional().describe(`Minimum number of fraction digits`),maximumFractionDigits:t.z.number().optional().describe(`Maximum number of fraction digits`),useGrouping:t.z.boolean().optional().describe(`Whether to use grouping separators (e.g., 1,000)`)}).describe(`Number formatting rules`)),yr=n(()=>t.z.object({dateStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Date display style`),timeStyle:t.z.enum([`full`,`long`,`medium`,`short`]).optional().describe(`Time display style`),timeZone:t.z.string().optional().describe(`IANA time zone (e.g., "America/New_York")`),hour12:t.z.boolean().optional().describe(`Use 12-hour format`)}).describe(`Date/time formatting rules`));n(()=>t.z.object({code:t.z.string().describe(`BCP 47 language code (e.g., "en-US", "zh-CN")`),fallbackChain:t.z.array(t.z.string()).optional().describe(`Fallback language codes in priority order (e.g., ["zh-TW", "en"])`),direction:t.z.enum([`ltr`,`rtl`]).default(`ltr`).describe(`Text direction: left-to-right or right-to-left`),numberFormat:vr.optional().describe(`Default number formatting rules`),dateFormat:yr.optional().describe(`Default date/time formatting rules`)}).describe(`Locale configuration`));var br=n(()=>t.z.enum([`bar`,`horizontal-bar`,`column`,`line`,`area`,`pie`,`donut`,`funnel`,`scatter`,`treemap`,`sankey`,`combo`,`gauge`,`solid-gauge`,`metric`,`kpi`,`bullet`,`radar`,`table`,`pivot`])),xr=n(()=>t.z.object({field:t.z.string().describe(`Data field key`),title:z.optional().describe(`Axis display title`),format:t.z.string().optional().describe(`Value format string (e.g., "$0,0.00")`),min:t.z.number().optional().describe(`Minimum value`),max:t.z.number().optional().describe(`Maximum value`),stepSize:t.z.number().optional().describe(`Step size for ticks`),showGridLines:t.z.boolean().default(!0),position:t.z.enum([`left`,`right`,`top`,`bottom`]).optional().describe(`Axis position`),logarithmic:t.z.boolean().default(!1)})),Sr=n(()=>t.z.object({name:t.z.string().describe(`Field name or series identifier`),label:z.optional().describe(`Series display label`),type:br.optional().describe(`Override chart type for this series`),color:t.z.string().optional().describe(`Series color (hex/rgb/token)`),stack:t.z.string().optional().describe(`Stack identifier to group series`),yAxis:t.z.enum([`left`,`right`]).default(`left`).describe(`Bind to specific Y-Axis`),variant:t.z.enum([`primary`,`comparison`]).default(`primary`).optional().describe(`Series visual role`),dashArray:t.z.string().optional().describe(`SVG stroke-dasharray override`),opacity:t.z.number().min(0).max(1).optional().describe(`Series opacity override`)})),Cr=n(()=>t.z.object({type:t.z.enum([`line`,`region`]).default(`line`),axis:t.z.enum([`x`,`y`]).default(`y`),value:t.z.union([t.z.number(),t.z.string()]).describe(`Start value`),endValue:t.z.union([t.z.number(),t.z.string()]).optional().describe(`End value for regions`),color:t.z.string().optional(),label:z.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),wr=n(()=>t.z.object({tooltips:t.z.boolean().default(!0).describe(`Show the hover tooltip`),brush:t.z.boolean().default(!1).describe(`Show the range selector under the plot`)}));n(()=>t.z.object({type:br,title:z.optional().describe(`Chart title`),subtitle:z.optional().describe(`Chart subtitle`),description:z.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:xr.optional().describe(`X-Axis configuration`),yAxis:t.z.array(xr).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(Sr).optional().describe(`Defined series configuration`),colors:t.z.union([t.z.array(t.z.string()),t.z.record(t.z.string(),t.z.string())]).optional().describe(`Color palette (string[]) or value→color map ({ value: color })`),height:t.z.number().optional().describe(`Fixed plot height in pixels (overrides the container default)`),showLegend:t.z.boolean().default(!0).describe(`Display legend`),showDataLabels:t.z.boolean().default(!1).describe(`Display data labels`),annotations:t.z.array(Cr).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:wr.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:_r.optional().describe(`ARIA accessibility attributes`)}));var Tr=n(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),Er=n(()=>t.z.union([t.z.string().describe(`Field to group by`),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:t.z.enum([`day`,`week`,`month`,`quarter`,`year`]).optional().describe(`Bucket date values into uniform periods`),alias:t.z.string().optional().describe("Alias for the projected group value (defaults to `field`) — this becomes the category column")})]));n(()=>t.z.object({field:t.z.string().optional().describe(`Field to aggregate — required for sum/avg/min/max, optional for count`),function:Tr.describe(`Aggregation function`),groupBy:Er.describe(`Field the rows are grouped by — the chart category axis`)}).superRefine((e,t)=>{e.function!==`count`&&!e.field&&t.addIssue({code:`custom`,path:[`field`],message:`aggregate.function "${e.function}" needs a "field" to aggregate (only "count" may omit it).`})}).describe(`Inline aggregation for an object-bound chart`));var Dr=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable public sharing`),publicLink:t.z.string().optional().describe(`Generated public share URL`),password:t.z.string().optional().describe(`Password required to access shared link`),allowedDomains:t.z.array(t.z.string()).optional().describe(`Restrict access to specific email domains (e.g. ["example.com"])`),expiresAt:t.z.string().optional().describe(`Expiration date/time in ISO 8601 format`),allowAnonymous:t.z.boolean().optional().default(!1).describe(`Allow access without authentication`)}));n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable iframe embedding`),allowedOrigins:t.z.array(t.z.string()).optional().describe(`Allowed iframe parent origins (e.g. ["https://example.com"])`),width:t.z.string().optional().default(`100%`).describe(`Embed width (CSS value)`),height:t.z.string().optional().default(`600px`).describe(`Embed height (CSS value)`),showHeader:t.z.boolean().optional().default(!0).describe(`Show interface header in embed`),showNavigation:t.z.boolean().optional().default(!1).describe(`Show navigation in embed`),responsive:t.z.boolean().optional().default(!0).describe(`Enable responsive resizing`)}));var Or=t.z.enum([`update`,`delete`,`custom`]),kr=t.z.enum([`perRecord`,`aggregate`]),Ar=n(()=>t.z.object({name:t.z.string().min(1).describe(`Param key — becomes params[name] in the patch / action params bag.`),label:t.z.string().optional().describe(`Field label in the dialog. Plain string: an authored def is not i18n-resolved (see module header).`),help:t.z.string().optional().describe("Help text under the field. (An ActionParam spells this `helpText` — known divergence, module header.)"),type:rr.describe(`Field widget to render, from the standard field-type vocabulary (text/number/select/lookup/date/…).`),required:t.z.boolean().optional().describe(`Blocks the Confirm button until a value is present.`),default:t.z.unknown().optional().describe("Value applied when the dialog opens. (An ActionParam spells this `defaultValue`.)"),options:t.z.array(t.z.object({label:t.z.string().describe(`Option label (plain string — not i18n-resolved on this path).`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Stored value.`)}).passthrough()).optional().describe("Static options for select-style widgets. Each entry is `{ label, value }` plus any extra widget config — the entry is open (`.passthrough()`) because the renderer forwards unknown option keys to the field widget, which reads `color` / `icon` / `disabled` / `visibleWhen` beyond the declared pair."),object:E.optional().describe("Target object for a `lookup` widget. (An ActionParam spells this `reference`.)"),labelField:t.z.string().optional().describe("Related-object field used as the option label for a `lookup` widget (defaults to name/full_name/email/id)."),multiple:t.z.boolean().optional().describe(`Allow picking multiple values — the param value becomes an array and is written to the patch as-is.`),placeholder:t.z.string().optional().describe(`Placeholder text.`)}).passthrough()),jr=L({surface:`this bulk action definition`,knownKeys:[`name`,`label`,`icon`,`variant`,`operation`,`execution`,`patch`,`params`,`confirmText`,`confirmLabel`,`visible`,`maxRecords`,`batchSize`],aliases:{action:`name`,actionname:`name`,title:`label`,op:`operation`,mode:`execution`,confirm:`confirmText`,confirmmessage:`confirmText`,limit:`maxRecords`,max:`maxRecords`,batch:`batchSize`},guidance:{actionDef:"`actionDef` is attached by the renderer, not authored: `resolveBulkActions` looks the action up by `name` and inlines it. Writing it by hand smuggles an action definition past the action registry — no permission gate, no param contract, no lint. Declare the action normally and let this def name it.",bulkEnabled:"`action.bulkEnabled` was retired in spec 17: the selection bar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, which is this array. There is nothing to set.",recordIdParam:"`recordIdParam` belongs on the ACTION, not on the def that names it — a per-record bulk run reuses the action's own declaration, and an `execution: 'aggregate'` run carries the whole selection in `params._selectedIds` instead of a single record id."},history:"Until #4457 the whole array was `z.array(z.record(z.string(), z.any()))` — every key parsed, so a mis-spelled one shipped as a button that silently ran the DEFAULT behaviour (or none at all)."}),Mr=n(()=>t.z.object({name:E.describe(`Stable identifier — the audit-log action key, and (for an aggregate def) the name of the object action to dispatch.`),label:t.z.string().optional().describe("Button + dialog-header text. Plain string: an authored def is not i18n-resolved (declare a real action and name it in `bulkActions` to get localization)."),icon:t.z.string().optional().describe(`Lucide icon name (e.g. "user-check", "trash-2").`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`outline`]).optional().describe(`Visual treatment of the button.`),operation:Or.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:kr.optional().describe("For `operation: 'custom'` — 'aggregate' dispatches the named action ONCE for the whole selection, carrying every id in `params._selectedIds` (objectui#3139). Required on a custom def: the per-record form is declared as `bulkActions: ['<name>']` instead."),patch:t.z.record(t.z.string(),t.z.unknown()).optional().describe("For `operation: 'update'` — static field values applied to every selected record, merged UNDER the user-supplied params so a fixed value can be declared without exposing it in the dialog."),params:t.z.array(Ar).optional().describe(`Inputs collected once before the run. Omit to skip the params step and go straight to confirm.`),confirmText:t.z.string().optional().describe(`Confirmation text shown above the affected-record summary.`),confirmLabel:t.z.string().optional().describe(`Custom Confirm button label (default: "Run").`),visible:I.optional().describe("Eligibility predicate (CEL), same shape as `action.visible`. Evaluated once PER SELECTED RECORD with that record bound: the button is offered when at least one passes, the run covers only those, and the rest are reported as skipped. A record-free predicate (`features.x`, `current_user.y`) therefore behaves as a plain button-level gate. Fail-closed — a predicate that faults excludes the record."),maxRecords:t.z.number().int().positive().optional().describe(`Selection size above which the run is blocked. Set it on defs whose server work is expensive — an aggregate def carries every selected id in one request.`),batchSize:t.z.number().int().positive().optional().describe(`Records per executor batch (default 200). Data-plane operations only — an aggregate run is a single call by definition.`)},{error:jr}).strict().superRefine((e,t)=>{e.operation===`custom`&&e.execution!==`aggregate`&&t.addIssue({code:`custom`,path:[`execution`],message:`Bulk action "${e.name}" declares \`operation: 'custom'\` without \`execution: 'aggregate'\`, which the renderer treats as a no-op \u2014 the button runs, reports success for every selected record, and does nothing. Pick the form you meant: to run the action ONCE PER record, drop this def and name the action in the view's \`bulkActions: ['${e.name}']\` (it is promoted with the action's label, params and \`visible\`); to run it ONCE for the whole selection, add \`execution: 'aggregate'\` (the handler reads \`params._selectedIds\`). For a mass field update or delete, use \`operation: 'update'\` / \`'delete'\` instead.`}),e.execution!==void 0&&e.operation!==`custom`&&t.addIssue({code:`custom`,path:[`execution`],message:`\`execution\` only applies to \`operation: 'custom'\` \u2014 a '${e.operation}' def is a data-plane mass mutation, always batched per record. Remove it, or switch the def to \`operation: 'custom'\` if you meant to dispatch an action.`}),e.patch!==void 0&&e.operation!==`update`&&t.addIssue({code:`custom`,path:[`patch`],message:`\`patch\` only applies to \`operation: 'update'\` \u2014 a '${e.operation}' def never writes fields, so these values are silently dropped. Use \`operation: 'update'\`, or move the constant into the action's own \`bodyExtra\`/\`params\` if this is a custom def.`}),e.params!==void 0&&e.operation===`delete`&&t.addIssue({code:`custom`,path:[`params`],message:"`params` on a `delete` def collects values the executor never reads — a bulk delete takes ids only. Remove them, or use `operation: 'update'` if the dialog is meant to write something."}),e.batchSize!==void 0&&e.execution===`aggregate`&&t.addIssue({code:`custom`,path:[`batchSize`],message:"`batchSize` does not apply to an aggregate def — the whole selection goes out in ONE call by definition, which is the point of `execution: 'aggregate'`. To bound how much a single call may carry, use `maxRecords`."})})),B=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,Nr=n(()=>t.z.discriminatedUnion(`provider`,[t.z.object({provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),t.z.object({provider:t.z.literal(`api`),read:Ne.optional().describe(`Configuration for fetching data`),write:Ne.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),t.z.object({provider:t.z.literal(`value`),items:t.z.array(t.z.unknown()).describe(`Static data array`)}),t.z.object({provider:t.z.literal(`schema`),schemaId:t.z.string().describe(`Schema identifier — typically the metadata type name`),schema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Inline JSON Schema (Draft 2020-12). Optional when schemaId is resolvable.`)})])),Pr=[`equals`,`not_equals`,`contains`,`not_contains`,`starts_with`,`ends_with`,`greater_than`,`less_than`,`greater_than_or_equal`,`less_than_or_equal`,`in`,`not_in`,`is_empty`,`is_not_empty`,`is_null`,`is_not_null`,`before`,`after`,`between`],Fr={eq:`equals`,ne:`not_equals`,neq:`not_equals`,notequals:`not_equals`,notEquals:`not_equals`,notcontains:`not_contains`,notContains:`not_contains`,startswith:`starts_with`,startsWith:`starts_with`,endswith:`ends_with`,endsWith:`ends_with`,gt:`greater_than`,greaterthan:`greater_than`,greaterThan:`greater_than`,lt:`less_than`,lessthan:`less_than`,lessThan:`less_than`,gte:`greater_than_or_equal`,greaterorequal:`greater_than_or_equal`,greaterOrEqual:`greater_than_or_equal`,greaterThanOrEqual:`greater_than_or_equal`,lte:`less_than_or_equal`,lessorequal:`less_than_or_equal`,lessOrEqual:`less_than_or_equal`,lessThanOrEqual:`less_than_or_equal`,nin:`not_in`,notin:`not_in`,notIn:`not_in`,isempty:`is_empty`,isEmpty:`is_empty`,isnotempty:`is_not_empty`,isNotEmpty:`is_not_empty`,isnull:`is_null`,isNull:`is_null`,isnotnull:`is_not_null`,isNotNull:`is_not_null`};function Ir(e){return typeof e!=`string`||Pr.includes(e)?e:Fr[e]??Fr[e.toLowerCase()]??e}var Lr=n(()=>R({surface:`this view filter rule`,history:B},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(Ir,t.z.enum(Pr)).describe(`Filter operator`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean(),t.z.null(),t.z.array(t.z.union([t.z.string(),t.z.number()]))]).optional().describe(`Filter value`)}).describe(`View filter rule`)),Rr=n(()=>t.z.enum([`none`,`count`,`count_empty`,`count_filled`,`count_unique`,`percent_empty`,`percent_filled`,`sum`,`avg`,`min`,`max`]).describe(`Aggregation function for column footer summary`)),zr=n(()=>R({surface:`this column summary configuration`,history:B},{type:Rr.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),Br=n(()=>R({surface:`this column prefix`,history:B},{field:t.z.string().describe(`Field whose value renders before the cell value`),type:t.z.enum([`badge`,`text`]).default(`text`).describe(`How the prefix value is rendered`)}).describe(`Compound-cell prefix configuration`)),Vr=n(()=>R({surface:`this list column`,history:B},{field:t.z.string().describe(`Field name (snake_case)`),label:z.optional().describe(`Display label override`),width:t.z.number().positive().optional().describe(`Column width in pixels`),align:t.z.enum([`left`,`center`,`right`]).optional().describe(`Text alignment`),hidden:t.z.boolean().optional().describe(`Hide column by default`),sortable:t.z.boolean().optional().describe(`Allow sorting by this column`),resizable:t.z.boolean().optional().describe(`Allow resizing this column`),wrap:t.z.boolean().optional().describe(`Allow text wrapping`),type:t.z.string().optional().describe(`Renderer type override (e.g., "currency", "date")`),pinned:t.z.enum([`left`,`right`]).optional().describe(`Pin/freeze column to left or right side`),summary:t.z.union([Rr,zr]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:Br.optional().describe(`Field rendered inline before this cell value`),link:t.z.boolean().optional().describe(`Functions as the primary navigation link (triggers View navigation)`),action:t.z.string().optional().describe(`Registered Action ID to execute when clicked`)})),Hr=n(()=>R({surface:`this selection configuration`,history:B},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),Ur=n(()=>R({surface:`this pagination configuration`,history:B},{pageSize:t.z.number().int().positive().default(25).describe(`Number of records per page`),pageSizeOptions:t.z.array(t.z.number().int().positive()).optional().describe(`Available page size options`)})),Wr=n(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),Gr=n(()=>R({surface:`this grouping field`,history:B},{field:t.z.string().describe(`Field name to group by`),order:t.z.enum([`asc`,`desc`]).default(`asc`).describe(`Group sort order`),collapsed:t.z.boolean().default(!1).describe(`Collapse groups by default`)})),Kr=n(()=>R({surface:`this grouping configuration`,history:B},{fields:t.z.array(Gr).min(1).describe(`Fields to group by (supports up to 3 levels)`)}).describe(`Record grouping configuration`)),qr=n(()=>R({surface:`this gallery configuration`,history:B},{coverField:t.z.string().optional().describe(`Attachment/image field to display as card cover`),coverFit:t.z.enum([`cover`,`contain`]).default(`cover`).describe(`Image fit mode for card cover`),cardSize:t.z.enum([`small`,`medium`,`large`]).default(`medium`).describe(`Card size in gallery view`),titleField:t.z.string().optional().describe(`Field to display as card title`),visibleFields:t.z.array(t.z.string()).optional().describe(`Fields to display on card body`)}).describe(`Gallery/card view configuration`)),Jr=n(()=>R({surface:`this timeline configuration`,history:B},{startDateField:t.z.string().describe(`Field for timeline item start date`),endDateField:t.z.string().optional().describe(`Field for timeline item end date`),titleField:t.z.string().describe(`Field to display as timeline item title`),groupByField:t.z.string().optional().describe(`Field to group timeline rows`),colorField:t.z.string().optional().describe(`Field to determine item color`),scale:t.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).default(`week`).describe(`Default timeline scale`)}).describe(`Timeline view configuration`)),Yr=n(()=>R({surface:`this view sharing`,history:B},{type:t.z.enum([`personal`,`collaborative`]).default(`collaborative`).describe(`View ownership type`),lockedBy:t.z.string().optional().describe(`User who locked the view configuration`)}).describe(`View sharing and access configuration`)),Xr=n(()=>R({surface:`this row color configuration`,history:B},{field:t.z.string().describe(`Field to derive color from (typically a select/status field)`),colors:t.z.record(t.z.string(),t.z.string()).optional().describe(`Map of field value to color (hex/token)`)}).describe(`Row color configuration based on field values`)),Zr=n(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),Qr=n(()=>R({surface:`this user actions configuration`,history:B},{sort:t.z.boolean().default(!0).describe(`Allow users to sort records`),search:t.z.boolean().default(!0).describe(`Allow users to search records`),filter:t.z.boolean().default(!0).describe(`Allow users to filter records`),refresh:t.z.boolean().default(!0).describe(`Allow users to reload the view data from the backend without a full page reload`),rowHeight:t.z.boolean().default(!0).describe(`Allow users to toggle row height/density`),addRecordForm:t.z.boolean().default(!1).describe(`Add records through a form instead of inline`),editInline:t.z.boolean().default(!1).describe(`Allow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in.`),buttons:t.z.array(t.z.string()).optional().describe(`Custom action button IDs to show in the toolbar`)}).describe(`User action toggles for the view toolbar`)),$r=n(()=>R({surface:`this appearance configuration`,history:B},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array(Zr).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),V=n(()=>R({surface:`this view tab`,history:B},{name:E.describe(`Tab identifier (snake_case)`),label:z.optional().describe(`Display label`),icon:t.z.string().optional().describe(`Tab icon name`),view:t.z.string().optional().describe(`Referenced list view name from listViews`),filter:t.z.array(Lr).optional().describe(`Tab-specific filter criteria`),order:t.z.number().int().min(0).optional().describe(`Tab display order`),pinned:t.z.boolean().default(!1).describe(`Pin tab (cannot be removed by users)`),isDefault:t.z.boolean().default(!1).describe(`Set as the default active tab`),visible:t.z.boolean().default(!0).describe(`Tab visibility`)}).describe(`Tab configuration for multi-tab view interface`)),ei=n(()=>R({surface:`this user filter field`,history:B},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:z.optional().describe(`Display label override (defaults to the field label)`),type:t.z.enum([`select`,`multi-select`,`boolean`,`date-range`,`text`]).optional().describe(`Filter control type. Omit to infer from the field definition`),options:t.z.array(t.z.object({value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Option value`),label:z.describe(`Option label`),color:t.z.string().optional().describe(`Option color token/hex`)})).optional().describe(`Static options. Omit to derive from the field definition (select options / lookup records)`),showCount:t.z.boolean().optional().describe(`Show per-option record counts`),defaultValues:t.z.array(t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().describe(`Pre-selected values when the view loads`)}).describe(`Quick-filter field configuration`)),ti=n(()=>t.z.object({element:t.z.enum([`dropdown`,`tabs`,`toggle`]).default(`dropdown`).describe(`Filter control style: "dropdown" (per-field value selectors) or "tabs" (named presets). "toggle" is deprecated.`),fields:t.z.array(ei).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(V).optional().describe(`Named filter presets rendered as tabs (tabs element). Reuses ViewTabSchema`),showAllRecords:t.z.boolean().optional().describe(`Show an "All records" tab before the presets (tabs element)`)}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),ni=n(()=>R({surface:`this add record configuration`,history:B},{enabled:t.z.boolean().default(!0).describe(`Show the add record entry point`),position:t.z.enum([`top`,`bottom`,`both`]).default(`bottom`).describe(`Position of the add record button`),mode:t.z.enum([`inline`,`form`,`modal`]).default(`inline`).describe(`How to add a new record`),formView:t.z.string().optional().describe(`Named form view to use when mode is "form" or "modal"`)}).describe(`Add record entry point configuration`)),ri=n(()=>R({surface:`this kanban configuration`,history:B},{groupByField:t.z.string().describe(`Field to group columns by (usually status/select)`),summarizeField:t.z.string().optional().describe(`Field to sum at top of column (e.g. amount)`),columns:t.z.array(t.z.string()).describe(`Fields to show on cards`)})),ii=n(()=>R({surface:`this list chart configuration`,history:B},{chartType:br.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:E.describe(`Dataset name to bind (ADR-0021)`),dimensions:t.z.array(t.z.string()).optional().describe(`Dimension names — X/group/split`),values:t.z.array(t.z.string()).min(1).describe(`Measure names — Y (at least one)`)}).describe(`List chart view configuration`)),ai=n(()=>R({surface:`this calendar configuration`,history:B},{startDateField:t.z.string().describe(`Field providing the event start date/time`),endDateField:t.z.string().optional().describe(`Field providing the event end date/time (defaults to a single-day event)`),titleField:t.z.string().describe(`Field displayed as the event title`),colorField:t.z.string().optional().describe(`Field whose value determines the event color`)})),oi=n(()=>R({surface:`this gantt quick filter`,history:B},{field:t.z.string().describe(`Record field / dot-path the dimension filters on`),label:t.z.string().optional().describe(`Trigger label (falls back to the field label)`),options:t.z.array(t.z.union([t.z.string(),t.z.object({value:t.z.union([t.z.string(),t.z.number()]),label:t.z.string().optional()})])).optional().describe(`Explicit option override for fixed enums`)})),si=n(()=>R({surface:`this gantt configuration`,history:B},{startDateField:t.z.string().describe(`Field providing the task start date`),endDateField:t.z.string().describe(`Field providing the task end date`),titleField:t.z.string().describe(`Field displayed as the task title`),progressField:t.z.string().optional().describe(`Field providing the task completion percentage`),dependenciesField:t.z.string().optional().describe(`Field listing the task's predecessor (dependency) record ids`),colorField:t.z.string().optional().describe(`Field that drives the bar color`),parentField:t.z.string().optional().describe(`Field holding the parent task id (builds the summary → step tree)`),typeField:t.z.string().optional().describe(`Field whose value maps to task/summary/milestone`),baselineStartField:t.z.string().optional().describe(`Baseline (planned) start field`),baselineEndField:t.z.string().optional().describe(`Baseline (planned) end field`),groupByField:t.z.string().optional().describe(`Field to group leaf tasks by (synthesized summary rows)`),resourceView:t.z.boolean().optional().describe(`Render a per-resource workload histogram instead of the timeline`),assigneeField:t.z.string().optional().describe(`Resource field to bucket load by (resource view)`),effortField:t.z.string().optional().describe(`Per-task load units (resource view; default 1)`),capacity:t.z.number().optional().describe(`Per-resource capacity ceiling; loads above this flag overload`),tooltipFields:t.z.array(t.z.union([t.z.string(),t.z.object({field:t.z.string(),label:t.z.string().optional()})])).optional().describe(`Fields to surface in the hover tooltip, in display order`),quickFilters:t.z.array(oi).optional().describe(`Multi-select filter dropdowns rendered above the chart`),autoZoomToFilter:t.z.boolean().optional().describe(`When true (default), filtering zooms the range to the filtered tasks`)}).passthrough()),ci=n(()=>R({surface:`this tree configuration`,history:B},{parentField:t.z.string().optional().describe(`Single-parent pointer field (auto-detected from the object schema when omitted)`),labelField:t.z.string().optional().describe(`Field rendered indented in the first column (defaults to "name")`),fields:t.z.array(t.z.string()).optional().describe(`Additional fields rendered as flat columns alongside the label`),defaultExpandedDepth:t.z.number().int().min(0).optional().describe(`Initial expansion depth (0 = roots only; omit = expand all)`)}).passthrough()),li=n(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),ui=n(()=>R({surface:`this navigation configuration`,history:B},{mode:li.default(`page`),view:t.z.string().optional().describe(`Name of the form view to use for details (e.g. "summary_view", "edit_form")`),preventNavigation:t.z.boolean().default(!1).describe(`Disable standard navigation entirely`),openNewTab:t.z.boolean().default(!1).describe(`Force open in new tab (applies to page mode)`),size:t.z.enum([`auto`,`sm`,`md`,`lg`,`xl`,`full`]).default(`auto`).describe("[#2578] Overlay size bucket for drawer/modal detail: 'auto' (default — renderer derives from field count + viewport; AI writes nothing) or a coarse override sm/md/lg/xl/full. Prefer this over the pixel `width`; page mode ignores it."),width:t.z.union([t.z.string(),t.z.number()]).optional().describe('[DEPRECATED → size] Pixel/percent width of the drawer/modal (e.g. "600px"). A pixel width cannot be chosen at authoring time without knowing the client viewport — use the `size` bucket.')})),di=n(()=>R({surface:`this list view`,history:B},{name:E.optional().describe(`Internal view name (lowercase snake_case)`),label:z.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:Nr.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(Vr)]).describe(`Fields to display as columns`),filter:t.z.array(Lr).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(t.z.object({field:t.z.string(),order:t.z.enum([`asc`,`desc`])}))]).optional(),searchableFields:t.z.array(t.z.string()).optional().describe(`Fields enabled for search`),filterableFields:t.z.array(t.z.string()).optional().describe(`Legacy shorthand for userFilters.fields — bare field names enabled for end-user filtering. Prefer userFilters`),userFilters:ti.optional().describe(`End-user quick-filter bar: dropdown/toggle fields or tab presets. Omit to let the renderer derive filters from select/boolean fields`),resizable:t.z.boolean().optional().describe(`Enable column resizing`),striped:t.z.boolean().optional().describe(`Striped row styling`),bordered:t.z.boolean().optional().describe(`Show borders`),compactToolbar:t.z.boolean().optional().describe(`Collapse Group/Color/Density/Hide-fields into a single View settings popover`),selection:Hr.optional().describe(`Row selection configuration`),navigation:ui.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:Ur.optional().describe(`Pagination configuration`),kanban:ri.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:ai.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:si.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:qr.optional(),timeline:Jr.optional(),chart:ii.optional(),tree:ci.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:z.optional().describe(`View description for documentation/tooltips`),sharing:Yr.optional().describe(`View sharing and access configuration`),rowHeight:Wr.optional().describe(`Row height / density setting`),grouping:Kr.optional().describe(`Group records by one or more fields`),rowColor:Xr.optional().describe(`Color rows based on field value`),hiddenFields:t.z.array(t.z.string()).optional().describe(`Fields to hide in this specific view`),fieldOrder:t.z.array(t.z.string()).optional().describe(`Explicit field display order for this view`),rowActions:t.z.array(t.z.string()).optional().describe(`Actions available for individual row items`),bulkActions:t.z.array(t.z.string()).optional().describe(`Actions available when multiple rows are selected`),bulkActionDefs:t.z.array(Mr).optional().describe("Rich bulk action definitions (schema-driven, executed via BulkActionDialog). Use a def for a mass data-plane mutation ('update' with a `patch` / 'delete') that no action expresses, or for an `operation: 'custom'` + `execution: 'aggregate'` entry (objectui#3139) that dispatches the action it NAMES once for the whole selection — the renderer injects `params._selectedIds: string[]` (read that on the server, not `recordId`) so a single call can produce one aggregate artifact (zip of QR codes, merged PDF, batch print). Aggregate results are all-or-nothing: a handler that cannot cover the whole selection must reject, and per-row retry is replaced by re-running the action. `batchSize` does not apply (the call is never chunked); set `maxRecords` on defs whose server work is expensive. For the PER-RECORD dispatch use `bulkActions: ['<name>']` instead — the bare-string form, promoted with the action's own label, params and `visible`; a 'custom' def without `execution: 'aggregate'` has no dispatcher and is refused at parse time (#4457). Toolbar url/api actions can also interpolate the current selection via `${ctx.selection.ids}` / `${ctx.selection.count}`."),virtualScroll:t.z.boolean().optional().describe(`Enable virtual scrolling for large datasets`),conditionalFormatting:t.z.array(t.z.object({condition:I.describe(`Predicate (CEL) to evaluate.`),style:t.z.record(t.z.string(),t.z.string()).describe(`CSS styles to apply when condition is true`)})).optional().describe(`Conditional formatting rules for list rows`),inlineEdit:t.z.boolean().optional().describe(`Allow inline editing of records directly in the list view`),exportOptions:t.z.array(t.z.enum([`csv`,`xlsx`,`pdf`,`json`])).optional().describe(`Available export format options`),userActions:Qr.optional().describe(`User action toggles for the view toolbar`),appearance:$r.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(V).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:ni.optional().describe(`Add record entry point configuration`),showRecordCount:t.z.boolean().optional().describe(`Show record count at the bottom of the list`),allowPrinting:t.z.boolean().optional().describe(`Allow users to print the view`),emptyState:t.z.object({title:z.optional(),message:z.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:_r.optional().describe(`ARIA accessibility attributes for the list view`),responsive:c("`view.responsive` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer ever read it; the grid is responsive by its own layout rules. Delete the key."),performance:c("`view.performance` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer or runtime read it; list-view performance tuning was never implemented. Delete the key.")})),fi=n(()=>t.z.object({field:t.z.string().describe(`Field name (snake_case)`),type:rr.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(ar).optional().describe(`Options for select/multiselect/radio/checkboxes fields`),reference:t.z.string().optional().describe(`Target object name for lookup/master_detail fields`),maxLength:t.z.number().optional().describe(`Maximum character length (for text/textarea/email/url/phone)`),minLength:t.z.number().optional().describe(`Minimum character length`),min:t.z.number().optional().describe(`Minimum value (for number/currency/percent/slider)`),max:t.z.number().optional().describe(`Maximum value`),precision:t.z.number().optional().describe(`Total digits (for number/currency)`),scale:t.z.number().optional().describe(`Decimal places`),multiple:t.z.boolean().optional().describe(`Allow multiple values (for select/lookup/file/image)`),label:z.optional().describe(`Display label override`),placeholder:z.optional().describe(`Placeholder text`),helpText:z.optional().describe(`Help/hint text`),readonly:t.z.boolean().optional().describe(`Read-only override`),immutable:t.z.boolean().optional().describe(`Editable on create, locked once the record exists (e.g. machine names).`),required:t.z.boolean().optional().describe(`Required override`),hidden:t.z.boolean().optional().describe(`Hidden override`),colSpan:t.z.number().int().min(1).max(4).optional().describe("[legacy — prefer `span`] Absolute column span (1-4). Fragile when the column count is derived per surface (mobile 1 / modal 2 / page 3-4): a fixed span only lines up at the width the author imagined. The renderer clamps it to the current column count. Prefer `span`."),span:t.z.enum([`auto`,`full`]).default(`auto`).describe("Relative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count (wide widgets like textarea/richtext/json/file/subform take the whole row). 'full': whole row at any column count. Prefer this over the absolute `colSpan`."),widget:t.z.string().optional().describe(`Custom widget/component name (overrides type-based inference)`),language:t.z.string().optional().describe(`Code editor language (for type=code)`),keyField:t.z.object({field:t.z.string().default(`name`).describe(`Property name that holds the key inside each item (defaults to "name")`),label:z.optional().describe(`Display label for the key column`),placeholder:z.optional().describe(`Placeholder when entering a new key`),helpText:z.optional().describe(`Help text under the key input`),regex:t.z.string().optional().describe(`JS regex source string the key must match (no flags)`),immutable:t.z.boolean().default(!0).describe(`If true, the key is read-only after creation`)}).optional().describe(`Key column config for record-typed fields`),dependsOn:t.z.string().optional().describe(`Parent field name for cascading`),visibleWhen:I.optional().describe("Visibility predicate (CEL) — field shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms). e.g. P`record.priority == 'urgent'`"),visibleOn:I.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Normalized to `visibleWhen` at parse."),disclosure:t.z.enum([`inline`,`popover`]).optional().describe(`Composite rendering: inline bordered box (default) or a summary line + gear popover (progressive disclosure).`)},{error:gr})),pi=n(()=>fi.extend({fields:t.z.array(t.z.lazy(()=>pi)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(mr)),mi=n(()=>t.z.object({name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:z.optional(),description:t.z.string().optional().describe(`Optional description rendered under the section header.`),collapsible:t.z.boolean().default(!1),collapsed:t.z.boolean().default(!1),visibleWhen:I.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms)."),visibleOn:I.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Hides the whole section when false. Normalized to `visibleWhen` at parse."),columns:t.z.union([t.z.enum([`1`,`2`,`3`,`4`]),t.z.literal(1),t.z.literal(2),t.z.literal(3),t.z.literal(4)]).default(1).transform(e=>typeof e==`string`?parseInt(e):e),pane:t.z.enum([`primary`,`secondary`]).optional().describe(`Split pane this section renders in (split forms only; a parse error elsewhere). Omitted → first section 'primary', others 'secondary'.`),fields:t.z.array(t.z.union([t.z.string(),pi]))},{error:gr}).strict().transform(mr)),hi=n(()=>R({surface:`this form button configuration`,history:B},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:z.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict()),gi=n(()=>R({surface:`this form view`,history:B},{type:t.z.enum([`simple`,`tabbed`,`wizard`,`split`,`drawer`,`modal`]).default(`simple`),layout:t.z.enum([`vertical`,`horizontal`,`inline`,`grid`]).optional().describe(`Field layout direction`),columns:t.z.number().int().min(1).optional().describe(`Number of columns for the form body`),title:t.z.string().optional().describe(`Form title`),description:t.z.string().optional().describe(`Form description`),defaultTab:t.z.string().optional().describe(`Initially active tab (tabbed forms)`),tabPosition:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Tab strip position (tabbed forms)`),allowSkip:t.z.boolean().optional().describe(`Allow skipping steps (wizard forms)`),showStepIndicator:t.z.boolean().optional().describe(`Show the step indicator (wizard forms)`),splitDirection:t.z.enum([`horizontal`,`vertical`]).optional().describe(`Split orientation (split forms)`),splitSize:t.z.number().optional().describe(`Primary split panel size, % (split forms)`),splitResizable:t.z.boolean().optional().describe(`Whether the split is resizable (split forms)`),drawerSide:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Drawer side (drawer forms)`),drawerWidth:t.z.string().optional().describe(`[DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it.`),modalSize:t.z.enum([`sm`,`default`,`lg`,`xl`,`full`]).optional().describe(`Modal size (modal forms)`),data:Nr.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(mi).optional(),groups:t.z.array(mi).optional(),subforms:t.z.array(t.z.object({childObject:t.z.string().describe(`Child object whose records are entered inline`),relationshipField:t.z.string().optional().describe(`FK on the child pointing back to the parent (auto-detected when omitted)`),columns:t.z.array(t.z.any()).optional().describe(`Editable grid columns (derived from the child object when omitted)`),amountField:t.z.string().optional().describe(`Numeric child column summed for the running total`),totalField:t.z.string().optional().describe(`Parent field to receive the rolled-up sum`),title:t.z.string().optional().describe(`Section title`),addLabel:t.z.string().optional().describe(`Add-row button label`),minRows:t.z.number().optional(),maxRows:t.z.number().optional()})).optional().describe(`Inline master-detail child collections`),defaultSort:c("`form.defaultSort` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — nothing read it: a related list inside a form sorts by its own list view's `sort`. Delete the key and set the sort on the related list view instead."),sharing:Dr.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.union([t.z.object({kind:t.z.literal(`thank-you`),title:t.z.string().optional(),message:t.z.string().optional()}),t.z.object({kind:t.z.literal(`redirect`),url:t.z.string(),delayMs:t.z.number().int().min(0).optional()}),t.z.object({kind:t.z.literal(`continue`)}),t.z.object({kind:t.z.literal(`next-record`)})]).optional().describe(`Post-submit behavior`),buttons:t.z.object({submit:hi.optional().describe(`Submit button`),cancel:hi.optional().describe(`Cancel button`),reset:hi.optional().describe(`Reset button`)}).strict().optional().describe(`Form action-button visibility & labels; folded onto the flat renderer props by ObjectUI ObjectForm (framework#1894 / #2998).`),defaults:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Initial field values for create-mode forms (folded into ObjectUI ObjectForm initial values; framework#1894 / #2998).`),aria:c("`form.aria` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no form renderer ever applied it, so declared ARIA attributes silently did not reach the DOM. Delete the key. The form renderer emits its own semantic markup; report gaps as renderer issues rather than per-view attribute overrides.")}).superRefine((e,t)=>{if(e.type!==`split`)for(let[n,r]of[[`sections`,e.sections],[`groups`,e.groups]])r?.forEach((r,i)=>{r?.pane!=null&&t.addIssue({code:`custom`,path:[n,i,`pane`],message:`\`pane\` places a section in a split pane and is only valid on \`type: 'split'\` form views (this form is '${e.type}'). Remove the key or change the form type.`})})})),_i=n(()=>ti.omit({tabs:!0,showAllRecords:!0}).extend({element:t.z.enum([`dropdown`,`toggle`]).default(`dropdown`).describe('Filter control style on object views: "dropdown" (per-field value chips). "toggle" is deprecated. "tabs" is page-only — use `listViews` for named presets.')})),vi=n(()=>di.omit({userFilters:!0}).extend({userFilters:_i.optional()})),yi=n(()=>R({surface:`this view container`,history:B,guidance:Object.fromEntries([`type`,`columns`,`data`,`viewKind`,`filters`,`sort`].map(e=>[e,`\`${e}\` belongs to a single VIEW, not to the container. Wrap it: \`defineView({ list: { type, data, columns, \u2026 } })\`, or name it \u2014 \`defineView({ listViews: { my_view: { \u2026 } } })\`. The container's own keys are \`list\`, \`form\`, \`listViews\`, \`formViews\`.`]))},{name:t.z.string().optional().describe(`Item name — supplied by the metadata door; for an object-scoped container it is the object name.`),label:z.optional().describe(`Human-readable label shown in metadata lists.`),object:t.z.string().optional().describe("Object this container binds to — how a stack-level `views: [...]` entry says which object its views belong to; read by `getViewsByObject()` / `GET /meta/view?object=`."),list:vi.optional(),form:gi.optional(),listViews:t.z.record(t.z.string(),vi).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),gi).optional().describe(`Additional named form views`),protection:Xn.optional().describe(`Package author protection block — lock policy for this view.`),...F})),bi=t.z.string().regex(/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/,`View item name must be a dotted snake_case qualified name, e.g. "crm_lead.pipeline".`).describe("Globally-unique view id, `<object>.<viewKey>`."),xi=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),Si=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function Ci(){return{name:bi,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:z.optional().describe(`Display label (supports i18n).`),isDefault:t.z.boolean().optional().describe(`Whether this is the object's default view in the switcher.`),order:t.z.number().int().optional().describe(`Sort order within the object's view switcher / left rail.`),scope:xi.optional().describe("Identity layer (defaults to `package` for source-loaded views)."),owner:t.z.string().optional().describe("Owner user id — set when `scope` is `personal`."),hidden:t.z.boolean().optional().describe(`Hidden from the switcher (per-user / per-org declutter).`),protection:Xn.optional().describe(`Package author protection block — lock policy for this view.`),...F}}var wi=n(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({viewKind:t.z.literal(`list`),config:di.describe(`List-family view configuration.`),...Ci()}),t.z.object({viewKind:t.z.literal(`form`),config:gi.describe(`Form view configuration.`),...Ci()})]));function Ti(){return{name:t.z.string().optional().describe(`Save name / qualified view id (stamped by the write path).`),object:t.z.string().optional().describe(`Bound object name (inherited from the shadowed entry — #2555).`),viewKind:Si.optional().describe(`View family (inherited from the shadowed entry — #2555).`),label:z.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:xi.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:Xn.optional(),...F,config:t.z.undefined().optional(),list:t.z.undefined().optional(),form:t.z.undefined().optional(),listViews:t.z.undefined().optional(),formViews:t.z.undefined().optional()}}function Ei(e){if(!e||typeof e!=`object`)return!1;let t=e;return!!(t.list||t.form||t.listViews&&typeof t.listViews==`object`&&Object.keys(t.listViews).length>0||t.formViews&&typeof t.formViews==`object`&&Object.keys(t.formViews).length>0)}n(()=>t.z.union([wi,yi.refine(Ei,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."}),di.extend(Ti()).strip(),gi.extend(Ti()).strip()]));var Di=t.z.enum([`select`,`insert`,`update`,`delete`,`all`]),Oi=L({surface:`this RLS policy`,knownKeys:[`name`,`label`,`description`,`object`,`operation`,`using`,`check`,`positions`,`enabled`,`tags`],aliases:{roles:`positions`,role:`positions`,withcheck:`check`,condition:`using`,filter:`using`,where:`using`},history:`Until #4001 these were dropped silently — the policy still parsed, so a row-level restriction the author wrote was never compiled into the filter.`}),ki=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Policy unique identifier (snake_case)`),label:t.z.string().optional().describe(`Human-readable policy label`),description:t.z.string().optional().describe(`Policy description and business justification`),object:t.z.string().describe(`Target object name`),operation:Di.describe(`Database operation this policy applies to`),using:t.z.string().optional().describe("Filter condition for SELECT/UPDATE/DELETE. One of the four compiler-supported forms: `field = current_user.<prop>`, `field = 'literal'`, `field IN (current_user.<array>)`, or `1 = 1`. Optional for INSERT-only policies."),check:t.z.string().optional().describe(`Validation condition for INSERT/UPDATE (defaults to USING clause if not specified - enforced at application level)`),positions:t.z.array(t.z.string()).optional().describe(`Positions this policy applies to (omit for all)`),enabled:t.z.boolean().default(!0).describe(`Whether this policy is active`),priority:c("`rowLevelSecurity[].priority` was removed in @objectstack/spec 17.0.0 (#3896 security audit). It never had an effect and could not: applicable policies OR-combine (most permissive wins), so there is no conflict to order. Delete the key — policy outcomes are unchanged."),tags:t.z.array(t.z.string()).optional().describe(`Policy categorization tags`)},{error:Oi}).strict().superRefine((e,n)=>{!e.using&&!e.check&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`At least one of "using" or "check" must be specified. For SELECT/UPDATE/DELETE operations, provide "using". For INSERT operations, provide "check".`})}));n(()=>t.z.object({id:t.z.string().describe(`User ID`),email:t.z.string().email().optional().describe(`User email`),tenantId:t.z.string().optional().describe(`Tenant/Organization ID`),positions:t.z.array(t.z.string()).optional().describe(`Positions held by the user`),department:t.z.string().optional().describe(`User department`),attributes:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional custom user attributes`)})),n(()=>t.z.object({policyName:t.z.string().describe(`Policy name`),granted:t.z.boolean().describe(`Whether access was granted`),durationMs:t.z.number().optional().describe(`Evaluation duration in milliseconds`),error:t.z.string().optional().describe(`Error message if evaluation failed`),usingResult:t.z.boolean().optional().describe(`USING clause evaluation result`),checkResult:t.z.boolean().optional().describe(`CHECK clause evaluation result`)}));var Ai={name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique rule name (snake_case)`),label:t.z.string().optional().describe(`Human-readable label for the rule listing`),description:t.z.string().optional().describe(`Administrative notes explaining the business reason`),active:t.z.boolean().default(!0),events:t.z.array(t.z.enum([`insert`,`update`])).default([`insert`,`update`]).describe("Write contexts the rule runs on. `delete` is intentionally absent — the evaluator only runs on the insert/update write path; guard deletions with a `beforeDelete` lifecycle hook"),priority:t.z.number().int().min(0).max(9999).default(100).describe(`Execution priority (lower runs first, default: 100)`),tags:t.z.array(t.z.string()).optional().describe(`Categorization tags (e.g., "compliance", "billing")`),severity:t.z.enum([`error`,`warning`,`info`]).default(`error`),message:t.z.string().describe(`Error message to display to the user`),...F},ji=n(()=>R({surface:`this script validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`,predicate:`condition`,rule:`condition`}},{...Ai,type:t.z.literal(`script`),condition:I.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),Mi=n(()=>R({surface:`this state-machine validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{states:`transitions`,statefield:`field`,from:`transitions`,initial:`initialStates`,initialstate:`initialStates`}},{...Ai,type:t.z.literal(`state_machine`),field:t.z.string().describe(`State field (e.g. status)`),transitions:t.z.record(t.z.string(),t.z.array(t.z.string())).describe(`Map of { OldState: [AllowedNewStates] }`),initialStates:t.z.array(t.z.string()).optional().describe("States a record may be CREATED in. When set, an INSERT whose state field carries a value outside this list is rejected (server-enforced) — the FSM entry point. `transitions` only governs UPDATE, and a `select` field permits ANY declared option as an initial value, so without this a record could be born mid-flow (e.g. created already `approved`). Omit to keep the legacy behavior (no initial-state check on insert). #3165.")})),Ni=n(()=>R({surface:`this format validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{pattern:`regex`,fieldname:`field`}},{...Ai,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),Pi=n(()=>R({surface:`this cross-field validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{formula:`condition`,expression:`condition`}},{...Ai,type:t.z.literal(`cross_field`),condition:I.describe("Predicate (CEL) comparing fields. e.g. P`record.end_date > record.start_date`"),fields:t.z.array(t.z.string()).describe(`Fields involved. Only fields[0] is read (labels which field the violation attaches to); the rest are advisory. Shares script’s evaluation path.`)})),Fi=n(()=>R({surface:`this JSON-schema validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{jsonschema:`schema`,fieldname:`field`}},{...Ai,type:t.z.literal(`json_schema`),field:t.z.string().describe(`JSON field to validate`),schema:t.z.record(t.z.string(),t.z.unknown()).describe(`JSON Schema object definition`)})),Ii=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[ji,Mi,Ni,Pi,Fi,Li])),Li=n(()=>R({surface:`this conditional validation rule`,history:`Until #4001 closed this shape these were dropped silently — the rule still registered and ran, minus whatever the key was meant to configure.`,aliases:{if:`when`,condition:`when`,match:`when`,else:`otherwise`}},{...Ai,type:t.z.literal(`conditional`),when:I.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:Ii.describe(`Validation rule to apply when condition is true`),otherwise:Ii.optional().describe(`Validation rule to apply when condition is false`)})),Ri='`crypto.hash` was removed from `HookBodyCapability` in @objectstack/spec 17 (#4391, ADR-0049 enforce-or-remove) — the sandbox never implemented it. `installCtx` wired only `ctx.crypto.randomUUID`, so `ctx.crypto.hash(...)` threw inside the VM on every call the token ever "granted", while the build-time extractor inferred the token from that very call and let `os build` pass. Delete the capability from `capabilities` AND delete the `ctx.crypto.hash(...)` call it was declared for — the call has never returned a value, so nothing that works today depends on it. There is no replacement inside the sandbox: hash in the host (a Connector recipe, or an engine-side hook) instead. If you need hashing in a body, reopen it through the capability admission process — implementation first, the declaration lands with the implementation. Run `os migrate meta --from 16` to rewrite it automatically.',zi=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?Ri:void 0}),Bi=[`language`,`source`],Vi=[`language`,`source`,`capabilities`,`timeoutMs`,`memoryMb`],Hi='is an L2 key — it only applies to `language: "js"`. An expression body is a pure formula: it performs no IO, so it has nothing to grant and no sandbox to bound.',Ui=L({surface:`this expression (L1) hook body`,knownKeys:Bi,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${Hi}`,timeoutMs:`\`timeoutMs\` ${Hi}`,memoryMb:`\`memoryMb\` ${Hi}`},history:`Until #4001 these were dropped silently.`}),Wi=L({surface:`this sandboxed JS (L2) hook body`,knownKeys:Vi,aliases:{capability:`capabilities`,caps:`capabilities`,permissions:`capabilities`,timeout:`timeoutMs`,timeoutms:`timeoutMs`,memory:`memoryMb`,memorymb:`memoryMb`,code:`source`,script:`source`,body:`source`},history:`Until #4001 these were dropped silently — the body still ran, just not under the limits or grants that were written.`}),Gi=t.z.object({language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)},{error:Ui}).strict().describe(`L1 expression body — pure formula, no IO`),Ki=t.z.object({language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(zi).default([]).describe(`Granted capability tokens`),timeoutMs:t.z.number().int().positive().max(3e4).optional().describe(`Per-invocation timeout (ms)`),memoryMb:t.z.number().int().positive().max(256).optional().describe(`Per-invocation memory cap (MB)`)},{error:Wi}).strict().describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),qi=t.z.discriminatedUnion(`language`,[Gi,Ki]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),Ji={twoFactor:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.enable_two_factor`,`sys_user.actions.disable_two_factor`,`sys_user.actions.generate_backup_codes`,`sys_two_factor.actions.enable_two_factor`,`sys_two_factor.actions.disable_two_factor`,`sys_two_factor.actions.regenerate_backup_codes`],notes:`Login-surface 2FA challenge is server-driven remediation (ADR-0069), so the flag is intentionally unread by objectui LoginForm.`},passkeys:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no passkey UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},magicLink:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input to gate. Typed in objectui (auth/src/types.ts) but no magic-link UI exists yet — advertised-but-unconsumed gap tracked in objectui#2514 (#2874 P2②).`}},organization:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_user.actions.invite_user`,`sys_member.actions.add_member`,`sys_member.actions.update_member_role`,`sys_member.actions.remove_member`,`sys_member.actions.transfer_ownership`,`sys_invitation.actions.invite_user`,`sys_invitation.actions.cancel_invitation`,`sys_invitation.actions.resend_invitation`,`sys_team.actions.create_team`,`sys_team.actions.update_team`,`sys_team.actions.remove_team`,`sys_team_member.actions.add_team_member`,`sys_team_member.actions.remove_team_member`],notes:`Org CAPABILITY gate, not multi-org (ADR-0081 D1).`},multiOrgEnabled:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_organization.actions.create_organization`,`sys_organization.actions.update_organization`,`sys_organization.actions.delete_organization`,`sys_organization.actions.set_active_organization`,`sys_organization.actions.leave_organization`,`sys_organization.actions.change_slug`],notes:"Reflects ACTUAL multi-tenancy capability (the tenancy posture enforces an organization wall — `group` or `isolated`, ADR-0093 D4 / ADR-0105 D1), not just the requested posture."},degradedTenancy:{surface:`status`,semantics:`opt-in`,exempt:{reason:`Operator status banner (ADR-0093 D5) — signals degraded tenant isolation, not an input capability gate.`}},oidcProvider:{surface:`crud`,semantics:`default-on`,gatedInputs:[`sys_oauth_application.actions.create_oauth_application`,`sys_oauth_application.actions.delete_oauth_application`,`sys_oauth_application.actions.disable_oauth_application`,`sys_oauth_application.actions.enable_oauth_application`,`sys_oauth_application.actions.rotate_client_secret`],notes:`Default-ON: the embedded OIDC authorization server follows the default-on MCP surface (resolveOidcProviderEnabled). Login surface consumes the socialProviders[] array (per-provider enabled), not this flag.`},sso:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Deliberately ungated on the CRUD surface: the served value is refined to "usable" (≥1 provider configured) via isSsoUsable() at /auth/config, so gating sys_sso_provider registration actions on it would deadlock first-provider setup. Login consumption verified: objectui LoginForm gates the "Sign in with SSO" button.`}},ssoEnforced:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: objectui LoginForm hides the password form and self-registration (break-glass link remains). No spec input to gate.`}},deviceAuthorization:{surface:`login`,semantics:`opt-in`,exempt:{reason:`No spec input (sys_device_code declares no actions). Known gap: objectui DeviceAuthPage hits the device-auth endpoints without checking this flag (absent from its client type) — tracked in objectui#2513 (#2874 P2②).`}},admin:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user`,`sys_user.actions.ban_user`,`sys_user.actions.unban_user`,`sys_user.actions.unlock_user`,`sys_user.actions.set_user_password`,`sys_user.actions.set_user_role`,`sys_user.actions.impersonate_user`],notes:`SCIM forces the admin plugin (and this flag) on — ADR-0071.`},phoneNumber:{surface:`crud`,semantics:`opt-in`,gatedInputs:[`sys_user.actions.create_user.params.phoneNumber`],notes:`The original #2871 fix. Also read by objectui LoginForm for the phone+password sign-in mode.`},phoneNumberOtp:{surface:`login`,semantics:`opt-in`,exempt:{reason:`Login-surface only: gates the "sign in with verification code" link (LoginForm) and the phone branch of forgot-password. Only advertised when SMS is actually deliverable (#2780).`}}},Yi=Object.keys(Ji);function Xi(e){return`features.${e} ${Ji[e].semantics===`opt-in`?`== true`:`!= false`}`}function Zi(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=Xi(n),a=r.visible;return a===void 0?{...r,visible:{dialect:`cel`,source:i}}:a.dialect!==`cel`||typeof a.source!=`string`?(t.addIssue({code:`custom`,path:[`requiresFeature`],message:"`requiresFeature` composes only with a CEL `visible` carrying a `source` string; this expression is AST-only or non-CEL — write the combined predicate by hand."}),r):{...r,visible:{...a,source:`(${a.source}) && ${i}`}}}var Qi=L({surface:`this action param`,knownKeys:[`name`,`field`,`objectOverride`,`label`,`type`,`required`,`options`,`placeholder`,`helpText`,`defaultValue`,`multiple`,`accept`,`maxSize`,`reference`,`defaultFromRow`,`visible`,`requiresFeature`],aliases:{referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},history:`Until #3405 these were dropped silently — the param still parsed, so a mis-spelled config shipped as a control that quietly ignored it.`}),$i=n(()=>t.z.object({name:t.z.string().optional(),field:E.optional(),objectOverride:E.optional(),label:z.optional(),type:rr.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(t.z.object({label:z,value:t.z.string()})).optional(),placeholder:t.z.string().optional(),helpText:t.z.string().optional(),defaultValue:t.z.unknown().optional(),multiple:t.z.boolean().optional().describe(`Allow multiple values (array value shape); mirrors FieldSchema.multiple.`),accept:t.z.array(t.z.string()).optional().describe(`Accepted upload types (MIME types / extensions) for file/image params.`),maxSize:t.z.number().int().positive().optional().describe(`Max upload size in bytes for file/image params.`),reference:E.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:I.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(Yi).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")},{error:Qi}).strict().refine(e=>!!e.name||!!e.field,{message:`ActionParam requires either "name" or "field"`}).refine(e=>!(!e.field&&(e.type===`lookup`||e.type===`master_detail`)&&!e.reference),{path:[`reference`],message:`ActionParam with type "lookup"/"master_detail" requires "reference" (the target object) when declared inline — without it the param dialog degrades to a raw record-id text input. Set \`reference: '<object>'\`, or use a field-backed param (\`{ field: '<lookup_field>' }\`) to inherit it.`}).transform((e,t)=>Zi(e,t))),ea=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),ta=new Set(ea.options.filter(e=>e!==`script`)),na=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`,`global_nav`]),ra=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),H=`Until #4001 closed this shape these were dropped silently — the action still registered and still ran, without whatever the key was meant to configure or gate.`,ia=R({surface:`this action's AI exposure block`,history:H,aliases:{enabled:`exposed`,enable:`exposed`,aiEnabled:`exposed`,expose:`exposed`,visible:`exposed`,prompt:`description`,toolDescription:`description`,summary:`description`,type:`category`,kind:`category`,toolCategory:`category`,hints:`paramHints`,parameterHints:`paramHints`,params:`paramHints`,returns:`outputSchema`,responseSchema:`outputSchema`,output:`outputSchema`,confirm:`requiresConfirmation`,requireConfirmation:`requiresConfirmation`,hitl:`requiresConfirmation`,humanInTheLoop:`requiresConfirmation`},guidance:{permissions:"AI invocation is not gated by a key here — an agent reaches this action only if a surface-compatible SKILL declares it (ADR-0064), and who may talk to that agent is gated by the agent's `access` / `permissions` (enforced at the chat route since #1884). For a human-approval step on the call itself, use `requiresConfirmation: true`.",approval:"there is no approval workflow key here — `requiresConfirmation: true` forces a human-in-the-loop gate on the AI call. A multi-step business approval is an `approval` metadata item, not an action field."}},{exposed:t.z.boolean().default(!1).describe("Expose this action to AI agents. Requires `description` when true."),description:t.z.string().min(40).optional().describe(`LLM-facing description (≥40 chars). Required when exposed.`),category:ra.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),R({surface:`this AI parameter hint`,history:H,aliases:{desc:`description`,hint:`description`,values:`enum`,options:`enum`,choices:`enum`,allowed:`enum`,example:`examples`,sample:`examples`}},{description:t.z.string().optional(),enum:t.z.array(t.z.union([t.z.string(),t.z.number()])).optional(),examples:t.z.array(t.z.unknown()).optional()})).optional().describe(`Per-parameter AI hints keyed by param name.`),outputSchema:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`JSON Schema for the action return value.`),requiresConfirmation:t.z.boolean().optional().describe(`Override HITL confirmation for AI invocations.`)}),aa=()=>R({surface:`this action`,history:H,aliases:{title:`label`,displayName:`label`,text:`label`,object:`objectName`,entity:`objectName`,actionType:`type`,url:`target`,endpoint:`target`,path:`target`,href:`target`,parameters:`params`,args:`params`,inputs:`params`,fields:`params`,confirm:`confirmText`,confirmation:`confirmText`,confirmMessage:`confirmText`,success:`successMessage`,successText:`successMessage`,toast:`successMessage`,visibleWhen:`visible`,showWhen:`visible`,disabledWhen:`disabled`,style:`variant`,color:`variant`,appearance:`variant`,placement:`locations`,location:`locations`,position:`locations`,verb:`method`,httpMethod:`method`,body:`bodyExtra`,payload:`bodyExtra`,llm:`ai`,tool:`ai`,dialog:`resultDialog`,result:`resultDialog`,refresh:`refreshAfter`,reload:`refreshAfter`,permissions:`requiredPermissions`,capabilities:`requiredPermissions`,requiresPermissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`,acl:`requiredPermissions`},guidance:{hidden:"`hidden` is not an action key, and hiding is not gating — `visible` and `disabled` are UI predicates that hide or grey a button, they do not stop a request. To actually gate invocation use `requiredPermissions` (ADR-0066 D4, enforced with a 403 on the platform action route). To declare an action with no UI surface at all, set `locations: []`.",exposed:"AI exposure lives under `ai` — write `ai: { exposed: true, description: … }`. The description is the LLM-facing contract and is REQUIRED (≥40 chars) whenever exposed.",requiresConfirmation:"the AI human-in-the-loop override lives under `ai` — write `ai: { requiresConfirmation: true }`. `confirmText` is the separate UI confirm prompt."}},{name:E.describe(`Machine name (lowercase snake_case)`),label:z.describe(`Display label`),objectName:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).optional().describe(`Target object this action belongs to. When set, the action is auto-merged into the object's actions array by defineStack().`),icon:t.z.string().optional().describe(`Icon name`),locations:t.z.array(na).optional().describe(`Locations where this action is visible`),component:t.z.enum([`action:button`,`action:icon`,`action:menu`,`action:group`]).optional().describe(`Visual component override`),type:ea.default(`script`).describe(`Action functionality type`),target:t.z.string().optional().describe("URL, Script Name, Flow ID, or API Endpoint. Supports ${param.X} and ${ctx.X} interpolation."),openIn:t.z.enum([`self`,`new-tab`]).optional().describe("For type:'url' — where to open `target`. 'new-tab' opens a new browser tab; 'self' navigates in place. When omitted, external/absolute URLs open in a new tab and relative URLs navigate in place. Static execution option — keep it OUT of `params` (which is user-input-collection only)."),body:qi.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:c("`execute` was removed in @objectstack/spec 17 (#3855) — use `target`. Rename the key; the value (a handler / flow / URL ref) is unchanged. Run `os migrate meta --from 16` to rewrite it automatically."),params:t.z.array($i).optional().describe(`Input parameters required from user`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`link`]).optional().describe(`Button visual variant for styling (primary = highlighted, danger = destructive, ghost = transparent)`),order:t.z.number().optional().describe("Sort order within a location group (lower = higher). Promotes/demotes an action toward the record_header primary button; stable, so actions without `order` keep their registration order."),confirmText:z.optional().describe(`Confirmation message before execution`),successMessage:z.optional().describe(`Success message to show after execution`),errorMessage:z.optional().describe(`Error message to show when the action fails (overrides the raw error).`),refreshAfter:t.z.boolean().default(!1).describe(`Refresh view after execution`),undoable:t.z.boolean().optional().describe(`Offer an Undo affordance after this single-record update action succeeds.`),resultDialog:R({surface:`this result dialog`,history:H,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:z.optional(),description:z.optional(),acknowledge:z.optional().describe(`Acknowledge button label, e.g. "I have saved this"`),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Default format for fields without their own format. Defaults to json when omitted.`),fields:t.z.array(R({surface:`this result dialog field`,history:H,aliases:{key:`path`,field:`path`,name:`path`,title:`label`,display:`format`,render:`format`}},{path:t.z.string().describe(`Dot path into result.data (e.g. "totpURI", "client.client_secret").`),label:z.optional(),format:t.z.enum([`qrcode`,`code-list`,`secret`,`text`,`json`]).optional().describe(`Per-field format override.`)})).optional().describe(`Which fields from result.data to render. Omit to dump full JSON.`)}).optional().describe(`Render API response in a one-shot reveal dialog (suppresses successMessage when set).`),visible:I.optional().describe(`Visibility predicate (CEL).`),requiresFeature:t.z.enum(Yi).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:t.z.union([t.z.boolean(),I]).optional().describe(`Boolean or predicate (CEL) — action is disabled when TRUE.`),requiredPermissions:t.z.array(t.z.string()).optional().describe("[ADR-0066 D4] Capabilities required to invoke this action. Enforced with 403 on the platform action route (script/flow/modal + MCP) and mirrored as a UI hide; a `type: api` action pointed at a custom endpoint must re-check it there."),shortcut:c("`action.shortcut` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never triggered anything: no keydown listener feeds ActionEngine.getShortcuts(), and objectui's keyboard stack (useKeyboardShortcuts) is hand-registered and never consults action metadata. Delete the key. For a real shortcut, register the key in the Console keyboard stack and have its handler invoke the action by name."),bulkEnabled:c("`action.bulkEnabled` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — the multi-select toolbar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, never by this flag, so setting it changed nothing. Delete the key and declare the action in the view's `bulkActions` instead."),ai:ia.optional().describe(`AI exposure (opt-in). Set ai.exposed=true + ai.description to make this callable by agents.`),recordIdParam:t.z.string().optional().describe(`Body key to inject the row id into when running from a list_item context.`),recordIdField:t.z.string().optional().describe(`Row field whose value seeds recordIdParam. Defaults to "id".`),bodyShape:t.z.union([t.z.literal(`flat`),R({surface:`this body shape`,history:H,aliases:{key:`wrap`,under:`wrap`,nest:`wrap`,root:`wrap`}},{wrap:t.z.string()})]).optional().describe(`Body wrapping: flat (default) or { wrap: key } to nest user-collected params under a key.`),method:t.z.enum([`POST`,`PATCH`,`PUT`,`DELETE`]).optional().describe(`HTTP method for type:"api" actions. Defaults to POST.`),bodyExtra:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Constant body fields merged into the API request (applied last; overrides user params).`),mode:t.z.enum([`create`,`edit`,`delete`,`custom`]).optional().describe(`Semantic mode of the action.`),opensInNewTab:t.z.boolean().optional().describe(`Open the action result in a new tab. The renderer pre-opens the tab synchronously on click (popup-blocker-safe) and navigates it to the handler's redirectUrl.`),newTabUrl:t.z.string().optional().describe(`Direct new-tab URL template ({recordId} placeholder). When set with opensInNewTab, the renderer navigates the pre-opened tab here immediately — no action POST. The endpoint must enforce auth itself.`),aria:_r.optional().describe(`ARIA accessibility attributes`),...F}),oa=n(()=>aa().refine(e=>!(ta.has(e.type)&&!e.target),{message:`Action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form'.`,path:[`target`]}).refine(e=>!(e.type===`script`&&!e.body&&!e.target),{message:"A 'script' action requires either an inline `body` (sandboxed L1/L2 handler) or a `target` (a registered bundle function name).",path:[`body`]}).refine(e=>!(e.type!==`script`&&e.body),{message:"`body` only runs for `type: 'script'` — a non-script action dispatches on `target` and silently ignores its body. To collect `params` and then run the body, use `type: 'script'`; to open a page/modal, drop the `body` and keep `type: 'modal'` with `target` naming the page.",path:[`body`]}).refine(e=>!(e.ai?.exposed===!0&&!e.ai.description),{message:`ai.description is required (≥40 chars) when ai.exposed is true.`,path:[`ai`,`description`]}).refine(e=>{let t=e.ai?.paramHints;if(!t)return!0;let n=new Set([`recordId`]);for(let t of e.params??[]){let e=t.name??t.field;e&&n.add(e)}return Object.keys(t).every(e=>n.has(e))},{message:`ai.paramHints keys must match a declared param name (or "recordId").`,path:[`ai`,`paramHints`]}).transform((e,t)=>Zi(e,t)));function sa(e){if(!e||typeof e!=`object`||Array.isArray(e))return e;let t=e,n=t.type===`navigation`,r=t.target===void 0&&typeof t.to==`string`;if(!n&&!r&&!(`to`in t))return e;let i={...t};return n&&(i.type=`url`),r&&(i.target=t.to),delete i.to,i}n(()=>t.z.preprocess(sa,aa().pick({type:!0,name:!0,label:!0,target:!0,openIn:!0,method:!0,params:!0,confirmText:!0,successMessage:!0,errorMessage:!0,refreshAfter:!0,opensInNewTab:!0}).partial({name:!0,label:!0}).refine(e=>!(ta.has(e.type)&&!e.target),{message:"Inline action 'target' is required when type is 'url', 'flow', 'modal', 'api', or 'form' (`to` is accepted as a legacy spelling).",path:[`target`]})));var ca=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),la=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],ua={upsert:"declare ['create','update'] — `upsert` derives from create ∧ update",aggregate:"declare ['list'] — `aggregate` derives from list",history:"declare ['get'] with `enable.trackHistory: true` — `history` derives from get ∧ trackHistory",search:"declare ['list'] (with `searchable` not false) — `search` derives from list ∧ searchable",restore:"delete the value — `restore` never derives (`enable.trash` retired, #2377); it returns only with a real recycle bin (#3146, parked)",purge:"delete the value — `purge` never derives (`enable.trash` retired, #2377)",import:"declare ['create'] and/or ['update'] — `import` derives from create ∨ update (writeMode-precise at the gate)",export:"declare ['list'] — `export` derives from list"},da=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`]),fa=new Set(la),pa=new Set;function ma(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&fa.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&fa.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return pa.has(i)||(pa.add(i),(e=>console.warn(e))(`[spec] enable.apiMethods declares retired legacy value(s) [${n.join(`, `)}] \u2014 the ApiMethod enum is the six primitives get/list/create/update/delete/bulk (#3543). Legacy values are stripped at parse; their semantics are DERIVED from the primitives:
19
19
  `+n.map(e=>` \u2022 \`${e}\`: ${ua[e]}`).join(`
20
20
  `)+(r.length===0?"\n ⚠ After stripping, this whitelist is EMPTY — `[]` means DENY-ALL (fully closed API). Declare the underlying primitives if the object should stay reachable.":``)+`
21
21
  Codemod: node scripts/codemod/apimethods-legacy-to-primitives.mjs`)),r}var ha={trash:"`enable.trash` was removed from @objectstack/spec in the 16.x line (#2377/#3207, ADR-0049) — it never had a runtime consumer: every delete has always been a hard delete, and a default-true flag promising a recycle bin was a false affordance (authors wrote `trash: false` believing they were opting out of a soft-delete that never ran). Delete the key. For recoverability use per-field `trackHistory` (audit trail) or a `lifecycle` policy; soft delete is parked at #3146 and, if built, returns as a live enforced flag (ADR-0049 prune-or-build). Run `os migrate meta --from 16` to rewrite it automatically.",mru:"`enable.mru` was removed from @objectstack/spec in the 16.x line (#2377/#3207, ADR-0049) — Most-Recently-Used tracking was never implemented; no reader existed, so the flag changed nothing. Delete the key. If MRU tracking is built it returns as a live enforced flag (ADR-0049 prune-or-build). Run `os migrate meta --from 16` to rewrite it automatically."},ga=t.z.object({trackHistory:t.z.boolean().default(!1).describe(`Show the record History tab (audit-trail UI). Pair with per-field trackHistory to pick which field diffs are summarized; audit capture itself is always on for compliance`),searchable:t.z.boolean().default(!0).describe(`Index records for global search`),apiEnabled:t.z.boolean().default(!0).describe(`Expose object via automatic APIs`),apiMethods:t.z.preprocess(e=>ma(e),t.z.array(ca)).optional().describe(`Whitelist of allowed API operations (six primitives; undefined = all, [] = none)`),files:t.z.boolean().default(!1).describe(`Generic record Attachments panel (sys_attachment). Opt-in: true surfaces the panel and permits attachments targeting this object; otherwise creation is rejected. Field.file/Field.image are independent`),feeds:t.z.boolean().default(!0).describe(`Record comments/collaboration feed. Default on; explicit false hides the feed UI and rejects new comments for this object`),activities:t.z.boolean().default(!0).describe(`Record activity timeline (sys_activity mirror of CRUD). Default on; explicit false stops mirroring and hides the timeline`),clone:t.z.boolean().default(!0).describe(`Allow record deep cloning`)},{error:e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=t.map(e=>ha[e]??`\`${e}\` is not an \`enable\` capability flag.`);return`Unrecognized key(s) on \`enable\`: ${t.map(e=>`\`${e}\``).join(`, `)}.