@objectstack/console 17.0.0-rc.3 → 17.0.0-rc.4
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.
- package/CHANGELOG.md +74 -1
- package/dist/.objectui-sha +1 -1
- package/dist/assets/{AdapterProvider-Bur-uZKZ.js → AdapterProvider-BJ47DW1h.js} +1 -1
- package/dist/assets/{AiPendingActionsPage-CJwQWg1W.js → AiPendingActionsPage-UIynjb20.js} +1 -1
- package/dist/assets/{ApiConsolePage-D0rZy0lx.js → ApiConsolePage-B7CzUZnr.js} +1 -1
- package/dist/assets/{AppDocsIndex-CQo6tZPY.js → AppDocsIndex-DUsMqAwN.js} +1 -1
- package/dist/assets/{AppManagementPage-jLhhl_WS.js → AppManagementPage-DJ6118-F.js} +1 -1
- package/dist/assets/ApprovalsInboxPage-CTVm3l-x.js +1 -0
- package/dist/assets/AuditLogPage-Riqi0U7P.js +1 -0
- package/dist/assets/{ComponentNavView-4vcZh2oX.js → ComponentNavView-B2otfGZ7.js} +1 -1
- package/dist/assets/CreateViewDialog-z6h6V9xj.js +1 -0
- package/dist/assets/{DashboardView-S5Fshq0v.js → DashboardView-6_sxqUcT.js} +1 -1
- package/dist/assets/{DeveloperHubPage-yTPx0th5.js → DeveloperHubPage-NbNGfp6j.js} +1 -1
- package/dist/assets/{DocShell-BhkelvR8.js → DocShell-DvmmtwpW.js} +1 -1
- package/dist/assets/{ExpressionProvider-BQFSoabd.js → ExpressionProvider-_qLpGaJS.js} +1 -1
- package/dist/assets/FlowRunsPage-ZTpe0n1O.js +1 -0
- package/dist/assets/{IntegrationsPage-BWBfrCWI.js → IntegrationsPage-DMuzWjMr.js} +2 -2
- package/dist/assets/{InterfaceListPage-DcFmVgXg.js → InterfaceListPage-BHcPP_6g.js} +1 -1
- package/dist/assets/{ManagedByBadge-pdWk_Jcc.js → ManagedByBadge-DNLmY8V4.js} +1 -1
- package/dist/assets/{MarketplaceAccessDenied-DDTfnIA8.js → MarketplaceAccessDenied-Drlrrrd9.js} +1 -1
- package/dist/assets/{MarketplaceInstalledPage-Byn6Undk.js → MarketplaceInstalledPage-CYP2CaJz.js} +1 -1
- package/dist/assets/MarketplacePackagePage-DZwFKOQv.js +4 -0
- package/dist/assets/MarketplacePage-XU0PQLAW.js +1 -0
- package/dist/assets/{MetadataInspector-B7LigfJm.js → MetadataInspector-CoxLxxKN.js} +1 -1
- package/dist/assets/{MetadataProvider-D9fSVVZp.js → MetadataProvider-DJXxy8nz.js} +1 -1
- package/dist/assets/ObjectDataPage-CHRZduUP.js +1 -0
- package/dist/assets/PageView-D27Yy4W9.js +1 -0
- package/dist/assets/ProfilePage-09XXYshY.js +1 -0
- package/dist/assets/{PublicFormsPage-C3z0TH0k.js → PublicFormsPage-O8fm4eBn.js} +1 -1
- package/dist/assets/RecordDetailView-aOOCQH95.js +9 -0
- package/dist/assets/RecordFormPage-oqNb9asS.js +1 -0
- package/dist/assets/ReportDefaultInspector-Bo94YiWL.js +3 -0
- package/dist/assets/ReportView-CwCw4i27.js +2 -0
- package/dist/assets/{SearchResultsPage-Ct2q9Lrf.js → SearchResultsPage-I8ngrVdn.js} +1 -1
- package/dist/assets/SettingsHub-BY_utblN.js +1 -0
- package/dist/assets/SettingsView-DNKEl-i-.js +1 -0
- package/dist/assets/{SystemHubPage-BSunYA-X.js → SystemHubPage-WWns1vXN.js} +1 -1
- package/dist/assets/{createDerive-CGF05Hgy.js → createDerive-CsNhKPNT.js} +1 -1
- package/dist/assets/data-adapter-Bh8GerYu.js +32 -0
- package/dist/assets/{drillUrlFilters-BL8PeMrH.js → drillUrlFilters-DHAQHZbx.js} +1 -1
- package/dist/assets/framework-s0wcPYfi.js +8 -0
- package/dist/assets/{getIcon-D3yCrAri.js → getIcon-CQlbi2Hn.js} +1 -1
- package/dist/assets/{highlighted-body-OFNGDK62-DrPiUj_V.js → highlighted-body-OFNGDK62-0kvj_GdK.js} +1 -1
- package/dist/assets/{i18n-DBmEJ9U1.js → i18n-BFepWCa9.js} +1 -1
- package/dist/assets/index-CB0grcA9.js +2 -0
- package/dist/assets/index-DwcytixP.css +2 -0
- package/dist/assets/{infrastructure-PXm1h5tB.js → infrastructure-BKCMsWnH.js} +2 -2
- package/dist/assets/maplibre-gl-shared.mjs +6 -0
- package/dist/assets/maplibre-gl-worker.mjs +6 -0
- package/dist/assets/mermaid-GHXKKRXX-CI_uxHoC.js +1 -0
- package/dist/assets/metadata-admin-CApOhXis.js +25 -0
- package/dist/assets/plugin-calendar-BOjBc2zc.js +1 -0
- package/dist/assets/plugin-charts-Bk48oCaW.js +7 -0
- package/dist/assets/{plugin-chatbot-DmEp7ZGx.js → plugin-chatbot-CEj8h-9I.js} +7 -7
- package/dist/assets/plugin-dashboard-B0k1x0iX.js +6 -0
- package/dist/assets/plugin-form-B_6Tki5r.js +1 -0
- package/dist/assets/plugin-gantt-va3r2kNG.js +63 -0
- package/dist/assets/plugin-grid-C0rE_dCh.js +8 -0
- package/dist/assets/plugin-kanban-BhzMbWNL.js +1 -0
- package/dist/assets/{plugin-map-D0SLy13S.js → plugin-map-zu5SGrw4.js} +1 -1
- package/dist/assets/{plugin-markdown-D7iZb8hK.js → plugin-markdown-BqKwZink.js} +1 -1
- package/dist/assets/plugin-report-DOylY2iS.js +59 -0
- package/dist/assets/{plugin-timeline-C_svagQ1.js → plugin-timeline-sB_LQnGB.js} +1 -1
- package/dist/assets/plugin-tree-CHZ2Wjl4.js +1 -0
- package/dist/assets/plugin-view-DoxfBkwY.js +1 -0
- package/dist/assets/plugins-views-DoZ6BQOM.js +4 -0
- package/dist/assets/{runtime-metadata-persistence-BjYxldgR.js → runtime-metadata-persistence-TwDeIZza.js} +1 -1
- package/dist/assets/{skeletons-C8REUFE6.js → skeletons-BZIrujxl.js} +1 -1
- package/dist/assets/src--uGAhLxY.js +19 -0
- package/dist/assets/{src-E-Ibo9NH.js → src-Boqr2A0h.js} +1 -1
- package/dist/assets/src-t-RiW1Dw.js +1 -0
- package/dist/assets/ui-components-BFOT5Gog.js +72 -0
- package/dist/assets/ui-layout-D4KJD2jH.js +1 -0
- package/dist/assets/{use-book-data-D8LHn21q.js → use-book-data-BIflvfeG.js} +1 -1
- package/dist/assets/useOpenRecordList-CptPt5Mv.js +1 -0
- package/dist/assets/useSettingsLabel-CeykvoQ_.js +1 -0
- package/dist/assets/vendor-objectstack-Dm5CaPeY.js +184 -0
- package/dist/index.html +4 -4
- package/package.json +1 -1
- package/dist/assets/ApprovalsInboxPage-COyyj1KQ.js +0 -1
- package/dist/assets/AuditLogPage-CxGLPqlB.js +0 -1
- package/dist/assets/CreateViewDialog-C6sZGaIB.js +0 -1
- package/dist/assets/FlowRunsPage-DGyj2PBP.js +0 -1
- package/dist/assets/MarketplacePackagePage-DZkqNaao.js +0 -4
- package/dist/assets/MarketplacePage-Dt4ldkBx.js +0 -1
- package/dist/assets/ObjectDataPage-BZ4pf0ji.js +0 -1
- package/dist/assets/PageView-B8qkF17f.js +0 -1
- package/dist/assets/ProfilePage-Do9aTArT.js +0 -1
- package/dist/assets/RecordDetailView-CP1b5rdr.js +0 -9
- package/dist/assets/RecordFormPage-CyAjEE1O.js +0 -1
- package/dist/assets/ReportDefaultInspector-BqgFtk2E.js +0 -3
- package/dist/assets/ReportView-CfQ-Z9TJ.js +0 -2
- package/dist/assets/SettingsHub-C-7kyHtx.js +0 -1
- package/dist/assets/SettingsView-HmY6cAH1.js +0 -1
- package/dist/assets/data-adapter-rnhaIuyx.js +0 -32
- package/dist/assets/framework-UESyszCj.js +0 -8
- package/dist/assets/index-AHnJRZYu.css +0 -2
- package/dist/assets/index-U6sSlA28.js +0 -2
- package/dist/assets/mermaid-GHXKKRXX-DicGABpj.js +0 -1
- package/dist/assets/metadata-admin-Ci8bBNxq.js +0 -25
- package/dist/assets/plugin-calendar-WGoi_n7i.js +0 -1
- package/dist/assets/plugin-charts-CK8c0x6J.js +0 -7
- package/dist/assets/plugin-dashboard-Cz2sTF7I.js +0 -6
- package/dist/assets/plugin-form-D_JAwPGr.js +0 -1
- package/dist/assets/plugin-gantt-BQGs0Vpj.js +0 -63
- package/dist/assets/plugin-grid-CKEYn10A.js +0 -8
- package/dist/assets/plugin-kanban-TdXxukPA.js +0 -1
- package/dist/assets/plugin-report-CPE7yyd4.js +0 -59
- package/dist/assets/plugin-tree-ieUxQVUL.js +0 -1
- package/dist/assets/plugin-view-Dy9ZzWYn.js +0 -1
- package/dist/assets/plugins-views-CJKuyDvq.js +0 -4
- package/dist/assets/src-CSrGzA_t.js +0 -19
- package/dist/assets/src-DzTCerTm.js +0 -1
- package/dist/assets/ui-components-BbC0qTrK.js +0 -72
- package/dist/assets/ui-layout-C3eKqnNJ.js +0 -1
- package/dist/assets/useOpenRecordList-aRVznRXU.js +0 -1
- package/dist/assets/useSettingsLabel-By0A6m6P.js +0 -1
- package/dist/assets/vendor-objectstack-CWf5hLam.js +0 -180
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import{t as e}from"./rolldown-runtime-C0FnF6B9.js";import{Hn as t,Zt as n,_t as r,dn as i,t as a}from"./framework-s0wcPYfi.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(),$icontains:t.z.string().optional().describe(`Contains substring, ignoring case — but ONLY ASCII case (A-Z against a-z). Every other character compares literally, so "café" does NOT match "CAFÉ" and "москва" does not match "МОСКВА". The domain is ASCII because that is the one fold all five backends can deliver: SQLite (and therefore turso and sqlite-wasm) folds ASCII only, so a Unicode promise here would be a guarantee three of the five could not keep. The comparand is matched LITERALLY — "%", "_" and regex metacharacters are ordinary characters, not wildcards. Case-SENSITIVE containment is $contains. [#5701: declared by the protocol; the driver lowerings land with #5702.]`)})),u=n(()=>t.z.object({$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),d=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(),$icontains:t.z.string().optional(),$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),f=t.z.lazy(()=>t.z.record(t.z.string(),t.z.unknown()).and(t.z.object({$and:t.z.array(f).optional(),$or:t.z.array(f).optional(),$not:f.optional()}))),ee=n(()=>t.z.object({where:f.optional()})),p=t.z.lazy(()=>t.z.object({$and:t.z.array(t.z.union([t.z.record(t.z.string(),d),p])).optional(),$or:t.z.array(t.z.union([t.z.record(t.z.string(),d),p])).optional(),$not:t.z.union([t.z.record(t.z.string(),d),p]).optional()})),te={"=":`$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 m(e){return te[e]}var h=new Set(Object.keys(te)),g={$eq:`=`,$ne:`!=`,$gt:`>`,$gte:`>=`,$lt:`<`,$lte:`<=`,$in:`in`,$nin:`nin`,$contains:`contains`,$notContains:`not_contains`,$startsWith:`starts_with`,$endsWith:`ends_with`,$between:`between`};function _(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=m(t);return n?g[n]??t:t}function v(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=>v(e));if(e.length>=2&&typeof e[1]==`string`)return h.has(e[1].toLowerCase())}return e.every(e=>v(e))?e.length>0:!1}function y(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=m(i);return a?{[t]:{[a]:r}}:{[t]:{[`$${i}`]:r}}}function ne(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=>ne(e)).filter(Boolean);return r.length===0?void 0:r.length===1?r[0]:{[n]:r}}if(e.length>=2&&typeof t==`string`)return y(e);if(e.every(e=>Array.isArray(e))){let t=e.map(e=>ne(e)).filter(Boolean);return t.length===0?void 0:t.length===1?t[0]:{$and:t}}}var re=[`and`,`or`],ie=t.z.string().min(1).refine(e=>!re.includes(e.toLowerCase()),{message:`'and' / 'or' in the first position open a logical group, so they cannot name a field. Write the comparison inside the group: ["and", ["field", "=", value]].`}),ae=t.z.string().refine(e=>h.has(e.toLowerCase()),{error:e=>`Unknown filter operator '${String(e.input)}'. Recognised operators: ${[...h].sort().join(`, `)}.`}),b=t.z.string().refine(e=>re.includes(e.toLowerCase()),{message:`A logical group opens with 'and' or 'or'.`}),oe=t.z.lazy(()=>t.z.union([t.z.tuple([ie,ae,t.z.unknown()]),t.z.tuple([ie,ae]),t.z.tuple([b,oe],oe),t.z.array(oe).min(1)]).describe(`Input-only authoring sugar for a filter: [field, operator, value], ["and"|"or", ...conditions], or a bare list of those. Lowered to a FilterCondition at the single sink parseFilterAST (@objectstack/spec/data) the moment it arrives; it is never stored and never travels the wire as an array. A query "where" is a FilterCondition and does not accept this shape (#5158).`)),se=[`$eq`,`$ne`,`$gt`,`$gte`,`$lt`,`$lte`,`$in`,`$nin`,`$between`,`$contains`,`$notContains`,`$startsWith`,`$endsWith`,`$null`,`$exists`],ce=[`$and`,`$or`,`$not`],le=[...se,...ce],x=Object.freeze({$regex:{to:`$icontains`,why:'`$regex` was never declared by the Filter Protocol and is retired (#4706). It could not mean one thing across the backends: driver-sql compiled it to a LIKE-escaped substring match (so "a.b" matched only the literal "a.b"), driver-memory evaluated it as a real RegExp (so it also matched "axb", and an invalid pattern silently matched nothing), and a real regex is not implementable on all five — driver-turso\'s remote transport cannot register a SQLite REGEXP function over its wire protocol. Write `$icontains` for the case-insensitive substring search this was almost always used for (ASCII case fold; the comparand is matched literally, so "." and "%" are ordinary characters), or `$contains` for a case-sensitive one. A pattern that genuinely needs a regex has no filter-level replacement — narrow with the declared operators and match in application code.'},$options:{to:`$icontains`,why:'`$options` was never a predicate — it was the regex-flags companion to `$regex`, which is retired (#4706). Its only real use was `$options: "i"` for a case-insensitive match: write `$icontains` instead, which says that in the operator name and folds ASCII case on every backend. On its own, with no `$regex` beside it, it never constrained anything.'}});function S(e){return t.z.never({error:()=>e}).optional().describe(`[REMOVED] ${e}`)}function ue(e){try{return e()}finally{}}var de=t.z.enum([`none`,`no-overlay`,`no-delete`,`full`]),fe=t.z.enum([`artifact`,`package`,`env-forced`]),pe=t.z.enum([`package`,`org`,`env-forced`]),C={_lock:de.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:fe.optional().describe(`Layer that set _lock (artifact | package | env-forced).`),_provenance:pe.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.`)},me=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)`)),w=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 he=t.z.enum([`cel`,`cron`,`template`]),ge=t.z.object({rationale:t.z.string().optional(),generatedBy:t.z.string().optional()}),T=t.z.object({dialect:he,source:t.z.string().min(1).optional(),ast:t.z.unknown().optional(),meta:ge.optional()}).refine(e=>e.source!==void 0||e.ast!==void 0,{message:"Expression requires at least one of `source` or `ast`"}),E=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cel`,source:e})),T]);t.z.union([t.z.string().min(1).transform(e=>({dialect:`cron`,source:e})),T]);var D=t.z.union([t.z.string().min(1).transform(e=>({dialect:`template`,source:e})),T]),O=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.`}}),_e=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`."}}),ve=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).`}}),ye=Object.freeze([`onEnable`,`functions`]);function be(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function xe(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:Be(s,o,3,1)[0]);a.push({path:`${i}.${s}`,surface:r,key:s,...c?{suggestion:c}:{},...e?.why?{guidance:e.why}:{}})}}function Se(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 Ce=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(`.`)),k=`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.`,we=n(()=>j({surface:`this select option`,history:k,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:me.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:E.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`")})),Te=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`)})),Ee=n(()=>j({surface:`this currency configuration`,history:k,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)`)})),De=n(()=>t.z.object({value:t.z.number().describe(`Monetary amount`),currency:t.z.string().length(3).describe(`Currency code (ISO 4217)`)})),Oe=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`)})),ke=e=>{if(e.code!==`invalid_union`)return;let t=e.input,n=typeof t==`string`?`'${t}'`:String(t);return`Invalid unique scope ${n}. Allowed: true/false, 'organization' (one holder per organization \u2014 the explicit spelling of true), or 'global' (one holder across the whole installation).${t===`tenant`||t===`org`?` ${n} is not accepted and is not an alias \u2014 the per-organization scope is spelled 'organization' (ADR-0120: "tenant" is overloaded across deployment topologies, and the platform spells the word out).`:``}`},Ae=n(()=>t.z.union([t.z.boolean(),t.z.literal(`global`),t.z.literal(`organization`)],{error:ke}));function je(e){return e===`global`}function Me(e){return e===!0||e===`global`||e===`organization`}function Ne(e){return e===`organization`}function Pe(){let e={},t={};for(let[n,r]of Object.entries(O))r.to?e[n]=r.to:r.why&&(t[n]=r.why);return{aliases:e,guidance:t}}var Fe=n(()=>j({surface:`this field`,history:k,aliases:{...Pe().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`,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:{...Pe().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:Ce.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:Ae.default(!1).describe(`Unique constraint and its scope (ADR-0120). 'organization' = one holder per organization (NULL-safe composite with the organization key part on organization-scoped objects) — prefer this explicit spelling in new code; true = same per-organization scope (positional synonym, stays valid); 'global' = one holder across the whole installation. 'tenant'/'org' are rejected — the word is 'organization'`),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(we).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(),j({surface:`this lookup column`,history:k,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(j({surface:`this lookup filter`,history:k,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(),j({surface:`this dependsOn entry`,history:k,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:E.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:j({surface:`this roll-up summary`,history:k,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:f.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:Ee.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:E.optional().describe("Predicate (CEL) — field is shown only when TRUE (else hidden). e.g. P`record.type == 'invoice'`"),readonlyWhen:E.optional().describe("Predicate (CEL) — field is read-only when TRUE. e.g. P`record.status == 'paid'`"),requiredWhen:E.optional().describe("Predicate (CEL) — field is required when TRUE. The only slot; the `conditionalRequired` alias was removed in protocol 17 (#3855)."),conditionalRequired:S("`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`),...C}).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)."})})),Ie={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})},Le=e=>e.toLowerCase().replace(/[_\-\s]/g,``);function Re(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]}var ze=e=>e.toLowerCase().replace(/[-\s]/g,`_`);function Be(e,t,n=3,r=3){let i=ze(e);return t.map(t=>({value:t,distance:Re(i,ze(t)),cased:Re(e,t)})).filter(t=>t.distance<=n&&t.value!==e).sort((e,t)=>e.distance-t.distance||e.cased-t.cased).slice(0,r).map(e=>e.value)}function A(e){let{surface:t,knownKeys:n,guidance:r={},history:i}=e,a={};for(let[t,n]of Object.entries(e.aliases??{}))a[Le(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[Le(e)]??Be(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
|
+
${c.map(e=>` \u2022 ${e}`).join(`
|
|
3
|
+
`)}`),l}}function Ve(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 Ve(n.innerType,t+1);default:return!1}}function j(e,n){let{surface:r,history:i,aliases:a,guidance:o,extraKeys:s=[],retiredForms:c}=e,l;return t.z.object(n,{error:e=>{if(c&&e.code===`invalid_type`){let t=typeof e.input==`string`?c[e.input]:void 0;if(t)return t}return(l??=ue(()=>A({surface:r,knownKeys:[...Object.keys(n).filter(e=>!Ve(n[e])),...s],history:i,aliases:a,guidance:o})))(e)}}).strict()}var He=n(()=>j({surface:`this sort node`,history:"Until #4721 an unknown key here was dropped silently and `order` fell back to its `asc` default, so a descending request came back ascending — and with `limit`, a different set of rows under an ordinary 200.",aliases:{direction:`order`}},{field:t.z.string(),order:t.z.enum([`asc`,`desc`]).default(`asc`)})),Ue=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`array_agg`,`string_agg`]),M=t.z.enum([`day`,`week`,`month`,`quarter`,`year`]),We=n(()=>t.z.union([t.z.string(),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:M.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`)})])),Ge=n(()=>t.z.object({function:Ue.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:f.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.")})),Ke="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`.",qe=t.z.string({error:e=>e.code===`invalid_type`&&typeof e.input==`object`&&e.input!==null&&!Array.isArray(e.input)?Ke:void 0}),Je="`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']`).",Ye='`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.',Xe="`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.",Ze="`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`.",Qe=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).`)})),$e=t.z.object({object:t.z.string().describe(`Object name (e.g. account)`),fields:t.z.array(qe).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:f.optional().describe(`Filtering criteria (WHERE)`),search:t.z.union([t.z.string(),Qe]).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(He).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:S(Ye),joins:S(Je),aggregations:t.z.array(Ge).optional().describe(`Aggregation functions`),groupBy:t.z.array(We).optional().describe("GROUP BY targets (strings or `{field, dateGranularity?}` objects for date bucketing)"),having:f.optional().describe(`HAVING — filter over the AGGREGATED rows (aggregation aliases + groupBy projections); applied engine-side after aggregation`),windowFunctions:S(Ze),distinct:S(Xe)}),N=n(()=>$e.extend({expand:t.z.lazy(()=>t.z.record(t.z.string(),N)).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.")})),et=[{id:`1`,a:`x`,b:`y`,c:`z`,d:`v1`,owner:`u1`,status:`active`,parent_object:`case`,parent_id:`c1`},{id:`2`,a:`x`,b:`zz`,c:`z`,d:`v2`,owner:`u1`,status:`archived`,parent_object:`case`,parent_id:`c2`},{id:`3`,a:`qq`,b:`y`,c:`z`,d:null,owner:`u2`,status:`active`,parent_object:`todo`,parent_id:`t1`},{id:`4`,a:`qq`,b:`zz`,c:`z`,d:null,owner:`u2`,status:`archived`,parent_object:`todo`,parent_id:`c1`}],tt=[{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:`empty $and is TRUE — the AND identity`,filter:{$and:[]},expected:[`1`,`2`,`3`,`4`],note:`#5322: a conjunction of zero conditions constrains nothing.`},{name:`empty $or is FALSE — the OR identity`,filter:{$or:[]},expected:[],note:`#5322/#5134: a disjunction of zero conditions matches nothing. Fail-closed for an RLS scope — a disjunct list that loops to zero items hides every row instead of exposing the table.`},{name:`a {} branch is a TRUE disjunct and absorbs its $or`,filter:{$or:[{a:`x`},{}]},expected:[`1`,`2`,`3`,`4`],note:"#5322: collapsing to the surviving branches instead compiles `a = x` — a silently NARROWED scope (#5297)."},{name:`$not of {} is FALSE — NOT TRUE`,filter:{$not:{}},expected:[],note:`#5322: emitting nothing for it runs the query UNSCOPED — on an RLS lowering that is a permission bypass (#5297).`},{name:`$ne returns the rows with no value`,filter:{d:{$ne:`v1`}},expected:[`2`,`3`,`4`],note:'#5298: "not v1" is true of a row whose d is absent. A three-valued `d <> ?` drops rows 3-4 — half the table, silently.'},{name:`$not returns the rows with no value`,filter:{$not:{d:`v1`}},expected:[`2`,`3`,`4`],note:"#5146: the same ruling reached through the combinator. `NOT (NULL = ?)` is UNKNOWN, so an unguarded negation drops rows 3-4 — and on a CEL `!expr` read scope that is one permission rule admitting different row sets per backend."},{name:`$null true selects exactly the no-value rows`,filter:{d:{$null:!0}},expected:[`3`,`4`],note:`The control for the two above: it pins WHICH rows have no value, so a case that returns 2-4 cannot be passing because the seed lost a value it should have kept.`},{name:`$null false selects exactly the valued rows`,filter:{d:{$null:!1}},expected:[`1`,`2`],note:"The complement, so `$null` is pinned as a partition of the table rather than one half of one. Together with the row-count control this makes a NOT NULL fixture column fail loudly instead of quietly passing everything."},{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.`}],nt=[{id:`1`,name:`ACME Corp`},{id:`2`,name:`acme corp`},{id:`3`,name:`CAFÉ`},{id:`4`,name:`café`},{id:`5`,name:`100% match`},{id:`6`,name:`100X match`},{id:`7`,name:`a_b`},{id:`8`,name:`axb`},{id:`9`,name:`a.b`}],P=[{name:`$icontains matches an upper-case row from a lower-case comparand`,filter:{name:{$icontains:`acme`}},expected:[`1`,`2`],note:`The fold has to run on BOTH sides — comparing a folded comparand against a raw column matches only row 2.`},{name:`$icontains matches a lower-case row from an upper-case comparand`,filter:{name:{$icontains:`ACME`}},expected:[`1`,`2`]},{name:`ASCII-only: a lower-case non-ASCII comparand does NOT match its upper-case row`,filter:{name:{$icontains:`café`}},expected:[`4`],note:`É does not fold to é. Row 3 (CAFÉ) must NOT match. A Unicode-folding backend returns [3,4] and fails here.`},{name:`ASCII-only: an upper-case non-ASCII comparand does NOT match its lower-case row`,filter:{name:{$icontains:`CAFÉ`}},expected:[`3`],note:`The mirror of the case above — the ASCII letters fold, É does not, so exactly one row survives each direction.`},{name:`$icontains treats % as a literal character, not a LIKE wildcard`,filter:{name:{$icontains:`100%`}},expected:[`5`],note:`An unescaped comparand compiles to LIKE '%100%%', which also matches row 6 (100X match).`},{name:`$icontains treats _ as a literal character, not a single-character wildcard`,filter:{name:{$icontains:`a_b`}},expected:[`7`],note:`An unescaped _ matches any one character, so LIKE '%a_b%' also returns rows 8 (axb) and 9 (a.b).`},{name:`$icontains treats . as a literal character, not a regex metacharacter`,filter:{name:{$icontains:`a.b`}},expected:[`9`],note:'This is the `$regex` defect restated as a requirement: on a regex-evaluating backend "a.b" also matched rows 7 and 8.'},{name:`$contains treats _ as a literal character too`,filter:{name:{$contains:`a_b`}},expected:[`7`],note:"The literal-comparand rule is the operator family's, not `$icontains`'s alone."},{name:`$contains is case-SENSITIVE — a lower-case comparand misses the upper-case row`,filter:{name:{$contains:`acme`}},expected:[`2`],note:`Row 1 (ACME Corp) must NOT match. On SQLite/turso today LIKE folds ASCII and returns both.`},{name:`$contains is case-SENSITIVE — an upper-case comparand misses the lower-case row`,filter:{name:{$contains:`ACME`}},expected:[`1`]},{name:`$startsWith is case-SENSITIVE`,filter:{name:{$startsWith:`ACME`}},expected:[`1`]},{name:`$endsWith is case-SENSITIVE`,filter:{name:{$endsWith:`corp`}},expected:[`2`],note:`Row 1 ends with "Corp" — a folding backend returns both and cannot be told apart from a working one by count alone.`},{name:`$notContains is case-SENSITIVE, and negation does not widen it`,filter:{name:{$notContains:`acme`}},expected:[`1`,`3`,`4`,`5`,`6`,`7`,`8`,`9`],note:`Row 1 is EXCLUDED from the negation only if the positive form excluded it — the case rule has to hold under $not too.`},{name:`$regex is REFUSED, and the refusal names $icontains`,filter:{name:{$regex:`ac.*`}},expectRejection:!0,code:`INVALID_FILTER`,mustMention:[`$regex`,`$icontains`],note:"Not `expected: []`. Answering zero rows is what driver-memory already did for an invalid pattern — the silent wrong answer #4706 retired the operator over."},{name:`$regex with $options is REFUSED as one mistake, not two`,filter:{name:{$regex:`^acme`,$options:`i`}},expectRejection:!0,code:`INVALID_FILTER`,mustMention:[`$regex`,`$options`,`$icontains`],note:`The exact shape plugin-auth's adapter can emit, and the one \`$icontains\` replaces one-for-one. #5710 flips that producer BEFORE any backend enrols this case. "One mistake" is about the AUTHOR's fix being single (write $icontains), not about the message naming one key: it must name BOTH retired spellings, or an author who fixes only $regex trips the dangling-$options refusal on the next attempt.`},{name:`a dangling $options with no $regex is REFUSED`,filter:{name:{$options:`i`}},expectRejection:!0,code:`INVALID_FILTER`,mustMention:[`$options`,`$icontains`],note:`It was a modifier, never a predicate: on its own it constrained nothing, so accepting it silently widens.`},{name:`an empty $icontains comparand is REFUSED`,filter:{name:{$icontains:``}},expectRejection:!0,code:`INVALID_FILTER`,mustMention:[`$icontains`],note:"Every row contains the empty substring, so evaluating it is a predicate that constrains nothing — the widening #5240 refused `{ field: {} }` over, one level in."},{name:`a non-string $icontains comparand is REFUSED`,filter:{name:{$icontains:42}},expectRejection:!0,code:`INVALID_FILTER`,mustMention:[`$icontains`],note:`Coercing 42 to "42" would answer a query nobody wrote; the declared comparand type is string.`}],rt=`2026-07-28T12:00:00.000Z`,it=[{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`}],at=[{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."}],ot=[{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`}],st=[{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.`}],ct=[{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`}],lt=[{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}],ut=[{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}],dt=ct.map(e=>e.id),ft=[`today`,`yesterday`,`tomorrow`,`now`],pt=[`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`],mt=[`week_start`,`week_end`,`month_start`,`month_end`,`quarter_start`,`quarter_end`,`year_start`,`year_end`],ht=[...ft,...pt,...mt],gt=/^(\d+)_(minutes?|hours?|days?|weeks?|months?|years?)_(ago|from_now)$/,_t=[`minute`,`hour`,`day`,`week`,`month`,`year`];function vt(e){return ht.includes(e)||gt.test(e)}function yt(e){let t=e.match(gt);if(!t)return null;let n=t[2].replace(/s$/,``);return{n:parseInt(t[1],10),unit:n,direction:t[3]}}var bt=t.z.string().refine(vt,{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: `+_t.join(`, `)}),xt=/^\$?\{([a-zA-Z0-9_]+)\}$/,St=t.z.string().refine(e=>{let t=e.match(xt);return!!t&&vt(t[1])},{message:`Not a recognised {date-macro} placeholder`}),Ct={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 wt(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 Et(new Date(Date.UTC(r,i-1,a)))===t?Et(new Date(Date.UTC(r,i-1,a+1))):null}function Tt(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 wt(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 Et(e){return`${String(e.getUTCFullYear()).padStart(4,`0`)}-${String(e.getUTCMonth()+1).padStart(2,`0`)}-${String(e.getUTCDate()).padStart(2,`0`)}`}var Dt=[`current_user_id`,`current_org_id`];function Ot(e){return Dt.includes(e)}var kt=xt,At=t.z.string().refine(Ot,{message:`Unknown context token. Must be one of: ${Dt.join(`, `)}`}),jt=t.z.string().refine(e=>{let t=e.match(kt);return!!t&&Ot(t[1])},{message:`Not a recognised {context-token} placeholder`}),Mt={current_user_id:"The signed-in user's id (`sys_user.id`).",current_org_id:`The active organization id.`},Nt={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 Pt(e){return Ot(e)||vt(e)}function Ft(e){if(typeof e!=`string`)return null;let t=e.match(kt);if(!t)return null;let n=t[1];return Ot(n)?{kind:`context`,token:n}:vt(n)?{kind:`date-macro`,token:n}:{kind:`unknown`,token:n,suggestion:Nt[n.toLowerCase()]}}var It=`NOW()`,Lt=`current_user`,Rt=[It,Lt],zt={"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 Bt(e){return typeof e==`string`&&/^now\(\)$/i.test(e.trim())}function Vt(e){return e===Lt}function Ht(e){return Bt(e)||Vt(e)}function Ut(e){return Ht(e)&&!Bt(e)}var Wt={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`),...C},Gt=n(()=>j({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`}},{...Wt,type:t.z.literal(`script`),condition:E.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),Kt=n(()=>j({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`}},{...Wt,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.")})),qt=n(()=>j({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`}},{...Wt,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),Jt=n(()=>j({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`}},{...Wt,type:t.z.literal(`cross_field`),condition:E.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.`)})),Yt=n(()=>j({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`}},{...Wt,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`)})),Xt=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[Gt,Kt,qt,Jt,Yt,Zt])),Zt=n(()=>j({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`}},{...Wt,type:t.z.literal(`conditional`),when:E.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:Xt.describe(`Validation rule to apply when condition is true`),otherwise:Xt.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 F=n(()=>t.z.string().describe(`Display label (plain string; i18n keys are auto-generated by the framework)`)),Qt=`Until #4001 closed this shape an unknown key was dropped silently — the component still rendered, with no accessible name and nothing to say the one you wrote had been discarded.`,$t=n(()=>j({surface:`these ARIA attributes`,history:Qt,aliases:{label:`ariaLabel`,describedBy:`ariaDescribedBy`,ariaRole:`role`},guidance:{live:"`live` is objectui's LIST-VIEW-ONLY extension, declared there as `AriaPropsSchema.extend({ live })` and read by `ListView` alone — this shared shape is carried by ~30 renderers and only one of them applies `aria-live`, so declaring it here would advertise a capability the other 29 do not deliver. On an objectui list view the key is valid as-is; anywhere else, drop it. Promoting it into the protocol is #5058.",ariaLabelledBy:"`aria-labelledby` has no counterpart in this protocol — it references another element's id, which is not the same thing as `ariaLabel` (a literal accessible name), so there is nothing to rename it to. Use `ariaLabel` only if a literal string is what you meant. Declaring the referencing form is #5058.",labelledBy:"`aria-labelledby` has no counterpart in this protocol — see `ariaLabelledBy`. Use `ariaLabel` only if a literal accessible name is what you meant; #5058 tracks the gap."}},{ariaLabel:F.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 en=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`)),tn=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:en.optional().describe(`Default number formatting rules`),dateFormat:tn.optional().describe(`Default date/time formatting rules`)}).describe(`Locale configuration`));var nn='`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.',rn=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?nn:void 0}),an=[`language`,`source`],on=[`language`,`source`,`capabilities`,`timeoutMs`,`memoryMb`],sn='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.',cn=A({surface:`this expression (L1) hook body`,knownKeys:an,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${sn}`,timeoutMs:`\`timeoutMs\` ${sn}`,memoryMb:`\`memoryMb\` ${sn}`},history:`Until #4001 these were dropped silently.`}),ln=A({surface:`this sandboxed JS (L2) hook body`,knownKeys:on,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.`}),un=t.z.object({language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)},{error:cn}).strict().describe(`L1 expression body — pure formula, no IO`),dn=t.z.object({language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(rn).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:ln}).strict().describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),fn=t.z.discriminatedUnion(`language`,[un,dn]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),pn={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).`}}},mn=Object.keys(pn);function hn(e){return`features.${e} ${pn[e].semantics===`opt-in`?`== true`:`!= false`}`}function gn(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=hn(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 _n=[`name`,`field`,`objectOverride`,`label`,`type`,`required`,`options`,`placeholder`,`helpText`,`defaultValue`,`multiple`,`accept`,`maxSize`,`reference`,`defaultFromRow`,`visible`,`requiresFeature`],vn={referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},yn=e=>`\`${e}\` is a per-option key of a FIELD's option list (\`SelectOptionSchema\` in \`data/field.zod.ts\`), where the object form and grid do read it. An action param's options are \`{ label, value }\` \u2014 and the action metadata door has always stripped anything else before a renderer could see it, so writing \`${e}\` here has never had an effect. Whether this surface should carry the full per-option vocabulary is #5016; do not rely on it today.`,bn=e=>`no option shape in the spec declares \`${e}\` \u2014 not this one, and not the field-level \`SelectOptionSchema\`. It exists only inside objectui's own \`SelectOptionMetadata\` type, which no metadata path populates. An action param's options are \`{ label, value }\`; drop the key.`,xn=A({surface:`this action param`,knownKeys:_n,aliases:vn,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:w.optional(),objectOverride:w.optional(),label:F.optional(),type:Ce.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(j({surface:`this action param option`,history:`Until #4001 批 14 closed this shape these were dropped silently — the param still rendered its picker, minus whatever the key was meant to colour, gate or disable.`,aliases:{text:`label`,name:`label`,title:`label`,key:`value`,id:`value`,optionValue:`value`,optionLabel:`label`,displayName:`label`},guidance:{color:yn(`color`),visibleWhen:yn(`visibleWhen`),icon:bn(`icon`),disabled:bn(`disabled`),default:"`default` on an OPTION is the field-level picklist default (`SelectOptionSchema.default`). A dialog param defaults through `defaultValue` on the PARAM itself, one level up — write `defaultValue: '<value>'` there."}},{label:F,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:w.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:E.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(mn).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")},{error:xn}).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)=>gn(e,t))),Sn=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),Cn=new Set(Sn.options.filter(e=>e!==`script`)),wn=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`,`global_nav`]),Tn=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),En=`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.`,Dn=j({surface:`this action's AI exposure block`,history:En,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:Tn.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),j({surface:`this AI parameter hint`,history:En,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.`)}),On=()=>j({surface:`this action`,history:En,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`,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:w.describe(`Machine name (lowercase snake_case)`),label:F.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(wn).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:Sn.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:fn.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:S("`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:F.optional().describe(`Confirmation message before execution`),successMessage:F.optional().describe(`Success message to show after execution`),errorMessage:F.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:j({surface:`this result dialog`,history:En,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:F.optional(),description:F.optional(),acknowledge:F.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(j({surface:`this result dialog field`,history:En,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:F.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:E.optional().describe(`Visibility predicate (CEL).`),requiresFeature:t.z.enum(mn).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:t.z.union([t.z.boolean(),E]).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:S("`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:S("`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:Dn.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`),j({surface:`this body shape`,history:En,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:$t.optional().describe(`ARIA accessibility attributes`),...C}),kn=n(()=>On().refine(e=>!(Cn.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)=>gn(e,t)));function An(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(An,On().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=>!(Cn.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 jn=t.z.object({lock:de.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 Mn(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 Nn(e){return/vis|conceal|hidden|show.?when/i.test(e)}var Pn=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(Nn)?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},Fn=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`])),In=n(()=>j({surface:`this chart axis`,history:`Until #4001 an undeclared axis key was dropped at parse and the axis rendered with the default scale and ticks — a chart that looked configured and was not.`,aliases:{name:`field`,key:`field`,dataKey:`field`,column:`field`,value:`field`,label:`title`,text:`title`,caption:`title`,grid:`showGridLines`,showGrid:`showGridLines`,gridLines:`showGridLines`,step:`stepSize`,tickStep:`stepSize`,interval:`stepSize`,log:`logarithmic`,logScale:`logarithmic`,scale:`logarithmic`,minimum:`min`,maximum:`max`,formatter:`format`,numberFormat:`format`,side:`position`,align:`position`}},{field:t.z.string().describe(`Data field key`),title:F.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)})),Ln=n(()=>j({surface:`this chart series`,history:`Until #4001 an undeclared series key was dropped at parse — the series still drew, in the palette colour, on the left axis, unstacked, which is precisely the configuration the author was overriding.`,aliases:{field:`name`,key:`name`,dataKey:`name`,column:`name`,title:`label`,text:`label`,caption:`label`,chartType:`type`,seriesType:`type`,kind:`type`,stackId:`stack`,stackGroup:`stack`,group:`stack`,axis:`yAxis`,yAxisId:`yAxis`,side:`yAxis`,role:`variant`,strokeDasharray:`dashArray`,dashed:`dashArray`,alpha:`opacity`,fillOpacity:`opacity`,strokeOpacity:`opacity`,colour:`color`,fill:`color`,stroke:`color`}},{name:t.z.string().describe(`Field name or series identifier`),label:F.optional().describe(`Series display label`),type:Fn.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`)})),Rn=n(()=>j({surface:`this chart annotation`,history:`Until #4001 an undeclared annotation key was dropped at parse and the reference line drew at the wrong place, in the default style, or not at all — while the annotation itself reported valid.`,aliases:{from:`value`,start:`value`,at:`value`,threshold:`value`,y:`value`,x:`value`,to:`endValue`,end:`endValue`,until:`endValue`,valueEnd:`endValue`,title:`label`,text:`label`,caption:`label`,lineStyle:`style`,strokeStyle:`style`,dash:`style`,colour:`color`,stroke:`color`,fill:`color`,orientation:`axis`,direction:`axis`,kind:`type`,shape:`type`}},{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:F.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),zn=n(()=>j({surface:`this chart interaction block`,history:"Until #4001 an undeclared interaction key was dropped at parse — including the two #3752 removed, so an author who kept writing `zoom` after it was retired got exactly the same silence as before the removal.",aliases:{tooltip:`tooltips`,hover:`tooltips`,showTooltip:`tooltips`,rangeSelector:`brush`,slider:`brush`},guidance:{zoom:"`zoom` was removed in #3752 — no renderer ever had a zoom primitive behind it, and `brush` already narrows the visible range. Write `brush: true`.",clickAction:"`clickAction` was removed in #3752 — a segment click already has owners that work: the host's own `onSegmentClick` in the react tier, `drilldown` on a report (`ReportSchema.drilldown`, ADR-0021 D2, already on by default), and the renderer's segment drill under a dashboard widget's `options` bag. Use one of those."}},{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(()=>j({surface:`this chart drill-down block`,history:"Until #5022 `drillDown` was not declared anywhere in this protocol at all — objectui's ObjectChart read it as an untyped `(schema as any).drillDown`, so every key inside it, right or wrong, reached the renderer unchecked and a misspelling was simply ignored at click time.",aliases:{enable:`enabled`,on:`enabled`,active:`enabled`,where:`filter`,criteria:`filter`,filters:`filter`,label:`title`,heading:`title`,drawerTitle:`title`,display:`target`,open:`target`,openIn:`target`,presentation:`target`,fields:`columns`,columnList:`columns`,select:`columns`,limit:`maxRows`,pageSize:`maxRows`,rowLimit:`maxRows`,max:`maxRows`},guidance:{drilldown:"`drilldown` (all lowercase) is a different capability on a different surface: it is `ReportSchema.drilldown`, a BOOLEAN that switches row/cell drill on a `summary`/`matrix` report (ADR-0021 D2, on by default). The chart's drill-down is `drillDown` (camelCase) and takes a configuration OBJECT. If you meant the chart, fix the capital D; if you meant the report, move the key to the report and write `true`/`false`.",mode:"`mode` (`'filter'` | `'record'`) is a TABLE / PIVOT / METRIC drill key, not a chart one: it chooses whether a click drills through an aggregate to a filtered list or straight to one record. A chart segment is always an aggregate, so a chart drill is always the filtered-list kind and there is nothing to discriminate. Delete the key.",report:"`report` (drill into an analytical report instead of the record list) is a METRIC / PIVOT widget capability in the objectui renderer; `<ObjectChart>` does not read it and renders the record list regardless. Delete the key, or drill from a metric widget instead.",view:"`view` (render a named list view inside the drill drawer) is declared in objectui's renderer-side type as reserved and is read by no renderer at all (objectui#3354). It has never done anything — delete it and use `columns` to choose what the drill list shows.",sort:"`sort` (default ordering for the drill list) is declared in objectui's renderer-side type and read by no renderer (objectui#3354). Delete it; the drill list uses the object's own default ordering."}},{enabled:t.z.boolean().optional().describe(`Turn the segment drill on/off; the block being present already means on, so this is only needed to force it off`),filter:t.z.record(t.z.string(),t.z.unknown()).optional().describe("Filter for the drilled list; values support ${event.*}. Omit to derive it from the clicked category"),title:t.z.string().optional().describe("Drill drawer/dialog heading; supports ${event.*} interpolation"),target:t.z.enum([`drawer`,`dialog`,`navigate`]).optional().describe(`Where the drilled list opens: 'drawer' (default, side sheet), 'dialog' (centered modal), or 'navigate' (skip the in-place view and open the object's full list page; needs host drill navigation, else falls back to 'drawer')`),columns:t.z.array(t.z.string()).optional().describe(`Field names to show as columns in the drilled list (default: the table's own columns)`),maxRows:t.z.number().int().positive().optional().describe(`Rows per page in the drilled list`)})),n(()=>j({surface:`this chart config`,history:`Until #4001 an undeclared chart key was dropped at parse and the chart rendered with the defaults it was written to override — the failure #4001 exists for, on a shape reachable from both the dashboard and report metadata roots.`,aliases:{chartType:`type`,kind:`type`,visualization:`type`,palette:`colors`,colorScheme:`colors`,colours:`colors`,legend:`showLegend`,showLegends:`showLegend`,dataLabels:`showDataLabels`,showLabels:`showDataLabels`,labels:`showDataLabels`,annotation:`annotations`,referenceLines:`annotations`,markers:`annotations`,interactions:`interaction`,interactivity:`interaction`,caption:`subtitle`,subTitle:`subtitle`,accessibility:`aria`,ariaProps:`aria`,plotHeight:`height`,xAxes:`xAxis`,yAxes:`yAxis`},guidance:{width:"`width` is not a chart-level key: a chart fills its container, and the container's width is owned by the dashboard widget's `layout.w` (or the report block). Only `height` is chart-level.",aggregate:"`aggregate` is not part of the chart config. On a DASHBOARD widget the pre-ADR-0021 inline analytics shape was removed — bind a `dataset` and select `dimensions` + `values`. On a react `<ObjectChart>` it is a sibling PROP next to `objectName`, not a key inside the chart config.",objectName:"`objectName` is not part of the chart config — the data binding lives one level up: `dataset` on a dashboard widget (ADR-0021), or the `objectName` PROP on a react `<ObjectChart>`.",dataset:"`dataset` is not part of the chart config — it is the dashboard widget's own key (ADR-0021), a sibling of `chartConfig`, not a key inside it.",data:"`data` is not part of the chart config. Inline/precomputed rows are a react-tier `<ObjectChart data={…}>` prop; a metadata chart gets its rows from the widget's `dataset` binding.",stacked:"`stacked` is not a chart-level key, because stacking is not a chart family: it is a property of the SERIES. Give the series that should stack a shared `series[].stack` group id; series without one are grouped.",axes:"`axes` is not a key — the two axes are declared separately and asymmetrically: `xAxis` is a single axis, `yAxis` is an ARRAY (that is how dual-axis and combo charts are configured).",options:"`options` is not part of the chart config — renderer-only presentation extras belong in the dashboard widget's `options` bag, which is deliberately open for exactly that.",drillDown:"`drillDown` is not part of the chart config — it is a REACT-TIER prop, written beside `objectName`/`aggregate`: `<ObjectChart objectName=\"…\" drillDown={{ columns: ['name'], maxRows: 50 }} />`. On a DASHBOARD widget there is no per-widget drill configuration at all: an ADR-0021 dataset-bound widget drills through the semantic layer (the drill target and filter come from the clicked dataset row), so a `drillDown` written here would parse and then do nothing. On a REPORT the switch is `drilldown` — all lowercase, and a boolean."}},{type:Fn,title:F.optional().describe(`Chart title`),subtitle:F.optional().describe(`Chart subtitle`),description:F.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:In.optional().describe(`X-Axis configuration`),yAxis:t.z.array(In).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(Ln).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(Rn).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:zn.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:$t.optional().describe(`ARIA accessibility attributes`)}));var Bn=n(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),Vn=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:Bn.describe(`Aggregation function`),groupBy:Vn.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 Hn=`Until #4001 closed this shape these were dropped silently — the form still published, without whatever the key was meant to open up, gate or expire.`,Un=n(()=>j({surface:`this sharing config`,history:Hn,aliases:{public:`enabled`,isPublic:`enabled`,shared:`enabled`,active:`enabled`,url:`publicLink`,link:`publicLink`,shareUrl:`publicLink`,shareLink:`publicLink`,slug:`publicLink`,anonymous:`allowAnonymous`,allowGuest:`allowAnonymous`,allowGuests:`allowAnonymous`,publicAccess:`allowAnonymous`,domains:`allowedDomains`,allowedDomain:`allowedDomains`,emailDomains:`allowedDomains`,expires:`expiresAt`,expiry:`expiresAt`,expiration:`expiresAt`,validUntil:`expiresAt`}},{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`)})),Wn=t.z.enum([`update`,`delete`,`custom`]),Gn=t.z.enum([`perRecord`,`aggregate`]),Kn=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:Ce.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:w.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()),qn=A({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)."}),Jn=n(()=>t.z.object({name:w.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:Wn.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:Gn.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(Kn).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:E.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:qn}).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`."})})),Yn=t.z.enum([`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`]).describe("HTTP method — the full routing vocabulary (`api/*` endpoints, router and REST-server routes). The narrower `HttpMethodSubset` is what view data sources may request."),Xn=n(()=>t.z.enum([`GET`,`POST`,`PUT`,`PATCH`,`DELETE`]).describe("HTTP methods a view data source may request — the subset of `HttpMethod` without `HEAD`/`OPTIONS`.")),Zn=n(()=>t.z.object({url:t.z.string().describe(`API endpoint URL`),method:Xn.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(Yn).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 L=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,Qn=n(()=>t.z.discriminatedUnion(`provider`,[j({surface:"this `object` data source",history:L,aliases:{objectName:`object`}},{provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),j({surface:"this `api` data source",history:L,guidance:{url:"Set the URL inside the request block: `read: { url, method }` (or `write: { … }`) — the data source itself declares only `read` / `write`.",method:"Set the method inside the request block: `read: { url, method }` (or `write: { … }`).",fetch:"Use `read` for the fetch request and `write` for the submit request.",submit:"Use `write` for the submit request (and `read` for the fetch request)."}},{provider:t.z.literal(`api`),read:Zn.optional().describe(`Configuration for fetching data`),write:Zn.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),j({surface:"this `value` data source",history:L,aliases:{data:`items`,rows:`items`,records:`items`,values:`items`}},{provider:t.z.literal(`value`),items:t.z.array(t.z.unknown()).describe(`Static data array`)}),j({surface:"this `schema` data source",history:L,aliases:{type:`schemaId`,metadataType:`schemaId`,jsonSchema:`schema`}},{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.`)})])),$n=[`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`],er={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 tr(e){return typeof e!=`string`||$n.includes(e)?e:er[e]??er[e.toLowerCase()]??e}var nr=[`id`],R=[`filter`,`sort`],rr=12,ir="`id` is a console row key (the filter/sort builders stamp a `crypto.randomUUID()` per row for React) — it is not part of the authoring contract, and the write path removes it before validating. Delete it from authored metadata.";function ar(e,t,n){if(n>rr||!e||typeof e!=`object`)return e;if(Array.isArray(e)){let r=!1,i=e.map(e=>{let i=ar(e,t,n+1);return i!==e&&(r=!0),i});return r?i:e}let r=e,i;if(t)for(let e of nr)e in r&&(i??={...r},delete i[e]);for(let[e,t]of Object.entries(i??r)){let a=ar(t,R.includes(e),n+1);a!==t&&(i??={...r},i[e]=a)}return i??e}function or(e){return ar(e,!1,0)}var sr=n(()=>j({surface:`this filter rule`,history:L,guidance:{id:ir}},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(tr,t.z.enum($n)).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`)),cr=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`)),lr=n(()=>j({surface:`this column summary configuration`,history:L},{type:cr.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),ur=n(()=>j({surface:`this column prefix`,history:L},{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`)),dr=n(()=>j({surface:`this list column`,history:L},{field:t.z.string().describe(`Field name (snake_case)`),label:F.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([cr,lr]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:ur.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`)})),fr=n(()=>j({surface:`this selection configuration`,history:L},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),pr=n(()=>j({surface:`this pagination configuration`,history:L},{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`)})),mr=n(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),hr=n(()=>j({surface:`this grouping field`,history:L},{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`)})),gr=n(()=>j({surface:`this grouping configuration`,history:L},{fields:t.z.array(hr).min(1).describe(`Fields to group by (supports up to 3 levels)`)}).describe(`Record grouping configuration`)),_r=n(()=>j({surface:`this gallery configuration`,history:L},{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`)),vr=n(()=>j({surface:`this timeline configuration`,history:L},{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(()=>j({surface:`this view sharing`,history:L},{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`)),br=n(()=>j({surface:`this row color configuration`,history:L},{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`)),xr=n(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),Sr=n(()=>j({surface:`this user actions configuration`,history:L},{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`)),Cr=n(()=>j({surface:`this appearance configuration`,history:L},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array(xr).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),wr=n(()=>j({surface:`this view tab`,history:L},{name:w.describe(`Tab identifier (snake_case)`),label:F.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(sr).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`)),Tr=n(()=>j({surface:`this user filter field`,history:L},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:F.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(j({surface:`this user filter option`,history:L,guidance:{count:"Per-option record counts are computed from the data, not authored. Set `showCount: true` on the filter FIELD to display them."}},{value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Option value`),label:F.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`)),Er=n(()=>j({surface:`these user filters`,history:L},{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(Tr).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(wr).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)`),allowAddTab:t.z.boolean().optional().describe('Render an "add tab" affordance after the presets (tabs element). Page lists only — object views use `listViews` for named presets')}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),Dr=n(()=>j({surface:`this add record configuration`,history:L},{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`)),Or=n(()=>j({surface:`this kanban configuration`,history:L},{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`)})),kr=n(()=>j({surface:`this list chart configuration`,history:L},{chartType:Fn.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:w.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`)),Ar=n(()=>j({surface:`this calendar configuration`,history:L},{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`)})),jr=n(()=>j({surface:`this gantt quick filter`,history:L},{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(),j({surface:`this gantt quick-filter option`,history:L,aliases:{text:`label`,title:`label`,name:`label`,key:`value`,id:`value`}},{value:t.z.union([t.z.string(),t.z.number()]),label:t.z.string().optional()})])).optional().describe(`Explicit option override for fixed enums`)})),Mr=n(()=>j({surface:`this gantt configuration`,history:L},{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(),j({surface:`this gantt tooltip field`,history:L,aliases:{name:`field`,fieldName:`field`,text:`label`,title:`label`}},{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(jr).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()),Nr=n(()=>j({surface:`this tree configuration`,history:L},{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()),Pr=n(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),Fr=n(()=>j({surface:`this navigation configuration`,history:L},{mode:Pr.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.')})),Ir=n(()=>j({surface:`this list view`,history:L},{name:w.optional().describe(`Internal view name (lowercase snake_case)`),label:F.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:Qn.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(dr)]).describe(`Fields to display as columns`),filter:t.z.array(sr).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(j({surface:`this sort entry`,history:L,aliases:{direction:`order`},guidance:{id:ir}},{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:Er.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:fr.optional().describe(`Row selection configuration`),navigation:Fr.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:pr.optional().describe(`Pagination configuration`),kanban:Or.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:Ar.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:Mr.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:_r.optional(),timeline:vr.optional(),chart:kr.optional(),tree:Nr.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:F.optional().describe(`View description for documentation/tooltips`),sharing:yr.optional().describe(`View sharing and access configuration`),rowHeight:mr.optional().describe(`Row height / density setting`),grouping:gr.optional().describe(`Group records by one or more fields`),rowColor:br.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(Jn).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(j({surface:`this conditional formatting rule`,history:L,aliases:{when:`condition`,expression:`condition`,visibleWhen:`condition`,rule:`condition`,styles:`style`,css:`style`},guidance:{color:'Row colouring by field value has its own block — see `rowColor` on this list view. To set a CSS colour from a predicate, put it in `style`: `{ condition, style: { color: "#b91c1c" } }`.'}},{condition:E.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:Sr.optional().describe(`User action toggles for the view toolbar`),appearance:Cr.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(wr).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:Dr.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:j({surface:`this empty state`,history:L,aliases:{description:`message`,text:`message`,subtitle:`message`,heading:`title`,label:`title`,image:`icon`},guidance:{action:'The empty state renders text only. Configure the "add record" entry point in the `addRecord` block on this list view.',button:'The empty state renders text only. Configure the "add record" entry point in the `addRecord` block on this list view.'}},{title:F.optional(),message:F.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:$t.optional().describe(`ARIA accessibility attributes for the list view`),responsive:S("`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:S("`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.")})),Lr=n(()=>t.z.object({field:t.z.string().describe(`Field name (snake_case)`),type:Ce.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(we).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:F.optional().describe(`Display label override`),placeholder:F.optional().describe(`Placeholder text`),helpText:F.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:j({surface:`this record key field`,history:L,aliases:{key:`field`,name:`field`,pattern:`regex`,placeHolder:`placeholder`,help:`helpText`,hint:`helpText`}},{field:t.z.string().default(`name`).describe(`Property name that holds the key inside each item (defaults to "name")`),label:F.optional().describe(`Display label for the key column`),placeholder:F.optional().describe(`Placeholder when entering a new key`),helpText:F.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:E.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:E.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:Pn})),Rr=n(()=>Lr.extend({fields:t.z.array(t.z.lazy(()=>Rr)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(Mn)),zr=n(()=>t.z.object({name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:F.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:E.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms)."),visibleOn:E.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(),Rr]))},{error:Pn}).strict().transform(Mn)),Br=n(()=>j({surface:`this form button configuration`,history:L},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:F.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict()),Vr=n(()=>j({surface:`this form view`,history:L},{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:Qn.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(zr).optional(),groups:t.z.array(zr).optional(),subforms:t.z.array(j({surface:`this subform`,history:L,aliases:{object:`childObject`,childObjectName:`childObject`,child:`childObject`,foreignKey:`relationshipField`,relationField:`relationshipField`,parentField:`relationshipField`,fields:`columns`,label:`title`,sumField:`amountField`,rollupField:`totalField`}},{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:S("`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:Un.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.discriminatedUnion(`kind`,[j({surface:"this `thank-you` submit behavior",history:L,aliases:{heading:`title`,text:`message`,body:`message`,description:`message`}},{kind:t.z.literal(`thank-you`),title:t.z.string().optional(),message:t.z.string().optional()}),j({surface:"this `redirect` submit behavior",history:L,aliases:{delay:`delayMs`,delayMS:`delayMs`,timeout:`delayMs`,to:`url`,href:`url`,target:`url`}},{kind:t.z.literal(`redirect`),url:t.z.string(),delayMs:t.z.number().int().min(0).optional()}),j({surface:"this `continue` submit behavior",history:L,guidance:{title:'The `continue` behavior takes no options — it just resets the form. For a confirmation panel use `{ kind: "thank-you", title, message }`.',message:'The `continue` behavior takes no options — it just resets the form. For a confirmation panel use `{ kind: "thank-you", title, message }`.'}},{kind:t.z.literal(`continue`)}),j({surface:"this `next-record` submit behavior",history:L,guidance:{title:'The `next-record` behavior takes no options — it advances to the next record. For a confirmation panel use `{ kind: "thank-you", title, message }`.',message:'The `next-record` behavior takes no options — it advances to the next record. For a confirmation panel use `{ kind: "thank-you", title, message }`.'}},{kind:t.z.literal(`next-record`)})]).optional().describe(`Post-submit behavior`),buttons:t.z.object({submit:Br.optional().describe(`Submit button`),cancel:Br.optional().describe(`Cancel button`),reset:Br.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:S("`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.`})})})),Hr=n(()=>j({surface:`these object user filters`,history:L,guidance:{tabs:"`tabs` presets are page-only: an object view's tab bar is its saved-view switcher (ViewTabBar), and a second one would collide. Define each preset as a named entry under the object's `listViews` instead — every one renders as a segmented tab.",showAllRecords:'`showAllRecords` configures the page-only `tabs` element. On an object view the default list view already is the "all records" entry; use `listViews` for the named presets beside it.',allowAddTab:"`allowAddTab` configures the page-only `tabs` element. An object view's tab bar is the saved-view switcher (ViewTabBar), which owns its own add control."}},{...Er.omit({tabs:!0,showAllRecords:!0,allowAddTab:!0}).shape,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.')})),Ur=n(()=>Ir.omit({userFilters:!0}).extend({userFilters:Hr.optional()})),Wr=n(()=>j({surface:`this view container`,history:L,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:F.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:Ur.optional(),form:Vr.optional(),listViews:t.z.record(t.z.string(),Ur).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),Vr).optional().describe(`Additional named form views`),protection:jn.optional().describe(`Package author protection block — lock policy for this view.`),...C})),Gr=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>`."),Kr=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),qr=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function Jr(){return{name:Gr,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:F.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:Kr.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:jn.optional().describe(`Package author protection block — lock policy for this view.`),...C}}function Yr(e,n){return{viewKind:t.z.literal(e),config:n,...Jr()}}var Xr={surface:`this view item`,history:L,guidance:{confg:"Did you mean `config`? A ViewItem carries its whole view definition under `config`.",isPinned:"Pinning is per-user Studio state, not authored metadata — the console writes it through the `view` metadata API. Remove it from authored metadata.",sortOrder:"Switcher position is per-user Studio state, not authored metadata — use `order` for the authored default. Remove it from authored metadata."}};n(()=>t.z.discriminatedUnion(`viewKind`,[j(Xr,Yr(`list`,Ir.describe(`List-family view configuration.`))),j(Xr,Yr(`form`,Vr.describe(`Form view configuration.`)))]));function z(){return{isPinned:t.z.boolean().optional().describe(`Studio round-trip: view pinned in the switcher (per-user state, written by the console — not authored).`),sortOrder:t.z.number().int().optional().describe(`Studio round-trip: position within the switcher (per-user state, written by the console — not authored).`)}}var Zr=n(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({...Yr(`list`,Ir.describe(`List-family view configuration.`)),...z()}).strip(),t.z.object({...Yr(`form`,Vr.describe(`Form view configuration.`)),...z()}).strip()]));function Qr(){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:qr.optional().describe(`View family (inherited from the shadowed entry — #2555).`),label:F.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:Kr.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:jn.optional(),...C,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 $r(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.preprocess(or,t.z.union([Zr,Wr.refine($r,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."}),Ir.extend(Qr()).strip(),Vr.extend(Qr()).strip()])));function B(e){let{schemaId:t,...n}=e;return Vr.parse({...n,data:{provider:`schema`,schemaId:t}})}var ei=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),ti=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],ni={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"},ri=[`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],ii=t.z.enum(ri),ai=new Set(ti),oi=new Set;function si(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&ai.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&ai.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return oi.has(i)||(oi.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
|
+
`+n.map(e=>` \u2022 \`${e}\`: ${ni[e]}`).join(`
|
|
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
|
+
Codemod: node scripts/codemod/apimethods-legacy-to-primitives.mjs`)),r}var ci={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."},li=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=>si(e),t.z.array(ei)).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=>ci[e]??`\`${e}\` is not an \`enable\` capability flag.`);return`Unrecognized key(s) on \`enable\`: ${t.map(e=>`\`${e}\``).join(`, `)}.
|
|
7
|
+
`+n.map(e=>` \u2022 ${e}`).join(`
|
|
8
|
+
`)}}).strict(),ui=n(()=>t.z.object({name:t.z.string().optional().describe(`Index name (auto-generated if not provided)`),fields:t.z.array(t.z.string()).describe(`Fields included in the index`),unique:Ae.optional().default(!1).describe("Whether the index enforces uniqueness, and at which scope (ADR-0120). 'global' = materialized over exactly `fields`, no organization column injected — one holder across the whole installation; 'organization' = the driver prepends the NULL-safe organization key part (COALESCE(organization_id, '__global__')) at registration — one holder per organization; bare true = deprecated positional spelling of 'global' (warned in 17.x by lint unique/unscoped-declared-index, rejected at protocol 18, #5082) — state the scope. 'tenant'/'org' are rejected — the word is 'organization'"),type:S("`indexes[].type` was removed in @objectstack/spec 17.0.0 (#5248, ADR-0049) — no driver ever read it. `SqlDriver.syncDeclaredIndexes` creates every declared index through knex's `table.index()` / `table.unique()`, which cannot express an access method, so the value changed no DDL; its `.default('btree')` merely made an inert knob show up in every parse output. Delete the key. The index method is the driver/dialect's decision (Postgres defaults to B-tree; `gin`/`gist`/`fulltext` are dialect-specific and are chosen by a database-layer migration when a workload actually needs one). Run `os migrate meta --from 16` to rewrite it automatically."),partial:S("`indexes[].partial` was removed in @objectstack/spec 17.0.0 (#5248, #4943, ADR-0049) — no driver ever emitted the `WHERE` clause, so a declared partial index was materialized as a FULL index and the predicate silently did nothing. Delete the key. Partial indexes are built at the database layer, not the declaration surface: issue `CREATE [UNIQUE] INDEX … WHERE <predicate>` from a runtime migration (this is what `metadata-protocol`'s `ensureOverlayIndex` already does for `sys_metadata`). Drift detection is unaffected — it reads partiality back from the database's own DDL, never from this key. Run `os migrate meta --from 16` to rewrite it automatically.")})),di={strategy:"`tenancy.strategy` was removed from @objectstack/spec after v15.0 (#2763) — it never had a consumer. The platform has exactly two tenancy modes and neither is object-level config: database-per-tenant isolation is an environment/deployment choice (each environment carries its own database URL), and row-level isolation is `tenancy.enabled` + `tenancy.tenantField`. Delete the key.",crossTenantAccess:"`tenancy.crossTenantAccess` was removed from @objectstack/spec after v15.0 (#2763) — it never had a consumer; setting it granted nothing. Cross-tenant visibility is governed by sharing rules / OWD (ADR-0056), `externalSharingModel` (ADR-0090 D11), and the object access posture. Delete the key."},fi=e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=t.map(e=>di[e]??`\`${e}\` is not a \`tenancy\` key.`);return`Unrecognized key(s) on \`tenancy\`: ${t.map(e=>`\`${e}\``).join(`, `)}. The two supported tenancy modes are: database-per-tenant = environment-level deployment (no object config); row-level isolation = \`tenancy.enabled\` + \`tenancy.tenantField\`.
|
|
9
|
+
`+n.map(e=>` \u2022 ${e}`).join(`
|
|
10
|
+
`)},pi=n(()=>t.z.object({enabled:t.z.boolean().describe(`Enable multi-tenancy for this object`),tenantField:t.z.string().optional().describe("Column this object is tenant-scoped by. Omit it unless the tenant column genuinely is not the platform's: when undeclared the driver falls back to `organization_id`, the kernel-injected column the RLS predicates and `tenantPolicy()` also assume. A declared name is honoured only when the object really has that field — otherwise the same `organization_id` fallback applies. No default is materialized here on purpose (#5315).")},{error:fi}).strict());function mi(e){return e?.tenancy?.enabled===!1}var hi=n(()=>j({surface:"this object's `access` block",history:"Until #4001 these were dropped silently — the block still parsed, so an object the author declared `private` shipped `public`: covered by every `'*'` wildcard grant, with no signal that the posture had been discarded.",aliases:{visibility:`default`,posture:`default`,defaultAccess:`default`},guidance:{sharingModel:"`sharingModel` is the object-wide default record visibility (OWD) and is a TOP-LEVEL object key, not an `access` key — write it beside `access`, not inside it. `access.default` decides wildcard-GRANT coverage; `sharingModel` decides record visibility between users (ADR-0090).",requiredPermissions:"`requiredPermissions` is a TOP-LEVEL object key (ADR-0066 D3) — it gates access on the caller HOLDING a capability, which is a different axis from `access.default` (whether a wildcard grant covers this object at all). Pair them, side by side."}},{default:t.z.enum([`public`,`private`]).default(`public`).describe(`Default exposure posture: public (covered by wildcard grants) | private (needs explicit grant; exempt from wildcard RLS).`)})),gi=t.z.object({read:t.z.array(t.z.string()).optional().describe(`Capabilities required to read (find/findOne/count/aggregate).`),create:t.z.array(t.z.string()).optional().describe(`Capabilities required to create (insert).`),update:t.z.array(t.z.string()).optional().describe(`Capabilities required to update (update/transfer/restore).`),delete:t.z.array(t.z.string()).optional().describe(`Capabilities required to delete (delete/purge).`)}).strict(),_i=t.z.union([t.z.array(t.z.string()),gi]),V=t.z.enum([`record`,`audit`,`telemetry`,`transient`,`event`]),vi=/^\d+(h|d|w|y)$/,yi=e=>t.z.string().regex(vi,`${e} must be a duration literal like '6h', '14d', '12w' or '7y'`),bi=n(()=>j({surface:"this object's `lifecycle` block",history:`Until #4001 these were dropped silently — the block still parsed, so a bounding policy written one level too high left the object with NO policy at all. ADR-0057 §3.5's own refine then passed, because the key it looks for was never there.`,aliases:{rotation:`storage`},guidance:{maxAge:"`maxAge` belongs to the retention block, one level down: `retention: { maxAge: '30d' }`. Written here it is not read, and a non-`record` class with no `retention`/`ttl`/`storage` is rejected as unbounded (ADR-0057 §3.5).",expireAfter:"`expireAfter` belongs to the TTL block, one level down: `ttl: { field: 'expires_at', expireAfter: '1d' }`.",field:"`field` belongs to the TTL block, one level down — it names the timestamp the TTL is measured from: `ttl: { field: 'expires_at', expireAfter: '1d' }`.",after:"`after` belongs to the archive block, one level down: `archive: { after: '7y', to: 'cold_store' }` — and ADR-0057 requires it to EQUAL `retention.maxAge`.",to:"`to` belongs to the archive block, one level down — it names the cold-storage datasource: `archive: { after: '7y', to: 'cold_store' }`.",keep:"`keep` belongs to the archive block, one level down — it is how long COLD rows are kept. The HOT window is `retention.maxAge`.",strategy:"`strategy` belongs to the storage block, one level down: `storage: { strategy: 'rotation', shards: 7, unit: 'day' }`.",shards:"`shards` belongs to the storage block, one level down: `storage: { strategy: 'rotation', shards: 7, unit: 'day' }`.",unit:"`unit` belongs to the storage block, one level down: `storage: { strategy: 'rotation', shards: 7, unit: 'day' }`."}},{class:V.describe(`Persistence contract: record (business truth, permanent) | audit (compliance ledger) | telemetry (high-freq log) | transient (ephemeral state) | event (bus messages).`),retention:j({surface:"this object's `lifecycle.retention` block",history:`Until #4001 these were dropped silently — the retention window still parsed, so a row filter written under the wrong key reaped rows the author had meant to exempt.`,aliases:{filter:`onlyWhen`,where:`onlyWhen`,when:`onlyWhen`,age:`maxAge`},guidance:{expireAfter:"`expireAfter` is a `ttl` key, not a retention key. Retention reaps by AGE from `created_at` (`maxAge`); TTL expires each row relative to a timestamp field you name (`ttl.field`). Pick the one that matches how the rows die.",keep:"`keep` is an `archive` key — how long COLD rows survive. The hot window is `retention.maxAge`."}},{maxAge:yi(`retention.maxAge`).describe("Rows older than this (by created_at) are deleted by the Reaper — or archived first when `archive` is set."),onlyWhen:t.z.record(t.z.string(),t.z.union([t.z.string(),t.z.number(),t.z.boolean(),t.z.object({$in:t.z.array(t.z.union([t.z.string(),t.z.number()])).min(1)}).strict()])).optional().describe(`Row filter the retention applies to — per-field equality or {$in: [...]} (e.g. { status: { $in: ["completed", "failed"] } }). Rows OUTSIDE the filter are retained regardless of age: for tables that interleave live workflow state with terminal history (sys_automation_run). Incompatible with rotation storage and archive, which act on whole shards / age alone.`)}).optional().describe(`Age-based retention window enforced by the LifecycleService Reaper.`),ttl:j({surface:"this object's `lifecycle.ttl` block",history:`Until #4001 these were dropped silently — the TTL block still parsed, so rows the author expected to auto-expire lived forever.`,aliases:{expiresAfter:`expireAfter`,after:`expireAfter`,timestampField:`field`,on:`field`},guidance:{maxAge:"`maxAge` is a `retention` key, not a TTL key. TTL measures from the timestamp field named in `ttl.field`; retention measures AGE from `created_at`. For age-based reaping write `retention: { maxAge: '30d' }` instead."}},{field:t.z.string().describe(`Timestamp field the TTL is measured from (e.g. created_at, expires_at).`),expireAfter:yi(`ttl.expireAfter`).describe("Rows expire this long after `field` and are deleted by the Reaper.")}).optional().describe(`Per-row TTL auto-expiry (transient/event classes).`),storage:j({surface:"this object's `lifecycle.storage` block",history:`Until #4001 these were dropped silently — the rotation block still parsed, so a telemetry table declared as rotating kept every shard it ever cut.`,aliases:{count:`shards`,interval:`unit`,period:`unit`,granularity:`unit`},guidance:{maxAge:"`maxAge` is a `retention` key. Rotation does not reap by age — it retains `shards` × `unit` of history and DROPs the oldest shard whole. Set the window with `shards`/`unit`, or use `retention` instead of rotation."}},{strategy:t.z.literal(`rotation`).describe(`Time-shard the table; rotate by DROPping the oldest shard (O(1) reclaim).`),shards:t.z.number().int().min(2).describe(`Number of shards retained; total window = shards × unit.`),unit:t.z.enum([`day`,`week`,`month`]).describe(`Time width of one shard.`)}).optional().describe(`Physical storage strategy for high-frequency telemetry (LifecycleService Rotator).`),archive:j({surface:"this object's `lifecycle.archive` block",history:`Until #4001 these were dropped silently — the archive block still parsed, so audit rows were reaped hot with no cold copy ever written.`,aliases:{datasource:`to`,target:`to`,destination:`to`,retain:`keep`},guidance:{maxAge:"`maxAge` is a `retention` key. The archive boundary is `archive.after`, and ADR-0057 requires the two to be EQUAL — the hot window ends exactly where the archive begins, so declare `retention.maxAge` and `archive.after` with the same value."}},{after:yi(`archive.after`).describe(`Rows older than this are copied to the archive datasource before hot deletion.`),to:t.z.string().describe(`Target datasource name for cold storage. When it is not registered, the Archiver skips (audit rows are then retained, never dropped unarchived).`),keep:yi(`archive.keep`).optional().describe(`How long archived rows are kept in cold storage (undefined = forever).`)}).optional().describe(`Cold-store archival (LifecycleService Archiver) — audit-class hot→cold hand-off.`),reclaim:t.z.boolean().optional().describe(`Run driver space reclamation (SQLite incremental_vacuum) after sweeping this object. Default true for non-record classes.`)}).superRefine((e,n)=>{e.class!==`record`&&!e.retention&&!e.ttl&&!e.storage&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.class '${e.class}' requires at least one bounding policy: retention, ttl, or storage (rotation) \u2014 ADR-0057 \xA73.5`}),e.class===`record`&&(e.retention||e.ttl||e.storage||e.archive)&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.class 'record' is permanent business truth — retention/ttl/storage/archive policies are not allowed on it (ADR-0057 §3.1)`}),e.archive&&e.retention&&e.archive.after!==e.retention.maxAge&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.archive.after ('${e.archive.after}') must equal retention.maxAge ('${e.retention.maxAge}') \u2014 the hot window ends where the archive begins`}),e.retention?.onlyWhen&&e.storage?.strategy===`rotation`&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.retention.onlyWhen cannot be combined with rotation storage — the Rotator DROPs whole shards and would destroy rows the filter protects`}),e.retention?.onlyWhen&&e.archive&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.retention.onlyWhen cannot be combined with archive — the Archiver moves rows by age alone and would archive rows the filter protects`})})),xi=n(()=>j({surface:`this field group`,history:`Until #4001 these were dropped silently — the group still parsed AND still rendered, which is the worst version of the failure: the section appeared, so the author had every reason to believe the setting they wrote had been applied.`,aliases:{title:`label`,name:`key`,id:`key`,help:`description`,helpText:`description`},guidance:{fields:"`fields` does not live on a group — membership is declared on the FIELD, pointing back: `fields: { email: { type: 'email', group: 'contact_info' } }`. The group declares only its `key`, `label` and presentation; `deriveFieldGroupLayout` (ADR-0085 §5) does the assembly.",order:"`order` is not a group key — ARRAY ORDER is display order. `fieldGroups: [...]` renders top to bottom, so move the entry rather than numbering it.",expanded:"`expanded` is not a group key — use the `collapse` enum: `collapse: 'expanded'` (collapsible, starts open), `'collapsed'` (starts closed), or `'none'` (always open, no toggle).",visibleWhen:"`visibleWhen` was REMOVED from field groups (ADR-0085 / ADR-0049 enforce-or-remove) — it existed here briefly with no consumer on any surface, so it never gated anything. Gate the individual fields, or assign a Page for per-surface control.",visibleOn:"`visibleOn` is not a field-group key — group-level visibility predicates were removed under ADR-0085 / ADR-0049 (nothing evaluated them). Gate the individual fields, or assign a Page."}},{key:t.z.string().regex(/^[a-z_][a-z0-9_]*$/,{message:`Field group key must be lowercase snake_case (e.g., "contact_info", "billing", "system")`}).describe(`Group machine key (snake_case). Referenced by Field.group.`),label:t.z.string().describe(`Group display label`),icon:t.z.string().optional().describe(`Icon name (Lucide/Material) for the group header`),description:t.z.string().optional().describe(`Optional description shown under the group header`),collapse:t.z.enum([`none`,`expanded`,`collapsed`]).optional().default(`none`).describe(`[ADR-0085] Section collapse behaviour: 'none' (always open, no toggle), 'expanded' (collapsible, starts open), 'collapsed' (collapsible, starts closed).`),defaultExpanded:t.z.boolean().optional().describe(`[DEPRECATED → collapse] true → 'expanded', false → 'collapsed'.`),collapsible:t.z.boolean().optional().describe("[DEPRECATED → collapse] Boolean pair with `collapsed`; use the `collapse` enum."),collapsed:t.z.boolean().optional().describe("[DEPRECATED → collapse] Boolean pair with `collapsible`; use the `collapse` enum.")})),Si=j({surface:"this object's `external` binding (ADR-0015)",history:`Until #4001 these were dropped silently — the binding still parsed, so a federated object bound to the wrong remote table, or shipped read-only after the author had explicitly asked for writes.`,aliases:{table:`remoteName`,tableName:`remoteName`,remoteTable:`remoteName`,schema:`remoteSchema`,columns:`columnMap`,skipColumns:`ignoreColumns`,excludeColumns:`ignoreColumns`},guidance:{allowWrites:"`allowWrites` is the DATASOURCE-level gate (`datasource.external.allowWrites`). The per-object opt-in is spelled `writable: true`. ADR-0015 requires BOTH — set `writable` here and `allowWrites` on the datasource; either one alone leaves the object read-only.",schemaMode:"`schemaMode` is a DATASOURCE key, not an object key — an object becomes external by being routed to a datasource whose `schemaMode !== 'managed'`. This block only describes the remote binding once that is true."}},{remoteName:t.z.string().optional().describe(`Remote table/view name. Defaults to object.name.`),remoteSchema:t.z.string().optional().describe(`Remote schema/database qualifier.`),writable:t.z.boolean().default(!1).describe(`Per-object write opt-in (also requires datasource.external.allowWrites).`),columnMap:t.z.record(t.z.string(),t.z.string()).optional().describe(`Remote column name → local field name.`),introspectedAt:t.z.string().datetime().optional().describe("Set by `os datasource introspect`; informational."),ignoreColumns:t.z.array(t.z.string()).optional().describe(`Remote columns to skip during validation (dev convenience).`)}).describe(`External datasource binding (ADR-0015)`),Ci=t.z.object({enabled:t.z.boolean().optional().describe(`Object-level on/off for the generic affordance; same meaning as the bare boolean form. Omitted → managedBy bucket default.`),visibleWhen:E.optional().describe(`Per-record CEL predicate; false → hide the row button for that record. Fail-closed.`),disabledWhen:E.optional().describe(`Per-record CEL predicate; true → render the row button disabled for that record. Fail-soft.`)}).strict().describe(`Boolean-or-predicates override for a built-in row CRUD affordance.`),wi,Ti=e=>(wi??=A({surface:`this object`,knownKeys:Object.keys(Di.shape),aliases:{capabilities:`enable`,features:`enable`},guidance:ki,history:"Until #4001 closed this shape these were dropped silently on the PARSE path — `ObjectSchema.create()` has rejected them since #1535, but `defineStack({ objects })`, `/api/v1/meta/types/object` and the Studio form all go through `parse()`, which did not."}))(e),Ei="`object.managedBy: 'system'` was removed in @objectstack/spec 17 (#3355, ADR-0103 v17 addendum) — v16 moved every engine-owned object to `engine-owned`, leaving `system` labelling admin/user-writable platform DATA under a name that says the opposite. Use `managedBy: 'system-data'` (platform-defined schema, admin/user-writable data; authz stays the DelegatedAdminGate / RLS / permission sets). Rename the value; nothing else about the object changes. Note `system-data` defaults to FULL CRUD affordances (the old `system` default was locked), so a `userActions` block that existed only to re-open create/edit/delete is now redundant and can be deleted — keep it only to NARROW. Run `os migrate meta --from 16` to rewrite it automatically.",Di=t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Machine unique key (snake_case). Immutable.`),label:t.z.string().optional().describe(`Human readable singular label (e.g. "Account")`),pluralLabel:t.z.string().optional().describe(`Human readable plural label (e.g. "Accounts")`),description:t.z.string().optional().describe(`Developer documentation / description`),icon:t.z.string().optional().describe(`Icon name (Lucide/Material) for UI representation`),isSystem:t.z.boolean().optional().default(!1).describe(`Is system object (protected from deletion; defaults its org-wide sharing to public when no sharingModel is set — plugin-sharing)`),managedBy:t.z.enum([`platform`,`config`,`system-data`,`engine-owned`,`append-only`,`better-auth`],{error:e=>e.input===`system`?Ei:void 0}).optional().describe(`Lifecycle bucket — platform (user CRUD) | config (admin authored) | system-data (platform-defined schema, admin/user-writable data) | engine-owned (engine owns the lifecycle, no user writes) | append-only (audit) | better-auth (identity). UI clients honour the resolved affordance matrix.`),ownership:t.z.enum([`user`,`org`,`none`],{error:"`ownership` is the record-ownership model — one of 'user' (default) | 'org' | 'none'. The package-contribution kind 'own'/'extend' is set via registerObject, not on the object schema."}).optional().describe(`Record-ownership model: user (default — injects reassignable owner_id) | org | none (no per-record owner, skips owner_id). Distinct from the package own/extend contribution kind.`),userActions:j({surface:"this object's `userActions` block",history:"Until #4001 these were dropped silently — the block still parsed, so an affordance the author meant to hide stayed on the toolbar, and the `managedBy`-derived default silently won.",aliases:{export:`exportCsv`,csvExport:`exportCsv`,exportcsv:`exportCsv`,new:`create`,add:`create`,insert:`create`,update:`edit`,remove:`delete`,destroy:`delete`},guidance:{sort:"`sort` is a VIEW `userActions` key, not an object one — the two blocks share a name and nothing else. The object block governs CRUD affordances (create/import/edit/delete/exportCsv); toolbar controls (sort/search/filter/refresh/rowHeight/editInline) live on the view.",search:"`search` is a VIEW `userActions` key. This object block governs CRUD affordances only — put toolbar controls on the view that renders the records.",filter:"`filter` is a VIEW `userActions` key. This object block governs CRUD affordances only — put toolbar controls on the view that renders the records.",editInline:"`editInline` is a VIEW `userActions` key. The object-level `edit` flag decides whether editing is offered AT ALL; how it is offered (inline vs form) is the view's call.",clone:"`clone` is a CAPABILITY, not a user action — write `enable: { clone: false }`. The `enable` block (ObjectCapabilities) is where record deep-cloning is governed.",read:"`userActions` toggles WRITE affordances only; there is no read toggle. Read access is governed by permissions (`requiredPermissions`) and `access.default`.",view:"`userActions` toggles WRITE affordances only; there is no view toggle. Visibility is governed by permissions (`requiredPermissions`) and `access.default`."}},{create:t.z.boolean().optional().describe(`Show generic "New" button.`),import:t.z.boolean().optional().describe(`Show CSV import wizard entry.`),edit:t.z.union([t.z.boolean(),Ci]).optional().describe(`Allow inline / form edit of existing rows. Boolean, or an object adding per-record visibleWhen/disabledWhen CEL predicates.`),delete:t.z.union([t.z.boolean(),Ci]).optional().describe(`Show row-level delete + bulk delete. Boolean, or an object adding per-record visibleWhen/disabledWhen CEL predicates.`),exportCsv:t.z.boolean().optional().describe(`Show CSV export entry.`)}).optional().describe(`Per-object override of the resolved CRUD affordance matrix.`),systemFields:t.z.union([t.z.literal(!1),j({surface:"this object's `systemFields` block",history:`Until #4001 these were dropped silently — the block still parsed, so an opt-out the author wrote had no effect and the registry injected the column anyway.`,aliases:{organization:`tenant`,org:`tenant`,tenancy:`tenant`,organizationId:`tenant`,auditFields:`audit`,timestamps:`audit`},guidance:{owner:"`owner` is not a `systemFields` key — `owner_id` injection is governed by the object-level `ownership` property (`ownership: 'none'` skips it; `'user'`/`'org'` choose the principal). `systemFields` controls only `tenant` (organization_id) and `audit` (created_at/created_by/updated_at/updated_by).",ownership:"`ownership` is a TOP-LEVEL object key, not a `systemFields` key — write it beside `systemFields`. It, not this block, decides whether `owner_id` is injected."}},{tenant:t.z.boolean().optional().describe(`Inject the organization_id column. Default true (the column is always provisioned; the multi-tenant flag governs only its index).`),audit:t.z.boolean().optional().describe(`Inject the audit columns (created_at/created_by/updated_at/updated_by). Default true.`)})]).optional().describe(`Opt out of, or selectively disable, registry-level system-field auto-injection.`),datasource:t.z.string().optional().default(`default`).describe(`Target Datasource ID. "default" is the primary DB.`),external:Si.optional().describe(`Remote table binding for federated (external) objects.`),fields:t.z.record(t.z.string().regex(/^[a-z_][a-z0-9_]*$/,{message:`Field names must be lowercase snake_case (e.g., "first_name", "company", "annual_revenue")`}),Fe).describe(`Field definitions map. Keys must be snake_case identifiers.`),indexes:t.z.array(ui).optional().describe(`Database performance indexes`),fieldGroups:t.z.array(xi).refine(e=>new Set(e.map(e=>e.key)).size===e.length,{message:`fieldGroups[].key must be unique within an object`}).optional().describe(`Ordered list of field groups (array order = display order). See ObjectFieldGroupSchema.`),tenancy:pi.optional().describe(`Multi-tenancy configuration for SaaS applications`),access:hi.optional().describe(`[ADR-0066 D2] Object exposure posture (public-by-default vs private secure-by-default).`),requiredPermissions:_i.optional().describe("[ADR-0066 D3/⑤] Capabilities required to access this object (AND-gate) — `string[]` gates all CRUD, or a `{read,create,update,delete}` map gates per operation."),lifecycle:bi.optional().describe(`Data lifecycle contract (ADR-0057): class + retention/ttl/rotation/archive policies enforced by the platform LifecycleService.`),fileAccessDelegate:t.z.string().optional().describe(`Kernel service that authorizes downloads of files owned by this object's media fields, instead of testing whether the caller can read the owning row. For objects whose access is mediated by a service (e.g. sys_approval_action → approvals). Fails closed.`),validations:t.z.array(Xt).optional().describe(`Object-level validation rules`),activityMilestones:t.z.array(j({surface:`this activity milestone`,history:`Until #4001 these were dropped silently — the milestone still parsed, so a mis-keyed template shipped a timeline row with the wrong text, or the milestone never fired at all.`,aliases:{message:`summary`,template:`summary`,text:`summary`,title:`summary`,to:`value`,watch:`field`,activityType:`type`},guidance:{from:"`from` is not a milestone key — a milestone fires on transition INTO `value`, whatever the previous value was. There is no from-state filter here; when the TRANSITION itself must be constrained, declare a `state_machine` rule in `validations` (ADR-0020), which is where the legal transition table lives.",when:"`when` is not a milestone key — the trigger is structural: `field` transitions INTO `value`. For a conditional timeline row, gate it with a `state_machine` rule in `validations` or a hook."}},{field:t.z.string().describe(`Field to watch (typically a status/stage select).`),value:t.z.string().describe(`The value the field must transition INTO to fire the milestone.`),summary:t.z.string().describe(`Activity summary template; {field} tokens interpolate the record value. e.g. "Deal won: {name}".`),type:t.z.string().optional().describe(`Activity type for the emitted row (default "completed").`)})).optional().describe(`Declarative semantic activity milestones — emit a templated timeline row when a field transitions into a value, no hook code (ADR-0052 §5b.2).`),nameField:t.z.string().optional().describe(`[ADR-0079] Canonical primary title field — the stored field used as the record display name (e.g. "name", "title").`),displayNameField:t.z.string().optional().describe(`[DEPRECATED → nameField] Field to use as the record display name (e.g., "name", "title"). Accepted as an alias for nameField.`),titleFormat:D.optional().describe(`[DEPRECATED → nameField (ADR-0079)] Render-only title template; the server cannot return or query it, and an explicit nameField now takes precedence. Migrate a single-field title to nameField, a composite to a formula field designated as nameField.`),highlightFields:t.z.array(t.z.string()).optional().describe(`[ADR-0085] Ordered most-important fields; first entry wins where only one fits. Drives default columns, cards, previews, detail highlight strip. Renamed from compactLayout.`),stageField:t.z.union([t.z.string(),t.z.literal(!1)]).optional().describe(`[ADR-0085] Lifecycle stage field (linear/ordered), or false to declare the status field non-linear and suppress stage heuristics. Absent = heuristic detection allowed.`),listViews:t.z.record(t.z.string(),Ur).optional().describe(`Built-in named list views (segmented tabs) shipped with the object schema — "views" mode, dropdown userFilters allowed, no page-only tabs (ADR-0047)`),searchableFields:t.z.array(t.z.string()).optional().describe("Fields the `$search` query matches against (ADR-0061). Canonical default for the record picker, list quick-search and global search; views may narrow it. When unset, search auto-defaults to the name/title field plus short-text fields."),enable:li.optional().describe(`Enabled system features modules`),sharingModel:t.z.enum([`private`,`public_read`,`public_read_write`,`controlled_by_parent`]).optional().describe(`Org-Wide Default record visibility (OWD) for INTERNAL users. Canonical four only (legacy aliases removed, ADR-0090 D4): private (owner-only) | public_read (everyone reads, owner writes) | public_read_write (everyone reads+writes) | controlled_by_parent (derived from the master record). A CUSTOM object that omits this resolves to private at runtime (ADR-0090 D1).`),externalSharingModel:t.z.enum([`private`,`public_read`,`public_read_write`,`controlled_by_parent`]).optional().describe(`[ADR-0090 D11] OWD for external (portal/partner) principals. Defaults to private; must be <= sharingModel in openness.`),publicSharing:j({surface:"this object's `publicSharing` policy",history:`Until #4001 these were dropped silently — the policy still parsed, so a redaction list or an expiry cap the author wrote was never applied to the links the platform went on to issue. On a policy whose whole job is to be restrictive, a silently dropped key fails OPEN.`,aliases:{audiences:`allowedAudiences`,permissions:`allowedPermissions`,redact:`redactFields`,redacted:`redactFields`,maxExpiry:`maxExpiryDays`,expiryDays:`maxExpiryDays`,condition:`eligibility`},guidance:{sharingModel:"`sharingModel` governs PRINCIPAL-based sharing (specific users / teams / roles) and is a TOP-LEVEL object key, not a `publicSharing` key. `publicSharing` is the separate opt-in for opaque share LINKS — an object may declare both, and they do not constrain each other.",externalSharingModel:"`externalSharingModel` is a TOP-LEVEL object key (ADR-0090 D11) — the OWD for external portal/partner principals. Link sharing is this block; principal-based external access is that key, one level up."}},{enabled:t.z.boolean().default(!1).describe(`Allow records of this object to be published via share link`),allowedAudiences:t.z.array(t.z.enum([`public`,`link_only`,`signed_in`,`email`])).optional().describe(`Audiences callers may select when creating a link`),allowedPermissions:t.z.array(t.z.enum([`view`,`comment`,`edit`])).optional().describe(`Permission levels selectable on the share dialog`),maxExpiryDays:t.z.number().int().positive().optional().describe(`Reject links with expiry beyond this many days`),redactFields:t.z.array(t.z.string()).optional().describe(`Field names removed from records served via a share token`),eligibility:t.z.string().optional().describe(`CEL expression that must evaluate to true on the target record`)}).optional().describe(`Public share-link policy (Notion/Figma-style link sharing)`),actions:t.z.array(kn).optional().describe(`Actions associated with this object (auto-populated from top-level actions via objectName)`),protection:jn.optional().describe(`Package author protection block — lock policy for this object.`),...C},{error:Ti}).strict();function Oi(e){return e.split(`_`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}var ki={workflows:"`workflows` is not an ObjectSchema field. Object-level, record-triggered automation is authored as a lifecycle hook (`src/objects/<name>.hook.ts`, wrapped in `defineHook()` from `@objectstack/spec/data`) or as a top-level `record_change` flow — not as `workflows[]` on the object schema.",workflow:"`workflow` is not an ObjectSchema field. Record-triggered automation is authored as a lifecycle hook (`src/objects/<name>.hook.ts`) or a top-level `record_change` flow.",hooks:"`hooks` is not an ObjectSchema field. Lifecycle hooks live in their own `src/objects/<name>.hook.ts` module, wrapped in `defineHook()` from `@objectstack/spec/data`.",triggers:"`triggers` is not an ObjectSchema field. Use a lifecycle hook (`src/objects/<name>.hook.ts`) or a top-level `record_change` flow.",namespace:'`namespace` was retired in ADR-0006 D4 — the object `name` IS the canonical id everywhere (API, ObjectQL, REST, SDK, DB table), so there is no separate namespace to declare. Embed the module prefix in the name instead: `namespace: "sys", name: "user"` becomes `name: "sys_user"`. Until #4001 closed this shape on the parse path it was stripped in silence, so an object declaring one shipped under the unprefixed name its author did not intend.',compactLayout:"`compactLayout` was renamed to `highlightFields` in @objectstack/spec 11.7.0 (ADR-0085 semantic roles) and the alias was retired in 11.9.1 (#2536). Rename the key — the value shape (ordered field-name list) is unchanged.",detail:"The `detail` UI-hints block was removed by ADR-0085 (spec 11.7.0). Its jobs moved to top-level semantic roles: `detail.stageField` → `stageField` (string | false), `detail.highlightFields` → `highlightFields`, section layout → `fieldGroups` + `Field.group`. Whole-page customization is done by assigning a custom Page schema instead of per-page hint keys.",views:"`views` is not an ObjectSchema field: the object-level `views.form/*` and `views.detail/*` UI-hint dialect was never part of the spec and its renderer support was removed (ADR-0085). Use the semantic roles (`highlightFields`, `stageField`, `fieldGroups`) for hints and `listViews` for named list views.",defaultDetailForm:"`defaultDetailForm` was never implemented and was removed from the spec (#2402). Curate the record page by assigning a custom Page schema; form layout derives from `fieldGroups` + `Field.group`.",softDelete:"`softDelete` was removed from the spec in 16.0 (#2377, ADR-0049 enforce-or-remove) — there is no soft-delete/recycle-bin runtime, so it stored nothing and implied restore semantics that do not exist. Deletes are hard deletes; remove the key.",versioning:"`versioning` was removed from the spec in 16.0 (#2377, ADR-0049) — no record-versioning engine ever read it (it snapshotted no history). Use per-field `Field.trackHistory` for field-level history, or a data lifecycle policy (`lifecycle`) for retention.",search:"`search` (the SearchConfig block) was removed from the spec in 16.0 (#2377, ADR-0049) — no search-engine config was consumed. Declare the indexed fields with `searchableFields` (ADR-0061); records stay queryable via the normal data API regardless.",recordName:"`recordName` was removed from the spec in 16.0 (#2377, ADR-0049) — it was never read. Auto-naming is modelled as a `Field` of type 'autonumber' (with `autonumberFormat`) designated as the object's `nameField`.",keyPrefix:"`keyPrefix` was removed from the spec in 16.0 (#2377, ADR-0049) — record ids are not prefixed from it (no Salesforce-style key-prefix runtime). Remove the key; it had no effect.",tags:"`tags` (object-level categorization) was removed from the spec (#2377, ADR-0049) — it had no runtime reader. Remove the key; use `managedBy` for lifecycle bucketing or a real field for per-record tagging.",active:'`active` was removed from the spec (#2377, ADR-0049) — no runtime reader gated on it, so an "inactive" object was still fully queryable and usable. Remove the key; gate availability with permissions/sharing instead.',abstract:"`abstract` was removed from the spec (#2377, ADR-0049) — object inheritance/abstraction is not implemented, so an abstract object still got a table and was instantiable. Remove the key."};function Ai(e,t){let n=Array.from({length:e.length+1},()=>Array(t.length+1).fill(0));for(let t=0;t<=e.length;t++)n[t][0]=t;for(let e=0;e<=t.length;e++)n[0][e]=e;for(let r=1;r<=e.length;r++)for(let i=1;i<=t.length;i++)n[r][i]=e[r-1]===t[i-1]?n[r-1][i-1]:1+Math.min(n[r-1][i],n[r][i-1],n[r-1][i-1]);return n[e.length][t.length]}function ji(e,t){let n,r=1/0;for(let i of t){let t=Ai(e.toLowerCase(),i.toLowerCase());t<r&&(r=t,n=i)}return n!==void 0&&r<=Math.max(2,Math.floor(e.length/3))?n:void 0}function Mi(e,t,n){let r=typeof e==`string`&&e.length>0?e:`<unnamed>`,i=t.map(e=>{let t=ki[e];if(t)return` \u2022 ${t}`;let r=ji(e,n);return r?` \u2022 \`${e}\` is not an ObjectSchema field \u2014 did you mean \`${r}\`?`:` \u2022 \`${e}\` is not an ObjectSchema field.`});return Error(`ObjectSchema.create('${r}'): unknown key(s) \u2014 ${t.join(`, `)}.
|
|
11
|
+
These keys would previously have been stripped silently at build, shipping dead metadata with no diagnostic (ADR-0032 "no silent failure", issue #1535).
|
|
12
|
+
|
|
13
|
+
${i.join(`
|
|
14
|
+
`)}
|
|
15
|
+
|
|
16
|
+
Remove the unknown key(s), fix the typo, or move the logic to a supported mechanism.`)}var Ni=new Set;function Pi(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>`;Ni.has(i)||(Ni.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 Fi(e,t,n){if(t!==`system-data`)return;let r=Bi({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 Ii(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 Ri=n(()=>{let e=Di.parse.bind(Di),t=Di.safeParse.bind(Di);return Object.assign(Di,{parse(t,n){return e(Li(Ii(t)),n)},safeParse(e,n){return t(Li(Ii(e)),n)},create:e=>{let t=e,n=Object.keys(Di.shape),r=Object.keys(t).filter(e=>!n.includes(e));if(r.length>0)throw Mi(t.name,r,n);Pi(t.name,t.fields,t.managedBy),Fi(t.name,t.managedBy,t.userActions);let i={...t,label:t.label??Oi(t.name)};return Di.parse(i)}})}),zi={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 Bi(e){let t=zi[e?.managedBy??`platform`]??zi.platform,n=e?.userActions??{},r=Vi(n.edit,t.edit),i=Vi(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 Vi(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 Hi=t.z.enum([`own`,`extend`]),Ui=n(()=>j({surface:`this object extension`,history:`Until #4001 these were dropped silently — the extension still parsed and still registered, so fields or rules an author meant to merge into someone else's object simply never arrived, on a surface where the target is owned by another package and the absence is easy to blame on precedence.`,aliases:{object:`extend`,objectName:`extend`,target:`extend`,name:`extend`,extends:`extend`,order:`priority`},guidance:{actions:"`actions` cannot be contributed through an object extension — the merge carries `fields`, `label`, `pluralLabel`, `description`, `validations` and `indexes` only. Declare a top-level action with `objectName: '<target>'`; `defineStack()` attaches it to the object.",hooks:"`hooks` cannot be contributed through an object extension — declare a top-level hook bound to the target object instead.",listViews:"`listViews` cannot be contributed through an object extension — declare a top-level `view` bound to the target object instead.",fieldGroups:"`fieldGroups` cannot be contributed through an object extension — the merge does not carry them. Add the fields here and declare the groups on the owning object, or assign a Page for the layout."}},{extend:t.z.string().describe(`Target object name (FQN) to extend`),fields:t.z.record(t.z.string(),Fe).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(Xt).optional().describe(`Additional validation rules to merge into the target object`),indexes:t.z.array(ui).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 Wi(e){return Ui.parse(e)}var Gi=[`get`,`list`,`create`,`update`,`delete`,`bulk`],Ki=ri,qi=new Set(Gi),Ji=new Set(ti);function Yi(e){return qi.has(e)}function Xi(e){return Ji.has(e)}var Zi={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}},Qi={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 $i(e,t,n,r){let i=Zi[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 ea(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 ti)$i(e,t,n,r)&&i.add(e);return i}function ta(e,t){let n=t?.userExportAllowed!==!1,r=e??{},i=r.apiMethods;if(i==null){let e=new Set(Gi);return{mode:`unrestricted`,primitives:e,operations:ea(`unrestricted`,e,r,n),userExportAllowed:n}}let a=Array.isArray(i)?new Set(i.map(e=>String(e)).filter(Yi)):new Set;return a.size===0?{mode:`deny-all`,primitives:new Set,operations:new Set,userExportAllowed:n}:{mode:`restricted`,primitives:a,operations:ea(`restricted`,a,r,n),userExportAllowed:n}}function na(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:na(e,n.bulkChild,{writeMode:n.writeMode});if(Yi(t))return r||e.primitives.has(t);if(Xi(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 ra(e){return ri.filter(t=>e.operations.has(t))}var ia={USER:`sys_user`},aa=new Set([`text`,`textarea`,`email`,`url`,`phone`,`password`,`secret`,`markdown`,`html`,`richtext`,`code`,`color`,`signature`,`qrcode`]),oa=new Set([`number`,`currency`,`percent`,`rating`,`slider`,`progress`,`summary`]),sa=new Set([`boolean`,`toggle`]),ca=new Set([`date`]),la=new Set([`datetime`]),ua=new Set([`time`]),H=new Set([`select`,`radio`]),da=new Set([`multiselect`,`checkboxes`,`tags`]),fa=new Set([`lookup`,`master_detail`,`user`,`tree`]),pa=new Map([[`user`,ia.USER]]);function ma(e){if(!e||typeof e!=`object`)return;let{type:t,reference:n}=e;if(!(typeof t!=`string`||!fa.has(t)))return typeof n==`string`&&n?n:pa.get(t)}var ha=new Set([`image`,`file`,`avatar`,`video`,`audio`]);function ga(e){return typeof e==`string`&&/^[A-Za-z0-9_-]{1,64}$/.test(e)}var _a=`__rawFileValues`,va=new Set([`json`,`composite`,`repeater`,`record`,`location`,`address`,`vector`]),ya=new Set([`formula`,`summary`,`autonumber`]),ba=new Set([`select`,`radio`,`lookup`,`user`,`file`,`image`]);function xa(e){return da.has(e.type)?!0:ba.has(e.type)&&e.multiple===!0}var Sa=n(()=>t.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,`expected YYYY-MM-DD (calendar day, not an instant)`)),Ca=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)`)),wa=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)`)),Ta=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`)})),Ea=Oe,Da=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()})),Oa=n(()=>t.z.string().regex(/^[A-Za-z0-9_-]{1,64}$/,`Expected an opaque sys_file id`)),ka=n(()=>t.z.union([t.z.string().min(1),Da])),Aa=/^\s*[[{]/,ja=n(()=>t.z.string().min(1).refine(e=>!Aa.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 Ma(e){return Array.isArray(e.options)?e.options.map(e=>String(typeof e==`object`&&e?e.value:e)):[]}function Na(e,n=`stored`){let r=e.type,i=(()=>{if(aa.has(r))return t.z.string();if(oa.has(r))return t.z.number().finite();if(sa.has(r))return t.z.boolean();if(ca.has(r))return Sa;if(la.has(r))return Ca;if(ua.has(r))return wa;if(H.has(r)||da.has(r)){let n=Ma(e);return n.length>0?t.z.enum(n):t.z.string()}return fa.has(r)?n===`expanded`?t.z.union([ja,t.z.record(t.z.string(),t.z.unknown())]):ja:ha.has(r)?n===`expanded`?t.z.union([Oa,Da]):Oa:r===`location`?Ta:r===`address`?Ea: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 xa(e)?t.z.array(i):i}var Pa=new Set([`true`,`t`,`yes`,`y`,`1`,`on`,`是`,`对`,`✓`,`√`]),Fa=new Set([`false`,`f`,`no`,`n`,`0`,`off`,`否`,`错`,`✗`,`×`]),Ia=new Set([...fa,`reference`]),La=new Set([`YYYY`,`YY`,`MM`,`DD`,`YYYYMMDD`]);function Ra(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 za(e){return e.some(e=>e.kind===`date`||e.kind===`field`)}function Ba(e,t=4){let n=e.find(e=>e.kind===`seq`);return n&&n.kind===`seq`?n.width:t}function Va(e){return e.filter(e=>e.kind===`field`).map(e=>e.field)}function Ha(e,t){let n=[];for(let r of Va(e)){let e=t?t[r]:void 0;(e==null||e===``)&&!n.includes(r)&&n.push(r)}return n}function Ua(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 Wa(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 Ga(e){let{tokens:t,seq:n,record:r,now:i,timezone:a}=e,o=Ua(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=Wa(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 u=za(t)?s:``,d=l===null?`${s}${n}`:`${s}${String(n).padStart(l,`0`)}${c}`;return{prefix:s,suffix:c,scope:u,value:d}}var Ka="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: '*'`.",qa=[`name`,`label`,`object`,`events`,`handler`,`body`,`priority`,`async`,`condition`,`description`,`retryPolicy`,`timeout`,`onError`],Ja=[`maxRetries`,`backoffMs`],Ya=A({surface:`this hook`,knownKeys:qa,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.`}),Xa=A({surface:`this hook's retryPolicy`,knownKeys:Ja,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`."}),Za=t.z.enum([`beforeFind`,`afterFind`,`beforeInsert`,`afterInsert`,`beforeUpdate`,`afterUpdate`,`beforeDelete`,`afterDelete`]),Qa=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:Ka}).describe(`Target object(s)`),events:t.z.array(Za).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:fn.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:E.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:Xa}).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`),...C},{error:Ya}).strict()),$a=n(()=>t.z.object({id:t.z.string().optional().describe(`Unique execution ID for tracing`),object:t.z.string(),event:Za,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)`),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.`),positions:t.z.array(t.z.string()).optional().describe("Position names held by the caller (ADR-0090 D3; formerly `roles`), copied from ExecutionContext.positions. For hook READS only — e.g. forwarding to the sharing service as evaluation context. Authorization is decided by the security service on the ExecutionContext (permissions / positions / derived posture); this is NOT an authorization input and a hook must not gate a write by testing it."),preserveAudit:t.z.boolean().optional().describe(`True when this write is a historical import that must KEEP its caller-supplied updated_at/updated_by (and the readonly audit family) instead of being stamped with the import instant (#3493). Server-set, opt-in, absent on normal writes; read by the built-in audit hook. A stamping policy, not an authorization input.`),roles:S("`HookContext.session.roles` was removed in @objectstack/spec 17.0.0 (#5050, ADR-0049 D2) — it was declared, read by two dead exemption branches (removed in #5049), and never produced: ObjectQL's `buildSession()` builds the session field by field and has never written `roles`, so every read resolved `undefined` and a guard keyed on it was dead code that merely LOOKED like an authorization decision. Delete the key. To gate a hook on the caller, read `ctx.session.userId` / `ctx.session.isSystem`; to judge PRIVILEGE, ask the security service, which evaluates the ADR-0095 vocabulary on the execution context — capability grants (`permissions`), placements (`positions`) and the derived posture — never a role-name string comparison (ADR-0090 D3 bans the `role` spelling outright). Nothing to migrate: a HookContext is built per operation by the engine and never stored, so no metadata source carries this key. NOTE an ACTION body's `ctx.session` is a different object and still carries its own `roles` array today; that surface is tracked separately (#5613) and is not what this key was.")}).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 eo(e){return Qa.parse(e)}var to=`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.`,no='`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.',ro="`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.",io="`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.",ao={extractQuery:no,query:no,errorPolicy:ro,onError:ro,errorHandling:ro,errorMode:ro,skipErrors:ro,batchSize:io,batch:io,chunkSize:io},oo=t.z.enum([`none`,`constant`,`lookup`,`split`,`join`,`javascript`,`map`]),so=n(()=>j({surface:`this field mapping`,history:to,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:oo.default(`none`),params:j({surface:`this transform’s params`,history:to,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()})),co=n(()=>j({surface:`this mapping`,history:to,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",...ao}},{name:w.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(so),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)`),...C}));function lo(e){return co.parse(e)}var uo=t.z.enum([`read`,`create`,`update`,`delete`,`transfer`,`restore`,`purge`,`export`]),fo=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.`),po=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.`)})),mo=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(po).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.`)})),ho=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:mo.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:uo,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:uo,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:fo.optional()}),layers:t.z.array(ho),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 go=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(go).default([])}));var _o=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:fo.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()})),vo=n(()=>t.z.union([t.z.record(t.z.string(),t.z.unknown()),f]).describe(`Data Engine query filter conditions`)),yo=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(He)]).describe(`Sort order definition`)),U=n(()=>t.z.object({context:_o.partial().optional()})),bo=n(()=>U.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),f]).optional(),fields:t.z.array(qe).optional(),orderBy:t.z.array(He).optional(),limit:t.z.number().optional(),offset:t.z.number().optional(),top:t.z.number().optional(),cursor:S(Ye),search:Qe.optional(),searchFields:t.z.array(t.z.string()).optional(),expand:t.z.lazy(()=>t.z.record(t.z.string(),N)).optional(),distinct:S(Xe)}).describe(`QueryAST-aligned query options for IDataEngine.find() operations`)),xo=n(()=>U.extend({filter:vo.optional(),select:t.z.array(t.z.string()).optional(),sort:yo.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`)),So=n(()=>U.extend({returning:t.z.boolean().default(!0).optional()}).describe(`Options for DataEngine.insert operations`)),Co=n(()=>U.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),f]).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`)),wo=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)`)),To=n(()=>U.extend({filter:vo.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`)),Eo=n(()=>U.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),f]).optional(),multi:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.delete operations`)),Do=n(()=>U.extend({filter:vo.optional(),multi:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.delete operations`)),Oo=n(()=>U.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),f]).optional(),groupBy:t.z.array(t.z.string()).optional(),aggregations:t.z.array(Ge).optional(),having:f.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`)),ko=n(()=>U.extend({filter:vo.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`)),Ao=n(()=>U.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),f]).optional()}).describe(`QueryAST-aligned options for DataEngine.count operations`)),jo=n(()=>U.extend({filter:vo.optional()}).describe(`Options for DataEngine.count operations`)),Mo=n(()=>t.z.object({find:t.z.function().input(t.z.tuple([t.z.string(),bo.optional()])).output(t.z.promise(t.z.array(t.z.unknown()))),findOne:t.z.function().input(t.z.tuple([t.z.string(),bo.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()))]),So.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()),Co.optional()])).output(t.z.promise(t.z.unknown())),delete:t.z.function().input(t.z.tuple([t.z.string(),Eo.optional()])).output(t.z.promise(t.z.unknown())),count:t.z.function().input(t.z.tuple([t.z.string(),Ao.optional()])).output(t.z.promise(t.z.number())),aggregate:t.z.function().input(t.z.tuple([t.z.string(),Oo])).output(t.z.promise(t.z.array(t.z.unknown())))}).describe(`Standard Data Engine Contract`)),W=[{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 No(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 Po=W.filter(e=>e.canonical===`where`);function Fo(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 Io={filter:vo.optional()};function Lo(e,t){let n={...e};return No(n,Po,e=>t.addIssue(Fo(e))),n}function Ro(e,t){let n={...e};return No(n,W,e=>t.addIssue(Fo(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 zo=bo.extend({...Io,select:t.z.array(t.z.string()).optional(),sort:yo.optional(),skip:t.z.number().int().min(0).optional(),populate:t.z.array(t.z.string()).optional()}).transform((e,t)=>Ro(e,t)),Bo=n(()=>t.z.object({method:t.z.literal(`find`),object:t.z.string(),query:zo.optional()})),Vo=n(()=>t.z.object({method:t.z.literal(`findOne`),object:t.z.string(),query:zo.optional()})),Ho=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:So.optional()})),Uo=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:Co.extend(Io).transform((e,t)=>Lo(e,t)).optional()})),Wo=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:Eo.extend(Io).transform((e,t)=>Lo(e,t)).optional()})),Go=n(()=>t.z.object({method:t.z.literal(`count`),object:t.z.string(),query:Ao.extend(Io).transform((e,t)=>Lo(e,t)).optional()})),Ko=n(()=>t.z.object({method:t.z.literal(`aggregate`),object:t.z.string(),query:Oo.extend(Io).transform((e,t)=>Lo(e,t))})),qo=n(()=>t.z.object({method:t.z.literal(`execute`),command:t.z.unknown(),options:t.z.record(t.z.string(),t.z.unknown()).optional()})),Jo=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()),f]).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`,[Bo,Vo,Ho,Uo,Wo,Go,Ko,qo,Jo]).describe(`Virtual ObjectQL Request Protocol`)),Xo=t.z.enum([`asc`,`desc`]).describe(`Sort order direction`);n(()=>t.z.object({field:t.z.string().describe(`Field name to sort by`),order:Xo.describe(`Sort direction`)}).describe(`Sort field and direction pair`)),t.z.enum([`insert`,`update`,`delete`,`upsert`]).describe(`Data mutation event types`);var Zo=t.z.enum([`read_uncommitted`,`read_committed`,`repeatable_read`,`serializable`,`snapshot`]).describe(`Transaction isolation levels (snake_case standard)`),G=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)`)})),K=(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.`,Qo=n(()=>t.z.object({queryDateGranularity:t.z.record(M,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:S(K(`create`,"CRUD is not optional for a driver: `create`/`find`/`findOne`/`update`/`delete` are REQUIRED `IDataDriver` methods and the engine calls them unconditionally.")),read:S(K(`read`,"CRUD is not optional for a driver: reads go through the REQUIRED `find`/`findOne`/`count` methods, called unconditionally.")),update:S(K(`update`,"CRUD is not optional for a driver: `update`/`upsert` are REQUIRED `IDataDriver` methods, called unconditionally.")),delete:S(K(`delete`,"CRUD is not optional for a driver: `delete` is a REQUIRED `IDataDriver` method, called unconditionally.")),bulkCreate:S(K(`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:S(K(`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:S(K(`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:S(K(`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:S(K(`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:S(K(`isolationLevels`,"Isolation is requested per transaction via `beginTransaction({ isolationLevel })`; no planner ever consulted this list to decide anything.")),queryFilters:S(K(`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:S(K(`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:S(K(`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:S(K(`queryAggregations`,"Aggregate pushdown is decided by `typeof driver.aggregate === 'function'` plus `queryDateGranularity` (engine aggregate dispatch) — never by this bit.")),queryWindowFunctions:S(K(`queryWindowFunctions`,`ObjectQL never plans window functions through a driver, so there was nothing for the bit to switch on.`)),querySubqueries:S(K(`querySubqueries`,`ObjectQL never plans subqueries through a driver, so there was nothing for the bit to switch on.`)),queryCTE:S(K(`queryCTE`,`ObjectQL never plans Common Table Expressions through a driver, so there was nothing for the bit to switch on.`)),joins:S(K(`joins`,"Related data is resolved by the engine (lookup expansion over `find()`), not by driver-side JOIN planning — no code consulted the bit.")),fullTextSearch:S(K(`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:S(K(`jsonQuery`,`No engine path ever branched on driver-side JSON querying.`)),geospatialQuery:S(K(`geospatialQuery`,`No geospatial query path exists in the platform — declaring the bit advertised a capability nothing delivers.`)),streaming:S("`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:S(K(`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:S(K(`arrayFields`,"Field-type handling is negotiated per object at `syncSchema` time by the driver itself; no engine path consulted the bit.")),vectorSearch:S(K(`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:S(K(`schemaSync`,"Schema sync is gated on METHOD PRESENCE — `typeof driver.syncSchema === 'function'` (engine and ObjectQL plugin init).")),migrations:S(K(`migrations`,`No migration engine ever consulted it.`)),indexes:S(K(`indexes`,"Declared indexes are materialised by the driver itself during schema sync (`SqlDriver.syncDeclaredIndexes`); no engine path consulted the bit.")),connectionPooling:S(K(`connectionPooling`,"Pooling is configured via `poolConfig` and owned by the driver; `getPoolStats` is duck-typed where monitoring wants it. Nothing consulted the bit.")),preparedStatements:S(K(`preparedStatements`,"Parameterised execution is an implementation detail of the driver (`execute(command, parameters)`); nothing consulted the bit.")),queryCache:S(K(`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."))})),$o=n(()=>t.z.object({name:t.z.string().describe(`Driver unique name`),version:t.z.string().describe(`Driver version`),supports:Qo,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(),G.optional()])).output(t.z.promise(t.z.unknown())).describe(`Execute raw command`),find:t.z.function().input(t.z.tuple([t.z.string(),N,G.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(),N,G.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()),G.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()),G.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(),G.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()),G.optional()])).output(t.z.promise(t.z.boolean())).describe(`Delete record`),count:t.z.function().input(t.z.tuple([t.z.string(),N.optional(),G.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())),G.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())})),G.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())),G.optional()])).output(t.z.promise(t.z.void())),updateMany:t.z.function().input(t.z.tuple([t.z.string(),N,t.z.record(t.z.string(),t.z.unknown()),G.optional()])).output(t.z.promise(t.z.number())).optional(),deleteMany:t.z.function().input(t.z.tuple([t.z.string(),N,G.optional()])).output(t.z.promise(t.z.number())).optional(),beginTransaction:t.z.function().input(t.z.tuple([t.z.object({isolationLevel:Zo.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(),G.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()})),G.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(),G.optional()])).output(t.z.promise(t.z.void())),explain:t.z.function().input(t.z.tuple([t.z.string(),N,G.optional()])).output(t.z.promise(t.z.unknown())).optional()})),es=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`)})),ts=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:Qo.describe(`Driver capability flags`),connectionString:t.z.string().optional().describe(`Database connection string (driver-specific format)`),poolConfig:es.optional().describe(`Connection pool configuration`)})),ns=n(()=>t.z.enum([`postgresql`,`mysql`,`sqlite`,`mssql`,`oracle`,`mariadb`])),rs=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)`)})),is=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`})),as=n(()=>ts.extend({type:t.z.literal(`sql`).describe(`Driver type must be "sql"`),dialect:ns.describe(`SQL database dialect`),dataTypeMapping:rs.describe(`SQL data type mapping configuration`),ssl:t.z.boolean().default(!1).describe(`Enable SSL/TLS connection`),sslConfig:is.optional().describe(`SSL/TLS configuration (required when ssl is true)`)}).refine(e=>!(e.ssl&&!e.sslConfig),{message:`sslConfig is required when ssl is true`})),q={text:`TEXT`,number:`REAL`,boolean:`INTEGER`,date:`TEXT`,datetime:`TEXT`,json:`TEXT`,uuid:`TEXT`,binary:`BLOB`},os={supportsAddColumn:!0,supportsRenameColumn:!0,supportsDropColumn:!0,supportsModifyColumn:!1,supportsAddConstraint:!1,rebuildStrategy:`create_copy_drop_rename`},ss=n(()=>t.z.enum([`mongodb`,`couchdb`,`dynamodb`,`cassandra`,`redis`,`elasticsearch`,`neo4j`,`orientdb`])),cs=n(()=>t.z.enum([`find`,`findOne`,`insert`,`update`,`delete`,`aggregate`,`mapReduce`,`count`,`distinct`,`createIndex`,`dropIndex`])),ls=n(()=>t.z.enum([`all`,`quorum`,`one`,`local_quorum`,`each_quorum`,`eventual`])),us=n(()=>t.z.enum([`single`,`compound`,`unique`,`text`,`geospatial`,`hashed`,`ttl`,`sparse`])),ds=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`)})),fs=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`)})),ps=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`)})),ms=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`)})),hs=n(()=>ts.extend({type:t.z.literal(`nosql`).describe(`Driver type must be "nosql"`),databaseType:ss.describe(`Specific NoSQL database type`),dataTypeMapping:ms.describe(`NoSQL data type mapping configuration`),consistency:ls.optional().describe(`Consistency level for operations`),replication:fs.optional().describe(`Replication configuration`),sharding:ds.optional().describe(`Sharding configuration`),schemaValidation:ps.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`)})),gs=n(()=>t.z.object({consistency:ls.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`)})),_s=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`)})),vs=n(()=>t.z.object({collection:t.z.string().describe(`Collection/table name`),stages:t.z.array(_s).describe(`Aggregation pipeline stages`),options:gs.optional().describe(`Query options`)})),ys=n(()=>t.z.object({name:t.z.string().describe(`Index name`),type:us.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`)})),bs=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)`)})),xs=t.z.enum([`insert`,`update`,`upsert`,`replace`,`ignore`]),Ss=n(()=>j({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:xs.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`),...C}));function Cs(e,t){return Ss.parse({...t,object:e.name})}var ws=B({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)`}]}]}]}),Ts=B({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`}]}]}),Es=B({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)`}]}]}]}),Ds=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`)),Os=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(Ds).describe(`Field-level reference details`)}).describe(`Object node in the seed data dependency graph`)),ks=n(()=>t.z.object({nodes:t.z.array(Os).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`)),As=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`)),js=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`),Ms=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:xs.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:js.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:xs.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`),summariesStale:t.z.number().int().min(0).default(0).describe(`Roll-up summary values left stale by writes for this dataset`),errors:t.z.array(As).default([]).describe(`Reference resolution errors`)}).describe(`Result of loading a single dataset`)),Ps=n(()=>t.z.object({success:t.z.boolean().describe(`Overall success status`),dryRun:t.z.boolean().describe(`Whether this was a dry-run`),dependencyGraph:ks.describe(`Object dependency graph`),results:t.z.array(Ns).describe(`Per-object load results`),errors:t.z.array(As).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`),totalSummariesStale:t.z.number().int().min(0).default(0).describe(`Total roll-up summary values left stale across the load`),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`)),Fs=n(()=>t.z.object({seeds:t.z.array(Ss).min(1).describe(`Seeds to load`),config:Ms.default(()=>Ms.parse({})).describe(`Loader configuration`)}).describe(`Seed loader request with datasets and configuration`)),Is=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`)})),Ls=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`)})),Rs=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`)})),zs=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(Is).describe(`Version history`),majorVersion:t.z.number().describe(`Major version`),minorVersion:t.z.number().describe(`Minor version`)}).optional().describe(`Version control`),template:Ls.optional().describe(`Document template`),eSignature:Rs.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`)})),Bs=n(()=>t.z.object({source:t.z.string().describe(`Source field name`),target:t.z.string().describe(`Target field name`),transform:S('`FieldMapping.transform` — authored as `connector.fieldMappings[].transform` and `externalLookup.fieldMappings[].transform` — was removed in @objectstack/spec 17.0.0 (#5552, ADR-0049), and the whole `FieldMappingTransform` union went with it (`constant` / `cast` / `lookup` / `javascript` / `map`) — no runtime ever executed any of the five, and the `javascript` member advertised `dialect: "js"`, a dialect retired in #3278. Delete the key. The transform pipeline that IS enforced is the import mapping\'s: `mapping.fieldMapping[].transform` (a string enum — `none`/`constant`/`map`/`split`/`join`/`lookup` — with its settings in `params`), applied by the REST import path, which rejects `javascript` with a 400 rather than pretending to run it. Run `os migrate meta --from 16` to rewrite it automatically.'),defaultValue:t.z.unknown().optional().describe(`Default if source is null/undefined`)})),Vs=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`)})),Hs=n(()=>Bs.extend({type:t.z.string().optional().describe(`Field type`),readonly:t.z.boolean().optional().default(!0).describe(`Read-only field`)})),Us=n(()=>t.z.object({fieldName:t.z.string().describe(`Field name`),dataSource:Vs.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(Hs).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`)})),Ws=t.z.enum([`off`,`safe`]).describe(`Dev-only non-destructive schema self-heal (#2186)`),J="`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).",Y=t.z.boolean().describe("Enable TLS. Certificates go in the datasource-level `ssl` block."),X="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.",Ks={target:`draft-2020-12`,io:`input`,unrepresentable:`any`};function qs(e){let n;return()=>(n===void 0&&(n=t.z.toJSONSchema(e,Ks)),n)}var Js=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`)),Ys=n(()=>t.z.enum([`file`,`local`,`auto`]).describe(`Persistence backend type`)),Xs=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`)),Zs=n(()=>t.z.object({type:t.z.literal(`local`),key:t.z.string().optional().describe(`localStorage key for persisted data`)}).describe(`localStorage persistence configuration`)),Qs=n(()=>t.z.object({adapter:Js}).describe(`Custom adapter persistence configuration`)),$s=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`)),ec=n(()=>t.z.union([Ys,Xs,Zs,$s,Qs]).describe(`Persistence configuration for the memory driver`)),tc=A({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:J,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."}),nc=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:ec.or(t.z.literal(!1)).default(!1).describe(`Persistence configuration (opt-in; defaults to pure in-memory)`)},{error:tc}).strict().describe(`Memory Driver Connection Configuration`)),rc=qs(nc),ic={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 rc()}},ac=A({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:J,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."}),oc=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:ac}).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."})})),sc=qs(oc),cc={id:`mongo`,label:`MongoDB`,description:`Official MongoDB Driver for ObjectStack. Supports rich queries, aggregation, and atomic updates.`,icon:`database`,get configSchema(){return sc()}},lc=A({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:J,readOnly:Gs,ca:X,cert:X,key:X,rejectUnauthorized:X,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."}),uc=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:Y.optional().meta({title:`Use SSL/TLS`}),autoMigrate:Ws.optional()},{error:lc}).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."})})),dc=qs(uc),fc=[`url`,`host`,`port`,`database`,`username`,`password`,`ssl`,`schema`,`applicationName`,`statementTimeout`,`autoMigrate`],pc=(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.)`,mc=A({surface:`this postgres datasource's config`,knownKeys:fc,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:pc(`pool`,`max`),min:pc(`min`,`min`),max:pc(`max`,`max`),idleTimeoutMillis:pc(`idleTimeoutMillis`,`idleTimeoutMillis`),connectionTimeoutMillis:pc(`connectionTimeoutMillis`,`connectionTimeoutMillis`),schemaMode:J,readOnly:Gs,ca:X,cert:X,key:X,rejectUnauthorized:X},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."}),hc=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:Y.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:Ws.optional()},{error:mc}).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."})})),gc=qs(hc),_c=[`filename`,`autoMigrate`],vc={file:`filename`,filepath:`filename`,path:`filename`,database:`filename`,db:`filename`,url:`filename`,connectionstring:`filename`},yc="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.",Z="`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'`.",bc=A({surface:`this sqlite datasource's config`,knownKeys:_c,aliases:vc,guidance:{schemaMode:J,readOnly:Gs,memory:Z,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:yc}),xc=n(()=>t.z.object({filename:t.z.string().default(`:memory:`).describe(`Database file path, or ":memory:" for an ephemeral database`).meta({title:`Filename`}),autoMigrate:Ws.optional()},{error:bc}).strict().describe(`SQLite connection configuration`)),Sc=qs(xc),Cc=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`),wc=A({surface:`this sqlite-wasm datasource's config`,knownKeys:[`filename`,`persist`],aliases:vc,guidance:{schemaMode:J,readOnly:Gs,memory:Z,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:yc}),Q=n(()=>t.z.object({filename:t.z.string().default(`:memory:`).describe(`Database file path, or ":memory:" for an ephemeral database`).meta({title:`Filename`}),persist:Cc.optional().meta({title:`Persist mode`})},{error:wc}).strict().describe(`SQLite (WASM) connection configuration`)),Tc=qs(Q),Ec=[`memory`,`sqlite`,`sqlite-wasm`,`postgres`,`mysql`,`mongo`],Dc={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 Oc(e){if(typeof e==`string`)return Dc[e.trim().toLowerCase()]}var kc={memory:nc,sqlite:xc,"sqlite-wasm":Q,postgres:hc,mysql:uc,mongo:oc};function Ac(e){let t=Oc(e);return t?kc[t]:void 0}var jc={memory:rc,sqlite:Sc,"sqlite-wasm":Tc,postgres:gc,mysql:dc,mongo:sc};function Mc(e){return jc[e]()}function Nc(e,t){let n=Ac(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 Pc=[`id`,`label`,`description`,`icon`,`configSchema`],Fc=[`allowedSchemas`,`allowWrites`,`validation`,`credentialsRef`,`queryTimeoutMs`],Ic=[`onMismatch`,`checkOnBoot`,`checkIntervalMs`],Lc=[`name`,`label`,`driver`,`config`,`pool`,`ssl`,`description`,`active`,`autoConnect`,`schemaMode`,`external`,`origin`],Rc=[`min`,`max`,`idleTimeoutMillis`,`connectionTimeoutMillis`],zc=[`enabled`,`rejectUnauthorized`,`ca`,`cert`,`key`],Bc="`datasource.capabilities` was removed in @objectstack/spec 17.0.0 (#4583, ADR-0049) — all eleven flags were declared, strict-guarded and read by nobody. ",Vc={capabilities:Bc+"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:Bc+"`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."},Uc=(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\`).`,Wc=A({surface:`this driver definition`,knownKeys:Pc,aliases:{name:`id`,driver:`id`,title:`label`,config:`configSchema`,schema:`configSchema`},guidance:{capabilities:Vc.capabilities,capability:Vc.capabilities},history:`Until #4001 these were dropped silently — the driver still registered.`}),Gc=A({surface:`this datasource's external settings`,knownKeys:Fc,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.`}),Kc=A({surface:`this datasource's external validation policy`,knownKeys:Ic,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.`}),qc="`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.",Jc=A({surface:`this datasource`,knownKeys:Lc,aliases:{type:`driver`,connection:`config`,connectionconfig:`config`,options:`config`,enabled:`active`,pooling:`pool`,mode:`schemaMode`,schema_mode:`schemaMode`,federation:`external`,tls:`ssl`},guidance:{host:Uc(`host`),port:Uc(`port`),database:Uc(`database`),user:Uc(`user`,`username`),username:Uc(`username`),filename:Uc(`filename`),url:Uc(`url`),connectionString:Uc(`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:qc,replicas:qc,capabilities:Vc.capabilities,readOnly:Vc.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.`}),Yc=A({surface:`this datasource's pool config`,knownKeys:Rc,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`."}),Xc=A({surface:`this datasource's ssl config`,knownKeys:zc,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.`}),Zc=t.z.string().describe(`Underlying driver identifier`),Qc=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:Wc}).strict()),$c=t.z.enum([`managed`,`external`,`validate-only`]).describe(`Schema ownership mode`),el=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:Kc}).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:Gc}).strict().describe(`External datasource federation settings (schemaMode != "managed")`);function tl(e,t,n,r){let i=Nc(t,n);if(i.known)for(let t of i.issues)e.addIssue({code:`custom`,path:[...r,...t.path],message:t.message})}var nl=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:Zc.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:Yc}).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:Xc}).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:$c.default(`managed`),external:el.optional(),origin:t.z.enum([`code`,`runtime`]).default(`code`).describe(`Datasource provenance (server-managed, read-only)`),...C},{error:Jc}).strict().superRefine((e,t)=>{tl(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 rl(e){return nl.parse(e)}var il={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`}},al={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`},ol={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 sl(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?il[t]:void 0;return i&&i[n]?i[n]:al[n]?al[n]:`unknown`}function cl(e,t){let n=sl(e,t);if(n!==`unknown`)return ol[n].suggested}function ll(e,t,n){let r=ol[sl(e,n)];return r.exact.includes(t)?!0:r.lossy.includes(t)?`lossy`:!1}var ul=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`)}),dl=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(ul).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`)}),fl=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(dl).describe(`Snapshotted remote tables.`)})),pl=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`number`,`string`,`boolean`]),ml=t.z.enum([`string`,`number`,`boolean`,`time`,`geo`]),hl=t.z.enum([`second`,`minute`,`hour`,`day`,`week`,`month`,`quarter`,`year`]),gl=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:pl,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()})),_l=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:ml,sql:t.z.string().describe(`SQL expression or column reference`),granularities:t.z.array(hl).optional()})),vl=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)`)})),yl=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(),gl).describe(`Quantitative metrics`),dimensions:t.z.record(t.z.string(),_l).describe(`Qualitative attributes`),joins:t.z.record(t.z.string(),vl).optional(),refreshKey:t.z.object({every:t.z.string().optional(),sql:t.z.string().optional()}).optional(),public:t.z.boolean().default(!1)})),bl=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:f.optional().describe(`Filtering criteria (canonical Query DSL FilterCondition)`),timeDimensions:t.z.array(t.z.object({dimension:t.z.string(),granularity:hl.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 xl(e){return yl.parse(e)}var Sl=new Set([`number`,`currency`,`percent`]);function Cl(e){return e===`percent`?`avg`:`sum`}function wl(e,t){return!(t!==`percent`||e!==`sum`&&e!==`count_distinct`)}function Tl(e){return e===`count`||e===`count_distinct`||e===`sum`?0:void 0}function El(e){if(e?.type===`percent`)return typeof e.max==`number`&&e.max>1?`whole`:`fraction`}var Dl=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(`.`)),Ol=new Set([`text`,`textarea`,`email`,`url`,`markdown`,`html`,`richtext`]),kl=Ol;function Al(e){if(!e)return!1;let t=e.type;return t?t===`formula`?(e.returnType??e.valueType)===`text`:!Dl.has(t)&&Ol.has(t):!1}var jl=new Set([`name`,`title`,`subject`,`label`,`full_name`,`display_name`]),Ml=[`_name`,`_title`],Nl=[`name_`];function Pl(e){return jl.has(e.toLowerCase())}function Fl(e){let t=e.toLowerCase();return jl.has(t)?!1:Ml.some(e=>t.endsWith(e))||Nl.some(e=>t.startsWith(e))}function Il(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&&Al(e[r]))return r;for(let n of t)if(Fl(n)&&Al(e[n]))return n;for(let n of t)if(!Pl(n)&&Al(e[n]))return n}function Ll(e){return e?(e.nameField??e.displayNameField)||Il(e.fields):void 0}function Rl(e){return e==null||typeof e==`string`&&e.trim()===``}function zl(e,t,n){let r=t??{},i=n?.viewTitleField??Ll(e),a=i?r[i]:void 0;return Rl(a)?`Record #${r.id??r._id??``}`.trimEnd():String(a)}function Bl(e,t){let n=Ll(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 Vl(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=Il(e.fields);return n?{status:`derived`,field:n}:{status:`none`}}var Hl=new Set([`text`,`email`,`phone`,`url`,`autonumber`,`textarea`,`markdown`]),Ul=new Set([`select`,`status`]),Wl=new Set([`id`,`_id`,`created`,`modified`,`created_at`,`updated_at`,`created_by`,`updated_by`,`owner_id`,`organization_id`,`space`,`company_id`]),Gl=new Set([`json`,`object`,`grid`,`image`,`file`,`avatar`,`vector`,`location`,`geometry`,`secret`,`password`,`encrypted`,`boolean`,`lookup`,`master_detail`]);function Kl(e,t){let n=Object.keys(e).filter(t=>{if(Wl.has(t))return!1;let n=e[t];if(!n||n.hidden)return!1;let r=n.type;return!r||Gl.has(r)?!1:Hl.has(r)||Ul.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 ql(e){let t=e.fields||{},n=e.searchableFields?.filter(e=>t[e]);return n&&n.length>0?{allowed:n,source:`declared`}:{allowed:Kl(t,e.displayField),source:`auto`}}function Jl(e){let{allowed:t}=ql(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 Yl=Object.freeze([`created_at`,`created_by`,`updated_at`,`updated_by`]),Xl=new Set([...Yl,`organization_id`,`tenant_id`,`is_deleted`,`deleted_at`]);function Zl(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 Ql(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=(Array.isArray(t.fieldGroups)?t.fieldGroups:[]).map(Zl).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):Xl.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 $l=12;function eu(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&&(Xl.has(e)||n++);return n}function tu(e,t={}){if(t.viewport===`mobile`)return`page`;let n=t.pageThreshold??$l;return eu(e)>=n?`page`:`drawer`}function nu(e,t,n={}){let r=tu(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 ru=`id`,iu=`owner_id`,au=`owning_business_unit_id`,ou=`organization_id`;function su(e){let t=e&&typeof e==`object`&&!Array.isArray(e)?e:{},n=t.systemFields,r=t.managedBy,i=typeof t.name==`string`?t.name:``,a=new Set([ru]),o={tenant:!1,audit:!1,owner:!1,owningBusinessUnit:!1,names:a};if(n===!1||r===`better-auth`)return o;let s=typeof n==`object`&&n?n:void 0,c=s?.tenant!==!1&&!mi(t),l=s?.audit!==!1,u=!r&&!i.startsWith(`sys_`),d=typeof t.ownership==`string`?t.ownership:void 0,f=u&&(d===void 0||d===`user`),ee=f||u&&d===`business_unit`;if(c&&a.add(ou),l)for(let e of Yl)a.add(e);return f&&a.add(iu),ee&&a.add(au),{tenant:c,audit:l,owner:f,owningBusinessUnit:ee,names:a}}var cu=t.z.enum([`comment`,`field_change`,`task`,`event`,`email`,`call`,`note`,`file`,`record_create`,`record_delete`,`approval`,`sharing`,`system`]),lu=t.z.enum([`all`,`comments_only`,`changes_only`,`tasks_only`]);e.ALL_OPERATORS=le,e.API_METHOD_DERIVATION=Zi,e.API_METHOD_ORDER=Ki,e.API_OPERATION_ORDER=ri,e.API_PRIMITIVES=Gi,e.AUDIT_PROVENANCE_FIELDS=Yl,e.AddressSchema=Oe,e.AddressValueSchema=Ea,e.AggregationFunction=Ue,e.AggregationMetricType=pl,e.AggregationNodeSchema=Ge,e.AggregationPipelineSchema=vs,e.AggregationStageSchema=_s,e.AnalyticsQuerySchema=bl,e.ApiMethod=ei,e.ApiOperationSchema=ii,e.AutoPersistenceConfigSchema=$s,e.BOOLEAN_VALUE_TYPES=sa,e.BUILTIN_DRIVER_IDS=Ec,e.BaseEngineOptionsSchema=U,e.CALENDAR_DATE_TYPES=ca,e.CLOCK_TIME_TYPES=ua,e.COMPUTED_VALUE_TYPES=ya,e.CONTEXT_TOKENS=Dt,e.CONTEXT_TOKEN_DESCRIPTIONS=Mt,e.CONTEXT_TOKEN_SUGGESTIONS=Nt,e.CONTEXT_TOKEN_WRAPPED_RE=kt,e.CalendarDateValueSchema=Sa,e.ClockTimeValueSchema=wa,e.ComparisonOperatorSchema=a,e.ConditionalValidationSchema=Zt,e.ConsistencyLevelSchema=ls,e.ContextTokenPlaceholderSchema=jt,e.ContextTokenSchema=At,e.CrossFieldValidationSchema=Jt,e.CubeJoinSchema=vl,e.CubeSchema=yl,e.CurrencyConfigSchema=Ee,e.CurrencyValueSchema=De,e.CustomPersistenceConfigSchema=Qs,e.DATA_ACTION_TO_API_OPERATION=Qi,e.DATE_MACRO_ALIAS_TOKENS=mt,e.DATE_MACRO_DESCRIPTIONS=Ct,e.DATE_MACRO_INSTANT_TOKENS=ft,e.DATE_MACRO_PARAM_RE=gt,e.DATE_MACRO_PERIOD_TOKENS=pt,e.DATE_MACRO_TOKENS=ht,e.DATE_MACRO_UNITS=_t,e.DATE_MACRO_WRAPPED_RE=xt,e.DEFAULT_VALUE_TOKENS=Rt,e.DEFAULT_VALUE_TOKEN_CURRENT_USER=Lt,e.DEFAULT_VALUE_TOKEN_DESCRIPTIONS=zt,e.DEFAULT_VALUE_TOKEN_NOW=It,e.DRIVER_CONFIG_SCHEMAS=kc,e.DRIVER_ID_ALIASES=Dc,e.DataEngineAggregateOptionsSchema=ko,e.DataEngineAggregateRequestSchema=Ko,e.DataEngineContractSchema=Mo,e.DataEngineCountOptionsSchema=jo,e.DataEngineCountRequestSchema=Go,e.DataEngineDeleteOptionsSchema=Do,e.DataEngineDeleteRequestSchema=Wo,e.DataEngineExecuteRequestSchema=qo,e.DataEngineFilterSchema=vo,e.DataEngineFindOneRequestSchema=Vo,e.DataEngineFindRequestSchema=Bo,e.DataEngineInsertOptionsSchema=So,e.DataEngineInsertRequestSchema=Ho,e.DataEngineQueryOptionsSchema=xo,e.DataEngineRequestSchema=Yo,e.DataEngineSortSchema=yo,e.DataEngineUpdateOptionsSchema=To,e.DataEngineUpdateRequestSchema=Uo,e.DataEngineVectorFindRequestSchema=Jo,e.DataTypeMappingSchema=rs,e.DatasourceSchema=nl,e.DateGranularity=M,e.DateMacroPlaceholderSchema=St,e.DateMacroTokenSchema=bt,e.DimensionSchema=_l,e.DimensionType=ml,e.DocumentSchema=zs,e.DocumentSchemaValidationSchema=ps,e.DocumentTemplateSchema=Ls,e.DocumentVersionSchema=Is,e.DriverCapabilitiesSchema=Qo,e.DriverConfigSchema=ts,e.DriverDefinitionSchema=Qc,e.DriverInterfaceSchema=$o,e.DriverOptionsSchema=G,e.DriverSslToggleSchema=Y,e.DriverType=Zc,e.DroppedFieldsEventSchema=wo,e.ESignatureConfigSchema=Rs,e.EngineAggregateOptionsSchema=Oo,e.EngineCountOptionsSchema=Ao,e.EngineDeleteOptionsSchema=Eo,e.EngineQueryOptionsSchema=bo,e.EngineUpdateOptionsSchema=Co,e.EqualityOperatorSchema=i,e.ExpressionBodySchema=un,e.ExternalCatalogSchema=fl,e.ExternalColumnSchema=ul,e.ExternalDataSourceSchema=Vs,e.ExternalDatasourceSettingsSchema=el,e.ExternalFieldMappingSchema=Hs,e.ExternalLookupSchema=Us,e.ExternalTableSchema=dl,e.FIELD_GROUP_SYSTEM_FIELDS=Xl,e.FIELD_KEY_GUIDANCE=O,e.FILE_REFERENCE_TYPES=ha,e.FILTER_ARRAY_LOGIC_KEYWORDS=re,e.FILTER_LOGIC_CASES=tt,e.FILTER_LOGIC_ROWS=et,e.FILTER_OPERATORS=se,e.FILTER_TEXT_CASES=P,e.FILTER_TEXT_ROWS=nt,e.FeedFilterMode=lu,e.FeedItemType=cu,e.Field=Ie,e.FieldNodeSchema=qe,e.FieldOperatorsSchema=d,e.FieldReferenceSchema=r,e.FieldSchema=Fe,e.FieldType=Ce,e.FileLikeValueSchema=ka,e.FilePersistenceConfigSchema=Xs,e.FileReferenceIdValueSchema=Oa,e.FileValueSchema=Da,e.FilterArraySchema=oe,e.FilterConditionSchema=f,e.FormatValidationSchema=qt,e.FullTextSearchSchema=Qe,e.GroupByNodeSchema=We,e.HookBodyCapability=rn,e.HookBodySchema=fn,e.HookContextSchema=$a,e.HookEvent=Za,e.HookSchema=Qa,e.IMPORT_BOOLEAN_FALSE_TOKENS=Fa,e.IMPORT_BOOLEAN_TRUE_TOKENS=Pa,e.IMPORT_REFERENCE_TYPES=Ia,e.INSTANT_TYPES=la,e.ImportFieldMappingSchema=so,e.IndexSchema=ui,e.InstantValueSchema=Ca,e.JSONValidationSchema=Yt,e.LEGACY_API_METHODS=ti,e.LEGACY_API_METHOD_GUIDANCE=ni,e.LIFECYCLE_DURATION_REGEX=vi,e.LOGICAL_OPERATORS=ce,e.LifecycleClassSchema=V,e.LifecycleSchema=bi,e.LocalStoragePersistenceConfigSchema=Zs,e.LocationCoordinatesSchema=Te,e.LocationValueSchema=Ta,e.MEASURE_FIELD_TYPES=Sl,e.MULTI_CAPABLE_TYPES=ba,e.MULTI_OPTION_TYPES=da,e.MappingSchema=co,e.MemoryConfigSchema=nc,e.MemoryDriverSpec=ic,e.MemoryPersistenceConfigSchema=ec,e.MetricSchema=gl,e.MongoConfigSchema=oc,e.MongoDriverSpec=cc,e.MysqlConfigSchema=uc,e.NUMERIC_VALUE_TYPES=oa,e.NoSQLDataTypeMappingSchema=ms,e.NoSQLDatabaseTypeSchema=ss,e.NoSQLDriverConfigSchema=hs,e.NoSQLIndexSchema=ys,e.NoSQLIndexTypeSchema=us,e.NoSQLOperationTypeSchema=cs,e.NoSQLQueryOptionsSchema=gs,e.NoSQLTransactionOptionsSchema=bs,e.NormalizedFilterSchema=p,e.OBJECT_KEY_GUIDANCE=_e,e.ObjectAccessConfigSchema=hi,e.ObjectCapabilities=li,e.ObjectDependencyGraphSchema=ks,e.ObjectDependencyNodeSchema=Os,e.ObjectExtensionSchema=Ui,e.ObjectExternalBindingSchema=Si,e.ObjectFieldGroupSchema=xi,e.ObjectOwnershipEnum=Hi,e.ObjectRequiredPermissionsSchema=_i,e.ObjectSchema=Ri,e.PAGINATION_ALL_IDS=dt,e.PAGINATION_CASES=lt,e.PAGINATION_ROWS=ct,e.PAGINATION_UNORDERED_CASES=ut,e.PerOperationRequiredPermissionsSchema=gi,e.PersistenceAdapterSchema=Js,e.PersistenceTypeSchema=Ys,e.PoolConfigSchema=es,e.PostgresConfigSchema=hc,e.QUERY_CURSOR_REMOVED=Ye,e.QUERY_DISTINCT_REMOVED=Xe,e.QueryFilterSchema=ee,e.QuerySchema=N,e.RAW_FILE_VALUES_CONTEXT_KEY=_a,e.READ_ONLY_BELONGS_ON_DATASOURCE=Gs,e.RECORD_SURFACE_PAGE_THRESHOLD=$l,e.REFERENCE_VALUE_TYPES=fa,e.RETIRED_FILTER_OPERATORS=x,e.RPC_QUERY_ALIAS_SLOTS=W,e.RangeOperatorSchema=c,e.ReferenceIdValueSchema=ja,e.ReferenceResolutionErrorSchema=As,e.ReferenceResolutionSchema=Ds,e.ReplicationConfigSchema=fs,e.RowCrudActionOverrideSchema=Ci,e.SCHEMA_MODE_BELONGS_ON_DATASOURCE=J,e.SEARCHABLE_ENUM_TYPES=Ul,e.SEARCHABLE_TEXTUAL_TYPES=Hl,e.SEARCH_AUTO_EXCLUDED_FIELDS=Wl,e.SEARCH_AUTO_EXCLUDED_TYPES=Gl,e.SINGLE_OPTION_TYPES=H,e.SQLDialectSchema=ns,e.SQLDriverConfigSchema=as,e.SQLiteAlterTableLimitations=os,e.SQLiteDataTypeMappingDefaults=q,e.SSLConfigSchema=is,e.SSL_DETAIL_BELONGS_ON_DATASOURCE=X,e.STACK_KEY_GUIDANCE=ve,e.STACK_RUNTIME_MEMBERS=ye,e.STRING_VALUE_TYPES=aa,e.STRUCTURED_JSON_TYPES=va,e.SchemaModeSchema=$c,e.ScriptBodySchema=dn,e.ScriptValidationSchema=Gt,e.SeedIdentitySchema=js,e.SeedLoadResultSchema=Ns,e.SeedLoaderConfigSchema=Ms,e.SeedLoaderRequestSchema=Fs,e.SeedLoaderResultSchema=Ps,e.SeedMode=xs,e.SeedSchema=Ss,e.SelectOptionSchema=we,e.SetOperatorSchema=s,e.ShardingConfigSchema=ds,e.SortNodeSchema=He,e.SpecialOperatorSchema=u,e.SqlAutoMigrateSchema=Ws,e.SqliteConfigSchema=xc,e.SqliteWasmConfigSchema=Q,e.SqliteWasmPersistModeSchema=Cc,e.StateMachineValidationSchema=Kt,e.StringOperatorSchema=l,e.TEMPORAL_CASES=at,e.TEMPORAL_NOW=rt,e.TEMPORAL_ROWS=it,e.TEMPORAL_TIME_CASES=st,e.TEMPORAL_TIME_ROWS=ot,e.TITLE_ELIGIBLE=kl,e.TITLE_ELIGIBLE_TYPES=Ol,e.TITLE_INELIGIBLE_TYPES=Dl,e.TenancyConfigSchema=pi,e.TimeUpdateInterval=hl,e.TransformType=oo,e.UniqueScopeSchema=Ae,e.VALID_AST_OPERATORS=h,e.ValidationRuleSchema=Xt,e.canonicalAstOperator=_,e.canonicalizeSqlType=sl,e.classifyFilterToken=Ft,e.countAuthorableFields=eu,e.defaultAggregateFor=Cl,e.defineCube=xl,e.defineDatasource=rl,e.defineHook=eo,e.defineMapping=lo,e.defineObjectExtension=Wi,e.defineSeed=Cs,e.deriveFieldGroupLayout=Ql,e.deriveRecordFlowSurface=nu,e.deriveRecordSurface=tu,e.driverConfigJsonSchema=qs,e.effectiveOperationsArray=ra,e.emptyGroupValueFor=Tl,e.fieldForm=Ts,e.foldQueryAliasSlots=No,e.formatUnknownAuthoringKey=Se,e.getDriverConfigJsonSchemaById=Mc,e.getDriverConfigSchema=Ac,e.getMemoryConfigJsonSchema=rc,e.getMongoConfigJsonSchema=sc,e.getMysqlConfigJsonSchema=dc,e.getPostgresConfigJsonSchema=gc,e.getSqliteConfigJsonSchema=Sc,e.getSqliteWasmConfigJsonSchema=Tc,e.hasDynamicTokens=za,e.hookForm=Es,e.isApiOperationAllowed=na,e.isApiPrimitive=Yi,e.isAppResolvedDefaultToken=Ut,e.isCompatible=ll,e.isContextToken=Ot,e.isCurrentUserDefaultToken=Vt,e.isDateMacroToken=vt,e.isFileIdToken=ga,e.isFilterAST=v,e.isGlobalUnique=je,e.isIncoherentAggregate=wl,e.isKnownFilterToken=Pt,e.isLegacyApiMethod=Xi,e.isMultiValueField=xa,e.isNowDefaultToken=Bt,e.isOrganizationUnique=Ne,e.isPlainRecord=be,e.isRuntimeDefaultToken=Ht,e.isTenancyDisabled=mi,e.isTitleEligible=Al,e.isUniqueDeclared=Me,e.lintAuthoredRecordKeys=xe,e.missingFieldValues=Ha,e.nextUtcCalendarDay=wt,e.objectForm=ws,e.objectTitleCompleteness=Vl,e.parseAutonumberFormat=Ra,e.parseDateMacroParam=yt,e.parseFilterAST=ne,e.percentScaleOf=El,e.provisionPrimary=Bl,e.referenceTargetOf=ma,e.referencedFields=Va,e.renderAutonumber=Ga,e.resolveCrudAffordances=Bi,e.resolveDisplayField=Ll,e.resolveDriverId=Oc,e.resolveEffectiveApiMethods=ta,e.resolveInjectedSystemColumns=su,e.resolveRecordDisplayName=zl,e.resolveSearchFieldResolution=ql,e.resolveSearchFields=Jl,e.sequenceWidth=Ba,e.stripLegacyApiMethods=si,e.suggestFieldTypeForSqlType=cl,e.utcInstantMs=Tt,e.validateDriverConfig=Nc,e.valueSchemaFor=Na})),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(),$icontains:t.z.string().optional().describe(`Contains substring, ignoring case — but ONLY ASCII case (A-Z against a-z). Every other character compares literally, so "café" does NOT match "CAFÉ" and "москва" does not match "МОСКВА". The domain is ASCII because that is the one fold all five backends can deliver: SQLite (and therefore turso and sqlite-wasm) folds ASCII only, so a Unicode promise here would be a guarantee three of the five could not keep. The comparand is matched LITERALLY — "%", "_" and regex metacharacters are ordinary characters, not wildcards. Case-SENSITIVE containment is $contains. [#5701: declared by the protocol; the driver lowerings land with #5702.]`)})),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(),$icontains: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()})),c=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`})),l=[`and`,`or`],u=t.z.string().min(1).refine(e=>!l.includes(e.toLowerCase()),{message:`'and' / 'or' in the first position open a logical group, so they cannot name a field. Write the comparison inside the group: ["and", ["field", "=", value]].`}),d=t.z.string().refine(e=>c.has(e.toLowerCase()),{error:e=>`Unknown filter operator '${String(e.input)}'. Recognised operators: ${[...c].sort().join(`, `)}.`}),f=t.z.string().refine(e=>l.includes(e.toLowerCase()),{message:`A logical group opens with 'and' or 'or'.`}),ee=t.z.lazy(()=>t.z.union([t.z.tuple([u,d,t.z.unknown()]),t.z.tuple([u,d]),t.z.tuple([f,ee],ee),t.z.array(ee).min(1)]).describe(`Input-only authoring sugar for a filter: [field, operator, value], ["and"|"or", ...conditions], or a bare list of those. Lowered to a FilterCondition at the single sink parseFilterAST (@objectstack/spec/data) the moment it arrives; it is never stored and never travels the wire as an array. A query "where" is a FilterCondition and does not accept this shape (#5158).`));function p(e){return t.z.never({error:()=>e}).optional().describe(`[REMOVED] ${e}`)}function te(e){try{return e()}finally{}}var m=t.z.enum([`none`,`no-overlay`,`no-delete`,`full`]),h=t.z.enum([`artifact`,`package`,`env-forced`]),g=t.z.enum([`package`,`org`,`env-forced`]),_={_lock:m.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:h.optional().describe(`Layer that set _lock (artifact | package | env-forced).`),_provenance:g.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.`)},v=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)`)),y=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)`)),ne=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)`)),re=t.z.enum([`cel`,`cron`,`template`]),ie=t.z.object({rationale:t.z.string().optional(),generatedBy:t.z.string().optional()}),ae=t.z.object({dialect:re,source:t.z.string().min(1).optional(),ast:t.z.unknown().optional(),meta:ie.optional()}).refine(e=>e.source!==void 0||e.ast!==void 0,{message:"Expression requires at least one of `source` or `ast`"}),b=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cel`,source:e})),ae]),oe=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cron`,source:e})),ae]),se=t.z.union([t.z.string().min(1).transform(e=>({dialect:`template`,source:e})),ae]),ce=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.`}}),le=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(`.`)),x=`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.`,S=n(()=>D({surface:`this select option`,history:x,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:v.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:b.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 ue=n(()=>D({surface:`this currency configuration`,history:x,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 de=e=>{if(e.code!==`invalid_union`)return;let t=e.input,n=typeof t==`string`?`'${t}'`:String(t);return`Invalid unique scope ${n}. Allowed: true/false, 'organization' (one holder per organization \u2014 the explicit spelling of true), or 'global' (one holder across the whole installation).${t===`tenant`||t===`org`?` ${n} is not accepted and is not an alias \u2014 the per-organization scope is spelled 'organization' (ADR-0120: "tenant" is overloaded across deployment topologies, and the platform spells the word out).`:``}`},fe=n(()=>t.z.union([t.z.boolean(),t.z.literal(`global`),t.z.literal(`organization`)],{error:de}));function pe(){let e={},t={};for(let[n,r]of Object.entries(ce))r.to?e[n]=r.to:r.why&&(t[n]=r.why);return{aliases:e,guidance:t}}var C=n(()=>D({surface:`this field`,history:x,aliases:{...pe().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`,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:{...pe().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:le.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:fe.default(!1).describe(`Unique constraint and its scope (ADR-0120). 'organization' = one holder per organization (NULL-safe composite with the organization key part on organization-scoped objects) — prefer this explicit spelling in new code; true = same per-organization scope (positional synonym, stays valid); 'global' = one holder across the whole installation. 'tenant'/'org' are rejected — the word is 'organization'`),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(S).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(),D({surface:`this lookup column`,history:x,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(D({surface:`this lookup filter`,history:x,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(),D({surface:`this dependsOn entry`,history:x,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:b.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:D({surface:`this roll-up summary`,history:x,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:ue.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:b.optional().describe("Predicate (CEL) — field is shown only when TRUE (else hidden). e.g. P`record.type == 'invoice'`"),readonlyWhen:b.optional().describe("Predicate (CEL) — field is read-only when TRUE. e.g. P`record.status == 'paid'`"),requiredWhen:b.optional().describe("Predicate (CEL) — field is required when TRUE. The only slot; the `conditionalRequired` alias was removed in protocol 17 (#3855)."),conditionalRequired:p("`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`),..._}).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)."})})),me=e=>e.toLowerCase().replace(/[_\-\s]/g,``);function w(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]}var he=e=>e.toLowerCase().replace(/[-\s]/g,`_`);function ge(e,t,n=3,r=3){let i=he(e);return t.map(t=>({value:t,distance:w(i,he(t)),cased:w(e,t)})).filter(t=>t.distance<=n&&t.value!==e).sort((e,t)=>e.distance-t.distance||e.cased-t.cased).slice(0,r).map(e=>e.value)}function T(e){let{surface:t,knownKeys:n,guidance:r={},history:i}=e,a={};for(let[t,n]of Object.entries(e.aliases??{}))a[me(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[me(e)]??ge(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
|
+
${c.map(e=>` \u2022 ${e}`).join(`
|
|
18
|
+
`)}`),l}}function E(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 E(n.innerType,t+1);default:return!1}}function D(e,n){let{surface:r,history:i,aliases:a,guidance:o,extraKeys:s=[],retiredForms:c}=e,l;return t.z.object(n,{error:e=>{if(c&&e.code===`invalid_type`){let t=typeof e.input==`string`?c[e.input]:void 0;if(t)return t}return(l??=te(()=>T({surface:r,knownKeys:[...Object.keys(n).filter(e=>!E(n[e])),...s],history:i,aliases:a,guidance:o})))(e)}}).strict()}var O=n(()=>D({surface:`this sort node`,history:"Until #4721 an unknown key here was dropped silently and `order` fell back to its `asc` default, so a descending request came back ascending — and with `limit`, a different set of rows under an ordinary 200.",aliases:{direction:`order`}},{field:t.z.string(),order:t.z.enum([`asc`,`desc`]).default(`asc`)})),_e=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`array_agg`,`string_agg`]),ve=t.z.enum([`day`,`week`,`month`,`quarter`,`year`]),ye=n(()=>t.z.union([t.z.string(),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:ve.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`)})])),be=n(()=>t.z.object({function:_e.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.")})),xe="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`.",Se=t.z.string({error:e=>e.code===`invalid_type`&&typeof e.input==`object`&&e.input!==null&&!Array.isArray(e.input)?xe:void 0}),Ce="`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']`).",k='`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.',we="`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.",Te="`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`.",Ee=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).`)})),De=t.z.object({object:t.z.string().describe(`Object name (e.g. account)`),fields:t.z.array(Se).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(),Ee]).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(O).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:p(k),joins:p(Ce),aggregations:t.z.array(be).optional().describe(`Aggregation functions`),groupBy:t.z.array(ye).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:p(Te),distinct:p(we)}),Oe=n(()=>De.extend({expand:t.z.lazy(()=>t.z.record(t.z.string(),Oe)).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.")})),ke=t.z.enum([`validation`,`authentication`,`authorization`,`not_found`,`conflict`,`rate_limit`,`server`,`external`,`maintenance`]),Ae=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(`.`)),je={validation:400,authentication:401,authorization:403,not_found:404,conflict:409,rate_limit:429,server:500,external:502,maintenance:503},Me={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 Ne(e){return Me[e]??(e>=500?`INTERNAL_ERROR`:`VALIDATION_ERROR`)}var Pe=t.z.enum([`no_retry`,`retry_immediate`,`retry_backoff`,`retry_after`]),Fe=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(`.`)),Ie=n(()=>t.z.object({field:t.z.string().describe(`Field path (supports dot notation)`),code:Fe.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 })`)})),Le=n(()=>t.z.object({code:Ae.describe(`Machine-readable error code`),message:t.z.string().describe(`Human-readable error message`),category:ke.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:Pe.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(Ie).optional().describe(`One entry per offending value`),fieldErrors:p("`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`)})),Re=n(()=>t.z.object({success:t.z.literal(!1).describe(`Always false for error responses`),error:Le.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`)})),ze={"@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_READONLY_FIELD_REJECTED`,`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`,`DATASET_INVALID`,`RAW_SQL_UNSUPPORTED`,`READ_SCOPE_COMPILE_FAILED`],"@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`]},Be=Object.freeze([...new Set(Object.values(ze).flat())].sort()),A=t.z.enum([...Ae.options,...Be]),Ve=n(()=>t.z.object({code:A.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`)})),j=n(()=>t.z.object({success:t.z.boolean().describe(`Operation success status`),error:Ve.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`)})),He=new Set([`success`,`data`,`error`,`meta`]);function Ue(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))He.has(e)||n.push(`stray top-level key \`${e}\` \u2014 the payload belongs under \`data\``);return n}var M=n(()=>t.z.record(t.z.string(),t.z.unknown()).describe(`Key-value map of record data`)),We=n(()=>t.z.object({data:M.describe(`Record data to insert`)})),Ge=n(()=>t.z.object({data:M.describe(`Partial record data to update`)})),Ke=n(()=>t.z.object({records:t.z.array(M).describe(`Array of records to process`),allOrNone:t.z.boolean().default(!0).describe(`If true, rollback entire transaction on any failure`)})),qe=n(()=>t.z.intersection(Oe,t.z.object({format:t.z.enum([`csv`,`json`,`xlsx`]).default(`csv`)}))),Je=n(()=>j.extend({data:M.describe(`The requested or modified record`)})),Ye=n(()=>j.extend({data:t.z.array(M).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`)})),Xe=n(()=>t.z.object({id:t.z.string().describe(`Record ID`)})),Ze=n(()=>t.z.object({id:t.z.string().optional().describe(`Record ID if processed`),success:t.z.boolean(),errors:t.z.array(Ve).optional(),index:t.z.number().optional().describe(`Index in original request`),data:t.z.unknown().optional().describe(`Result data (e.g. created record)`)})),Qe=n(()=>j.extend({data:t.z.array(Ze).describe(`Results for each item in the batch`)})),$e=n(()=>j.extend({id:t.z.string().describe(`ID of the deleted record`)})),N={create:{input:We,output:Je},delete:{input:Xe,output:$e},get:{input:Xe,output:Je},update:{input:Ge,output:Je},list:{input:Oe,output:Ye},bulkCreate:{input:Ke,output:Qe},bulkUpdate:{input:Ke,output:Qe},bulkUpsert:{input:Ke,output:Qe},bulkDelete:{input:t.z.object({ids:t.z.array(t.z.string())}),output:Qe}},et=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`)})),tt=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`)})),nt=n(()=>t.z.object({preventNPlusOne:t.z.boolean().describe(`Enable N+1 query detection and prevention`),dataLoader:et.optional().describe(`DataLoader batch loading configuration`),batchStrategy:tt.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`)})),P=t.z.enum([`GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`HEAD`,`OPTIONS`]).describe("HTTP method — the full routing vocabulary (`api/*` endpoints, router and REST-server routes). The narrower `HttpMethodSubset` is what view data sources may request."),rt=n(()=>t.z.enum([`GET`,`POST`,`PUT`,`PATCH`,`DELETE`]).describe("HTTP methods a view data source may request — the subset of `HttpMethod` without `HEAD`/`OPTIONS`.")),it=n(()=>t.z.object({url:t.z.string().describe(`API endpoint URL`),method:rt.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`)})),at=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(P).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`)})),ot=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`)})),st=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`)})),ct=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`)})),lt=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 — must be inside this stack's endpoint carve-out: `/api/v1/apps/<manifest.namespace>/<subpath>` with a non-empty subpath (ADR-0121 D1), e.g. `/api/v1/apps/crm/leads` for a stack whose `manifest.namespace` is `crm`. Only the subpath is yours to name; the namespace segment is derived from `manifest.namespace` (ADR-0121 D2), never authored here. A path outside the carve-out is rejected at publish and would match NOTHING at runtime."),method:P.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(ct).optional().describe(`Map Request Body to Internal Params`),outputMapping:t.z.array(ct).optional().describe(`Map Internal Result to Response Body`),authRequired:t.z.boolean().default(!0).describe(`Require authentication`),rateLimit:ot.optional().describe(`Rate limiting policy`),cacheTtl:t.z.number().optional().describe(`Response cache TTL in seconds`),..._});function ut(e){let t=String(e??``);return t.length>1&&t.endsWith(`/`)?t.slice(0,-1):t}var dt=Object.assign(lt,{create:e=>e}),ft=`apps`,pt=`/api/v1`;function mt(e){return`${pt}/${ft}/${e}/`}var ht=new Set([`__proto__`,`prototype`,`constructor`]),gt=new Set([`find`,`get`,`delete`]),_t=[`inputMapping`,`outputMapping`],vt=/^[a-z][a-z0-9_]{1,19}$/;function yt(e){if(typeof e!=`string`||e===``)return;let t=e.split(`.`);for(let e of t)if(e===``||ht.has(e))return;return t}function bt(e,t){return e.length>t.length?!1:e.every((e,n)=>t[n]===e)}var xt="`source` and `target` are dot-separated field paths ('user.profile.email'). An empty path, an empty segment ('a..b') and the JavaScript prototype keys (__proto__, prototype, constructor) are refused — the runtime refuses the identical set, so accepting one here would publish a declaration that answers 501 on every request.";function St(e,t){if(!e||e.length===0)return[];let n=[],r=typeof t.namespace==`string`?t.namespace:void 0,i=r!==void 0&&vt.test(r);i||n.push({path:[`apis`],message:"A stack that declares `apis:` MUST declare an explicit `manifest.namespace` "+(r===void 0?`(none is declared).`:`(got '${r}', which is not a legal namespace).`)+` The endpoint URL carve-out is derived from it (ADR-0121 D2): every declared \`path\` must be \`${pt}/${ft}/<manifest.namespace>/<subpath>\`. The namespace is 2-20 chars matching /^[a-z][a-z0-9_]{1,19}$/ and is the same identity that prefixes every object name (\`<namespace>_<short name>\`). It is NOT derived from \`manifest.id\`: an outward URL contract must not move because a package id was rewritten.`});let a=i?mt(r):void 0,o=new Map;for(let t=0;t<e.length;t++){let r=e[t],i=Tt(r,`Endpoint '${r.name}' (apis[${t}])`,(...e)=>[`apis`,t,...e],a,o);if(i){n.push(i);continue}o.set(wt(r),{index:t,name:r.name})}return n}function Ct(e){return Tt(e,`Endpoint '${e.name}'`,(...e)=>e,void 0,new Map)}function wt(e){return`${e.method.toUpperCase()} ${ut(e.path)}`}function Tt(e,t,n,r,i){return Et(e,t,n,r)??Dt(e,t,n)??Ot(e,t,n)??jt(e,t,n)??Mt(e,t,n,i)}function Et(e,t,n,r){if(r===void 0)return;let i=e.path,a=ut(i),o=a.startsWith(r)?a.slice(r.length):void 0;if(!(o!==void 0&&o!==``&&!o.startsWith(`/`)))return{path:n(`path`),message:`${t} declares path '${i}', which is not inside this stack's endpoint carve-out. A declared path must be \`${r}<subpath>\` with a non-empty subpath \u2014 for example '${r}things' (ADR-0121 D1). The \`apps/<namespace>/\` segment is what makes route ownership structural rather than a list to maintain: no built-in domain lives under \`apps/\`, and two packages can never collide because their namespaces differ. A path outside it would parse today and match NOTHING at runtime \u2014 the endpoint step only ever consults declarations under that mount. Only the subpath is yours to name; the prefix and namespace segments are derived from the deployment and from \`manifest.namespace\`.`}}function Dt(e,t,n){if(e.type===`object_operation`){let r=e.objectParams?.object,i=e.objectParams?.operation;if(!r||!i){let e=r?`operation`:`object`;return{path:n(`objectParams`),message:`${t} declares \`type: 'object_operation'\` but \`objectParams.${e}\` is missing. An object_operation endpoint must declare BOTH \`objectParams.object\` (the object name, e.g. 'crm_lead') and \`objectParams.operation\` (one of find / get / create / update / delete). The executor delegates to the same data pipeline \`/data\` uses and cannot infer either half; an incomplete declaration would answer 501 on every request.`}}return}return e.type===`flow`?e.target?void 0:{path:n(`target`),message:`${t} declares \`type: 'flow'\` but names no target flow in \`target\`. Set \`target\` to the flow name (snake_case) this endpoint triggers \u2014 the endpoint is a stable URL over that flow, executed through the same automation pipeline as \`POST /automation/<name>/trigger\`.`}:{path:n(`type`),message:`${t} declares \`type: '${e.type}'\`, which this runtime does not execute. Only 'object_operation' and 'flow' endpoints execute in 17.x. \`script\` is refused because no path in this repo verifies that a script target is reachable through the automation service \u2014 express the logic as a flow (\`type: 'flow'\`) whose script node runs your registered function. \`proxy\` is refused because forwarding to an arbitrary outbound URL is a new egress/SSRF surface that needs its own security ruling before it can be served (#5040 \xA77-3); call the third-party system from a flow instead, where the outbound call is made by a declared connector. Both stay in the vocabulary and are rejected here rather than parsed and ignored.`}}function Ot(e,t,n){for(let r of _t){let i=kt(e,r,t,n);if(i)return i}return At(e,t,n)}function kt(e,t,n,r){let i=e[t];if(!Array.isArray(i)||i.length===0)return;let a=[];for(let e=0;e<i.length;e++){let o=i[e],s=`${t}[${e}]`;if(o.transform!==void 0)return{path:r(t,e,`transform`),message:`${n} declares ${s}.transform ('${String(o.transform)}'), which this runtime does not execute. There is no transformation-function registry anywhere in the platform, so the key would be parsed and ignored \u2014 the declared-but-inert state this gate exists to end. A mapping entry MOVES and RENAMES fields by dot path and nothing more: drop \`transform\`, or shape the value where it is produced (a flow endpoint whose flow computes the value, or a formula field on the object). A function-valued transform needs a registry and a sandbox ruling of its own before it can be declared.`};if(!yt(o.source))return{path:r(t,e,`source`),message:`${n} declares ${s}.source '${String(o.source)}', which is not a usable field path. ${xt}`};let c=yt(o.target);if(!c)return{path:r(t,e,`target`),message:`${n} declares ${s}.target '${String(o.target)}', which is not a usable field path. ${xt}`};let l=a.find(e=>bt(e.segments,c)||bt(c,e.segments));if(l)return{path:r(t,e,`target`),message:`${n} declares ${s}.target '${o.target}', which collides with ${t}[${l.index}].target '${l.path}'. Two mapping entries cannot write the same target path, and neither can write INSIDE the other's ('x' and 'x.y'): one would silently discard the other, so the declaration you read is not the projection you would get. Give each entry a distinct target.`};a.push({index:e,path:o.target,segments:c})}}function At(e,t,n){let r=e.inputMapping;if(!Array.isArray(r)||r.length===0||e.type!==`object_operation`)return;let i=e.objectParams?.operation;if(!(!i||!gt.has(i)))return{path:n(`inputMapping`),message:`${t} declares \`inputMapping\` on a '${i}' object_operation, which never reads a request body \u2014 so every entry would be parsed and then do nothing. \`inputMapping\` maps the REQUEST BODY to internal params (its own vocabulary text); \`find\` takes its criteria from the query string and \`get\` / \`delete\` take the record id from \`query.id\`. Remove the key, or move the endpoint to an operation that carries a body (\`create\` / \`update\`). Same rule, same reason as \`cacheTtl\` on a non-GET endpoint: a declaration that cannot take effect is rejected instead of silently ignored.`}}function jt(e,t,n){let r=e.rateLimit,i=r?.enabled===!0;if(e.authRequired===!1&&!i)return{path:n(`rateLimit`),message:`${t} declares \`authRequired: false\` without an ARMED rate limit. An anonymous endpoint is a free, unauthenticated execution entry point, so ADR-0121 D6 requires it to carry its own budget: declare \`rateLimit: { enabled: true, windowMs: 60000, maxRequests: 100 }\`. `+(r===void 0?"No `rateLimit` is declared at all.":"`enabled` is not `true` — and it DEFAULTS to `false`, so writing only `windowMs` / `maxRequests` declares a budget that meters nothing and the endpoint would be anonymous AND unmetered.")+" `authRequired` defaults to `true`; setting it to `false` is the only way to open an endpoint, and arming the budget is the paired obligation."};if(i){let{maxRequests:e,windowMs:i}=r;if(typeof e==`number`&&e<=0)return{path:n(`rateLimit`,`maxRequests`),message:`${t} declares \`rateLimit.enabled: true\` with \`maxRequests: ${e}\`, a budget that can never be honoured: a zero-or-negative allowance rejects every request, including your own health checks. Set \`maxRequests\` above 0, or turn metering off with \`enabled: false\`. (The runtime fails closed on this shape \u2014 every request to the endpoint would error \u2014 because "the author asked for metering and got none" is the worse outcome.)`};if(typeof i==`number`&&i<=0)return{path:n(`rateLimit`,`windowMs`),message:`${t} declares \`rateLimit.enabled: true\` with \`windowMs: ${i}\`, which is not a usable window. \`windowMs\` is the budget window in MILLISECONDS \u2014 60000 is one minute. Set it above 0, or turn metering off with \`enabled: false\`.`}}let a=e.cacheTtl;if(typeof a==`number`&&a<0)return{path:n(`cacheTtl`),message:`${t} declares \`cacheTtl: ${a}\`. A response cache lifetime cannot be negative \u2014 seconds only, 0 or more. Use a positive number of seconds for a cacheable answer, or \`cacheTtl: 0\` to say explicitly "never store this response" (it emits \`Cache-Control: no-store\`); omit the key to send no caching header at all.`};if(a!==void 0&&e.method!==`GET`)return{path:n(`cacheTtl`),message:`${t} declares \`cacheTtl\` on a ${e.method} endpoint. \`cacheTtl\` is GET-only (#5040 \xA73.3): it becomes a \`Cache-Control\` header on a successful response, and a non-GET answer is not a cacheable representation, so the key would be parsed and never take effect. Remove \`cacheTtl\`, or declare the endpoint as GET if it really is a read.`}}function Mt(e,t,n,r){let i=wt(e),a=r.get(i);if(a)return{path:n(`path`),message:`${t} claims ${e.method} ${e.path}, already claimed by endpoint '${a.name}' (apis[${a.index}]). One stack cannot declare the same METHOD and path twice: the matcher indexes exactly one endpoint per claim, so only the lexicographically first name would ever serve and the other would be dead metadata. Paths are compared with one trailing slash trimmed, the same rule the matcher applies \u2014 '/x' and '/x/' are the same claim. Give one of them a different path or method, or delete the one you do not want.`}}var Nt=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`),Pt=n(()=>t.z.object({enabled:t.z.boolean(),status:Nt,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`)})),Ft=`__serviceInfo`,It=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 Lt(e){if(!e||typeof e!=`object`)return;let t=e[Ft];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 Rt=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`),mcp:t.z.string().optional().describe(`e.g. /api/v1/mcp — always the unscoped base; absent when MCP is disabled or unserveable`)})),zt=n(()=>t.z.enum([`production`,`sandbox`,`development`]).describe('Deployment posture a discovery response advertises. Deliberately three coarse buckets — a client reads this to answer "am I talking to production?", not to identify a specific environment (that is `sys_environment` / EnvironmentTypeSchema, a richer 7-member taxonomy).')),Bt={production:`production`,prod:`production`,sandbox:`sandbox`,staging:`sandbox`,development:`development`,dev:`development`,test:`development`};function Vt(e){return typeof e==`string`?Bt[e.trim().toLowerCase()]??`development`:`development`}var Ht=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.`),websockets:t.z.boolean().describe(`Whether the backend mounts a realtime push surface (WebSocket/SSE) clients can subscribe to. False while realtime is an in-process bus with no mounted HTTP/WS surface (ADR-0076 D12, #2462).`),files:t.z.boolean().describe(`Whether a file-storage surface (upload/download/attachments) is served`),analytics:t.z.boolean().describe(`Whether the backend serves the analytics / BI query surface`),ai:t.z.boolean().describe(`Whether the backend serves the AI surface (NLQ, chat, agents, suggest)`),notifications:t.z.boolean().describe(`Whether the backend serves the notification surface (inbox, delivery)`),i18n:t.z.boolean().describe(`Whether the backend serves the i18n surface (translations, locale negotiation)`)}).describe(`Well-known capability flags for frontend intelligent adaptation`)),Ut=Object.freeze(Object.keys(Ht.shape)),Wt=n(()=>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`)}));function Gt(){return Object.fromEntries(Object.entries(Ht.shape).map(([e,t])=>{let n=t.description;return[e,n?Wt.describe(n):Wt]}))}var Kt=n(()=>t.z.object({name:t.z.string(),version:t.z.string(),environment:zt,routes:Rt,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(),Pt).describe(`Per-service availability map keyed by CoreServiceName`),capabilities:t.z.object(Gt()).describe(`Hierarchical capability descriptors — the full WellKnownCapabilities vocabulary, every key present`),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`),scoping:t.z.object({enabled:t.z.boolean().describe(`Whether environment-scoped routes are mounted at all`),resolution:t.z.enum([`required`,`optional`,`auto`]).describe(`How the environment id is resolved when scoping is enabled (mirrors RestApiConfig.projectResolution)`),scoped:t.z.boolean().describe(`Whether THIS response was served from the environment-scoped mount`),environmentId:t.z.string().optional().describe(`The resolved environment id — present only on a scoped mount`)}).optional().describe(`Environment-scoping posture, added by the REST discovery endpoint`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Custom metadata key-value pairs for extensibility`)})),qt=n(()=>t.z.object({route:t.z.string().describe(`Route path pattern`),method:P.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`)})),Jt=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(qt).describe(`Per-route health entries`)})),Yt=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(`,`)),Xt=t.z.enum([`data.record.created`,`data.record.updated`,`data.record.deleted`]),Zt=t.z.enum([`data.records.updated`,`data.records.deleted`]),F=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:Yt.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`)})),Qt=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:Xt.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`)})),$t=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:Zt.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`)})),en=t.z.enum([`online`,`away`,`busy`,`offline`]),tn=t.z.enum([`created`,`updated`,`deleted`]),nn=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),status:en.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)`)})),rn=t.z.enum([`websocket`,`sse`,`polling`]),an=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)`),on=n(()=>t.z.object({type:an.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`)})),sn=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique subscription identifier`),events:t.z.array(on).describe(`Array of events to subscribe to`),transport:rn.describe(`Transport protocol to use`),channel:t.z.string().optional().describe(`Optional channel name for grouping subscriptions`)})),cn=n(()=>nn),ln=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:tn.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`)})),un=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable realtime synchronization`),transport:rn.default(`websocket`).describe(`Transport protocol`),subscriptions:t.z.array(sn).optional().describe(`Default subscriptions`)}).passthrough()),dn=t.z.enum([`subscribe`,`unsubscribe`,`event`,`ping`,`pong`,`ack`,`error`,`presence`,`cursor`,`edit`]),fn=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")`)),pn=n(()=>t.z.object({subscriptionId:t.z.string().uuid().describe(`Unique subscription identifier`),events:t.z.array(fn).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`)})),mn=n(()=>t.z.object({subscriptionId:t.z.string().uuid().describe(`Subscription ID to unsubscribe from`)})),hn=en,gn=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),sessionId:t.z.string().uuid().describe(`Unique session identifier`),status:hn.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`)})),_n=n(()=>t.z.object({status:hn.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`)})),vn=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`)})),yn=t.z.enum([`insert`,`delete`,`replace`]),bn=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:yn.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)`)})),xn=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`)})),I=t.z.object({messageId:t.z.string().uuid().describe(`Unique message identifier`),type:dn.describe(`Message type`),timestamp:t.z.string().datetime().describe(`ISO 8601 datetime when message was sent`)}),Sn=n(()=>I.extend({type:t.z.literal(`subscribe`),subscription:pn.describe(`Subscription configuration`)})),Cn=n(()=>I.extend({type:t.z.literal(`unsubscribe`),request:mn.describe(`Unsubscribe request`)})),wn=n(()=>I.extend({type:t.z.literal(`event`),subscriptionId:t.z.string().uuid().describe(`Subscription ID this event belongs to`),eventName:ne.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`)})),Tn=n(()=>I.extend({type:t.z.literal(`presence`),presence:gn.describe(`Presence state`)})),En=n(()=>I.extend({type:t.z.literal(`cursor`),cursor:vn.describe(`Cursor position`)})),Dn=n(()=>I.extend({type:t.z.literal(`edit`),operation:bn.describe(`Edit operation`)})),On=n(()=>I.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`)})),kn=n(()=>I.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`)})),An=n(()=>I.extend({type:t.z.literal(`ping`)})),jn=n(()=>I.extend({type:t.z.literal(`pong`),pingMessageId:t.z.string().uuid().optional().describe(`ID of ping message being responded to`)})),Mn=n(()=>t.z.discriminatedUnion(`type`,[Sn,Cn,wn,Tn,En,Dn,On,kn,An,jn])),Nn=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`)})),Pn=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`)})),Fn=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)`)})),In=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)`)})),Ln=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`)})),Rn=t.z.enum([`system`,`api`,`auth`,`static`,`webhook`,`plugin`]),zn=t.z.enum([`error`,`priority`,`first-wins`,`last-wins`]),Bn=n(()=>t.z.object({method:P,path:t.z.string().describe(`URL Path pattern`),category:Rn.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`)})),Vn=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:at.optional(),staticMounts:t.z.array(st).optional()})),Hn=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`)})),Un=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(`.`))),Wn=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`)})),Gn=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`)})})),Kn=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`)})),qn={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 `)}},Jn=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:Kn.optional().describe(`OData metadata configuration`)}).passthrough()),Yn=t.z.enum([`read`,`create`,`update`,`delete`,`transfer`,`restore`,`purge`,`export`]),Xn=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.`),Zn=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.`)})),L=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(Zn).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.`)})),Qn=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:L.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:Yn,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:Yn,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:Xn.optional()}),layers:t.z.array(Qn),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 $n=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($n).default([])}));var er=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:Xn.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()})),tr=n(()=>t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).describe(`Data Engine query filter conditions`)),nr=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(O)]).describe(`Sort order definition`)),R=n(()=>t.z.object({context:er.partial().optional()})),rr=n(()=>R.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),a]).optional(),fields:t.z.array(Se).optional(),orderBy:t.z.array(O).optional(),limit:t.z.number().optional(),offset:t.z.number().optional(),top:t.z.number().optional(),cursor:p(k),search:Ee.optional(),searchFields:t.z.array(t.z.string()).optional(),expand:t.z.lazy(()=>t.z.record(t.z.string(),Oe)).optional(),distinct:p(we)}).describe(`QueryAST-aligned query options for IDataEngine.find() operations`));n(()=>R.extend({filter:tr.optional(),select:t.z.array(t.z.string()).optional(),sort:nr.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 ir=n(()=>R.extend({returning:t.z.boolean().default(!0).optional()}).describe(`Options for DataEngine.insert operations`)),ar=n(()=>R.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`)),or=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(()=>R.extend({filter:tr.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 sr=n(()=>R.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(()=>R.extend({filter:tr.optional(),multi:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.delete operations`));var cr=n(()=>R.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(be).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(()=>R.extend({filter:tr.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 lr=n(()=>R.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(()=>R.extend({filter:tr.optional()}).describe(`Options for DataEngine.count operations`)),n(()=>t.z.object({find:t.z.function().input(t.z.tuple([t.z.string(),rr.optional()])).output(t.z.promise(t.z.array(t.z.unknown()))),findOne:t.z.function().input(t.z.tuple([t.z.string(),rr.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()))]),ir.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()),ar.optional()])).output(t.z.promise(t.z.unknown())),delete:t.z.function().input(t.z.tuple([t.z.string(),sr.optional()])).output(t.z.promise(t.z.unknown())),count:t.z.function().input(t.z.tuple([t.z.string(),lr.optional()])).output(t.z.promise(t.z.number())),aggregate:t.z.function().input(t.z.tuple([t.z.string(),cr])).output(t.z.promise(t.z.array(t.z.unknown())))}).describe(`Standard Data Engine Contract`));var ur=[{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 dr(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 fr=ur.filter(e=>e.canonical===`where`);function pr(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 mr={filter:tr.optional()};function hr(e,t){let n={...e};return dr(n,fr,e=>t.addIssue(pr(e))),n}function gr(e,t){let n={...e};return dr(n,ur,e=>t.addIssue(pr(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 _r=rr.extend({...mr,select:t.z.array(t.z.string()).optional(),sort:nr.optional(),skip:t.z.number().int().min(0).optional(),populate:t.z.array(t.z.string()).optional()}).transform((e,t)=>gr(e,t)),vr=n(()=>t.z.object({method:t.z.literal(`find`),object:t.z.string(),query:_r.optional()})),yr=n(()=>t.z.object({method:t.z.literal(`findOne`),object:t.z.string(),query:_r.optional()})),br=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:ir.optional()})),xr=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:ar.extend(mr).transform((e,t)=>hr(e,t)).optional()})),Sr=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:sr.extend(mr).transform((e,t)=>hr(e,t)).optional()})),Cr=n(()=>t.z.object({method:t.z.literal(`count`),object:t.z.string(),query:lr.extend(mr).transform((e,t)=>hr(e,t)).optional()})),wr=n(()=>t.z.object({method:t.z.literal(`aggregate`),object:t.z.string(),query:cr.extend(mr).transform((e,t)=>hr(e,t))})),Tr=n(()=>t.z.object({method:t.z.literal(`execute`),command:t.z.unknown(),options:t.z.record(t.z.string(),t.z.unknown()).optional()})),Er=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`,[vr,yr,br,xr,Sr,Cr,wr,Tr,Er]).describe(`Virtual ObjectQL Request Protocol`));var Dr=t.z.enum([`create`,`update`,`upsert`,`delete`]),Or=n(()=>t.z.object({id:t.z.string().optional().describe(`Record ID (required for update/delete)`),data:M.optional().describe(`Record data (required for create/update/upsert)`),externalId:t.z.string().optional().describe(`External ID for upsert matching`)})),kr=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:p('`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.')})),Ar=n(()=>t.z.object({operation:Dr.describe(`Type of batch operation`),records:t.z.array(Or).describe(`Array of records to process (server caps the count — see batch.maxBatchSize)`),options:kr.optional().describe(`Batch operation options`)})),jr=n(()=>t.z.object({id:t.z.string().describe(`Record ID`),data:M.describe(`Fields to update`)})),Mr=n(()=>t.z.object({records:t.z.array(jr).describe(`Array of records to update (server caps the count — see batch.maxBatchSize)`),options:kr.optional().describe(`Update options`)})),Nr=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(Ve).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:M.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(or).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.")})),Pr=n(()=>j.extend({operation:Dr.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(Nr).describe(`Detailed results for each record`)})),Fr=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:kr.optional().describe(`Delete options`)})),Ir={batchOperation:{input:Ar,output:Pr},updateMany:{input:Mr,output:Pr},deleteMany:{input:Fr,output:Pr}},Lr=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:kr.optional().describe(`Default batch options`)}).passthrough()),Rr=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:M.optional().describe(`Record payload for create/update; a value may be { $ref: <opIndex> } to reference an earlier op's created id`)})),zr=n(()=>t.z.object({operations:t.z.array(Rr).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`)})),Br=n(()=>or.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`)),Vr=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(Br).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.")})),Hr=t.z.enum([`public`,`private`,`no-cache`,`no-store`,`must-revalidate`,`max-age`]),Ur=n(()=>t.z.object({directives:t.z.array(Hr).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)`)})),Wr=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`)})),Gr=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:Ur.optional().describe(`Client cache control preferences`)})),Kr=n(()=>t.z.object({data:t.z.unknown().optional().describe(`Metadata payload (omitted for 304 Not Modified)`),etag:Wr.optional().describe(`ETag for this resource version`),lastModified:t.z.string().datetime().optional().describe(`Last modification timestamp`),cacheControl:Ur.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`)})),qr=t.z.enum([`all`,`object`,`field`,`permission`,`layout`,`custom`]),Jr=n(()=>t.z.object({target:qr.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)`)})),Yr=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`)})),Xr={getCached:{input:Gr,output:Kr},invalidate:{input:Jr,output:Yr}},z=t.z.object({lock:m.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 Zr(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 Qr(e){return/vis|conceal|hidden|show.?when/i.test(e)}var $r=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(Qr)?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 B=n(()=>t.z.string().describe(`Display label (plain string; i18n keys are auto-generated by the framework)`)),ei=`Until #4001 closed this shape an unknown key was dropped silently — the component still rendered, with no accessible name and nothing to say the one you wrote had been discarded.`,ti=n(()=>D({surface:`these ARIA attributes`,history:ei,aliases:{label:`ariaLabel`,describedBy:`ariaDescribedBy`,ariaRole:`role`},guidance:{live:"`live` is objectui's LIST-VIEW-ONLY extension, declared there as `AriaPropsSchema.extend({ live })` and read by `ListView` alone — this shared shape is carried by ~30 renderers and only one of them applies `aria-live`, so declaring it here would advertise a capability the other 29 do not deliver. On an objectui list view the key is valid as-is; anywhere else, drop it. Promoting it into the protocol is #5058.",ariaLabelledBy:"`aria-labelledby` has no counterpart in this protocol — it references another element's id, which is not the same thing as `ariaLabel` (a literal accessible name), so there is nothing to rename it to. Use `ariaLabel` only if a literal string is what you meant. Declaring the referencing form is #5058.",labelledBy:"`aria-labelledby` has no counterpart in this protocol — see `ariaLabelledBy`. Use `ariaLabel` only if a literal accessible name is what you meant; #5058 tracks the gap."}},{ariaLabel:B.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 ni=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`)),ri=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:ni.optional().describe(`Default number formatting rules`),dateFormat:ri.optional().describe(`Default date/time formatting rules`)}).describe(`Locale configuration`));var ii=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`])),ai=n(()=>D({surface:`this chart axis`,history:`Until #4001 an undeclared axis key was dropped at parse and the axis rendered with the default scale and ticks — a chart that looked configured and was not.`,aliases:{name:`field`,key:`field`,dataKey:`field`,column:`field`,value:`field`,label:`title`,text:`title`,caption:`title`,grid:`showGridLines`,showGrid:`showGridLines`,gridLines:`showGridLines`,step:`stepSize`,tickStep:`stepSize`,interval:`stepSize`,log:`logarithmic`,logScale:`logarithmic`,scale:`logarithmic`,minimum:`min`,maximum:`max`,formatter:`format`,numberFormat:`format`,side:`position`,align:`position`}},{field:t.z.string().describe(`Data field key`),title:B.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)})),oi=n(()=>D({surface:`this chart series`,history:`Until #4001 an undeclared series key was dropped at parse — the series still drew, in the palette colour, on the left axis, unstacked, which is precisely the configuration the author was overriding.`,aliases:{field:`name`,key:`name`,dataKey:`name`,column:`name`,title:`label`,text:`label`,caption:`label`,chartType:`type`,seriesType:`type`,kind:`type`,stackId:`stack`,stackGroup:`stack`,group:`stack`,axis:`yAxis`,yAxisId:`yAxis`,side:`yAxis`,role:`variant`,strokeDasharray:`dashArray`,dashed:`dashArray`,alpha:`opacity`,fillOpacity:`opacity`,strokeOpacity:`opacity`,colour:`color`,fill:`color`,stroke:`color`}},{name:t.z.string().describe(`Field name or series identifier`),label:B.optional().describe(`Series display label`),type:ii.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`)})),si=n(()=>D({surface:`this chart annotation`,history:`Until #4001 an undeclared annotation key was dropped at parse and the reference line drew at the wrong place, in the default style, or not at all — while the annotation itself reported valid.`,aliases:{from:`value`,start:`value`,at:`value`,threshold:`value`,y:`value`,x:`value`,to:`endValue`,end:`endValue`,until:`endValue`,valueEnd:`endValue`,title:`label`,text:`label`,caption:`label`,lineStyle:`style`,strokeStyle:`style`,dash:`style`,colour:`color`,stroke:`color`,fill:`color`,orientation:`axis`,direction:`axis`,kind:`type`,shape:`type`}},{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:B.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),ci=n(()=>D({surface:`this chart interaction block`,history:"Until #4001 an undeclared interaction key was dropped at parse — including the two #3752 removed, so an author who kept writing `zoom` after it was retired got exactly the same silence as before the removal.",aliases:{tooltip:`tooltips`,hover:`tooltips`,showTooltip:`tooltips`,rangeSelector:`brush`,slider:`brush`},guidance:{zoom:"`zoom` was removed in #3752 — no renderer ever had a zoom primitive behind it, and `brush` already narrows the visible range. Write `brush: true`.",clickAction:"`clickAction` was removed in #3752 — a segment click already has owners that work: the host's own `onSegmentClick` in the react tier, `drilldown` on a report (`ReportSchema.drilldown`, ADR-0021 D2, already on by default), and the renderer's segment drill under a dashboard widget's `options` bag. Use one of those."}},{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(()=>D({surface:`this chart drill-down block`,history:"Until #5022 `drillDown` was not declared anywhere in this protocol at all — objectui's ObjectChart read it as an untyped `(schema as any).drillDown`, so every key inside it, right or wrong, reached the renderer unchecked and a misspelling was simply ignored at click time.",aliases:{enable:`enabled`,on:`enabled`,active:`enabled`,where:`filter`,criteria:`filter`,filters:`filter`,label:`title`,heading:`title`,drawerTitle:`title`,display:`target`,open:`target`,openIn:`target`,presentation:`target`,fields:`columns`,columnList:`columns`,select:`columns`,limit:`maxRows`,pageSize:`maxRows`,rowLimit:`maxRows`,max:`maxRows`},guidance:{drilldown:"`drilldown` (all lowercase) is a different capability on a different surface: it is `ReportSchema.drilldown`, a BOOLEAN that switches row/cell drill on a `summary`/`matrix` report (ADR-0021 D2, on by default). The chart's drill-down is `drillDown` (camelCase) and takes a configuration OBJECT. If you meant the chart, fix the capital D; if you meant the report, move the key to the report and write `true`/`false`.",mode:"`mode` (`'filter'` | `'record'`) is a TABLE / PIVOT / METRIC drill key, not a chart one: it chooses whether a click drills through an aggregate to a filtered list or straight to one record. A chart segment is always an aggregate, so a chart drill is always the filtered-list kind and there is nothing to discriminate. Delete the key.",report:"`report` (drill into an analytical report instead of the record list) is a METRIC / PIVOT widget capability in the objectui renderer; `<ObjectChart>` does not read it and renders the record list regardless. Delete the key, or drill from a metric widget instead.",view:"`view` (render a named list view inside the drill drawer) is declared in objectui's renderer-side type as reserved and is read by no renderer at all (objectui#3354). It has never done anything — delete it and use `columns` to choose what the drill list shows.",sort:"`sort` (default ordering for the drill list) is declared in objectui's renderer-side type and read by no renderer (objectui#3354). Delete it; the drill list uses the object's own default ordering."}},{enabled:t.z.boolean().optional().describe(`Turn the segment drill on/off; the block being present already means on, so this is only needed to force it off`),filter:t.z.record(t.z.string(),t.z.unknown()).optional().describe("Filter for the drilled list; values support ${event.*}. Omit to derive it from the clicked category"),title:t.z.string().optional().describe("Drill drawer/dialog heading; supports ${event.*} interpolation"),target:t.z.enum([`drawer`,`dialog`,`navigate`]).optional().describe(`Where the drilled list opens: 'drawer' (default, side sheet), 'dialog' (centered modal), or 'navigate' (skip the in-place view and open the object's full list page; needs host drill navigation, else falls back to 'drawer')`),columns:t.z.array(t.z.string()).optional().describe(`Field names to show as columns in the drilled list (default: the table's own columns)`),maxRows:t.z.number().int().positive().optional().describe(`Rows per page in the drilled list`)})),n(()=>D({surface:`this chart config`,history:`Until #4001 an undeclared chart key was dropped at parse and the chart rendered with the defaults it was written to override — the failure #4001 exists for, on a shape reachable from both the dashboard and report metadata roots.`,aliases:{chartType:`type`,kind:`type`,visualization:`type`,palette:`colors`,colorScheme:`colors`,colours:`colors`,legend:`showLegend`,showLegends:`showLegend`,dataLabels:`showDataLabels`,showLabels:`showDataLabels`,labels:`showDataLabels`,annotation:`annotations`,referenceLines:`annotations`,markers:`annotations`,interactions:`interaction`,interactivity:`interaction`,caption:`subtitle`,subTitle:`subtitle`,accessibility:`aria`,ariaProps:`aria`,plotHeight:`height`,xAxes:`xAxis`,yAxes:`yAxis`},guidance:{width:"`width` is not a chart-level key: a chart fills its container, and the container's width is owned by the dashboard widget's `layout.w` (or the report block). Only `height` is chart-level.",aggregate:"`aggregate` is not part of the chart config. On a DASHBOARD widget the pre-ADR-0021 inline analytics shape was removed — bind a `dataset` and select `dimensions` + `values`. On a react `<ObjectChart>` it is a sibling PROP next to `objectName`, not a key inside the chart config.",objectName:"`objectName` is not part of the chart config — the data binding lives one level up: `dataset` on a dashboard widget (ADR-0021), or the `objectName` PROP on a react `<ObjectChart>`.",dataset:"`dataset` is not part of the chart config — it is the dashboard widget's own key (ADR-0021), a sibling of `chartConfig`, not a key inside it.",data:"`data` is not part of the chart config. Inline/precomputed rows are a react-tier `<ObjectChart data={…}>` prop; a metadata chart gets its rows from the widget's `dataset` binding.",stacked:"`stacked` is not a chart-level key, because stacking is not a chart family: it is a property of the SERIES. Give the series that should stack a shared `series[].stack` group id; series without one are grouped.",axes:"`axes` is not a key — the two axes are declared separately and asymmetrically: `xAxis` is a single axis, `yAxis` is an ARRAY (that is how dual-axis and combo charts are configured).",options:"`options` is not part of the chart config — renderer-only presentation extras belong in the dashboard widget's `options` bag, which is deliberately open for exactly that.",drillDown:"`drillDown` is not part of the chart config — it is a REACT-TIER prop, written beside `objectName`/`aggregate`: `<ObjectChart objectName=\"…\" drillDown={{ columns: ['name'], maxRows: 50 }} />`. On a DASHBOARD widget there is no per-widget drill configuration at all: an ADR-0021 dataset-bound widget drills through the semantic layer (the drill target and filter come from the clicked dataset row), so a `drillDown` written here would parse and then do nothing. On a REPORT the switch is `drilldown` — all lowercase, and a boolean."}},{type:ii,title:B.optional().describe(`Chart title`),subtitle:B.optional().describe(`Chart subtitle`),description:B.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:ai.optional().describe(`X-Axis configuration`),yAxis:t.z.array(ai).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(oi).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(si).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:ci.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:ti.optional().describe(`ARIA accessibility attributes`)}));var li=n(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),ui=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:li.describe(`Aggregation function`),groupBy:ui.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 di=`Until #4001 closed this shape these were dropped silently — the form still published, without whatever the key was meant to open up, gate or expire.`,fi=n(()=>D({surface:`this sharing config`,history:di,aliases:{public:`enabled`,isPublic:`enabled`,shared:`enabled`,active:`enabled`,url:`publicLink`,link:`publicLink`,shareUrl:`publicLink`,shareLink:`publicLink`,slug:`publicLink`,anonymous:`allowAnonymous`,allowGuest:`allowAnonymous`,allowGuests:`allowAnonymous`,publicAccess:`allowAnonymous`,domains:`allowedDomains`,allowedDomain:`allowedDomains`,emailDomains:`allowedDomains`,expires:`expiresAt`,expiry:`expiresAt`,expiration:`expiresAt`,validUntil:`expiresAt`}},{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`)})),pi=t.z.enum([`update`,`delete`,`custom`]),mi=t.z.enum([`perRecord`,`aggregate`]),hi=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:le.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:y.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()),gi=T({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)."}),_i=n(()=>t.z.object({name:y.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:pi.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:mi.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(hi).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:b.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:gi}).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`."})})),V=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,vi=n(()=>t.z.discriminatedUnion(`provider`,[D({surface:"this `object` data source",history:V,aliases:{objectName:`object`}},{provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),D({surface:"this `api` data source",history:V,guidance:{url:"Set the URL inside the request block: `read: { url, method }` (or `write: { … }`) — the data source itself declares only `read` / `write`.",method:"Set the method inside the request block: `read: { url, method }` (or `write: { … }`).",fetch:"Use `read` for the fetch request and `write` for the submit request.",submit:"Use `write` for the submit request (and `read` for the fetch request)."}},{provider:t.z.literal(`api`),read:it.optional().describe(`Configuration for fetching data`),write:it.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),D({surface:"this `value` data source",history:V,aliases:{data:`items`,rows:`items`,records:`items`,values:`items`}},{provider:t.z.literal(`value`),items:t.z.array(t.z.unknown()).describe(`Static data array`)}),D({surface:"this `schema` data source",history:V,aliases:{type:`schemaId`,metadataType:`schemaId`,jsonSchema:`schema`}},{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.`)})])),yi=[`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`],bi={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 xi(e){return typeof e!=`string`||yi.includes(e)?e:bi[e]??bi[e.toLowerCase()]??e}var Si=[`id`],Ci=[`filter`,`sort`],wi=12,Ti="`id` is a console row key (the filter/sort builders stamp a `crypto.randomUUID()` per row for React) — it is not part of the authoring contract, and the write path removes it before validating. Delete it from authored metadata.";function Ei(e,t,n){if(n>wi||!e||typeof e!=`object`)return e;if(Array.isArray(e)){let r=!1,i=e.map(e=>{let i=Ei(e,t,n+1);return i!==e&&(r=!0),i});return r?i:e}let r=e,i;if(t)for(let e of Si)e in r&&(i??={...r},delete i[e]);for(let[e,t]of Object.entries(i??r)){let a=Ei(t,Ci.includes(e),n+1);a!==t&&(i??={...r},i[e]=a)}return i??e}function Di(e){return Ei(e,!1,0)}var Oi=n(()=>D({surface:`this filter rule`,history:V,guidance:{id:Ti}},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(xi,t.z.enum(yi)).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`)),ki=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`)),Ai=n(()=>D({surface:`this column summary configuration`,history:V},{type:ki.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),ji=n(()=>D({surface:`this column prefix`,history:V},{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`)),Mi=n(()=>D({surface:`this list column`,history:V},{field:t.z.string().describe(`Field name (snake_case)`),label:B.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([ki,Ai]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:ji.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`)})),Ni=n(()=>D({surface:`this selection configuration`,history:V},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),Pi=n(()=>D({surface:`this pagination configuration`,history:V},{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`)})),Fi=n(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),Ii=n(()=>D({surface:`this grouping field`,history:V},{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`)})),Li=n(()=>D({surface:`this grouping configuration`,history:V},{fields:t.z.array(Ii).min(1).describe(`Fields to group by (supports up to 3 levels)`)}).describe(`Record grouping configuration`)),Ri=n(()=>D({surface:`this gallery configuration`,history:V},{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`)),zi=n(()=>D({surface:`this timeline configuration`,history:V},{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`)),Bi=n(()=>D({surface:`this view sharing`,history:V},{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`)),Vi=n(()=>D({surface:`this row color configuration`,history:V},{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`)),Hi=n(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),Ui=n(()=>D({surface:`this user actions configuration`,history:V},{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`)),Wi=n(()=>D({surface:`this appearance configuration`,history:V},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array(Hi).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),Gi=n(()=>D({surface:`this view tab`,history:V},{name:y.describe(`Tab identifier (snake_case)`),label:B.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(Oi).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`)),Ki=n(()=>D({surface:`this user filter field`,history:V},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:B.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(D({surface:`this user filter option`,history:V,guidance:{count:"Per-option record counts are computed from the data, not authored. Set `showCount: true` on the filter FIELD to display them."}},{value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Option value`),label:B.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`)),qi=n(()=>D({surface:`these user filters`,history:V},{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(Ki).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(Gi).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)`),allowAddTab:t.z.boolean().optional().describe('Render an "add tab" affordance after the presets (tabs element). Page lists only — object views use `listViews` for named presets')}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),Ji=n(()=>D({surface:`this add record configuration`,history:V},{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`)),Yi=n(()=>D({surface:`this kanban configuration`,history:V},{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`)})),Xi=n(()=>D({surface:`this list chart configuration`,history:V},{chartType:ii.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:y.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`)),Zi=n(()=>D({surface:`this calendar configuration`,history:V},{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`)})),Qi=n(()=>D({surface:`this gantt quick filter`,history:V},{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(),D({surface:`this gantt quick-filter option`,history:V,aliases:{text:`label`,title:`label`,name:`label`,key:`value`,id:`value`}},{value:t.z.union([t.z.string(),t.z.number()]),label:t.z.string().optional()})])).optional().describe(`Explicit option override for fixed enums`)})),$i=n(()=>D({surface:`this gantt configuration`,history:V},{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(),D({surface:`this gantt tooltip field`,history:V,aliases:{name:`field`,fieldName:`field`,text:`label`,title:`label`}},{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(Qi).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()),ea=n(()=>D({surface:`this tree configuration`,history:V},{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()),ta=n(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),na=n(()=>D({surface:`this navigation configuration`,history:V},{mode:ta.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.')})),ra=n(()=>D({surface:`this list view`,history:V},{name:y.optional().describe(`Internal view name (lowercase snake_case)`),label:B.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:vi.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(Mi)]).describe(`Fields to display as columns`),filter:t.z.array(Oi).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(D({surface:`this sort entry`,history:V,aliases:{direction:`order`},guidance:{id:Ti}},{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:qi.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:Ni.optional().describe(`Row selection configuration`),navigation:na.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:Pi.optional().describe(`Pagination configuration`),kanban:Yi.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:Zi.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:$i.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:Ri.optional(),timeline:zi.optional(),chart:Xi.optional(),tree:ea.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:B.optional().describe(`View description for documentation/tooltips`),sharing:Bi.optional().describe(`View sharing and access configuration`),rowHeight:Fi.optional().describe(`Row height / density setting`),grouping:Li.optional().describe(`Group records by one or more fields`),rowColor:Vi.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(_i).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(D({surface:`this conditional formatting rule`,history:V,aliases:{when:`condition`,expression:`condition`,visibleWhen:`condition`,rule:`condition`,styles:`style`,css:`style`},guidance:{color:'Row colouring by field value has its own block — see `rowColor` on this list view. To set a CSS colour from a predicate, put it in `style`: `{ condition, style: { color: "#b91c1c" } }`.'}},{condition:b.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:Ui.optional().describe(`User action toggles for the view toolbar`),appearance:Wi.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(Gi).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:Ji.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:D({surface:`this empty state`,history:V,aliases:{description:`message`,text:`message`,subtitle:`message`,heading:`title`,label:`title`,image:`icon`},guidance:{action:'The empty state renders text only. Configure the "add record" entry point in the `addRecord` block on this list view.',button:'The empty state renders text only. Configure the "add record" entry point in the `addRecord` block on this list view.'}},{title:B.optional(),message:B.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:ti.optional().describe(`ARIA accessibility attributes for the list view`),responsive:p("`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:p("`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.")})),ia=n(()=>t.z.object({field:t.z.string().describe(`Field name (snake_case)`),type:le.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(S).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:B.optional().describe(`Display label override`),placeholder:B.optional().describe(`Placeholder text`),helpText:B.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:D({surface:`this record key field`,history:V,aliases:{key:`field`,name:`field`,pattern:`regex`,placeHolder:`placeholder`,help:`helpText`,hint:`helpText`}},{field:t.z.string().default(`name`).describe(`Property name that holds the key inside each item (defaults to "name")`),label:B.optional().describe(`Display label for the key column`),placeholder:B.optional().describe(`Placeholder when entering a new key`),helpText:B.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:b.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:b.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:$r})),aa=n(()=>ia.extend({fields:t.z.array(t.z.lazy(()=>aa)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(Zr)),oa=n(()=>t.z.object({name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:B.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:b.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record`+`current_user` (runtime forms) or `data` (metadata forms)."),visibleOn:b.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(),aa]))},{error:$r}).strict().transform(Zr)),sa=n(()=>D({surface:`this form button configuration`,history:V},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:B.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict()),ca=n(()=>D({surface:`this form view`,history:V},{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:vi.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(oa).optional(),groups:t.z.array(oa).optional(),subforms:t.z.array(D({surface:`this subform`,history:V,aliases:{object:`childObject`,childObjectName:`childObject`,child:`childObject`,foreignKey:`relationshipField`,relationField:`relationshipField`,parentField:`relationshipField`,fields:`columns`,label:`title`,sumField:`amountField`,rollupField:`totalField`}},{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:p("`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:fi.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.discriminatedUnion(`kind`,[D({surface:"this `thank-you` submit behavior",history:V,aliases:{heading:`title`,text:`message`,body:`message`,description:`message`}},{kind:t.z.literal(`thank-you`),title:t.z.string().optional(),message:t.z.string().optional()}),D({surface:"this `redirect` submit behavior",history:V,aliases:{delay:`delayMs`,delayMS:`delayMs`,timeout:`delayMs`,to:`url`,href:`url`,target:`url`}},{kind:t.z.literal(`redirect`),url:t.z.string(),delayMs:t.z.number().int().min(0).optional()}),D({surface:"this `continue` submit behavior",history:V,guidance:{title:'The `continue` behavior takes no options — it just resets the form. For a confirmation panel use `{ kind: "thank-you", title, message }`.',message:'The `continue` behavior takes no options — it just resets the form. For a confirmation panel use `{ kind: "thank-you", title, message }`.'}},{kind:t.z.literal(`continue`)}),D({surface:"this `next-record` submit behavior",history:V,guidance:{title:'The `next-record` behavior takes no options — it advances to the next record. For a confirmation panel use `{ kind: "thank-you", title, message }`.',message:'The `next-record` behavior takes no options — it advances to the next record. For a confirmation panel use `{ kind: "thank-you", title, message }`.'}},{kind:t.z.literal(`next-record`)})]).optional().describe(`Post-submit behavior`),buttons:t.z.object({submit:sa.optional().describe(`Submit button`),cancel:sa.optional().describe(`Cancel button`),reset:sa.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:p("`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.`})})})),la=n(()=>D({surface:`these object user filters`,history:V,guidance:{tabs:"`tabs` presets are page-only: an object view's tab bar is its saved-view switcher (ViewTabBar), and a second one would collide. Define each preset as a named entry under the object's `listViews` instead — every one renders as a segmented tab.",showAllRecords:'`showAllRecords` configures the page-only `tabs` element. On an object view the default list view already is the "all records" entry; use `listViews` for the named presets beside it.',allowAddTab:"`allowAddTab` configures the page-only `tabs` element. An object view's tab bar is the saved-view switcher (ViewTabBar), which owns its own add control."}},{...qi.omit({tabs:!0,showAllRecords:!0,allowAddTab:!0}).shape,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.')})),ua=n(()=>ra.omit({userFilters:!0}).extend({userFilters:la.optional()})),H=n(()=>D({surface:`this view container`,history:V,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:B.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:ua.optional(),form:ca.optional(),listViews:t.z.record(t.z.string(),ua).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),ca).optional().describe(`Additional named form views`),protection:z.optional().describe(`Package author protection block — lock policy for this view.`),..._})),da=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>`."),fa=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),pa=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function ma(){return{name:da,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:B.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:fa.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:z.optional().describe(`Package author protection block — lock policy for this view.`),..._}}function ha(e,n){return{viewKind:t.z.literal(e),config:n,...ma()}}var ga={surface:`this view item`,history:V,guidance:{confg:"Did you mean `config`? A ViewItem carries its whole view definition under `config`.",isPinned:"Pinning is per-user Studio state, not authored metadata — the console writes it through the `view` metadata API. Remove it from authored metadata.",sortOrder:"Switcher position is per-user Studio state, not authored metadata — use `order` for the authored default. Remove it from authored metadata."}};n(()=>t.z.discriminatedUnion(`viewKind`,[D(ga,ha(`list`,ra.describe(`List-family view configuration.`))),D(ga,ha(`form`,ca.describe(`Form view configuration.`)))]));function _a(){return{isPinned:t.z.boolean().optional().describe(`Studio round-trip: view pinned in the switcher (per-user state, written by the console — not authored).`),sortOrder:t.z.number().int().optional().describe(`Studio round-trip: position within the switcher (per-user state, written by the console — not authored).`)}}var va=n(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({...ha(`list`,ra.describe(`List-family view configuration.`)),..._a()}).strip(),t.z.object({...ha(`form`,ca.describe(`Form view configuration.`)),..._a()}).strip()]));function ya(){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:pa.optional().describe(`View family (inherited from the shadowed entry — #2555).`),label:B.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:fa.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:z.optional(),..._,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 ba(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.preprocess(Di,t.z.union([va,H.refine(ba,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."}),ra.extend(ya()).strip(),ca.extend(ya()).strip()])));var xa=t.z.enum([`select`,`insert`,`update`,`delete`,`all`]),Sa=T({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.`}),Ca=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:xa.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:p("`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:Sa}).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 wa={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`),..._},Ta=n(()=>D({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`}},{...wa,type:t.z.literal(`script`),condition:b.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),Ea=n(()=>D({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`}},{...wa,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.")})),Da=n(()=>D({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`}},{...wa,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),Oa=n(()=>D({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`}},{...wa,type:t.z.literal(`cross_field`),condition:b.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.`)})),ka=n(()=>D({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`}},{...wa,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`)})),Aa=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[Ta,Ea,Da,Oa,ka,ja])),ja=n(()=>D({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`}},{...wa,type:t.z.literal(`conditional`),when:b.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:Aa.describe(`Validation rule to apply when condition is true`),otherwise:Aa.optional().describe(`Validation rule to apply when condition is false`)})),Ma='`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.',Na=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?Ma:void 0}),Pa=[`language`,`source`],Fa=[`language`,`source`,`capabilities`,`timeoutMs`,`memoryMb`],Ia='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.',La=T({surface:`this expression (L1) hook body`,knownKeys:Pa,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${Ia}`,timeoutMs:`\`timeoutMs\` ${Ia}`,memoryMb:`\`memoryMb\` ${Ia}`},history:`Until #4001 these were dropped silently.`}),Ra=T({surface:`this sandboxed JS (L2) hook body`,knownKeys:Fa,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.`}),za=t.z.object({language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)},{error:La}).strict().describe(`L1 expression body — pure formula, no IO`),Ba=t.z.object({language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(Na).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:Ra}).strict().describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),Va=t.z.discriminatedUnion(`language`,[za,Ba]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),Ha={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).`}}},Ua=Object.keys(Ha);function Wa(e){return`features.${e} ${Ha[e].semantics===`opt-in`?`== true`:`!= false`}`}function Ga(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=Wa(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 Ka=[`name`,`field`,`objectOverride`,`label`,`type`,`required`,`options`,`placeholder`,`helpText`,`defaultValue`,`multiple`,`accept`,`maxSize`,`reference`,`defaultFromRow`,`visible`,`requiresFeature`],qa={referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},Ja=e=>`\`${e}\` is a per-option key of a FIELD's option list (\`SelectOptionSchema\` in \`data/field.zod.ts\`), where the object form and grid do read it. An action param's options are \`{ label, value }\` \u2014 and the action metadata door has always stripped anything else before a renderer could see it, so writing \`${e}\` here has never had an effect. Whether this surface should carry the full per-option vocabulary is #5016; do not rely on it today.`,Ya=e=>`no option shape in the spec declares \`${e}\` \u2014 not this one, and not the field-level \`SelectOptionSchema\`. It exists only inside objectui's own \`SelectOptionMetadata\` type, which no metadata path populates. An action param's options are \`{ label, value }\`; drop the key.`,Xa=T({surface:`this action param`,knownKeys:Ka,aliases:qa,history:`Until #3405 these were dropped silently — the param still parsed, so a mis-spelled config shipped as a control that quietly ignored it.`}),Za=n(()=>t.z.object({name:t.z.string().optional(),field:y.optional(),objectOverride:y.optional(),label:B.optional(),type:le.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(D({surface:`this action param option`,history:`Until #4001 批 14 closed this shape these were dropped silently — the param still rendered its picker, minus whatever the key was meant to colour, gate or disable.`,aliases:{text:`label`,name:`label`,title:`label`,key:`value`,id:`value`,optionValue:`value`,optionLabel:`label`,displayName:`label`},guidance:{color:Ja(`color`),visibleWhen:Ja(`visibleWhen`),icon:Ya(`icon`),disabled:Ya(`disabled`),default:"`default` on an OPTION is the field-level picklist default (`SelectOptionSchema.default`). A dialog param defaults through `defaultValue` on the PARAM itself, one level up — write `defaultValue: '<value>'` there."}},{label:B,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:y.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:b.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(Ua).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")},{error:Xa}).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)=>Ga(e,t))),Qa=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),$a=new Set(Qa.options.filter(e=>e!==`script`)),eo=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`,`global_nav`]),to=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),no=`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.`,ro=D({surface:`this action's AI exposure block`,history:no,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:to.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),D({surface:`this AI parameter hint`,history:no,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.`)}),io=()=>D({surface:`this action`,history:no,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`,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:y.describe(`Machine name (lowercase snake_case)`),label:B.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(eo).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:Qa.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:Va.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:p("`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(Za).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:B.optional().describe(`Confirmation message before execution`),successMessage:B.optional().describe(`Success message to show after execution`),errorMessage:B.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:D({surface:`this result dialog`,history:no,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:B.optional(),description:B.optional(),acknowledge:B.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(D({surface:`this result dialog field`,history:no,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:B.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:b.optional().describe(`Visibility predicate (CEL).`),requiresFeature:t.z.enum(Ua).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:t.z.union([t.z.boolean(),b]).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:p("`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:p("`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:ro.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`),D({surface:`this body shape`,history:no,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:ti.optional().describe(`ARIA accessibility attributes`),..._}),ao=n(()=>io().refine(e=>!($a.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)=>Ga(e,t)));function oo(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(oo,io().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=>!($a.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 so=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),co=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],lo={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"},uo=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`]),fo=new Set(co),po=new Set;function mo(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&fo.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&fo.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return po.has(i)||(po.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
|
+
`+n.map(e=>` \u2022 \`${e}\`: ${lo[e]}`).join(`
|
|
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
|
+
Codemod: node scripts/codemod/apimethods-legacy-to-primitives.mjs`)),r}var ho={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."},go=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=>mo(e),t.z.array(so)).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=>ho[e]??`\`${e}\` is not an \`enable\` capability flag.`);return`Unrecognized key(s) on \`enable\`: ${t.map(e=>`\`${e}\``).join(`, `)}.
|
|
22
|
+
`+n.map(e=>` \u2022 ${e}`).join(`
|
|
23
|
+
`)}}).strict(),_o=n(()=>t.z.object({name:t.z.string().optional().describe(`Index name (auto-generated if not provided)`),fields:t.z.array(t.z.string()).describe(`Fields included in the index`),unique:fe.optional().default(!1).describe("Whether the index enforces uniqueness, and at which scope (ADR-0120). 'global' = materialized over exactly `fields`, no organization column injected — one holder across the whole installation; 'organization' = the driver prepends the NULL-safe organization key part (COALESCE(organization_id, '__global__')) at registration — one holder per organization; bare true = deprecated positional spelling of 'global' (warned in 17.x by lint unique/unscoped-declared-index, rejected at protocol 18, #5082) — state the scope. 'tenant'/'org' are rejected — the word is 'organization'"),type:p("`indexes[].type` was removed in @objectstack/spec 17.0.0 (#5248, ADR-0049) — no driver ever read it. `SqlDriver.syncDeclaredIndexes` creates every declared index through knex's `table.index()` / `table.unique()`, which cannot express an access method, so the value changed no DDL; its `.default('btree')` merely made an inert knob show up in every parse output. Delete the key. The index method is the driver/dialect's decision (Postgres defaults to B-tree; `gin`/`gist`/`fulltext` are dialect-specific and are chosen by a database-layer migration when a workload actually needs one). Run `os migrate meta --from 16` to rewrite it automatically."),partial:p("`indexes[].partial` was removed in @objectstack/spec 17.0.0 (#5248, #4943, ADR-0049) — no driver ever emitted the `WHERE` clause, so a declared partial index was materialized as a FULL index and the predicate silently did nothing. Delete the key. Partial indexes are built at the database layer, not the declaration surface: issue `CREATE [UNIQUE] INDEX … WHERE <predicate>` from a runtime migration (this is what `metadata-protocol`'s `ensureOverlayIndex` already does for `sys_metadata`). Drift detection is unaffected — it reads partiality back from the database's own DDL, never from this key. Run `os migrate meta --from 16` to rewrite it automatically.")})),vo={strategy:"`tenancy.strategy` was removed from @objectstack/spec after v15.0 (#2763) — it never had a consumer. The platform has exactly two tenancy modes and neither is object-level config: database-per-tenant isolation is an environment/deployment choice (each environment carries its own database URL), and row-level isolation is `tenancy.enabled` + `tenancy.tenantField`. Delete the key.",crossTenantAccess:"`tenancy.crossTenantAccess` was removed from @objectstack/spec after v15.0 (#2763) — it never had a consumer; setting it granted nothing. Cross-tenant visibility is governed by sharing rules / OWD (ADR-0056), `externalSharingModel` (ADR-0090 D11), and the object access posture. Delete the key."},yo=e=>{if(e.code!==`unrecognized_keys`)return;let t=e.keys??[],n=t.map(e=>vo[e]??`\`${e}\` is not a \`tenancy\` key.`);return`Unrecognized key(s) on \`tenancy\`: ${t.map(e=>`\`${e}\``).join(`, `)}. The two supported tenancy modes are: database-per-tenant = environment-level deployment (no object config); row-level isolation = \`tenancy.enabled\` + \`tenancy.tenantField\`.
|
|
24
|
+
`+n.map(e=>` \u2022 ${e}`).join(`
|
|
25
|
+
`)},U=n(()=>t.z.object({enabled:t.z.boolean().describe(`Enable multi-tenancy for this object`),tenantField:t.z.string().optional().describe("Column this object is tenant-scoped by. Omit it unless the tenant column genuinely is not the platform's: when undeclared the driver falls back to `organization_id`, the kernel-injected column the RLS predicates and `tenantPolicy()` also assume. A declared name is honoured only when the object really has that field — otherwise the same `organization_id` fallback applies. No default is materialized here on purpose (#5315).")},{error:yo}).strict()),bo=n(()=>D({surface:"this object's `access` block",history:"Until #4001 these were dropped silently — the block still parsed, so an object the author declared `private` shipped `public`: covered by every `'*'` wildcard grant, with no signal that the posture had been discarded.",aliases:{visibility:`default`,posture:`default`,defaultAccess:`default`},guidance:{sharingModel:"`sharingModel` is the object-wide default record visibility (OWD) and is a TOP-LEVEL object key, not an `access` key — write it beside `access`, not inside it. `access.default` decides wildcard-GRANT coverage; `sharingModel` decides record visibility between users (ADR-0090).",requiredPermissions:"`requiredPermissions` is a TOP-LEVEL object key (ADR-0066 D3) — it gates access on the caller HOLDING a capability, which is a different axis from `access.default` (whether a wildcard grant covers this object at all). Pair them, side by side."}},{default:t.z.enum([`public`,`private`]).default(`public`).describe(`Default exposure posture: public (covered by wildcard grants) | private (needs explicit grant; exempt from wildcard RLS).`)})),xo=t.z.object({read:t.z.array(t.z.string()).optional().describe(`Capabilities required to read (find/findOne/count/aggregate).`),create:t.z.array(t.z.string()).optional().describe(`Capabilities required to create (insert).`),update:t.z.array(t.z.string()).optional().describe(`Capabilities required to update (update/transfer/restore).`),delete:t.z.array(t.z.string()).optional().describe(`Capabilities required to delete (delete/purge).`)}).strict(),So=t.z.union([t.z.array(t.z.string()),xo]),Co=t.z.enum([`record`,`audit`,`telemetry`,`transient`,`event`]),wo=/^\d+(h|d|w|y)$/,To=e=>t.z.string().regex(wo,`${e} must be a duration literal like '6h', '14d', '12w' or '7y'`),Eo=n(()=>D({surface:"this object's `lifecycle` block",history:`Until #4001 these were dropped silently — the block still parsed, so a bounding policy written one level too high left the object with NO policy at all. ADR-0057 §3.5's own refine then passed, because the key it looks for was never there.`,aliases:{rotation:`storage`},guidance:{maxAge:"`maxAge` belongs to the retention block, one level down: `retention: { maxAge: '30d' }`. Written here it is not read, and a non-`record` class with no `retention`/`ttl`/`storage` is rejected as unbounded (ADR-0057 §3.5).",expireAfter:"`expireAfter` belongs to the TTL block, one level down: `ttl: { field: 'expires_at', expireAfter: '1d' }`.",field:"`field` belongs to the TTL block, one level down — it names the timestamp the TTL is measured from: `ttl: { field: 'expires_at', expireAfter: '1d' }`.",after:"`after` belongs to the archive block, one level down: `archive: { after: '7y', to: 'cold_store' }` — and ADR-0057 requires it to EQUAL `retention.maxAge`.",to:"`to` belongs to the archive block, one level down — it names the cold-storage datasource: `archive: { after: '7y', to: 'cold_store' }`.",keep:"`keep` belongs to the archive block, one level down — it is how long COLD rows are kept. The HOT window is `retention.maxAge`.",strategy:"`strategy` belongs to the storage block, one level down: `storage: { strategy: 'rotation', shards: 7, unit: 'day' }`.",shards:"`shards` belongs to the storage block, one level down: `storage: { strategy: 'rotation', shards: 7, unit: 'day' }`.",unit:"`unit` belongs to the storage block, one level down: `storage: { strategy: 'rotation', shards: 7, unit: 'day' }`."}},{class:Co.describe(`Persistence contract: record (business truth, permanent) | audit (compliance ledger) | telemetry (high-freq log) | transient (ephemeral state) | event (bus messages).`),retention:D({surface:"this object's `lifecycle.retention` block",history:`Until #4001 these were dropped silently — the retention window still parsed, so a row filter written under the wrong key reaped rows the author had meant to exempt.`,aliases:{filter:`onlyWhen`,where:`onlyWhen`,when:`onlyWhen`,age:`maxAge`},guidance:{expireAfter:"`expireAfter` is a `ttl` key, not a retention key. Retention reaps by AGE from `created_at` (`maxAge`); TTL expires each row relative to a timestamp field you name (`ttl.field`). Pick the one that matches how the rows die.",keep:"`keep` is an `archive` key — how long COLD rows survive. The hot window is `retention.maxAge`."}},{maxAge:To(`retention.maxAge`).describe("Rows older than this (by created_at) are deleted by the Reaper — or archived first when `archive` is set."),onlyWhen:t.z.record(t.z.string(),t.z.union([t.z.string(),t.z.number(),t.z.boolean(),t.z.object({$in:t.z.array(t.z.union([t.z.string(),t.z.number()])).min(1)}).strict()])).optional().describe(`Row filter the retention applies to — per-field equality or {$in: [...]} (e.g. { status: { $in: ["completed", "failed"] } }). Rows OUTSIDE the filter are retained regardless of age: for tables that interleave live workflow state with terminal history (sys_automation_run). Incompatible with rotation storage and archive, which act on whole shards / age alone.`)}).optional().describe(`Age-based retention window enforced by the LifecycleService Reaper.`),ttl:D({surface:"this object's `lifecycle.ttl` block",history:`Until #4001 these were dropped silently — the TTL block still parsed, so rows the author expected to auto-expire lived forever.`,aliases:{expiresAfter:`expireAfter`,after:`expireAfter`,timestampField:`field`,on:`field`},guidance:{maxAge:"`maxAge` is a `retention` key, not a TTL key. TTL measures from the timestamp field named in `ttl.field`; retention measures AGE from `created_at`. For age-based reaping write `retention: { maxAge: '30d' }` instead."}},{field:t.z.string().describe(`Timestamp field the TTL is measured from (e.g. created_at, expires_at).`),expireAfter:To(`ttl.expireAfter`).describe("Rows expire this long after `field` and are deleted by the Reaper.")}).optional().describe(`Per-row TTL auto-expiry (transient/event classes).`),storage:D({surface:"this object's `lifecycle.storage` block",history:`Until #4001 these were dropped silently — the rotation block still parsed, so a telemetry table declared as rotating kept every shard it ever cut.`,aliases:{count:`shards`,interval:`unit`,period:`unit`,granularity:`unit`},guidance:{maxAge:"`maxAge` is a `retention` key. Rotation does not reap by age — it retains `shards` × `unit` of history and DROPs the oldest shard whole. Set the window with `shards`/`unit`, or use `retention` instead of rotation."}},{strategy:t.z.literal(`rotation`).describe(`Time-shard the table; rotate by DROPping the oldest shard (O(1) reclaim).`),shards:t.z.number().int().min(2).describe(`Number of shards retained; total window = shards × unit.`),unit:t.z.enum([`day`,`week`,`month`]).describe(`Time width of one shard.`)}).optional().describe(`Physical storage strategy for high-frequency telemetry (LifecycleService Rotator).`),archive:D({surface:"this object's `lifecycle.archive` block",history:`Until #4001 these were dropped silently — the archive block still parsed, so audit rows were reaped hot with no cold copy ever written.`,aliases:{datasource:`to`,target:`to`,destination:`to`,retain:`keep`},guidance:{maxAge:"`maxAge` is a `retention` key. The archive boundary is `archive.after`, and ADR-0057 requires the two to be EQUAL — the hot window ends exactly where the archive begins, so declare `retention.maxAge` and `archive.after` with the same value."}},{after:To(`archive.after`).describe(`Rows older than this are copied to the archive datasource before hot deletion.`),to:t.z.string().describe(`Target datasource name for cold storage. When it is not registered, the Archiver skips (audit rows are then retained, never dropped unarchived).`),keep:To(`archive.keep`).optional().describe(`How long archived rows are kept in cold storage (undefined = forever).`)}).optional().describe(`Cold-store archival (LifecycleService Archiver) — audit-class hot→cold hand-off.`),reclaim:t.z.boolean().optional().describe(`Run driver space reclamation (SQLite incremental_vacuum) after sweeping this object. Default true for non-record classes.`)}).superRefine((e,n)=>{e.class!==`record`&&!e.retention&&!e.ttl&&!e.storage&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.class '${e.class}' requires at least one bounding policy: retention, ttl, or storage (rotation) \u2014 ADR-0057 \xA73.5`}),e.class===`record`&&(e.retention||e.ttl||e.storage||e.archive)&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.class 'record' is permanent business truth — retention/ttl/storage/archive policies are not allowed on it (ADR-0057 §3.1)`}),e.archive&&e.retention&&e.archive.after!==e.retention.maxAge&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.archive.after ('${e.archive.after}') must equal retention.maxAge ('${e.retention.maxAge}') \u2014 the hot window ends where the archive begins`}),e.retention?.onlyWhen&&e.storage?.strategy===`rotation`&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.retention.onlyWhen cannot be combined with rotation storage — the Rotator DROPs whole shards and would destroy rows the filter protects`}),e.retention?.onlyWhen&&e.archive&&n.addIssue({code:t.z.ZodIssueCode.custom,message:`lifecycle.retention.onlyWhen cannot be combined with archive — the Archiver moves rows by age alone and would archive rows the filter protects`})})),Do=n(()=>D({surface:`this field group`,history:`Until #4001 these were dropped silently — the group still parsed AND still rendered, which is the worst version of the failure: the section appeared, so the author had every reason to believe the setting they wrote had been applied.`,aliases:{title:`label`,name:`key`,id:`key`,help:`description`,helpText:`description`},guidance:{fields:"`fields` does not live on a group — membership is declared on the FIELD, pointing back: `fields: { email: { type: 'email', group: 'contact_info' } }`. The group declares only its `key`, `label` and presentation; `deriveFieldGroupLayout` (ADR-0085 §5) does the assembly.",order:"`order` is not a group key — ARRAY ORDER is display order. `fieldGroups: [...]` renders top to bottom, so move the entry rather than numbering it.",expanded:"`expanded` is not a group key — use the `collapse` enum: `collapse: 'expanded'` (collapsible, starts open), `'collapsed'` (starts closed), or `'none'` (always open, no toggle).",visibleWhen:"`visibleWhen` was REMOVED from field groups (ADR-0085 / ADR-0049 enforce-or-remove) — it existed here briefly with no consumer on any surface, so it never gated anything. Gate the individual fields, or assign a Page for per-surface control.",visibleOn:"`visibleOn` is not a field-group key — group-level visibility predicates were removed under ADR-0085 / ADR-0049 (nothing evaluated them). Gate the individual fields, or assign a Page."}},{key:t.z.string().regex(/^[a-z_][a-z0-9_]*$/,{message:`Field group key must be lowercase snake_case (e.g., "contact_info", "billing", "system")`}).describe(`Group machine key (snake_case). Referenced by Field.group.`),label:t.z.string().describe(`Group display label`),icon:t.z.string().optional().describe(`Icon name (Lucide/Material) for the group header`),description:t.z.string().optional().describe(`Optional description shown under the group header`),collapse:t.z.enum([`none`,`expanded`,`collapsed`]).optional().default(`none`).describe(`[ADR-0085] Section collapse behaviour: 'none' (always open, no toggle), 'expanded' (collapsible, starts open), 'collapsed' (collapsible, starts closed).`),defaultExpanded:t.z.boolean().optional().describe(`[DEPRECATED → collapse] true → 'expanded', false → 'collapsed'.`),collapsible:t.z.boolean().optional().describe("[DEPRECATED → collapse] Boolean pair with `collapsed`; use the `collapse` enum."),collapsed:t.z.boolean().optional().describe("[DEPRECATED → collapse] Boolean pair with `collapsible`; use the `collapse` enum.")})),Oo=D({surface:"this object's `external` binding (ADR-0015)",history:`Until #4001 these were dropped silently — the binding still parsed, so a federated object bound to the wrong remote table, or shipped read-only after the author had explicitly asked for writes.`,aliases:{table:`remoteName`,tableName:`remoteName`,remoteTable:`remoteName`,schema:`remoteSchema`,columns:`columnMap`,skipColumns:`ignoreColumns`,excludeColumns:`ignoreColumns`},guidance:{allowWrites:"`allowWrites` is the DATASOURCE-level gate (`datasource.external.allowWrites`). The per-object opt-in is spelled `writable: true`. ADR-0015 requires BOTH — set `writable` here and `allowWrites` on the datasource; either one alone leaves the object read-only.",schemaMode:"`schemaMode` is a DATASOURCE key, not an object key — an object becomes external by being routed to a datasource whose `schemaMode !== 'managed'`. This block only describes the remote binding once that is true."}},{remoteName:t.z.string().optional().describe(`Remote table/view name. Defaults to object.name.`),remoteSchema:t.z.string().optional().describe(`Remote schema/database qualifier.`),writable:t.z.boolean().default(!1).describe(`Per-object write opt-in (also requires datasource.external.allowWrites).`),columnMap:t.z.record(t.z.string(),t.z.string()).optional().describe(`Remote column name → local field name.`),introspectedAt:t.z.string().datetime().optional().describe("Set by `os datasource introspect`; informational."),ignoreColumns:t.z.array(t.z.string()).optional().describe(`Remote columns to skip during validation (dev convenience).`)}).describe(`External datasource binding (ADR-0015)`),ko=t.z.object({enabled:t.z.boolean().optional().describe(`Object-level on/off for the generic affordance; same meaning as the bare boolean form. Omitted → managedBy bucket default.`),visibleWhen:b.optional().describe(`Per-record CEL predicate; false → hide the row button for that record. Fail-closed.`),disabledWhen:b.optional().describe(`Per-record CEL predicate; true → render the row button disabled for that record. Fail-soft.`)}).strict().describe(`Boolean-or-predicates override for a built-in row CRUD affordance.`),Ao,jo=e=>(Ao??=T({surface:`this object`,knownKeys:Object.keys(W.shape),aliases:{capabilities:`enable`,features:`enable`},guidance:Po,history:"Until #4001 closed this shape these were dropped silently on the PARSE path — `ObjectSchema.create()` has rejected them since #1535, but `defineStack({ objects })`, `/api/v1/meta/types/object` and the Studio form all go through `parse()`, which did not."}))(e),Mo="`object.managedBy: 'system'` was removed in @objectstack/spec 17 (#3355, ADR-0103 v17 addendum) — v16 moved every engine-owned object to `engine-owned`, leaving `system` labelling admin/user-writable platform DATA under a name that says the opposite. Use `managedBy: 'system-data'` (platform-defined schema, admin/user-writable data; authz stays the DelegatedAdminGate / RLS / permission sets). Rename the value; nothing else about the object changes. Note `system-data` defaults to FULL CRUD affordances (the old `system` default was locked), so a `userActions` block that existed only to re-open create/edit/delete is now redundant and can be deleted — keep it only to NARROW. Run `os migrate meta --from 16` to rewrite it automatically.",W=t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Machine unique key (snake_case). Immutable.`),label:t.z.string().optional().describe(`Human readable singular label (e.g. "Account")`),pluralLabel:t.z.string().optional().describe(`Human readable plural label (e.g. "Accounts")`),description:t.z.string().optional().describe(`Developer documentation / description`),icon:t.z.string().optional().describe(`Icon name (Lucide/Material) for UI representation`),isSystem:t.z.boolean().optional().default(!1).describe(`Is system object (protected from deletion; defaults its org-wide sharing to public when no sharingModel is set — plugin-sharing)`),managedBy:t.z.enum([`platform`,`config`,`system-data`,`engine-owned`,`append-only`,`better-auth`],{error:e=>e.input===`system`?Mo:void 0}).optional().describe(`Lifecycle bucket — platform (user CRUD) | config (admin authored) | system-data (platform-defined schema, admin/user-writable data) | engine-owned (engine owns the lifecycle, no user writes) | append-only (audit) | better-auth (identity). UI clients honour the resolved affordance matrix.`),ownership:t.z.enum([`user`,`org`,`none`],{error:"`ownership` is the record-ownership model — one of 'user' (default) | 'org' | 'none'. The package-contribution kind 'own'/'extend' is set via registerObject, not on the object schema."}).optional().describe(`Record-ownership model: user (default — injects reassignable owner_id) | org | none (no per-record owner, skips owner_id). Distinct from the package own/extend contribution kind.`),userActions:D({surface:"this object's `userActions` block",history:"Until #4001 these were dropped silently — the block still parsed, so an affordance the author meant to hide stayed on the toolbar, and the `managedBy`-derived default silently won.",aliases:{export:`exportCsv`,csvExport:`exportCsv`,exportcsv:`exportCsv`,new:`create`,add:`create`,insert:`create`,update:`edit`,remove:`delete`,destroy:`delete`},guidance:{sort:"`sort` is a VIEW `userActions` key, not an object one — the two blocks share a name and nothing else. The object block governs CRUD affordances (create/import/edit/delete/exportCsv); toolbar controls (sort/search/filter/refresh/rowHeight/editInline) live on the view.",search:"`search` is a VIEW `userActions` key. This object block governs CRUD affordances only — put toolbar controls on the view that renders the records.",filter:"`filter` is a VIEW `userActions` key. This object block governs CRUD affordances only — put toolbar controls on the view that renders the records.",editInline:"`editInline` is a VIEW `userActions` key. The object-level `edit` flag decides whether editing is offered AT ALL; how it is offered (inline vs form) is the view's call.",clone:"`clone` is a CAPABILITY, not a user action — write `enable: { clone: false }`. The `enable` block (ObjectCapabilities) is where record deep-cloning is governed.",read:"`userActions` toggles WRITE affordances only; there is no read toggle. Read access is governed by permissions (`requiredPermissions`) and `access.default`.",view:"`userActions` toggles WRITE affordances only; there is no view toggle. Visibility is governed by permissions (`requiredPermissions`) and `access.default`."}},{create:t.z.boolean().optional().describe(`Show generic "New" button.`),import:t.z.boolean().optional().describe(`Show CSV import wizard entry.`),edit:t.z.union([t.z.boolean(),ko]).optional().describe(`Allow inline / form edit of existing rows. Boolean, or an object adding per-record visibleWhen/disabledWhen CEL predicates.`),delete:t.z.union([t.z.boolean(),ko]).optional().describe(`Show row-level delete + bulk delete. Boolean, or an object adding per-record visibleWhen/disabledWhen CEL predicates.`),exportCsv:t.z.boolean().optional().describe(`Show CSV export entry.`)}).optional().describe(`Per-object override of the resolved CRUD affordance matrix.`),systemFields:t.z.union([t.z.literal(!1),D({surface:"this object's `systemFields` block",history:`Until #4001 these were dropped silently — the block still parsed, so an opt-out the author wrote had no effect and the registry injected the column anyway.`,aliases:{organization:`tenant`,org:`tenant`,tenancy:`tenant`,organizationId:`tenant`,auditFields:`audit`,timestamps:`audit`},guidance:{owner:"`owner` is not a `systemFields` key — `owner_id` injection is governed by the object-level `ownership` property (`ownership: 'none'` skips it; `'user'`/`'org'` choose the principal). `systemFields` controls only `tenant` (organization_id) and `audit` (created_at/created_by/updated_at/updated_by).",ownership:"`ownership` is a TOP-LEVEL object key, not a `systemFields` key — write it beside `systemFields`. It, not this block, decides whether `owner_id` is injected."}},{tenant:t.z.boolean().optional().describe(`Inject the organization_id column. Default true (the column is always provisioned; the multi-tenant flag governs only its index).`),audit:t.z.boolean().optional().describe(`Inject the audit columns (created_at/created_by/updated_at/updated_by). Default true.`)})]).optional().describe(`Opt out of, or selectively disable, registry-level system-field auto-injection.`),datasource:t.z.string().optional().default(`default`).describe(`Target Datasource ID. "default" is the primary DB.`),external:Oo.optional().describe(`Remote table binding for federated (external) objects.`),fields:t.z.record(t.z.string().regex(/^[a-z_][a-z0-9_]*$/,{message:`Field names must be lowercase snake_case (e.g., "first_name", "company", "annual_revenue")`}),C).describe(`Field definitions map. Keys must be snake_case identifiers.`),indexes:t.z.array(_o).optional().describe(`Database performance indexes`),fieldGroups:t.z.array(Do).refine(e=>new Set(e.map(e=>e.key)).size===e.length,{message:`fieldGroups[].key must be unique within an object`}).optional().describe(`Ordered list of field groups (array order = display order). See ObjectFieldGroupSchema.`),tenancy:U.optional().describe(`Multi-tenancy configuration for SaaS applications`),access:bo.optional().describe(`[ADR-0066 D2] Object exposure posture (public-by-default vs private secure-by-default).`),requiredPermissions:So.optional().describe("[ADR-0066 D3/⑤] Capabilities required to access this object (AND-gate) — `string[]` gates all CRUD, or a `{read,create,update,delete}` map gates per operation."),lifecycle:Eo.optional().describe(`Data lifecycle contract (ADR-0057): class + retention/ttl/rotation/archive policies enforced by the platform LifecycleService.`),fileAccessDelegate:t.z.string().optional().describe(`Kernel service that authorizes downloads of files owned by this object's media fields, instead of testing whether the caller can read the owning row. For objects whose access is mediated by a service (e.g. sys_approval_action → approvals). Fails closed.`),validations:t.z.array(Aa).optional().describe(`Object-level validation rules`),activityMilestones:t.z.array(D({surface:`this activity milestone`,history:`Until #4001 these were dropped silently — the milestone still parsed, so a mis-keyed template shipped a timeline row with the wrong text, or the milestone never fired at all.`,aliases:{message:`summary`,template:`summary`,text:`summary`,title:`summary`,to:`value`,watch:`field`,activityType:`type`},guidance:{from:"`from` is not a milestone key — a milestone fires on transition INTO `value`, whatever the previous value was. There is no from-state filter here; when the TRANSITION itself must be constrained, declare a `state_machine` rule in `validations` (ADR-0020), which is where the legal transition table lives.",when:"`when` is not a milestone key — the trigger is structural: `field` transitions INTO `value`. For a conditional timeline row, gate it with a `state_machine` rule in `validations` or a hook."}},{field:t.z.string().describe(`Field to watch (typically a status/stage select).`),value:t.z.string().describe(`The value the field must transition INTO to fire the milestone.`),summary:t.z.string().describe(`Activity summary template; {field} tokens interpolate the record value. e.g. "Deal won: {name}".`),type:t.z.string().optional().describe(`Activity type for the emitted row (default "completed").`)})).optional().describe(`Declarative semantic activity milestones — emit a templated timeline row when a field transitions into a value, no hook code (ADR-0052 §5b.2).`),nameField:t.z.string().optional().describe(`[ADR-0079] Canonical primary title field — the stored field used as the record display name (e.g. "name", "title").`),displayNameField:t.z.string().optional().describe(`[DEPRECATED → nameField] Field to use as the record display name (e.g., "name", "title"). Accepted as an alias for nameField.`),titleFormat:se.optional().describe(`[DEPRECATED → nameField (ADR-0079)] Render-only title template; the server cannot return or query it, and an explicit nameField now takes precedence. Migrate a single-field title to nameField, a composite to a formula field designated as nameField.`),highlightFields:t.z.array(t.z.string()).optional().describe(`[ADR-0085] Ordered most-important fields; first entry wins where only one fits. Drives default columns, cards, previews, detail highlight strip. Renamed from compactLayout.`),stageField:t.z.union([t.z.string(),t.z.literal(!1)]).optional().describe(`[ADR-0085] Lifecycle stage field (linear/ordered), or false to declare the status field non-linear and suppress stage heuristics. Absent = heuristic detection allowed.`),listViews:t.z.record(t.z.string(),ua).optional().describe(`Built-in named list views (segmented tabs) shipped with the object schema — "views" mode, dropdown userFilters allowed, no page-only tabs (ADR-0047)`),searchableFields:t.z.array(t.z.string()).optional().describe("Fields the `$search` query matches against (ADR-0061). Canonical default for the record picker, list quick-search and global search; views may narrow it. When unset, search auto-defaults to the name/title field plus short-text fields."),enable:go.optional().describe(`Enabled system features modules`),sharingModel:t.z.enum([`private`,`public_read`,`public_read_write`,`controlled_by_parent`]).optional().describe(`Org-Wide Default record visibility (OWD) for INTERNAL users. Canonical four only (legacy aliases removed, ADR-0090 D4): private (owner-only) | public_read (everyone reads, owner writes) | public_read_write (everyone reads+writes) | controlled_by_parent (derived from the master record). A CUSTOM object that omits this resolves to private at runtime (ADR-0090 D1).`),externalSharingModel:t.z.enum([`private`,`public_read`,`public_read_write`,`controlled_by_parent`]).optional().describe(`[ADR-0090 D11] OWD for external (portal/partner) principals. Defaults to private; must be <= sharingModel in openness.`),publicSharing:D({surface:"this object's `publicSharing` policy",history:`Until #4001 these were dropped silently — the policy still parsed, so a redaction list or an expiry cap the author wrote was never applied to the links the platform went on to issue. On a policy whose whole job is to be restrictive, a silently dropped key fails OPEN.`,aliases:{audiences:`allowedAudiences`,permissions:`allowedPermissions`,redact:`redactFields`,redacted:`redactFields`,maxExpiry:`maxExpiryDays`,expiryDays:`maxExpiryDays`,condition:`eligibility`},guidance:{sharingModel:"`sharingModel` governs PRINCIPAL-based sharing (specific users / teams / roles) and is a TOP-LEVEL object key, not a `publicSharing` key. `publicSharing` is the separate opt-in for opaque share LINKS — an object may declare both, and they do not constrain each other.",externalSharingModel:"`externalSharingModel` is a TOP-LEVEL object key (ADR-0090 D11) — the OWD for external portal/partner principals. Link sharing is this block; principal-based external access is that key, one level up."}},{enabled:t.z.boolean().default(!1).describe(`Allow records of this object to be published via share link`),allowedAudiences:t.z.array(t.z.enum([`public`,`link_only`,`signed_in`,`email`])).optional().describe(`Audiences callers may select when creating a link`),allowedPermissions:t.z.array(t.z.enum([`view`,`comment`,`edit`])).optional().describe(`Permission levels selectable on the share dialog`),maxExpiryDays:t.z.number().int().positive().optional().describe(`Reject links with expiry beyond this many days`),redactFields:t.z.array(t.z.string()).optional().describe(`Field names removed from records served via a share token`),eligibility:t.z.string().optional().describe(`CEL expression that must evaluate to true on the target record`)}).optional().describe(`Public share-link policy (Notion/Figma-style link sharing)`),actions:t.z.array(ao).optional().describe(`Actions associated with this object (auto-populated from top-level actions via objectName)`),protection:z.optional().describe(`Package author protection block — lock policy for this object.`),..._},{error:jo}).strict();function No(e){return e.split(`_`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}var Po={workflows:"`workflows` is not an ObjectSchema field. Object-level, record-triggered automation is authored as a lifecycle hook (`src/objects/<name>.hook.ts`, wrapped in `defineHook()` from `@objectstack/spec/data`) or as a top-level `record_change` flow — not as `workflows[]` on the object schema.",workflow:"`workflow` is not an ObjectSchema field. Record-triggered automation is authored as a lifecycle hook (`src/objects/<name>.hook.ts`) or a top-level `record_change` flow.",hooks:"`hooks` is not an ObjectSchema field. Lifecycle hooks live in their own `src/objects/<name>.hook.ts` module, wrapped in `defineHook()` from `@objectstack/spec/data`.",triggers:"`triggers` is not an ObjectSchema field. Use a lifecycle hook (`src/objects/<name>.hook.ts`) or a top-level `record_change` flow.",namespace:'`namespace` was retired in ADR-0006 D4 — the object `name` IS the canonical id everywhere (API, ObjectQL, REST, SDK, DB table), so there is no separate namespace to declare. Embed the module prefix in the name instead: `namespace: "sys", name: "user"` becomes `name: "sys_user"`. Until #4001 closed this shape on the parse path it was stripped in silence, so an object declaring one shipped under the unprefixed name its author did not intend.',compactLayout:"`compactLayout` was renamed to `highlightFields` in @objectstack/spec 11.7.0 (ADR-0085 semantic roles) and the alias was retired in 11.9.1 (#2536). Rename the key — the value shape (ordered field-name list) is unchanged.",detail:"The `detail` UI-hints block was removed by ADR-0085 (spec 11.7.0). Its jobs moved to top-level semantic roles: `detail.stageField` → `stageField` (string | false), `detail.highlightFields` → `highlightFields`, section layout → `fieldGroups` + `Field.group`. Whole-page customization is done by assigning a custom Page schema instead of per-page hint keys.",views:"`views` is not an ObjectSchema field: the object-level `views.form/*` and `views.detail/*` UI-hint dialect was never part of the spec and its renderer support was removed (ADR-0085). Use the semantic roles (`highlightFields`, `stageField`, `fieldGroups`) for hints and `listViews` for named list views.",defaultDetailForm:"`defaultDetailForm` was never implemented and was removed from the spec (#2402). Curate the record page by assigning a custom Page schema; form layout derives from `fieldGroups` + `Field.group`.",softDelete:"`softDelete` was removed from the spec in 16.0 (#2377, ADR-0049 enforce-or-remove) — there is no soft-delete/recycle-bin runtime, so it stored nothing and implied restore semantics that do not exist. Deletes are hard deletes; remove the key.",versioning:"`versioning` was removed from the spec in 16.0 (#2377, ADR-0049) — no record-versioning engine ever read it (it snapshotted no history). Use per-field `Field.trackHistory` for field-level history, or a data lifecycle policy (`lifecycle`) for retention.",search:"`search` (the SearchConfig block) was removed from the spec in 16.0 (#2377, ADR-0049) — no search-engine config was consumed. Declare the indexed fields with `searchableFields` (ADR-0061); records stay queryable via the normal data API regardless.",recordName:"`recordName` was removed from the spec in 16.0 (#2377, ADR-0049) — it was never read. Auto-naming is modelled as a `Field` of type 'autonumber' (with `autonumberFormat`) designated as the object's `nameField`.",keyPrefix:"`keyPrefix` was removed from the spec in 16.0 (#2377, ADR-0049) — record ids are not prefixed from it (no Salesforce-style key-prefix runtime). Remove the key; it had no effect.",tags:"`tags` (object-level categorization) was removed from the spec (#2377, ADR-0049) — it had no runtime reader. Remove the key; use `managedBy` for lifecycle bucketing or a real field for per-record tagging.",active:'`active` was removed from the spec (#2377, ADR-0049) — no runtime reader gated on it, so an "inactive" object was still fully queryable and usable. Remove the key; gate availability with permissions/sharing instead.',abstract:"`abstract` was removed from the spec (#2377, ADR-0049) — object inheritance/abstraction is not implemented, so an abstract object still got a table and was instantiable. Remove the key."};function Fo(e,t){let n=Array.from({length:e.length+1},()=>Array(t.length+1).fill(0));for(let t=0;t<=e.length;t++)n[t][0]=t;for(let e=0;e<=t.length;e++)n[0][e]=e;for(let r=1;r<=e.length;r++)for(let i=1;i<=t.length;i++)n[r][i]=e[r-1]===t[i-1]?n[r-1][i-1]:1+Math.min(n[r-1][i],n[r][i-1],n[r-1][i-1]);return n[e.length][t.length]}function Io(e,t){let n,r=1/0;for(let i of t){let t=Fo(e.toLowerCase(),i.toLowerCase());t<r&&(r=t,n=i)}return n!==void 0&&r<=Math.max(2,Math.floor(e.length/3))?n:void 0}function Lo(e,t,n){let r=typeof e==`string`&&e.length>0?e:`<unnamed>`,i=t.map(e=>{let t=Po[e];if(t)return` \u2022 ${t}`;let r=Io(e,n);return r?` \u2022 \`${e}\` is not an ObjectSchema field \u2014 did you mean \`${r}\`?`:` \u2022 \`${e}\` is not an ObjectSchema field.`});return Error(`ObjectSchema.create('${r}'): unknown key(s) \u2014 ${t.join(`, `)}.
|
|
26
|
+
These keys would previously have been stripped silently at build, shipping dead metadata with no diagnostic (ADR-0032 "no silent failure", issue #1535).
|
|
27
|
+
|
|
28
|
+
${i.join(`
|
|
29
|
+
`)}
|
|
30
|
+
|
|
31
|
+
Remove the unknown key(s), fix the typo, or move the logic to a supported mechanism.`)}var Ro=new Set;function zo(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>`;Ro.has(i)||(Ro.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 Bo(e,t,n){if(t!==`system-data`)return;let r=Go({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 Vo(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 Ho(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 Uo=n(()=>{let e=W.parse.bind(W),t=W.safeParse.bind(W);return Object.assign(W,{parse(t,n){return e(Ho(Vo(t)),n)},safeParse(e,n){return t(Ho(Vo(e)),n)},create:e=>{let t=e,n=Object.keys(W.shape),r=Object.keys(t).filter(e=>!n.includes(e));if(r.length>0)throw Lo(t.name,r,n);zo(t.name,t.fields,t.managedBy),Bo(t.name,t.managedBy,t.userActions);let i={...t,label:t.label??No(t.name)};return W.parse(i)}})}),Wo={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 Go(e){let t=Wo[e?.managedBy??`platform`]??Wo.platform,n=e?.userActions??{},r=Ko(n.edit,t.edit),i=Ko(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 Ko(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}}t.z.enum([`own`,`extend`]),n(()=>D({surface:`this object extension`,history:`Until #4001 these were dropped silently — the extension still parsed and still registered, so fields or rules an author meant to merge into someone else's object simply never arrived, on a surface where the target is owned by another package and the absence is easy to blame on precedence.`,aliases:{object:`extend`,objectName:`extend`,target:`extend`,name:`extend`,extends:`extend`,order:`priority`},guidance:{actions:"`actions` cannot be contributed through an object extension — the merge carries `fields`, `label`, `pluralLabel`, `description`, `validations` and `indexes` only. Declare a top-level action with `objectName: '<target>'`; `defineStack()` attaches it to the object.",hooks:"`hooks` cannot be contributed through an object extension — declare a top-level hook bound to the target object instead.",listViews:"`listViews` cannot be contributed through an object extension — declare a top-level `view` bound to the target object instead.",fieldGroups:"`fieldGroups` cannot be contributed through an object extension — the merge does not carry them. Add the fields here and declare the groups on the owning object, or assign a Page for the layout."}},{extend:t.z.string().describe(`Target object name (FQN) to extend`),fields:t.z.record(t.z.string(),C).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(Aa).optional().describe(`Additional validation rules to merge into the target object`),indexes:t.z.array(_o).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)`)}));var qo=t.z.enum([`own`,`own_and_reports`,`unit`,`unit_and_below`,`org`]),Jo=T({surface:`this object permission`,knownKeys:[`allowCreate`,`allowRead`,`allowEdit`,`allowDelete`,`allowExport`,`allowTransfer`,`allowRestore`,`allowPurge`,`viewAllRecords`,`modifyAllRecords`,`readScope`,`writeScope`],aliases:{read:`allowRead`,create:`allowCreate`,edit:`allowEdit`,update:`allowEdit`,write:`allowEdit`,delete:`allowDelete`,remove:`allowDelete`,export:`allowExport`,transfer:`allowTransfer`,restore:`allowRestore`,purge:`allowPurge`,canread:`allowRead`,cancreate:`allowCreate`,canedit:`allowEdit`,candelete:`allowDelete`,viewall:`viewAllRecords`,viewalldata:`viewAllRecords`,modifyall:`modifyAllRecords`,modifyalldata:`modifyAllRecords`},guidance:{apiOperations:"`apiOperations` is the server-resolved effective operation set (#3391) — it exists only on the RESPONSE surface (`/me/permissions`) and is never authored. Grant capability with the `allow*` bits here; tighten an object's exposure with `apiMethods` on the object schema."},history:`Until #4001 these were dropped silently — the permission set still parsed, so the author believed a grant or restriction was in place that the runtime never saw.`}),Yo=n(()=>t.z.object({allowCreate:t.z.boolean().default(!1).describe(`Create permission`),allowRead:t.z.boolean().default(!1).describe(`Read permission`),allowEdit:t.z.boolean().default(!1).describe(`Edit permission`),allowDelete:t.z.boolean().default(!1).describe(`Delete permission`),allowExport:t.z.boolean().optional().describe(`[#3544] User-level export axis over read (opt-in grant). true = export granted (still bounded by read); unset/false = no export. Merged most-permissively like the CRUD bits; NOT implied by viewAllRecords/modifyAllRecords.`),allowTransfer:t.z.boolean().default(!1).describe(`[RBAC-gated; ENFORCED now via insert/update owner_id guard, #3004] Change record ownership (assign/reassign/disown owner_id)`),allowRestore:t.z.boolean().default(!1).describe(`[RBAC-gated; operation pending M2] Restore from trash (Undelete)`),allowPurge:t.z.boolean().default(!1).describe(`[RBAC-gated; operation pending M2] Permanently delete (Hard Delete/GDPR)`),viewAllRecords:t.z.boolean().default(!1).describe(`View All Data (Bypass Sharing)`),modifyAllRecords:t.z.boolean().default(!1).describe(`Modify All Data (Bypass Sharing)`),readScope:qo.optional().describe(`[ADR-0057 D1] Read depth: own|unit|unit_and_below|org`),writeScope:qo.optional().describe(`[ADR-0057 D1] Write depth: own|unit|unit_and_below|org`)},{error:Jo}).strict()),Xo=n(()=>Yo.extend({apiOperations:t.z.array(uo).optional().describe(`Server-resolved effective API operations for this object (#3391). Present only when the object tightens exposure via apiMethods; absent = default-allow. The frontend renders this effective set, never the raw whitelist. Vocabulary is the EFFECTIVE ApiOperation set (six primitives + eight derived verbs, #3543), not the authored six-value ApiMethod enum.`)}).strip()),Zo=T({surface:`this admin scope`,knownKeys:[`businessUnit`,`includeSubtree`,`manageAssignments`,`manageBindings`,`authorEnvironmentSets`,`assignablePermissionSets`],history:`Until #4001 these were dropped silently — the scope still parsed, so a delegation boundary the author intended was never enforced.`}),G=n(()=>t.z.object({businessUnit:t.z.string().describe(`[ADR-0090 D12] Delegation boundary: sys_business_unit.name of the subtree root`),includeSubtree:t.z.boolean().default(!0).describe(`Cover descendant business units too (default true)`),manageAssignments:t.z.boolean().default(!1).describe(`Manage user↔position assignments within the subtree`),manageBindings:t.z.boolean().default(!1).describe(`Manage position↔permission-set bindings within the subtree`),authorEnvironmentSets:t.z.boolean().default(!1).describe(`Author environment-owned permission sets`),assignablePermissionSets:t.z.array(t.z.string()).default([]).describe(`Allowlist of permission-set names the delegate may hand out`)},{error:Zo}).strict()),K=T({surface:`this field permission`,knownKeys:[`readable`,`editable`],aliases:{read:`readable`,visible:`readable`,write:`editable`,edit:`editable`,update:`editable`},guidance:{hidden:"`hidden` is not a FieldPermission key — FLS is declared positively: set `readable: false` to hide the field."},history:`Until #4001 these were dropped silently — the entry still parsed, so field-level security the author intended was never applied.`}),Qo=n(()=>t.z.object({readable:t.z.boolean().default(!0).describe(`Field read access`),editable:t.z.boolean().default(!1).describe(`Field edit access`)},{error:K}).strict()),$o=T({surface:`this permission set`,knownKeys:[`name`,`label`,`description`,`packageId`,`managedBy`,`isDefault`,`objects`,`fields`,`systemPermissions`,`tabPermissions`,`rowLevelSecurity`,`adminScope`,`protection`,`_lock`,`_lockReason`,`_lockSource`,`_provenance`,`_packageId`,`_packageVersion`,`_lockDocsUrl`],aliases:{objectpermissions:`objects`,entities:`objects`,entitypermissions:`objects`,fieldpermissions:`fields`,fls:`fields`,fieldlevelsecurity:`fields`,tabs:`tabPermissions`,tabvisibility:`tabPermissions`,rls:`rowLevelSecurity`,rowlevelsecurityrules:`rowLevelSecurity`,policies:`rowLevelSecurity`},guidance:{contextVariables:"`contextVariables` was removed by ADR-0105 D11 (enforce-or-remove, ADR-0049): it was authorable but had zero runtime consumers. A custom membership set a policy needs as `field IN (current_user.<key>)` is staged by a registered rlsMembership resolver; a constant belongs inline in the policy's `using` expression.",isProfile:"`isProfile` was removed by ADR-0090 D2 — there is no Profile concept. Permission sets are the only capability container; use `isDefault` to mark the app baseline bound to the built-in `everyone` position.",profiles:"`profiles` is not a PermissionSet field (ADR-0090 D2: no Profile concept). Distribution is a runtime binding — positions bind sets to people (`sys_position_permission_set`), never the set itself.",roles:"`roles` is not a PermissionSet field — ObjectStack has no role hierarchy: capability = permission sets (union-merged), distribution = positions, visibility depth = business units (ADR-0057 / ADR-0090).",users:"`users` is not a PermissionSet field — assignment is a runtime binding (`sys_user_permission_set` / positions), never authored on the set (ADR-0090)."},history:`Until #4001 these were dropped silently — the set still parsed, so the author believed a capability boundary was declared that the runtime never saw.`});n(()=>t.z.object({name:y.describe(`Permission set unique name (lowercase snake_case)`),label:t.z.string().optional().describe(`Display label`),description:t.z.string().optional().describe(`Human-readable description shown in Setup (persisted as sys_permission_set.description)`),packageId:t.z.string().optional().describe(`[ADR-0086 D3] Owning package id for a package-shipped set (absent = env-authored)`),managedBy:t.z.enum([`package`,`platform`,`user`]).optional().describe(`[ADR-0086 D3] Record provenance: package (upgrade-owned metadata) vs platform/user (env config)`),isDefault:t.z.boolean().default(!1).describe(`[ADR-0090 D5] App baseline for the everyone position: app-level sets are auto-bound at boot (guarded, idempotent); package-level sets become install-time suggestions an admin confirms`),objects:t.z.record(t.z.string(),Yo).describe(`Entity permissions`),fields:t.z.record(t.z.string(),Qo).optional().describe(`Field level security`),systemPermissions:t.z.array(t.z.string()).optional().describe(`System level capabilities`),tabPermissions:t.z.record(t.z.string(),t.z.enum([`visible`,`hidden`,`default_on`,`default_off`])).optional().describe(`App/tab visibility: visible, hidden, default_on (shown by default), default_off (available but hidden initially)`),rowLevelSecurity:t.z.array(Ca).optional().describe(`Row-level security policies (see rls.zod.ts for full spec)`),adminScope:G.optional().describe(`[ADR-0090 D12] Scoped delegated-administration grant (BU subtree + assignable-set allowlist)`),protection:z.optional().describe(`Package author protection block — lock policy for this permission set.`),..._},{error:$o}).strict());var es=n(()=>t.z.enum([`timer`,`signal`,`webhook`,`manual`,`condition`]).describe(`Wait event type determining how a paused flow is resumed`));n(()=>t.z.object({executionId:t.z.string().describe(`Execution ID of the paused flow`),checkpointId:t.z.string().describe(`Checkpoint ID to resume from`),nodeId:t.z.string().describe(`Wait node ID being resumed`),eventType:es.describe(`Event type that triggered resume`),signalName:t.z.string().optional().describe(`Signal name (when eventType is signal)`),webhookPayload:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Webhook request payload (when eventType is webhook)`),resumedBy:t.z.string().optional().describe(`User ID or system identifier that triggered resume`),resumedAt:t.z.string().datetime().describe(`ISO 8601 timestamp of the resume event`),variables:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Variables to merge into flow context upon resume`)}).describe(`Payload for resuming a paused wait node`));var ts=n(()=>t.z.enum([`fail`,`continue`,`fallback`]).describe(`Behavior when a wait node exceeds its timeout`));n(()=>t.z.object({defaultTimeoutMs:t.z.number().int().min(0).default(864e5).describe(`Default timeout in ms (default: 24 hours)`),defaultTimeoutBehavior:ts.default(`fail`).describe(`Default behavior when wait timeout is exceeded`),conditionPollIntervalMs:t.z.number().int().min(1e3).default(3e4).describe(`Polling interval for condition waits in ms (default: 30s)`),conditionMaxPolls:t.z.number().int().min(0).default(0).describe(`Max polling attempts for condition waits (0 = unlimited)`),webhookUrlPattern:t.z.string().default(`/api/v1/automation/resume/{executionId}/{nodeId}`).describe(`URL pattern for webhook resume endpoints`),persistCheckpoints:t.z.boolean().default(!0).describe(`Persist wait checkpoints to durable storage`),maxPausedExecutions:t.z.number().int().min(0).default(0).describe(`Max concurrent paused executions (0 = unlimited)`)}).describe(`Wait node executor plugin configuration`)),n(()=>t.z.object({id:t.z.string().describe(`Unique executor plugin identifier`),name:t.z.string().describe(`Display name`),nodeTypes:t.z.array(t.z.string()).min(1).describe(`FlowNodeAction types this executor handles`),version:t.z.string().describe(`Plugin version (semver)`),description:t.z.string().optional().describe(`Executor description`),supportsPause:t.z.boolean().default(!1).describe(`Whether the executor supports async pause/resume`),supportsCancellation:t.z.boolean().default(!1).describe(`Whether the executor supports mid-execution cancellation`),supportsRetry:t.z.boolean().default(!0).describe(`Whether the executor supports retry on failure`),configSchemaRef:t.z.string().optional().describe(`JSON Schema $ref for executor-specific config`)}).describe(`Node executor plugin descriptor`));var ns=n(()=>t.z.enum([`logic`,`data`,`io`,`human`,`control`,`custom`]).describe(`Action palette category`)),rs=n(()=>t.z.enum([`flow`,`approval`]).describe(`Authoring paradigm that may offer this action`)),is=n(()=>t.z.object({type:t.z.string().min(1).describe(`Registry action/node type (matches the executor type)`),version:t.z.string().describe(`Executor version (semver)`),name:t.z.string().describe(`Display label (or i18n key)`),description:t.z.string().optional().describe(`Action description`),icon:t.z.string().optional().describe(`Icon id resolved by the designer`),category:ns.default(`custom`).describe(`Palette category`),paradigms:t.z.array(rs).default([`flow`]).describe(`Authoring surfaces that may offer this action`),configSchema:t.z.unknown().optional().describe(`JSON Schema for the node config (drives the designer form; undeclared keys are rejected at registration)`),supportsPause:t.z.boolean().default(!1).describe(`Supports async pause/resume`),supportsCancellation:t.z.boolean().default(!1).describe(`Supports cancellation`),supportsRetry:t.z.boolean().default(!0).describe(`Supports retry on failure`),needsOutbox:t.z.boolean().default(!1).describe(`Dispatch via service-messaging outbox (retry/idempotency/dead-letter)`),isAsync:t.z.boolean().default(!1).describe(`Suspends the flow awaiting an external reply`),handlerContract:t.z.enum([`none`,`pure`]).default(`none`).describe(`Effect contract for author-supplied code this action invokes: 'none' (invokes none) or 'pure' (must not write — it returns a value and the flow graph persists it)`),resumeAuthority:t.z.enum([`any`,`service`]).optional().describe(`Who may resume a run this node suspended: 'any' (the generic resume route) or 'service' (only the owning service, e.g. approvals). Deliberately has no default — an omission is a distinct, reportable fact, and a pausing node type that omits it is warned about at registration (#5561)`),maturity:t.z.enum([`ga`,`beta`,`reserved`]).default(`ga`).describe(`Runtime maturity: ga (shipped), beta, or reserved (contract only — designers grey this out)`),source:t.z.enum([`builtin`,`plugin`]).default(`plugin`).describe(`builtin = platform baseline; plugin = third-party contributed`),deprecated:t.z.boolean().default(!1).describe(`Deprecated alias kept for back-compat`),aliasOf:t.z.string().optional().describe(`Canonical type this alias forwards to`)}).describe(`Canonical cross-paradigm action/node descriptor (ADR-0018)`)),as=n(()=>t.z.string().describe(`BCP-47 Language Tag (e.g. en-US, zh-CN)`)),q=`Until #4001 closed these shapes an unknown key was dropped silently — the bundle still loaded, and whatever it was meant to translate rendered in the source language with no diagnostic, indistinguishable from a translation nobody had written yet.`,os=n(()=>D({surface:`this field translation`,history:q,aliases:{helpText:`help`,hint:`help`,tooltip:`help`,picklist:`options`,values:`options`,choices:`options`}},{label:t.z.string().optional().describe(`Translated field label`),help:t.z.string().optional().describe(`Translated help text`),placeholder:t.z.string().optional().describe(`Translated placeholder text for form inputs`),options:t.z.record(t.z.string(),t.z.string()).optional().describe(`Option value to translated label map`)}).describe(`Translation data for a single field`)),ss=n(()=>D({surface:`this action result dialog translation`,history:q,aliases:{label:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,acknowledgeLabel:`acknowledge`}},{title:t.z.string().optional().describe(`Translated result dialog title`),description:t.z.string().optional().describe(`Translated result dialog description`),acknowledge:t.z.string().optional().describe(`Translated acknowledge button label`),fields:t.z.record(t.z.string(),t.z.string()).optional().describe(`Result field labels keyed by the literal field path declared in the action metadata (keys may contain dots)`)}).describe(`Translations for an action result dialog`)),cs=e=>D({surface:e,history:q,aliases:{name:`label`,title:`label`,confirm:`confirmText`,confirmation:`confirmText`,confirmMessage:`confirmText`,success:`successMessage`,successText:`successMessage`,toast:`successMessage`,parameters:`params`,args:`params`,inputs:`params`,result:`resultDialog`,dialog:`resultDialog`}},{label:t.z.string().optional().describe(`Translated action label`),confirmText:t.z.string().optional().describe(`Translated confirmation prompt`),successMessage:t.z.string().optional().describe(`Translated success toast/message`),params:t.z.record(t.z.string(),D({surface:`this action parameter translation`,history:q,aliases:{help:`helpText`,hint:`helpText`,tooltip:`helpText`,name:`label`,choices:`options`,values:`options`}},{label:t.z.string().optional().describe(`Translated action parameter label`),helpText:t.z.string().optional().describe(`Translated action parameter help/hint text`),placeholder:t.z.string().optional().describe(`Translated action parameter placeholder`),options:t.z.record(t.z.string(),t.z.string()).optional().describe(`Param select option value to translated label`)})).optional().describe(`Action parameter translations keyed by parameter name`),resultDialog:ss.optional().describe(`Translations for the action result dialog`)}),ls=n(()=>D({surface:`this object translation`,history:q,aliases:{views:`_views`,actions:`_actions`,sections:`_sections`,plural:`pluralLabel`,labelPlural:`pluralLabel`,name:`label`,title:`label`,columns:`fields`,properties:`fields`,attributes:`fields`}},{label:t.z.string().optional().describe(`Translated singular label`),pluralLabel:t.z.string().optional().describe(`Translated plural label`),description:t.z.string().optional().describe(`Translated object description`),fields:t.z.record(t.z.string(),os).optional().describe(`Field-level translations`),_views:t.z.record(t.z.string(),D({surface:`this view translation`,history:q,aliases:{name:`label`,title:`label`,empty:`emptyState`,emptyMessage:`emptyState`}},{label:t.z.string().optional().describe(`Translated view label`),description:t.z.string().optional().describe(`Translated view description`),emptyState:D({surface:`this view empty-state translation`,history:q,aliases:{label:`title`,heading:`title`,description:`message`,text:`message`,body:`message`}},{title:t.z.string().optional().describe(`Translated empty-state title`),message:t.z.string().optional().describe(`Translated empty-state message`)}).optional().describe(`Translated empty-state copy shown when the view has no rows`)})).optional().describe(`View translations keyed by view name`),_actions:t.z.record(t.z.string(),cs(`this object action translation`)).optional().describe(`Action translations keyed by action name`),_sections:t.z.record(t.z.string(),D({surface:`this section translation`,history:q,aliases:{name:`label`,title:`label`,heading:`label`}},{label:t.z.string().optional().describe(`Translated section label`),description:t.z.string().optional().describe(`Translated section description`)})).optional().describe(`Section translations keyed by section name`)}).describe(`Translation data for a single object`)),us={validationMessages:"`validationMessages` was removed in @objectstack/spec 17.0.0 (#4667, ADR-0049) — no resolver ever read it, so a translated rule message was stored and never shown. Validation messages are not translated through a translation group: author the message on the rule itself (`object.validations[].message`), which the engine evaluates and returns on every rejected write. Delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically.",o:"`o` is the retired object-first dialect, which no resolver reads — use 'objects.<object_name>'",app:"`app` is the retired object-first dialect, which no resolver reads — use 'apps.<app_name>'",nav:"`nav` is the retired object-first dialect, which no resolver reads — use 'apps.<app_name>.navigation.<node_id>.label'",dashboard:"`dashboard` is the retired object-first dialect, which no resolver reads — use 'dashboards.<dashboard_name>' (plural)",reports:"`reports` is the retired object-first dialect — reports have no translation group, omit them",notifications:"`notifications` is the retired object-first dialect — notifications have no translation group, omit them",errors:"`errors` is the retired object-first dialect and has no replacement — rule messages are not translated through a translation group at all. Author the message on the rule itself (`object.validations[].message`); omit `errors`.",_globalOptions:"`_globalOptions` is the retired object-first dialect — use 'objects.<object_name>.fields.<field_name>.options'",_meta:"`_meta` is the retired object-first dialect — use the top-level 'locale' field (on a bundle, the locale is the map key)",namespace:"`namespace` is not part of the translation contract — omit it (ADR-0006 D4 retired namespaces platform-wide)"},ds=()=>({objects:t.z.record(t.z.string(),ls).optional().describe(`Object translations keyed by object name`),apps:t.z.record(t.z.string(),D({surface:`this app translation`,history:q,aliases:{name:`label`,title:`label`,nav:`navigation`,menu:`navigation`,menus:`navigation`}},{label:t.z.string().describe(`Translated app label`),description:t.z.string().optional().describe(`Translated app description`),navigation:t.z.record(t.z.string(),D({surface:`this navigation group translation`,history:q,aliases:{name:`label`,title:`label`,text:`label`}},{label:t.z.string().describe(`Translated navigation group label`)})).optional().describe(`Navigation group translations keyed by group ID`)})).optional().describe(`App translations keyed by app name`),messages:t.z.record(t.z.string(),t.z.string()).optional().describe(`UI message translations keyed by message ID`),globalActions:t.z.record(t.z.string(),cs(`this global action translation`)).optional().describe(`Global action translations keyed by action name`),dashboards:t.z.record(t.z.string(),D({surface:`this dashboard translation`,history:q,aliases:{name:`label`,title:`label`,components:`widgets`,charts:`widgets`,cards:`widgets`}},{label:t.z.string().optional().describe(`Translated dashboard title`),description:t.z.string().optional().describe(`Translated dashboard description`),actions:t.z.record(t.z.string(),D({surface:`this dashboard header action translation`,history:q,aliases:{name:`label`,title:`label`,text:`label`}},{label:t.z.string().optional().describe(`Translated header action label`)})).optional().describe(`Header action label translations keyed by action url/key`),widgets:t.z.record(t.z.string(),D({surface:`this widget translation`,history:q,aliases:{label:`title`,name:`title`,heading:`title`,subtitle:`description`}},{title:t.z.string().optional().describe(`Translated widget title`),description:t.z.string().optional().describe(`Translated widget description`)})).optional().describe(`Widget translations keyed by widget id`)})).optional().describe(`Dashboard translations keyed by dashboard name`),pages:t.z.record(t.z.string(),D({surface:`this page translation`,history:q,aliases:{name:`label`,heading:`title`,header:`title`,subheading:`subtitle`,tagline:`subtitle`}},{label:t.z.string().optional().describe(`Translated page label (nav / breadcrumb)`),description:t.z.string().optional().describe(`Translated page description`),title:t.z.string().optional().describe("Translated `page:header` title (defaults to `label`)"),subtitle:t.z.string().optional().describe("Translated `page:header` subtitle")})).optional().describe(`Page translations keyed by page name`),settings:t.z.record(t.z.string(),D({surface:`this settings manifest translation`,history:q,aliases:{label:`title`,name:`title`,sections:`groups`,fields:`keys`,settings:`keys`}},{title:t.z.string().optional().describe(`Translated settings manifest title`),description:t.z.string().optional().describe(`Translated settings manifest description`),groups:t.z.record(t.z.string(),D({surface:`this settings group translation`,history:q,aliases:{label:`title`,name:`title`,heading:`title`}},{title:t.z.string().optional().describe(`Translated group title`),description:t.z.string().optional().describe(`Translated group description`)})).optional().describe(`Group translations keyed by group key`),keys:t.z.record(t.z.string(),D({surface:`this setting translation`,history:q,aliases:{title:`label`,name:`label`,helpText:`help`,hint:`help`,description:`help`,choices:`options`,values:`options`}},{label:t.z.string().optional().describe(`Translated setting label`),help:t.z.string().optional().describe(`Translated setting help text`),placeholder:t.z.string().optional().describe(`Translated input placeholder`),options:t.z.record(t.z.string(),t.z.string()).optional().describe(`Enum option value → translated label`)})).optional().describe(`Per-setting field translations keyed by setting key`),actions:t.z.record(t.z.string(),D({surface:`this settings action translation`,history:q,aliases:{name:`label`,title:`label`,confirm:`confirmText`,success:`successMessage`},guidance:{params:"settings actions take no parameters — there is no `params` group to translate",resultDialog:"settings actions have no result dialog — `resultDialog` translations belong under `objects.<object>._actions` or `globalActions`"}},{label:t.z.string().optional().describe(`Translated action label`),confirmText:t.z.string().optional().describe(`Translated confirmation prompt`),successMessage:t.z.string().optional().describe(`Translated success toast/message`)})).optional().describe(`Action button translations keyed by action id`)})).optional().describe(`Settings manifest translations keyed by namespace`),metadataForms:t.z.record(t.z.string(),D({surface:`this metadata-form translation`,history:q,aliases:{name:`label`,title:`label`,groups:`sections`,properties:`fields`}},{label:t.z.string().optional().describe(`Translated metadata-type display label (overrides registry label)`),description:t.z.string().optional().describe(`Translated metadata-type description`),sections:t.z.record(t.z.string(),D({surface:`this metadata-form section translation`,history:q,aliases:{name:`label`,title:`label`,heading:`label`}},{label:t.z.string().optional().describe(`Translated section label`),description:t.z.string().optional().describe(`Translated section description`)})).optional().describe(`Section translations keyed by section.name`),fields:t.z.record(t.z.string(),D({surface:`this metadata-form field translation`,history:q,aliases:{name:`label`,title:`label`,help:`helpText`,hint:`helpText`,description:`helpText`}},{label:t.z.string().optional().describe(`Translated field label`),helpText:t.z.string().optional().describe(`Translated field help/hint text`),placeholder:t.z.string().optional().describe(`Translated field placeholder text`)})).optional().describe(`Field translations keyed by field path (dot-notation for nested fields)`)})).optional().describe(`Translations for metadata-type configuration forms keyed by metadata type`),settingsCommon:D({surface:`the shared Settings UI translations`,history:q},{sourceLabels:D({surface:`the settings source-badge labels`,history:q,aliases:{org:`tenant`,workspace:`tenant`,system:`global`,fallback:`default`,environment:`env`}},{env:t.z.string().optional(),global:t.z.string().optional(),tenant:t.z.string().optional(),user:t.z.string().optional(),default:t.z.string().optional()}).optional().describe(`Source badge labels by resolution layer`)}).optional().describe(`Cross-namespace Settings UI strings`)}),fs=n(()=>D({surface:`this locale of the translation bundle`,history:q,guidance:us,aliases:{object:`objects`,fields:`objects`,app:`apps`,page:`pages`,dashboard:`dashboards`,setting:`settings`,message:`messages`,strings:`messages`,labels:`messages`,actions:`globalActions`},extraKeys:[`locale`]},ds()).describe(`Translation data for objects, apps, and UI messages`));n(()=>t.z.record(as,fs).describe(`Map of locale codes to translation data`)),n(()=>D({surface:`the i18n configuration`,history:`Until #4001 closed this shape an unknown key was dropped silently — the stack still built, with the setting the author wrote never reaching any runtime.`,aliases:{locale:`defaultLocale`,defaultLanguage:`defaultLocale`,locales:`supportedLocales`,languages:`supportedLocales`,fallback:`fallbackLocale`,fallbackLanguage:`fallbackLocale`},guidance:{fileOrganization:"`fileOrganization` was removed in #3494 — no runtime ever read it; how you split bundle files is a convention of your source tree, and the loader reads whatever `translations` you hand `defineStack`",messageFormat:"`messageFormat` was removed in #3494 — there is no ICU engine; interpolation is always simple `{variable}` substitution",lazyLoad:"`lazyLoad` was removed in #3494 — no runtime ever read it, so setting it changed nothing",cache:"`cache` was removed in #3494 — no runtime ever read it, so setting it changed nothing"}},{defaultLocale:as.describe(`Default locale (e.g., "en")`),supportedLocales:t.z.array(as).describe(`Supported BCP-47 locale codes`),fallbackLocale:as.optional().describe(`Fallback locale code`)}).describe(`Internationalization configuration`)),n(()=>D({surface:`this translation`,history:q,guidance:us,aliases:{object:`objects`,app:`apps`,page:`pages`,setting:`settings`,message:`messages`,strings:`messages`,labels:`messages`,actions:`globalActions`,lang:`locale`,language:`locale`}},{...ds(),locale:as.describe(`BCP-47 locale this item translates (e.g. "zh-CN")`),name:t.z.string().optional().describe("Item name — conventionally the locale code (`zh-CN`); the runtime sync falls back to it when `locale` is absent"),label:t.z.string().optional().describe(`Human-readable label shown in metadata lists`),..._}).describe("One locale of translations — the `translation` metadata type"));var ps=n(()=>t.z.enum([`missing`,`redundant`,`stale`]).describe(`Translation diff status: missing from bundle, redundant (no matching metadata), or stale (metadata changed)`)),ms=n(()=>t.z.object({key:t.z.string().describe(`Dot-path translation key`),status:ps.describe(`Diff status of this translation key`),objectName:t.z.string().optional().describe(`Associated object name (snake_case)`),locale:t.z.string().describe(`BCP-47 locale code`),sourceHash:t.z.string().optional().describe(`Hash of source metadata for precise stale detection`),aiSuggested:t.z.string().optional().describe(`AI-suggested translation for this key`),aiConfidence:t.z.number().min(0).max(1).optional().describe(`AI suggestion confidence score (0–1)`)}).describe(`A single translation diff item`)),hs=n(()=>t.z.object({group:t.z.string().describe(`Translation group category`),totalKeys:t.z.number().int().nonnegative().describe(`Total keys in this group`),translatedKeys:t.z.number().int().nonnegative().describe(`Translated keys in this group`),coveragePercent:t.z.number().min(0).max(100).describe(`Coverage percentage for this group`)}).describe(`Coverage breakdown for a single translation group`));n(()=>t.z.object({locale:t.z.string().describe(`BCP-47 locale code`),objectName:t.z.string().optional().describe(`Object name scope (omit for full bundle)`),totalKeys:t.z.number().int().nonnegative().describe(`Total translatable keys from metadata`),translatedKeys:t.z.number().int().nonnegative().describe(`Number of translated keys`),missingKeys:t.z.number().int().nonnegative().describe(`Number of missing translations`),redundantKeys:t.z.number().int().nonnegative().describe(`Number of redundant translations`),staleKeys:t.z.number().int().nonnegative().describe(`Number of stale translations`),coveragePercent:t.z.number().min(0).max(100).describe(`Translation coverage percentage`),items:t.z.array(ms).describe(`Detailed diff items`),breakdown:t.z.array(hs).optional().describe(`Per-group coverage breakdown`)}).describe(`Aggregated translation coverage result`));var gs=n(()=>t.z.enum([`full`,`partial`,`experimental`,`deprecated`]).describe(`Level of protocol conformance`)),_s=n(()=>t.z.object({major:t.z.number().int().min(0),minor:t.z.number().int().min(0),patch:t.z.number().int().min(0)}).describe(`Semantic version of the protocol`)),vs=n(()=>t.z.object({id:t.z.string().regex(/^([a-z][a-z0-9]*\.)+protocol\.[a-z][a-z0-9._]*\.v\d+$/).describe(`Unique protocol identifier (e.g., com.objectstack.protocol.storage.v1)`),label:t.z.string(),version:_s,specification:t.z.string().optional().describe(`URL or path to protocol specification`),description:t.z.string().optional()})),ys=n(()=>t.z.object({name:t.z.string().describe(`Feature identifier within the protocol`),enabled:t.z.boolean().default(!0),description:t.z.string().optional(),sinceVersion:t.z.string().optional().describe(`Version when this feature was added`),deprecatedSince:t.z.string().optional().describe(`Version when deprecated`)})),bs=n(()=>t.z.object({protocol:vs,conformance:gs.default(`full`),implementedFeatures:t.z.array(t.z.string()).optional().describe(`List of implemented feature names`),features:t.z.array(ys).optional(),metadata:t.z.record(t.z.string(),t.z.unknown()).optional(),certified:t.z.boolean().default(!1).describe(`Has passed official conformance tests`),certificationDate:t.z.string().datetime().optional()})),xs=n(()=>t.z.object({id:t.z.string().regex(/^([a-z][a-z0-9]*\.)+interface\.[a-z][a-z0-9._]+$/).describe(`Unique interface identifier`),name:t.z.string(),description:t.z.string().optional(),version:_s,methods:t.z.array(t.z.object({name:t.z.string().describe(`Method name`),description:t.z.string().optional(),parameters:t.z.array(t.z.object({name:t.z.string(),type:t.z.string().describe(`Type notation (e.g., string, number, User)`),required:t.z.boolean().default(!0),description:t.z.string().optional()})).optional(),returnType:t.z.string().optional().describe(`Return value type`),async:t.z.boolean().default(!1).describe(`Whether method returns a Promise`)})),events:t.z.array(t.z.object({name:t.z.string().describe(`Event name`),description:t.z.string().optional(),payload:t.z.string().optional().describe(`Event payload type`)})).optional(),stability:t.z.enum([`stable`,`beta`,`alpha`,`experimental`]).default(`stable`)})),Ss=n(()=>t.z.object({pluginId:t.z.string().regex(/^([a-z][a-z0-9]*\.)+[a-z][a-z0-9-]+$/).describe(`Required plugin identifier`),version:t.z.string().describe(`Semantic version constraint`),optional:t.z.boolean().default(!1),reason:t.z.string().optional(),requiredCapabilities:t.z.array(t.z.string()).optional().describe(`Protocol IDs the dependency must support`)})),Cs=n(()=>t.z.object({id:t.z.string().regex(/^([a-z][a-z0-9]*\.)+extension\.[a-z][a-z0-9._]+$/).describe(`Unique extension point identifier`),name:t.z.string(),description:t.z.string().optional(),type:t.z.enum([`action`,`hook`,`widget`,`provider`,`transformer`,`validator`,`decorator`]),contract:t.z.object({input:t.z.string().optional().describe(`Input type/schema`),output:t.z.string().optional().describe(`Output type/schema`),signature:t.z.string().optional().describe(`Function signature if applicable`)}).optional(),cardinality:t.z.enum([`single`,`multiple`]).default(`multiple`).describe(`Whether multiple extensions can register to this point`)})),ws=n(()=>t.z.object({implements:t.z.array(bs).optional().describe(`List of protocols this plugin conforms to`),provides:t.z.array(xs).optional().describe(`Services/APIs this plugin offers to others`),requires:t.z.array(Ss).optional().describe(`Required plugins and their capabilities`),extensionPoints:t.z.array(Cs).optional().describe(`Points where other plugins can extend this plugin`),extensions:t.z.array(t.z.object({targetPluginId:t.z.string().describe(`Plugin ID being extended`),extensionPointId:t.z.string().describe(`Extension point identifier`),implementation:t.z.string().describe(`Path to implementation module`),priority:t.z.number().int().default(100).describe(`Registration priority (lower = higher priority)`)})).optional().describe(`Extensions contributed to other plugins`)})),Ts=n(()=>t.z.enum([`eager`,`lazy`,`parallel`,`deferred`,`on-demand`]).describe(`Plugin loading strategy`)),Es=n(()=>t.z.object({enabled:t.z.boolean().default(!1),priority:t.z.number().int().min(0).default(100),resources:t.z.array(t.z.enum([`metadata`,`dependencies`,`assets`,`code`,`services`])).optional(),conditions:t.z.object({routes:t.z.array(t.z.string()).optional(),roles:t.z.array(t.z.string()).optional(),deviceType:t.z.array(t.z.enum([`desktop`,`mobile`,`tablet`])).optional(),minNetworkSpeed:t.z.enum([`slow-2g`,`2g`,`3g`,`4g`]).optional()}).optional()}).describe(`Plugin preloading configuration`)),Ds=n(()=>t.z.object({enabled:t.z.boolean().default(!0),strategy:t.z.enum([`route`,`feature`,`size`,`custom`]).default(`feature`),chunkNaming:t.z.enum([`hashed`,`named`,`sequential`]).default(`hashed`),maxChunkSize:t.z.number().int().min(10).optional().describe(`Max chunk size in KB`),sharedDependencies:t.z.object({enabled:t.z.boolean().default(!0),minChunks:t.z.number().int().min(1).default(2)}).optional()}).describe(`Plugin code splitting configuration`)),Os=n(()=>t.z.object({enabled:t.z.boolean().default(!0),mode:t.z.enum([`async`,`sync`,`eager`,`lazy`]).default(`async`),prefetch:t.z.boolean().default(!1).describe(`Prefetch module in idle time`),preload:t.z.boolean().default(!1).describe(`Preload module in parallel with parent`),webpackChunkName:t.z.string().optional().describe(`Custom chunk name for webpack`),timeout:t.z.number().int().min(100).default(3e4).describe(`Dynamic import timeout (ms)`),retry:t.z.object({enabled:t.z.boolean().default(!0),maxAttempts:t.z.number().int().min(1).max(10).default(3),backoffMs:t.z.number().int().min(0).default(1e3).describe(`Exponential backoff base delay`)}).optional()}).describe(`Plugin dynamic import configuration`)),ks=n(()=>t.z.object({mode:t.z.enum([`sync`,`async`,`parallel`,`sequential`]).default(`async`),timeout:t.z.number().int().min(100).default(3e4),priority:t.z.number().int().min(0).default(100),critical:t.z.boolean().default(!1).describe(`If true, kernel bootstrap fails if plugin fails`),retry:t.z.object({enabled:t.z.boolean().default(!1),maxAttempts:t.z.number().int().min(1).max(5).default(3),backoffMs:t.z.number().int().min(0).default(1e3)}).optional(),healthCheckInterval:t.z.number().int().min(0).optional().describe(`Health check interval in ms (0 = disabled)`)}).describe(`Plugin initialization configuration`)),As=n(()=>t.z.object({strategy:t.z.enum([`strict`,`compatible`,`latest`,`pinned`]).default(`compatible`),peerDependencies:t.z.object({resolve:t.z.boolean().default(!0),onMissing:t.z.enum([`error`,`warn`,`ignore`]).default(`warn`),onMismatch:t.z.enum([`error`,`warn`,`ignore`]).default(`warn`)}).optional(),optionalDependencies:t.z.object({load:t.z.boolean().default(!0),onFailure:t.z.enum([`warn`,`ignore`]).default(`warn`)}).optional(),conflictResolution:t.z.enum([`fail`,`latest`,`oldest`,`manual`]).default(`latest`),circularDependencies:t.z.enum([`error`,`warn`,`allow`]).default(`warn`)}).describe(`Plugin dependency resolution configuration`)),js=n(()=>t.z.object({enabled:t.z.boolean().default(!1),environment:t.z.enum([`development`,`staging`,`production`]).default(`development`).describe(`Target environment controlling safety level`),strategy:t.z.enum([`full`,`partial`,`state-preserve`]).default(`full`),watchPatterns:t.z.array(t.z.string()).optional().describe(`Glob patterns for files to watch`),ignorePatterns:t.z.array(t.z.string()).optional().describe(`Glob patterns for files to ignore`),debounceMs:t.z.number().int().min(0).default(300),preserveState:t.z.boolean().default(!1),stateSerialization:t.z.object({enabled:t.z.boolean().default(!1),handler:t.z.string().optional()}).optional(),hooks:t.z.object({beforeReload:t.z.string().optional().describe(`Function to call before reload`),afterReload:t.z.string().optional().describe(`Function to call after reload`),onError:t.z.string().optional().describe(`Function to call on reload error`)}).optional(),productionSafety:t.z.object({healthValidation:t.z.boolean().default(!0).describe(`Run health checks after reload before accepting traffic`),rollbackOnFailure:t.z.boolean().default(!0).describe(`Auto-rollback if reloaded plugin fails health check`),healthTimeout:t.z.number().int().min(1e3).default(3e4).describe(`Health check timeout after reload in ms`),drainConnections:t.z.boolean().default(!0).describe(`Gracefully drain active requests before reloading`),drainTimeout:t.z.number().int().min(0).default(15e3).describe(`Max wait time for connection draining in ms`),maxConcurrentReloads:t.z.number().int().min(1).default(1).describe(`Limit concurrent reloads to prevent system instability`),minReloadInterval:t.z.number().int().min(1e3).default(5e3).describe(`Cooldown period between reloads of the same plugin`)}).optional()}).describe(`Plugin hot reload configuration`)),Ms=n(()=>t.z.object({enabled:t.z.boolean().default(!0),storage:t.z.enum([`memory`,`disk`,`indexeddb`,`hybrid`]).default(`memory`),keyStrategy:t.z.enum([`version`,`hash`,`timestamp`]).default(`version`),ttl:t.z.number().int().min(0).optional().describe(`Time to live in seconds (0 = infinite)`),maxSize:t.z.number().int().min(1).optional().describe(`Max cache size in MB`),invalidateOn:t.z.array(t.z.enum([`version-change`,`dependency-change`,`manual`,`error`])).optional(),compression:t.z.object({enabled:t.z.boolean().default(!1),algorithm:t.z.enum([`gzip`,`brotli`,`deflate`]).default(`gzip`)}).optional()}).describe(`Plugin caching configuration`)),Ns=n(()=>t.z.object({enabled:t.z.boolean().default(!1),scope:t.z.enum([`automation-only`,`untrusted-only`,`all-plugins`]).default(`automation-only`).describe(`Which plugins are subject to isolation`),isolationLevel:t.z.enum([`none`,`process`,`vm`,`iframe`,`web-worker`]).default(`none`),allowedCapabilities:t.z.array(t.z.string()).optional().describe(`List of allowed capability IDs`),resourceQuotas:t.z.object({maxMemoryMB:t.z.number().int().min(1).optional(),maxCpuTimeMs:t.z.number().int().min(100).optional(),maxFileDescriptors:t.z.number().int().min(1).optional(),maxNetworkKBps:t.z.number().int().min(1).optional()}).optional(),permissions:t.z.object({allowedAPIs:t.z.array(t.z.string()).optional(),allowedPaths:t.z.array(t.z.string()).optional(),allowedEndpoints:t.z.array(t.z.string()).optional(),allowedEnvVars:t.z.array(t.z.string()).optional()}).optional(),ipc:t.z.object({enabled:t.z.boolean().default(!0).describe(`Allow sandboxed plugins to communicate via IPC`),transport:t.z.enum([`message-port`,`unix-socket`,`tcp`,`memory`]).default(`message-port`).describe(`IPC transport for cross-boundary communication`),maxMessageSize:t.z.number().int().min(1024).default(1048576).describe(`Maximum IPC message size in bytes (default 1MB)`),timeout:t.z.number().int().min(100).default(3e4).describe(`IPC message response timeout in ms`),allowedServices:t.z.array(t.z.string()).optional().describe(`Service names the sandboxed plugin may invoke via IPC`)}).optional()}).describe(`Plugin sandboxing configuration`)),Ps=n(()=>t.z.object({enabled:t.z.boolean().default(!1),metrics:t.z.array(t.z.enum([`load-time`,`init-time`,`memory-usage`,`cpu-usage`,`api-calls`,`error-rate`,`cache-hit-rate`])).optional(),samplingRate:t.z.number().min(0).max(1).default(1),reportingInterval:t.z.number().int().min(1).default(60),budgets:t.z.object({maxLoadTimeMs:t.z.number().int().min(0).optional(),maxInitTimeMs:t.z.number().int().min(0).optional(),maxMemoryMB:t.z.number().int().min(0).optional()}).optional(),onBudgetViolation:t.z.enum([`warn`,`error`,`ignore`]).default(`warn`)}).describe(`Plugin performance monitoring configuration`)),Fs=n(()=>t.z.object({strategy:Ts.default(`lazy`),preload:Es.optional(),codeSplitting:Ds.optional(),dynamicImport:Os.optional(),initialization:ks.optional(),dependencyResolution:As.optional(),hotReload:js.optional(),caching:Ms.optional(),sandboxing:Ns.optional(),monitoring:Ps.optional()}).describe(`Complete plugin loading configuration`));n(()=>t.z.object({type:t.z.enum([`load-started`,`load-completed`,`load-failed`,`init-started`,`init-completed`,`init-failed`,`preload-started`,`preload-completed`,`cache-hit`,`cache-miss`,`hot-reload`,`dynamic-load`,`dynamic-unload`,`dynamic-discover`]),pluginId:t.z.string(),timestamp:t.z.number().int().min(0),durationMs:t.z.number().int().min(0).optional(),metadata:t.z.record(t.z.string(),t.z.unknown()).optional(),error:t.z.object({message:t.z.string(),code:t.z.string().optional(),stack:t.z.string().optional()}).optional()}).describe(`Plugin loading lifecycle event`)),n(()=>t.z.object({pluginId:t.z.string(),state:t.z.enum([`pending`,`loading`,`loaded`,`initializing`,`ready`,`failed`,`reloading`,`unloading`,`unloaded`]),progress:t.z.number().min(0).max(100).default(0),startedAt:t.z.number().int().min(0).optional(),completedAt:t.z.number().int().min(0).optional(),lastError:t.z.string().optional(),retryCount:t.z.number().int().min(0).default(0)}).describe(`Plugin loading state`)),n(()=>t.z.object({ql:t.z.object({object:t.z.function().describe(`Get object handle for method chaining`),query:t.z.function().describe(`Execute a query`)}).passthrough().describe(`ObjectQL Engine Interface`),os:t.z.object({getCurrentUser:t.z.function().describe(`Get the current authenticated user`),getConfig:t.z.function().describe(`Get platform configuration`)}).passthrough().describe(`ObjectStack Kernel Interface`),logger:t.z.object({debug:t.z.function().describe(`Log debug message`),info:t.z.function().describe(`Log info message`),warn:t.z.function().describe(`Log warning message`),error:t.z.function().describe(`Log error message`)}).passthrough().describe(`Logger Interface`),storage:t.z.object({get:t.z.function().describe(`Get a value from storage`),set:t.z.function().describe(`Set a value in storage`),delete:t.z.function().describe(`Delete a value from storage`)}).passthrough().describe(`Storage Interface`),i18n:t.z.object({t:t.z.function().describe(`Translate a key`),getLocale:t.z.function().describe(`Get current locale`)}).passthrough().describe(`Internationalization Interface`),metadata:t.z.record(t.z.string(),t.z.unknown()),events:t.z.record(t.z.string(),t.z.unknown()),app:t.z.object({router:t.z.object({get:t.z.function().describe(`Register GET route handler`),post:t.z.function().describe(`Register POST route handler`),use:t.z.function().describe(`Register middleware`)}).passthrough()}).passthrough().describe(`App Framework Interface`),drivers:t.z.object({register:t.z.function().describe(`Register a driver`)}).passthrough().describe(`Driver Registry`)}));var Is=[`ui`,`driver`,`server`,`app`,`theme`,`agent`,`objectql`],Ls=[`app`];n(()=>t.z.object({id:t.z.string().min(1).optional().describe(`Unique Plugin ID (e.g. com.example.crm)`),type:t.z.enum([`standard`,...Is]).default(`standard`).optional().describe(`Plugin Type categorization for runtime behavior`),staticPath:t.z.string().optional().describe(`Absolute path to static assets (Required for type="ui-plugin")`),slug:t.z.string().regex(/^[a-z0-9-_]+$/).optional().describe(`URL path segment (Required for type="ui-plugin")`),default:t.z.boolean().optional().describe(`Serve at root path (Only one "ui-plugin" can be default)`),version:t.z.string().regex(/^\d+\.\d+\.\d+$/).optional().describe(`Semantic Version`),description:t.z.string().optional(),author:t.z.string().optional(),homepage:t.z.string().url().optional()}));var Rs=t.z.enum([`insert`,`update`,`upsert`,`replace`,`ignore`]),zs=n(()=>D({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:Rs.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`),..._})),Bs=[`id`,`label`,`icon`,`order`,`badge`,`badgeVariant`,`visible`,`requiredPermissions`,`requiresObject`,`requiresService`,`type`],Vs={visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,hidden:`visible`,title:`label`,name:`id`,sort:`order`,sortorder:`order`,position:`order`,permissions:`requiredPermissions`,requiredpermission:`requiredPermissions`,requiresobjects:`requiresObject`,badgecolor:`badgeVariant`,badgestyle:`badgeVariant`},Hs={defaultopen:`expanded`,open:`expanded`,collapsed:`expanded`,isopen:`expanded`},Us={defaultopen:`type: 'group' (with expanded)`,open:`type: 'group' (with expanded)`,collapsed:`type: 'group' (with expanded)`,isopen:`type: 'group' (with expanded)`},Ws={object:[`objectName`,`viewName`,`recordId`,`recordMode`,`filters`,`children`],dashboard:[`dashboardName`],page:[`pageName`,`params`],url:[`url`,`target`],report:[`reportName`],action:[`actionDef`],component:[`componentRef`,`params`],group:[`expanded`,`children`],separator:[]},J=e=>T({surface:`this \`${e}\` navigation item`,knownKeys:[...Bs,...Ws[e]],aliases:{...Vs,...e===`object`?{}:{objectname:`type: 'object' (with objectName)`},...e===`page`?{}:{pagename:`type: 'page' (with pageName)`},...e===`url`?{}:{url:`type: 'url' (with url)`},...e===`dashboard`?{}:{dashboardname:`type: 'dashboard' (with dashboardName)`},...e===`report`?{}:{reportname:`type: 'report' (with reportName)`},...e===`component`?{}:{componentref:`type: 'component' (with componentRef)`},...e===`group`?Hs:Us},guidance:{children:"`children` is only meaningful on a `group` item (or an `object` item nesting its views). Nest entries under `{ type: 'group', children: [...] }`."},history:"Until #4001 these were dropped silently — the entry still parsed, so a mis-spelled config shipped as a nav item that quietly ignored it (a stripped `visible` renders an entry that should have been gated)."}),Gs=T({surface:`this nav item's action definition`,knownKeys:[`actionName`,`params`],aliases:{action:`actionName`,name:`actionName`,args:`params`,input:`params`},history:`Until #4001 these were dropped silently — the definition still parsed, so clicking the entry dispatched a different action than the author declared.`}),Y=t.z.object({id:y.describe(`Unique identifier for this navigation item (lowercase snake_case)`),label:B.describe(`Display proper label`),icon:t.z.string().optional().describe(`Icon name`),order:t.z.number().optional().describe(`Sort order within the same level (lower = first)`),badge:t.z.union([t.z.string(),t.z.number()]).optional().describe(`Badge text or count displayed on the item`),badgeVariant:t.z.enum([`default`,`secondary`,`destructive`,`outline`]).optional().describe(`Visual variant of the nav badge. Declared to match the objectui NavigationRenderer read (inverse-drift fix, liveness audit #1878/#1891/#1894).`),visible:b.optional().describe("Visibility predicate (CEL). e.g. P`'org_admin' in current_user.positions`"),requiredPermissions:t.z.array(t.z.string()).optional().describe(`Permissions required to access this item`),requiresObject:t.z.string().optional().describe(`Hide/disable this entry unless the named object is registered in the runtime`),requiresService:t.z.string().optional().describe(`Hide/disable this entry unless the named kernel service is registered`)}),X=n(()=>t.z.object({...Y.shape,type:t.z.literal(`object`),objectName:t.z.string().describe(`Target object name`),viewName:t.z.string().optional().describe('Default list view to open. Defaults to "all". Ignored when `recordId` is set.'),recordId:t.z.string().optional().describe(`Navigate directly to this record id instead of the list view. Supports template vars: {current_user_id}, {current_org_id}.`),recordMode:t.z.enum([`view`,`edit`]).optional().describe("Open the record in view (default) or edit mode. Only meaningful when `recordId` is set."),filters:t.z.record(t.z.string(),t.z.string()).optional().describe(`URL filter conditions — targets the /:objectName/data bare surface via filter[<field>]=<value> params instead of a saved view. Values support template vars {current_user_id}, {current_org_id}. Mutually exclusive with recordId/viewName.`)},{error:J(`object`)}).strict()),Ks=(e,n)=>{e.filters&&(e.recordId||e.viewName)&&n.addIssue({code:t.z.ZodIssueCode.custom,path:[`filters`],message:"`filters` cannot be combined with `recordId` or `viewName` — pick ONE landing: recordId (record deep-link), filters (/data slice), or viewName (named view). Remove the extra field(s); runtime precedence would silently ignore them."})},qs=n(()=>t.z.object({...Y.shape,type:t.z.literal(`dashboard`),dashboardName:t.z.string().describe(`Target dashboard name`)},{error:J(`dashboard`)}).strict()),Js=n(()=>t.z.object({...Y.shape,type:t.z.literal(`page`),pageName:t.z.string().describe(`Target custom page component name`),params:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Parameters passed to the page context`)},{error:J(`page`)}).strict()),Ys=n(()=>t.z.object({...Y.shape,type:t.z.literal(`url`),url:t.z.string().describe(`Target external URL`),target:t.z.enum([`_self`,`_blank`]).default(`_self`).describe(`Link target window`)},{error:J(`url`)}).strict()),Xs=n(()=>t.z.object({...Y.shape,type:t.z.literal(`report`),reportName:t.z.string().describe(`Target report name`)},{error:J(`report`)}).strict()),Zs=n(()=>t.z.object({...Y.shape,type:t.z.literal(`action`),actionDef:t.z.object({actionName:t.z.string().describe(`Action machine name to execute`),params:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Parameters passed to the action`)},{error:Gs}).strict().describe(`Action definition to execute when clicked`)},{error:J(`action`)}).strict()),Qs=n(()=>t.z.object({...Y.shape,type:t.z.literal(`component`),componentRef:t.z.string().describe(`Component registry key (e.g. "metadata:directory")`),params:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Props passed to the component`)},{error:J(`component`)}).strict()),$s=n(()=>t.z.object({...Y.shape,type:t.z.literal(`group`),expanded:t.z.boolean().default(!1).describe(`Default expansion state in sidebar`)},{error:J(`group`)}).strict()),ec=n(()=>t.z.object({type:t.z.literal(`separator`),id:y.optional().describe(`Optional id for the separator`),order:t.z.number().optional().describe(`Sort order within the same level (lower = first)`)},{error:J(`separator`)}).strict()),tc=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[X.extend({children:t.z.array(tc).optional().describe(`Child navigation items (e.g. specific views)`)}).strict().superRefine(Ks),qs,Js,Ys,Xs,Zs,Qs,ec,$s.extend({children:t.z.array(tc).describe(`Child navigation items`)}).strict()])),nc=n(()=>t.z.object({app:y.describe(`Target app name to contribute navigation into (e.g. "setup")`),group:y.optional().describe(`Target group nav-item id to append into (e.g. "group_integrations"); omit to append at the app top level`),priority:t.z.number().int().min(0).default(200).describe(`Merge priority within the target group — lower applied first (matches object extender priority)`),items:t.z.array(tc).describe(`Navigation items contributed into the target app/group`)},{error:T({surface:`this navigation contribution`,knownKeys:[`app`,`group`,`priority`,`items`],aliases:{targetapp:`app`,appname:`app`,targetgroup:`group`,groupid:`group`,order:`priority`,navigation:`items`},history:`Until #4001 these were dropped silently — the contribution still parsed, so a package injected its menu into the wrong place, or nowhere.`})}).strict().describe(`A navigation contribution: a package injecting nav items into an app it does not own (ADR-0029 D7)`)),rc=n(()=>t.z.object({primaryColor:t.z.string().optional().describe(`Primary theme color hex code`),accentColor:t.z.string().optional().describe(`Accent color hex code (highlights, active states). Declared to match the objectui ConsoleLayout read of branding.accentColor (inverse-drift fix, liveness audit #1878/#1891/#1894).`),logo:t.z.string().optional().describe(`Custom logo URL for this app`),favicon:t.z.string().optional().describe(`Custom favicon URL for this app`)},{error:T({surface:`this app's branding block`,knownKeys:[`primaryColor`,`accentColor`,`logo`,`favicon`],aliases:{primary:`primaryColor`,accent:`accentColor`,color:`primaryColor`,logourl:`logo`,icon:`favicon`,theme:`primaryColor`},history:`Until #4001 these were dropped silently — branding still parsed, so a theme the author set never reached the shell.`})}).strict()),ic="`areas[].order` was removed in @objectstack/spec 17.0.0 (#4667, ADR-0049) — no renderer ever sorted areas; both the sidebar and the schema renderer iterate the array as authored, so declaration order already IS display order. Delete the key and reorder the `areas` array itself. NOTE the neighbour that behaves differently: a navigation ITEM's `order` is genuinely sorted — this removal does not touch it. Run `os migrate meta --from 16` to rewrite existing sources automatically.",ac="`areas[].visible` was removed in @objectstack/spec 17.0.0 (#4651, ADR-0049) — nothing ever evaluated an area-level predicate, so an area \"hidden\" by one rendered for EVERYONE: a gate that fails open, which is worse than no gate at all. Delete the key and gate the items INSIDE the area — a navigation ITEM's `visible` takes the same CEL expression and IS evaluated per item by the shell. For a gate the SERVER enforces, use `requiredPermissions` instead: on the app itself, or on the ITEMS of either navigation tree — the app's top-level `navigation` AND every `areas[].navigation`, both stripped server-side since #4722. The distinction survives at every level: `visible` is CEL evaluated in the browser, so it hides an entry that has already been sent, while `requiredPermissions` stops that entry from being served at all. Run `os migrate meta --from 16` to rewrite existing sources automatically.",oc='`areas[].requiredPermissions` was removed in @objectstack/spec 17.0.0 (#4651, ADR-0049) — no layer ever checked it, so a "permission-gated" area was served to, and rendered for, every user: a fail-open access gate, not merely an unread key. Delete it and move the gate to a layer that is actually enforced. `requiredPermissions` on the APP is checked server-side (the app is dropped from /meta entirely for a caller who lacks them), and `requiredPermissions` / `requiresService` on a navigation ITEM are stripped server-side in BOTH trees — the app\'s top-level `navigation` AND every `areas[].navigation`, through the same filter since #4722 — then re-checked in the shell, so an item gated inside an area never reaches the browser either. That enforces the items INSIDE an area; the area-level key is not revived. Still evaluated client-side ONLY, at every level: `visible` (CEL) and `requiresObject` — so anything that must never reach the browser goes in `requiredPermissions`, never in `visible`. Run `os migrate meta --from 16` to rewrite existing sources automatically.',sc=n(()=>t.z.object({id:y.describe(`Unique area identifier (lowercase snake_case)`),label:B.describe(`Area display label`),icon:t.z.string().optional().describe(`Area icon name`),description:B.optional().describe(`Area description`),navigation:t.z.array(tc).describe(`Navigation items within this area`)},{error:T({surface:`this navigation area`,knownKeys:[`id`,`label`,`icon`,`description`,`navigation`],aliases:{title:`label`,name:`id`,items:`navigation`,children:`navigation`},guidance:{order:ic,sort:ic,visible:ac,visibleWhen:ac,visibleOn:ac,requiredPermissions:oc,permissions:oc},history:`Until #4001 these were dropped silently — the area still parsed, so its gating or ordering was quietly ignored.`})}).strict()),cc={includeAll:"`contextSelectors[].includeAll` was removed in @objectstack/spec 17.0.0 (#4509, ADR-0049) — the shell deliberately ignored it. A context selector is a MANDATORY scope: an \"All\" row would clear the scope on a surface that exists to be scoped, and on Studio's package selector that means listing the platform's own system/cloud kernel metadata to a developer who scoped to their own package. The renderer never offered an All row regardless of this flag, so `includeAll: false` hardened nothing and `includeAll: true` unlocked nothing. Delete the key. To widen what a selector offers, widen `optionsSource.filter` instead. Run `os migrate meta --from 16` to rewrite existing sources automatically.",showall:'`contextSelectors[].includeAll` (which `showall` aliased) was removed in @objectstack/spec 17.0.0 (#4509) — selectors are mandatory-scope and never render an "All" row. Delete the key; widen `optionsSource.filter` to widen the choices.',placement:"`contextSelectors[].placement` was removed in @objectstack/spec 17.0.0 (#4509, ADR-0049) — no renderer ever read it. Selectors always render in the sidebar header block, and `'topbar'` placed nothing in the topbar. Delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically.",location:"`contextSelectors[].placement` (which `location` aliased) was removed in @objectstack/spec 17.0.0 (#4509) — selectors always render in the sidebar header. Delete the key."},lc=n(()=>t.z.object({id:y.describe(`Selector id; selected value is exposed as the nav template var {<id>}`),label:B.describe(`Dropdown label`),icon:t.z.string().optional().describe(`Icon name`),optionsSource:t.z.object({endpoint:t.z.string().describe(`REST endpoint returning the option rows (e.g. /api/v1/packages)`),valueKey:t.z.string().default(`id`).describe(`Row property used as the option value (dotted path allowed, e.g. "manifest.id")`),labelKey:t.z.string().default(`name`).describe(`Row property used as the option label (dotted path allowed, e.g. "manifest.name")`),filter:t.z.array(t.z.object({key:t.z.string().describe(`Dotted path on each row to compare (e.g. "manifest.scope")`),op:t.z.enum([`eq`,`ne`,`in`,`nin`]).default(`eq`).describe(`Comparison operator: eq | ne | in | nin`),value:t.z.union([t.z.string(),t.z.array(t.z.string())]).describe(`Comparison value (string for eq/ne, string[] for in/nin)`)},{error:T({surface:`this context-selector option filter`,knownKeys:[`key`,`op`,`value`],aliases:{field:`key`,path:`key`,operator:`op`,values:`value`},history:`Until #4001 these were dropped silently — the predicate still parsed, so the option list was not narrowed the way the author declared.`})}).strict()).optional().describe(`Predicates (AND) each option row must satisfy`)},{error:T({surface:`this context selector's options source`,knownKeys:[`endpoint`,`valueKey`,`labelKey`,`filter`],aliases:{url:`endpoint`,path:`endpoint`,value:`valueKey`,label:`labelKey`,filters:`filter`,where:`filter`},history:`Until #4001 these were dropped silently — the source still parsed, so the dropdown resolved its options from a different shape than declared.`})}).strict().describe(`Option data source`),allValue:t.z.string().default(``).describe(`Sentinel value meaning "no concrete selection yet" (empty string is almost always right)`),persist:t.z.enum([`query`,`session`,`none`]).default(`query`).describe(`Persist selection via URL query, sessionStorage, or not at all`)},{error:T({surface:`this app context selector`,knownKeys:[`id`,`label`,`icon`,`optionsSource`,`allValue`,`persist`],aliases:{name:`id`,title:`label`,source:`optionsSource`,options:`optionsSource`},guidance:cc,history:`Until #4001 these were dropped silently — the selector still parsed, so its scope variable behaved differently than declared.`})}).strict()),uc=`name.label.description.icon.branding.active.isDefault.hidden.navigation.areas.contextSelectors.homePageId.requiredPermissions.defaultAgent.protection._lock._lockReason._lockSource._provenance._packageId._packageVersion._lockDocsUrl.version.aria.objects.apis.sharing.embed.mobileNavigation`.split(`.`),dc="`app.homePageId` was removed in @objectstack/spec 17.0.0 (#4667, #4709, ADR-0049). objectui's console did read it before v17 (`resolveLandingRoute`), so this key had a consumer — it was retired because the capability is better expressed on the navigation item itself than as an ID cross-reference that silently falls back when it dangles. An app's landing page IS its first navigation item (by `order`), and the root landing follows `isDefault` routing. Delete the key; to change where an app opens, reorder `navigation` so the intended entry is first, and set `isDefault` on the app that should own the root landing. Run `os migrate meta --from 16` to rewrite existing sources automatically.",fc=T({surface:`this app`,knownKeys:uc,aliases:{title:`label`,nav:`navigation`,menu:`navigation`,menus:`navigation`,items:`navigation`,sidebar:`navigation`,tabs:`navigation`,sections:`areas`,groups:`areas`,permissions:`requiredPermissions`,agent:`defaultAgent`,logo:`branding`,theme:`branding`,enabled:`active`,default:`isDefault`,selectors:`contextSelectors`},guidance:{pages:"`pages` is not an App field — a page is its own metadata record; reference it from navigation with `{ type: 'page', pageName: '<name>' }`.",views:"`views` is not an App field — views belong to their object (`listViews`); reference one from navigation with `{ type: 'object', objectName, viewName }`.",flows:"`flows` is not an App field — flows are top-level stack metadata (`defineStack({ flows })`), not app-scoped.",home:dc,homepage:dc,landingpage:dc},history:`Until #4001 these were dropped silently — the app still parsed, so navigation or gating the author declared never reached the shell.`}),pc=n(()=>t.z.object({name:y.describe(`App unique machine name (lowercase snake_case)`),label:B.describe(`App display label`),version:p("`App.version` was removed in @objectstack/spec 17.0.0 (2026-06 liveness audit — no consumer in framework or objectui). An app is versioned by its owning package: use `manifest.version`. Delete the key."),description:B.optional().describe(`App description`),icon:t.z.string().optional().describe(`App icon used in the App Launcher`),branding:rc.optional().describe(`App-specific branding`),active:t.z.boolean().optional().default(!0).describe(`Whether the app is enabled`),isDefault:t.z.boolean().optional().default(!1).describe(`Is default app`),hidden:t.z.boolean().optional().describe(`Hide from the App Switcher; the shell surfaces hidden apps via the avatar menu instead`),navigation:t.z.array(tc).optional().describe(`Full navigation tree for the app sidebar`),areas:t.z.array(sc).optional().describe(`Navigation areas for partitioning navigation by business domain`),contextSelectors:t.z.array(lc).optional().describe(`App-level scope dropdowns whose value is injected into nav items as {<id>} template vars`),homePageId:p(dc),requiredPermissions:t.z.array(t.z.string()).optional().describe(`Permissions required to access this app`),objects:p('`App.objects` was removed in @objectstack/spec 17.0.0 (2026-06 liveness audit — never read; the spec itself labelled it "config file convenience"). Objects belong to the stack (`defineStack({ objects })`); an app reaches them through its navigation items. Delete the key.'),apis:p("`App.apis` was removed in @objectstack/spec 17.0.0 (2026-06 liveness audit — never read). Delete the key and declare the endpoint one level up, on the STACK: `defineStack({ apis })`. That surface EXECUTES from protocol 17 (#5040). Between #4936 and the executor landing it was refused wholesale — nothing mounted a declared path, so every key including `authRequired` parsed and gated nothing — and that blanket refusal is now narrowed to five per-endpoint publish gates (namespace, supported target, mapping, policy, uniqueness): an endpoint that passes them is mounted and serves traffic as soon as the stack is published. Two things to get right when you move it: the path must sit inside your own carve-out, `/api/v1/apps/<manifest.namespace>/<subpath>` with an explicit `manifest.namespace` (ADR-0121 D1/D2), and `authRequired` defaults to `true` — an explicit `false` is the only thing that opens anonymous access, and ADR-0121 D6 then requires an armed `rateLimit: { enabled: true, windowMs, maxRequests }`. Read the `declarative-apis-endpoints-live` entry of the protocol upgrade guide first; it is a security review, not a rename. A route that genuinely needs handler CODE still belongs in a plugin manifest `contributes.routes` entry."),sharing:p("`App.sharing` was removed in @objectstack/spec 17.0.0 (2026-06 liveness audit / ADR-0049 enforce-or-remove) — no public-app route ever read it, so it declared sharing that did not exist. Public access is granted per FORM VIEW (`FormView.sharing`, the public-data-collection surface). Delete the key."),embed:p("`App.embed` was removed in @objectstack/spec 17.0.0 (2026-06 liveness audit / ADR-0049) — no iframe route ever read it. Embedding is a per-form-view surface (`FormView.sharing`), not an app-level switch. Delete the key."),mobileNavigation:p("`App.mobileNavigation` was removed in @objectstack/spec 17.0.0 (2026-06 liveness audit — fully unimplemented; no renderer, including packages/mobile, ever read it). Delete the key; the block returns if/when a real mobile navigation ships."),defaultAgent:y.optional().describe(`Platform agent bound to this app's ambient chat ('ask' is the implicit default; 'build' for authoring surfaces) — ADR-0063 §1`),aria:p("`App.aria` was removed in @objectstack/spec 17.0.0 (2026-06 liveness audit — no renderer read app-level ARIA attributes). Declare `aria` on the component/widget that renders the DOM node instead. Delete the key."),protection:z.optional().describe(`Package author protection block — lock policy for this app.`),..._},{error:fc}).strict()),mc=t.z.object({services:t.z.array(t.z.string()).optional().describe(`Platform services the plugin may resolve (e.g. "object", "http")`),hooks:t.z.array(t.z.string()).optional().describe(`Lifecycle hooks the plugin may register (e.g. "record.beforeInsert")`),network:t.z.array(t.z.string()).optional().describe(`Network hosts the plugin may reach (e.g. "api.acme.com")`),fs:t.z.array(t.z.string()).optional().describe(`Filesystem paths the plugin may access`)}).strict().describe(`Structured plugin permission grants (ADR-0025 §3.2)`),hc=t.z.union([t.z.array(t.z.string()),mc]),gc=t.z.object({platform:t.z.string().optional().describe(`ObjectStack platform release range (SemVer, e.g. ">=4.0 <5")`),protocol:t.z.string().optional().describe(`Runtime/metadata protocol range, checked first (ADR §3.10 #3)`)}).describe(`Plugin compatibility ranges (ADR-0025 §3.2)`),_c=t.z.enum([`node`,`sandbox`,`worker`]).describe(`Plugin trust tier (ADR-0025 §3.6)`),vc=t.z.enum([`bundled`,`manifest-deps`]).describe(`Dependency packaging strategy (ADR-0025 §3.3)`),yc=t.z.record(t.z.string(),t.z.string()).describe(`Per-file content digests of the plugin artifact (ADR-0025 §3.2)`),Z=t.z.object({id:t.z.string().describe(`Unique package identifier (reverse domain style)`),namespace:t.z.string().regex(/^[a-z][a-z0-9_]{1,19}$/,`Namespace must be 2-20 chars, lowercase alphanumeric + underscore`).optional().describe(`Short namespace identifier; also the mandatory prefix of every object name (e.g. "todo" → object names "todo_task", "todo_project")`),defaultDatasource:t.z.string().optional().default(`default`).describe(`Default datasource for all objects in this package`),version:t.z.string().regex(/^\d+\.\d+\.\d+$/).describe(`Package version (semantic versioning)`),type:t.z.enum([`plugin`,...Is,`module`,`gateway`,`adapter`]).describe(`Type of package`),scope:t.z.enum([`cloud`,`system`,`project`]).default(`project`).describe(`Deployment scope: cloud | system | project`),name:t.z.string().describe(`Human-readable package name`),description:t.z.string().optional().describe(`Package description`),permissions:hc.optional().describe(`Required permissions: legacy string[] or structured plugin block (ADR-0025 §3.2)`),objects:t.z.array(t.z.string()).optional().describe(`Glob patterns for ObjectQL schemas files`),datasources:t.z.array(t.z.string()).optional().describe(`Glob patterns for Datasource definitions`),dependencies:t.z.record(t.z.string(),t.z.string()).optional().describe(`Package dependencies`),configuration:t.z.object({title:t.z.string().optional(),properties:t.z.record(t.z.string(),t.z.object({type:t.z.enum([`string`,`number`,`boolean`,`array`,`object`]).describe(`Data type of the setting`),default:t.z.unknown().optional().describe(`Default value`),description:t.z.string().optional().describe(`Tooltip description`),required:t.z.boolean().optional().describe(`Is this setting required?`),secret:t.z.boolean().optional().describe(`If true, value is encrypted/masked (e.g. API Keys)`),enum:t.z.array(t.z.string()).optional().describe(`Allowed values for select inputs`)})).describe(`Map of configuration keys to their definitions`)}).optional().describe(`Plugin configuration settings`),contributes:t.z.object({kinds:t.z.array(t.z.object({id:t.z.string().describe(`The generic identifier of the kind (e.g., "sys.bi.report")`),globs:t.z.array(t.z.string()).describe(`File patterns to watch (e.g., ["**/*.report.ts"])`),description:t.z.string().optional().describe(`Description of what this kind represents`)})).optional().describe(`New Metadata Types to recognize`),events:t.z.array(t.z.string()).optional().describe(`Events this plugin listens to`),menus:t.z.record(t.z.string(),t.z.array(t.z.object({id:t.z.string(),label:t.z.string(),command:t.z.string().optional()}))).optional().describe(`UI Menu contributions`),themes:t.z.array(t.z.object({id:t.z.string(),label:t.z.string(),path:t.z.string()})).optional().describe(`Theme contributions`),translations:t.z.array(t.z.object({locale:t.z.string(),path:t.z.string()})).optional().describe(`Translation resources`),actions:t.z.array(t.z.object({name:t.z.string().describe(`Unique action name`),label:t.z.string().optional(),description:t.z.string().optional(),input:t.z.unknown().optional().describe(`Input validation schema`),output:t.z.unknown().optional().describe(`Output schema`)})).optional().describe(`Exposed server actions`),drivers:t.z.array(t.z.object({id:t.z.string().describe(`Driver unique identifier (e.g. "postgres", "mongo")`),label:t.z.string().describe(`Human readable name`),description:t.z.string().optional()})).optional().describe(`Driver contributions`),fieldTypes:t.z.array(t.z.object({name:t.z.string().describe(`Unique field type name (e.g. "vector")`),label:t.z.string().describe(`Display label`),description:t.z.string().optional()})).optional().describe(`Field Type contributions`),functions:t.z.array(t.z.object({name:t.z.string().describe(`Function name (e.g. "distance")`),description:t.z.string().optional(),args:t.z.array(t.z.string()).optional().describe(`Argument types`),returnType:t.z.string().optional()})).optional().describe(`Query Function contributions`),routes:t.z.array(t.z.object({prefix:t.z.string().regex(/^\//).describe(`API path prefix`),service:t.z.string().describe(`Service name this plugin provides`),methods:t.z.array(t.z.string()).optional().describe(`Protocol method names implemented (e.g. ["getLocales", "getTranslations"])`)})).optional().describe(`API route contributions to HttpDispatcher`),commands:t.z.array(t.z.object({name:t.z.string().regex(/^[a-z][a-z0-9-]*$/,`Command name must be lowercase alphanumeric with hyphens`).describe(`CLI command name`),description:t.z.string().optional().describe(`Command description for help text`),module:t.z.string().optional().describe(`Module path exporting Commander.js commands`)})).optional().describe(`CLI command contributions`)}).optional().describe(`Platform contributions`),data:t.z.array(zs).optional().describe(`Initial seed data (prefer top-level data field)`),capabilities:ws.optional().describe(`Plugin capability declarations for interoperability`),extensions:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Extension points and contributions`),navigationContributions:t.z.array(nc).optional().describe(`Navigation items this package contributes into apps owned by other packages`),loading:Fs.optional().describe(`Plugin loading and runtime behavior configuration`),engine:t.z.object({objectstack:t.z.string().regex(/^[><=~^]*\d+\.\d+\.\d+/).describe(`ObjectStack platform version requirement (SemVer range, e.g. ">=3.0.0")`)}).optional().describe("Platform compatibility requirements (legacy; superseded by `engines`)"),engines:gc.optional().describe("Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`)"),runtime:_c.optional().describe(`Plugin trust tier (ADR-0025 §3.6)`),packaging:vc.optional().describe(`Dependency packaging strategy (ADR-0025 §3.3)`),integrity:yc.optional().describe(`Per-file content digests of the plugin artifact (ADR-0025 §3.2)`)}),bc=t.z.enum([`satisfied`,`needs_install`,`needs_upgrade`,`conflict`]).describe(`Resolution status for a dependency`),xc=n(()=>t.z.object({packageId:t.z.string().describe(`Dependency package identifier`),requiredRange:t.z.string().describe(`SemVer range required (e.g. "^2.0.0")`),resolvedVersion:t.z.string().optional().describe(`Actual version resolved from registry`),installedVersion:t.z.string().optional().describe(`Currently installed version`),status:bc.describe(`Resolution status`),conflictReason:t.z.string().optional().describe(`Explanation of the conflict`)}).describe(`Resolution result for a single dependency`)),Sc=n(()=>t.z.object({type:t.z.enum([`install`,`upgrade`,`confirm_conflict`]).describe(`Type of action required`),packageId:t.z.string().describe(`Target package identifier`),description:t.z.string().describe(`Human-readable action description`)}).describe(`Action required before installation can proceed`)),Cc=n(()=>t.z.object({dependencies:t.z.array(xc).describe(`Resolution result for each dependency`),canProceed:t.z.boolean().describe(`Whether installation can proceed`),requiredActions:t.z.array(Sc).describe(`Actions required before proceeding`),installOrder:t.z.array(t.z.string()).describe(`Topologically sorted package IDs for installation`),circularDependencies:t.z.array(t.z.array(t.z.string())).optional().describe(`Circular dependency chains detected (e.g. [["A", "B", "A"]])`)}).describe(`Complete dependency resolution result`)),wc=t.z.enum([`installed`,`disabled`,`installing`,`upgrading`,`uninstalling`,`error`]).describe(`Package installation status`),Q=n(()=>t.z.object({manifest:Z.describe(`Full package manifest`),status:wc.default(`installed`).describe(`Package state: installed, disabled, installing, upgrading, uninstalling, or error`),enabled:t.z.boolean().default(!0).describe(`Whether the package is currently enabled`),installedAt:t.z.string().datetime().optional().describe(`Installation timestamp`),updatedAt:t.z.string().datetime().optional().describe(`Last update timestamp`),installedVersion:t.z.string().optional().describe(`Currently installed version for quick access`),previousVersion:t.z.string().optional().describe(`Version before the last upgrade`),statusChangedAt:t.z.string().datetime().optional().describe(`Status change timestamp`),errorMessage:t.z.string().optional().describe(`Error message when status is error`),settings:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`User-provided configuration settings`),upgradeHistory:t.z.array(t.z.object({fromVersion:t.z.string().describe(`Version before upgrade`),toVersion:t.z.string().describe(`Version after upgrade`),upgradedAt:t.z.string().datetime().describe(`Upgrade timestamp`),status:t.z.enum([`success`,`failed`,`rolled_back`]).describe(`Upgrade outcome`),migrationLog:t.z.array(t.z.string()).optional().describe(`Migration step logs`)})).optional().describe(`Version upgrade history`),registeredNamespaces:t.z.array(t.z.string()).optional().describe(`Namespace prefixes registered by this package`)}).describe(`Installed package with runtime lifecycle state`));n(()=>t.z.object({namespace:t.z.string().describe(`Namespace prefix`),packageId:t.z.string().describe(`Owning package ID`),registeredAt:t.z.string().datetime().describe(`Registration timestamp`),status:t.z.enum([`active`,`disabled`,`reserved`]).describe(`Namespace status`)}).describe(`Namespace ownership entry in the registry`)),n(()=>t.z.object({type:t.z.literal(`namespace_conflict`).describe(`Error type`),requestedNamespace:t.z.string().describe(`Requested namespace`),conflictingPackageId:t.z.string().describe(`Conflicting package ID`),conflictingPackageName:t.z.string().describe(`Conflicting package display name`),suggestion:t.z.string().optional().describe(`Suggested alternative namespace`)}).describe(`Namespace collision error during installation`));var Tc=n(()=>t.z.object({status:wc.optional().describe(`Filter by package status`),type:Z.shape.type.optional().describe(`Filter by package type`),enabled:t.z.boolean().optional().describe(`Filter by enabled state`)}).describe(`List packages request`)),Ec=n(()=>t.z.object({packages:t.z.array(Q).describe(`List of installed packages`),total:t.z.number().describe(`Total package count`)}).describe(`List packages response`)),Dc=n(()=>t.z.object({id:t.z.string().describe(`Package identifier`)}).describe(`Get package request`)),Oc=n(()=>t.z.object({package:Q.describe(`Package details`)}).describe(`Get package response`)),kc=n(()=>t.z.object({manifest:Z.describe(`Package manifest to install`),settings:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`User-provided settings at install time`),enableOnInstall:t.z.boolean().default(!0).describe(`Whether to enable immediately after install`),platformVersion:t.z.string().optional().describe(`Current platform version for compatibility verification`)}).describe(`Install package request`)),Ac=n(()=>t.z.object({package:Q.describe(`Installed package details`),message:t.z.string().optional().describe(`Installation status message`),dependencyResolution:Cc.optional().describe(`Dependency resolution result from install analysis`)}).describe(`Install package response`)),jc=n(()=>t.z.object({id:t.z.string().describe(`Package ID to uninstall`)}).describe(`Uninstall package request`)),Mc=n(()=>t.z.object({id:t.z.string().describe(`Uninstalled package ID`),success:t.z.boolean().describe(`Whether uninstall succeeded`),message:t.z.string().optional().describe(`Uninstall status message`)}).describe(`Uninstall package response`)),Nc=n(()=>t.z.object({id:t.z.string().describe(`Package ID to enable`)}).describe(`Enable package request`)),Pc=n(()=>t.z.object({package:Q.describe(`Enabled package details`),message:t.z.string().optional().describe(`Enable status message`)}).describe(`Enable package response`)),Fc=n(()=>t.z.object({id:t.z.string().describe(`Package ID to disable`)}).describe(`Disable package request`)),Ic=n(()=>t.z.object({package:Q.describe(`Disabled package details`),message:t.z.string().optional().describe(`Disable status message`)}).describe(`Disable package response`)),Lc=n(()=>t.z.object({trigger:t.z.string(),payload:t.z.record(t.z.string(),t.z.unknown())})),Rc=n(()=>t.z.object({success:t.z.boolean(),jobId:t.z.string().optional(),result:t.z.unknown().optional()})),zc=n(()=>t.z.object({actions:t.z.array(is).describe(`Registered action descriptors (built-in + plugin)`),total:t.z.number().int().nonnegative().describe(`Number of descriptors returned (after any filters)`)})),Bc=n(()=>t.z.object({})),Vc=n(()=>Kt.partial().required({version:!0}).extend({apiName:t.z.string().optional().describe("API name (deprecated — use `name`; removed in protocol 18)")})),Hc=n(()=>t.z.object({})),Uc=n(()=>t.z.object({types:t.z.array(t.z.string()).describe(`Available metadata type names (e.g., "object", "plugin", "view")`),entries:t.z.array(t.z.object({type:t.z.string().describe(`Singular type identifier`),label:t.z.string().describe(`Human-readable label`),description:t.z.string().optional().describe(`Brief description`),filePatterns:t.z.array(t.z.string()).describe(`Glob patterns used to discover artifacts of this type`),supportsOverlay:t.z.boolean().describe(`Loader can merge per-org overlays on top of artifact`),allowOrgOverride:t.z.boolean().describe(`Per-org overlay writes accepted at runtime (may be env-elevated)`),allowRuntimeCreate:t.z.boolean().describe(`New artifacts of this type can be created via runtime API`),supportsVersioning:t.z.boolean().describe(`History is tracked for this type`),executionPinned:t.z.boolean().describe(`Runtime transactions pin a specific historical version_hash (ADR-0009)`),loadOrder:t.z.number().int().describe(`Loading priority (lower = earlier)`),domain:t.z.enum([`data`,`ui`,`automation`,`system`,`security`,`ai`]).describe(`Protocol domain`),overrideSource:t.z.enum([`registry`,`env`]).describe(`Whether allowOrgOverride is set in the static registry or via OS_METADATA_WRITABLE env var`),createSeed:t.z.unknown().optional().describe(`Authoritative minimal valid create seed for this type — Studio/CLI/API derive create defaults from it (single source of truth in @objectstack/spec). Absent for canvas-create types whose shape is built interactively.`)})).optional().describe(`Enriched per-type registry entries (Phase 3a)`)})),Wc=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name (e.g., "object", "plugin")`),packageId:t.z.string().optional().describe(`Optional package ID to filter items by`)})),Gc=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),items:t.z.array(t.z.unknown()).describe(`Array of metadata items`)})),Kc=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),name:t.z.string().describe(`Item name (snake_case identifier)`),packageId:t.z.string().optional().describe(`Optional package ID to filter items by`)})),qc=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),name:t.z.string().describe(`Item name`),item:t.z.unknown().describe(`Metadata item definition`)})),Jc=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),name:t.z.string().describe(`Item name`),item:t.z.unknown().describe(`Metadata item definition`)})),Yc=n(()=>t.z.object({success:t.z.boolean(),version:t.z.string().describe("Content hash of the just-committed body, and the token the ADR-0008 optimistic-concurrency chain runs on: send it back as the `If-Match` request header on the next write to that item and a concurrent edit is reported as 409 `metadata_conflict` instead of silently overwritten. Opaque to callers — echo it verbatim, never parse it. Currently emitted as `sha256:<64 hex chars>`, but the format is not part of this contract."),seq:t.z.number().int().describe("Monotonic sequence number of the metadata event this write appended to the item history (sys_metadata_history.event_seq). Orders writes; unlike `version` it is not an OCC token."),state:t.z.enum([`draft`,`active`]).describe('Lifecycle the body was written into: "draft" when the request asked for draft mode (`?mode=draft`), otherwise "active" (published and live). A draft is staged only — it is not served to the runtime until published.'),projectionApplied:t.z.object({success:t.z.boolean().describe(`False when the projector threw; the metadata write itself still succeeded.`),error:t.z.string().optional().describe("Projector failure message, present only when `success` is false.")}).optional().describe('Outcome of the awaited ADR-0094 mutation projector — the post-persist step that materializes this metadata into its derived data-plane read model (e.g. `permission` → `sys_permission_set`). Present ONLY when a projector is registered for this metadata type, which is why it is optional: its absence means "no projector ran", never "the projection failed". Best-effort by design — a projector failure is reported here and logged, never thrown, so a caller that needs the read model to be live must check `projectionApplied.success` rather than rely on the 200.'),message:t.z.string().optional()})),Xc=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),name:t.z.string().describe(`Item name`)})),Zc=n(()=>t.z.object({success:t.z.boolean(),reset:t.z.boolean().optional(),message:t.z.string().optional()})),Qc=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),name:t.z.string().describe(`Item name`),cacheRequest:Gr.optional().describe(`Cache validation parameters`),locale:t.z.string().optional().describe(`Resolved response locale. Folded into the ETag so a language switch never returns a stale-locale 304 — metadata is translated *after* the cache validator check (issue #1319).`)})),$c=n(()=>Kr),el=n(()=>t.z.object({object:t.z.string().describe(`Object name (snake_case)`),type:t.z.enum([`list`,`form`]).describe(`View type`)})),tl=n(()=>H),nl=n(()=>t.z.object({object:t.z.string().describe(`The unique machine name of the object to query (e.g. "account").`),query:Oe.optional().describe(`Structured query definition (filter, sort, select, pagination).`)})),rl=n(()=>t.z.object({object:t.z.string().describe(`The object name for the returned records.`),records:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`The list of matching records.`),total:t.z.number().optional().describe(`Total number of records matching the filter (if requested).`),nextCursor:t.z.string().optional().describe(`Cursor for the next page of results (cursor-based pagination).`),hasMore:t.z.boolean().optional().describe(`True if there are more records available (pagination).`)})),il=n(()=>t.z.object({filter:t.z.string().optional().describe(`JSON-encoded filter expression (canonical, singular).`),filters:t.z.string().optional().describe(`JSON-encoded filter expression (deprecated plural alias).`),select:t.z.string().optional().describe(`Comma-separated list of fields to retrieve.`),sort:t.z.string().optional().describe(`Sort expression (e.g. "name asc,created_at desc" or "-created_at").`),orderBy:t.z.string().optional().describe(`Alias for sort (OData compatibility).`),top:t.z.coerce.number().optional().describe(`Max records to return (limit).`),skip:t.z.coerce.number().optional().describe(`Records to skip (offset).`),expand:t.z.string().optional().describe(`Comma-separated list of lookup/master_detail field names to expand. Resolved to populate array and passed to the engine for batch $in expansion.`),search:t.z.string().optional().describe(`Full-text search query.`),distinct:p(we),count:t.z.coerce.boolean().optional().describe(`Include total count in response.`)})),al=n(()=>t.z.object({object:t.z.string().describe(`The object name.`),id:t.z.string().describe(`The unique record identifier (primary key).`),select:t.z.array(t.z.string()).optional().describe(`Fields to include in the response (allowlisted query param).`),expand:t.z.array(t.z.string()).optional().describe(`Lookup/master_detail field names to expand. The engine resolves these via batch $in queries, replacing foreign key IDs with full objects.`)})),ol=n(()=>t.z.object({object:t.z.string().describe(`The object name.`),id:t.z.string().describe(`The record ID.`),record:t.z.record(t.z.string(),t.z.unknown()).describe(`The complete record data.`)})),sl=n(()=>t.z.object({object:t.z.string().describe(`The object name.`),data:t.z.record(t.z.string(),t.z.unknown()).describe(`The dictionary of field values to insert.`)})),cl=n(()=>t.z.object({object:t.z.string().describe(`The object name.`),id:t.z.string().describe(`The ID of the newly created record.`),record:t.z.record(t.z.string(),t.z.unknown()).describe(`The created record, including server-generated fields (created_at, owner).`),droppedFields:t.z.array(or).optional().describe("Write-observability (#3407/#3431): caller-supplied fields that were LEGALLY stripped before the record was written — a non-system create cannot seed a static `readonly` column (#3043 ingress strip), so those keys are dropped and the field re-derives its default. Present ONLY when ≥1 field was dropped; the create still succeeded without them (status/success semantics unchanged). REST additionally surfaces this as the `X-ObjectStack-Dropped-Fields` response header. Optional — omit-when-empty keeps the shape backward-compatible for existing clients.")})),ll=n(()=>t.z.object({object:t.z.string().describe(`The object name.`),id:t.z.string().describe(`The ID of the record to update.`),data:t.z.record(t.z.string(),t.z.unknown()).describe(`The fields to update (partial update).`),expectedVersion:t.z.string().optional().describe("Optimistic concurrency token (typically the `updated_at` value the client read). When provided, the server compares it against the current record version and returns 409 CONCURRENT_UPDATE if they differ. Optional — omit to skip the check.")})),ul=n(()=>t.z.object({object:t.z.string().describe(`Object name`),id:t.z.string().describe(`Updated record ID`),record:t.z.record(t.z.string(),t.z.unknown()).describe(`Updated record`),droppedFields:t.z.array(or).optional().describe("Write-observability (#3407/#3431): caller-supplied fields the engine LEGALLY stripped from the write before persisting — static `readonly` (#2948) or a TRUE `readonlyWhen` predicate (#3042). Present ONLY when ≥1 field was dropped; the update still succeeded without them (status/success semantics unchanged — stripping is legitimate, not an error). REST additionally surfaces this as the `X-ObjectStack-Dropped-Fields` response header. Optional — omit-when-empty keeps the shape backward-compatible for existing clients that only read `record`.")})),dl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),id:t.z.string().describe(`Record ID to delete`),expectedVersion:t.z.string().optional().describe("Optimistic concurrency token (typically the `updated_at` value the client read). When provided, the server compares it against the current record version and returns 409 CONCURRENT_UPDATE if they differ. Optional — omit to skip the check.")})),fl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),id:t.z.string().describe(`Deleted record ID`),success:t.z.boolean().describe(`Whether deletion succeeded`)})),pl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),request:Ar.describe(`Batch operation request`)})),ml=n(()=>Pr),hl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),records:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Array of records to create`)})),gl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),records:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Created records`),count:t.z.number().describe(`Number of records created`),droppedFields:t.z.array(or).optional().describe("Write-observability (#3407/#3431/#3455): caller-supplied `readonly` fields the #3043 create-ingress strip removed before the rows were written. AGGREGATED across the batch (one event per object/reason with the union of dropped field names) rather than per-row, because the insert-time strip is static-`readonly` only — schema-uniform, so every row drops the same set. Present ONLY when ≥1 field was dropped; the creates still succeeded without them (count/success unchanged). Optional — omit-when-empty keeps the shape backward-compatible. (The per-row `insertMany`/`batch` paths carry per-row `droppedFields` on each result instead — see BatchOperationResultSchema.)")})),_l=n(()=>Mr.extend({object:t.z.string().describe(`Object name`)})),vl=n(()=>Pr),yl=n(()=>Fr.extend({object:t.z.string().describe(`Object name`)})),bl=n(()=>Pr),xl=n(()=>t.z.object({object:t.z.string().describe(`Object name (snake_case)`),type:t.z.enum([`list`,`form`]).optional().describe(`Filter by view type`)})),Sl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),views:t.z.array(H).describe(`Array of view definitions`)})),Cl=n(()=>t.z.object({object:t.z.string().describe(`Object name (snake_case)`),viewId:t.z.string().describe(`View identifier`)})),wl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),view:H.describe(`View definition`)})),Tl=n(()=>t.z.object({object:t.z.string().describe(`Object name (snake_case)`),data:H.describe(`View definition to create`)})),El=n(()=>t.z.object({object:t.z.string().describe(`Object name`),viewId:t.z.string().describe(`Created view identifier`),view:H.describe(`Created view definition`)})),Dl=n(()=>t.z.object({object:t.z.string().describe(`Object name (snake_case)`),viewId:t.z.string().describe(`View identifier`),data:H.partial().describe(`Partial view data to update`)})),Ol=n(()=>t.z.object({object:t.z.string().describe(`Object name`),viewId:t.z.string().describe(`Updated view identifier`),view:H.describe(`Updated view definition`)})),kl=n(()=>t.z.object({object:t.z.string().describe(`Object name (snake_case)`),viewId:t.z.string().describe(`View identifier to delete`)})),Al=n(()=>t.z.object({object:t.z.string().describe(`Object name`),viewId:t.z.string().describe(`Deleted view identifier`),success:t.z.boolean().describe(`Whether deletion succeeded`)})),jl=n(()=>t.z.object({object:t.z.string().describe(`Object name to check permissions for`),action:t.z.enum([`create`,`read`,`edit`,`delete`,`transfer`,`restore`,`purge`]).describe(`Action to check`),recordId:t.z.string().optional().describe(`Specific record ID (for record-level checks)`),field:t.z.string().optional().describe(`Specific field name (for field-level checks)`)})),Ml=n(()=>t.z.object({allowed:t.z.boolean().describe(`Whether the action is permitted`),reason:t.z.string().optional().describe(`Reason if denied`)})),Nl=n(()=>t.z.object({object:t.z.string().describe(`Object name to get permissions for`)})),Pl=n(()=>t.z.object({object:t.z.string().describe(`Object name`),permissions:Yo.describe(`Object-level permissions`),fieldPermissions:t.z.record(t.z.string(),Qo).optional().describe(`Field-level permissions keyed by field name`)})),Fl=n(()=>t.z.object({})),Il=n(()=>t.z.object({objects:t.z.record(t.z.string(),Xo).describe(`Effective object permissions keyed by object name`),systemPermissions:t.z.array(t.z.string()).describe(`Effective system-level permissions`)})),Ll=n(()=>t.z.object({transport:rn.optional().describe(`Preferred transport protocol`),channels:t.z.array(t.z.string()).optional().describe(`Channels to subscribe to on connect`),token:t.z.string().optional().describe(`Authentication token`)})),Rl=n(()=>t.z.object({connectionId:t.z.string().describe(`Unique connection identifier`),transport:rn.describe(`Negotiated transport protocol`),url:t.z.string().optional().describe(`WebSocket/SSE endpoint URL`)})),zl=n(()=>t.z.object({connectionId:t.z.string().optional().describe(`Connection ID to disconnect`)})),Bl=n(()=>t.z.object({success:t.z.boolean().describe(`Whether disconnection succeeded`)})),Vl=n(()=>t.z.object({channel:t.z.string().describe(`Channel name to subscribe to`),events:t.z.array(t.z.string()).optional().describe(`Specific event types to listen for`),filter:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Event filter criteria`)})),Hl=n(()=>t.z.object({subscriptionId:t.z.string().describe(`Unique subscription identifier`),channel:t.z.string().describe(`Subscribed channel name`)})),Ul=n(()=>t.z.object({subscriptionId:t.z.string().describe(`Subscription ID to cancel`)})),Wl=n(()=>t.z.object({success:t.z.boolean().describe(`Whether unsubscription succeeded`)})),Gl=n(()=>t.z.object({channel:t.z.string().describe(`Channel to set presence in`),state:cn.describe(`Presence state to set`)})),Kl=n(()=>t.z.object({success:t.z.boolean().describe(`Whether presence was set`)})),ql=n(()=>t.z.object({channel:t.z.string().describe(`Channel to get presence for`)})),Jl=n(()=>t.z.object({channel:t.z.string().describe(`Channel name`),members:t.z.array(cn).describe(`Active members and their presence state`)})),Yl=n(()=>t.z.object({token:t.z.string().describe(`Device push notification token`),platform:t.z.enum([`ios`,`android`,`web`]).describe(`Device platform`),deviceId:t.z.string().optional().describe(`Unique device identifier`),name:t.z.string().optional().describe(`Device friendly name`)})),Xl=n(()=>t.z.object({deviceId:t.z.string().describe(`Registered device ID`),success:t.z.boolean().describe(`Whether registration succeeded`)})),Zl=n(()=>t.z.object({deviceId:t.z.string().describe(`Device ID to unregister`)})),Ql=n(()=>t.z.object({success:t.z.boolean().describe(`Whether unregistration succeeded`)})),$l=n(()=>t.z.object({email:t.z.boolean().default(!0).describe(`Receive email notifications`),push:t.z.boolean().default(!0).describe(`Receive push notifications`),inApp:t.z.boolean().default(!0).describe(`Receive in-app notifications`),digest:t.z.enum([`none`,`daily`,`weekly`]).default(`none`).describe(`Email digest frequency`),channels:t.z.record(t.z.string(),t.z.object({enabled:t.z.boolean().default(!0).describe(`Whether this channel is enabled`),email:t.z.boolean().optional().describe(`Override email setting`),push:t.z.boolean().optional().describe(`Override push setting`)})).optional().describe(`Per-channel notification preferences`)})),eu=n(()=>t.z.object({})),tu=n(()=>t.z.object({preferences:$l.describe(`Current notification preferences`)})),nu=n(()=>t.z.object({preferences:$l.partial().describe(`Preferences to update`)})),ru=n(()=>t.z.object({preferences:$l.describe(`Updated notification preferences`)})),iu=n(()=>t.z.object({id:t.z.string().describe(`Notification ID`),type:t.z.string().describe(`Notification type`),title:t.z.string().describe(`Notification title`),body:t.z.string().describe(`Notification body text`),read:t.z.boolean().default(!1).describe(`Whether notification has been read`),data:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional notification data`),actionUrl:t.z.string().optional().describe(`URL to navigate to when clicked`),createdAt:t.z.string().datetime().describe(`When notification was created`)})),au=n(()=>t.z.object({read:t.z.boolean().optional().describe(`Filter by read status`),type:t.z.string().optional().describe(`Filter by notification type`),limit:t.z.number().default(20).describe(`Maximum number of notifications to return`),cursor:t.z.string().optional().describe(`Pagination cursor`)})),ou=n(()=>t.z.object({notifications:t.z.array(iu).describe(`List of notifications`),unreadCount:t.z.number().describe(`Total number of unread notifications`),cursor:t.z.string().optional().describe(`Next page cursor`)})),su=n(()=>t.z.object({ids:t.z.array(t.z.string()).describe(`Notification IDs to mark as read`)})),cu=n(()=>t.z.object({success:t.z.boolean().describe(`Whether the operation succeeded`),readCount:t.z.number().describe(`Number of notifications marked as read`)})),lu=n(()=>t.z.object({})),uu=n(()=>t.z.object({success:t.z.boolean().describe(`Whether the operation succeeded`),readCount:t.z.number().describe(`Number of notifications marked as read`)})),du=n(()=>t.z.object({role:t.z.enum([`system`,`user`,`assistant`,`tool`]).describe(`Message role`),content:t.z.unknown().optional().describe(`Message content: a string, or an array of content parts`),parts:t.z.array(t.z.unknown()).optional().describe("Vercel AI SDK v6 message parts (alternative to `content`)")}).passthrough()),fu=n(()=>t.z.object({messages:t.z.array(du).min(1).describe(`Conversation messages (at least one)`),system:t.z.string().optional().describe(`System prompt, prepended as a system message`),model:t.z.string().optional().describe(`Model id override`),temperature:t.z.number().optional().describe(`Sampling temperature`),maxTokens:t.z.number().int().positive().optional().describe(`Maximum tokens to generate`),stream:t.z.boolean().optional().describe(`false → JSON response; otherwise the UI Message Stream Protocol`),conversationId:t.z.string().optional().describe(`Conversation to persist this turn into (auto-created when omitted)`),turnId:t.z.string().optional().describe(`Stable per-turn idempotency key (ADR-0013 D1)`),options:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Legacy nested request options`)})),pu=n(()=>t.z.object({content:t.z.string().describe(`Generated text`),model:t.z.string().optional().describe(`Model that produced it`),toolCalls:t.z.array(t.z.unknown()).optional().describe("Tool calls the model requested (Vercel `ToolCallPart`)"),usage:t.z.object({promptTokens:t.z.number().describe(`Tokens consumed by the prompt`),completionTokens:t.z.number().describe(`Tokens generated`),totalTokens:t.z.number().describe(`prompt + completion`)}).optional().describe(`Token usage`),conversationId:t.z.string().optional().describe(`Conversation the turn was persisted into`)})),mu=n(()=>t.z.object({prompt:t.z.string().describe(`Prompt text`),options:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Request options (model, temperature, maxTokens, …)`)})),hu=n(()=>t.z.object({models:t.z.array(t.z.union([t.z.string(),t.z.object({id:t.z.string().describe(`Model id`),label:t.z.string().describe(`Display label for the picker`),default:t.z.boolean().describe(`Whether this is the environment default`)})])).describe(`Models this environment offers`),defaultModel:t.z.string().optional().describe(`Default model id, when the service reports one`)})),gu=n(()=>t.z.object({id:t.z.string().describe(`Conversation id`),title:t.z.string().optional().describe(`Title / summary`),agentId:t.z.string().optional().describe(`Agent this conversation is bound to`),userId:t.z.string().optional().describe(`Owning user`),messages:t.z.array(du).describe(`Message history`),createdAt:t.z.string().describe(`Creation timestamp (ISO 8601)`),updatedAt:t.z.string().describe(`Last update timestamp (ISO 8601)`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Conversation metadata`)})),_u=n(()=>t.z.object({title:t.z.string().optional().describe(`Initial title`),agentId:t.z.string().optional().describe(`Agent to bind the conversation to`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Conversation metadata`)})),vu=n(()=>t.z.object({agentId:t.z.string().optional().describe(`Filter by agent`),limit:t.z.number().int().positive().optional().describe(`Maximum conversations to return`),cursor:t.z.string().optional().describe(`Pagination cursor`)})),yu=n(()=>t.z.object({conversations:t.z.array(gu).describe(`Matching conversations`)})),bu=n(()=>t.z.object({type:t.z.string().describe(`Frame type (text-delta, tool-input-available, finish, error, …)`)}).passthrough()),xu=n(()=>t.z.object({title:t.z.string().optional().describe(`New title`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`New metadata`)}).refine(e=>e.title!==void 0||e.metadata!==void 0,{message:`at least one of title or metadata is required`})),Su=n(()=>t.z.object({authoring:t.z.boolean().describe(`Authors app metadata (objects/views/flows)`),canvas:t.z.boolean().describe(`Drives the Live Canvas split view (ADR-0037)`),debug:t.z.boolean().describe(`Exposes the build-doctor debug drawer`),resume:t.z.boolean().describe(`Turns resume durable multi-step runs (ADR-0013)`)})),Cu=n(()=>t.z.object({name:t.z.string().describe("Agent name — the `:agentName` path segment"),label:t.z.string().describe(`Display label`),role:t.z.string().describe(`Agent role`),capabilities:Su.describe(`Capability set implied by the agent surface`)})),wu=n(()=>t.z.object({agents:t.z.array(Cu).describe(`Agents this caller may chat with`)})),Tu=n(()=>t.z.object({messages:t.z.array(du).min(1).describe(`Conversation messages (at least one)`),context:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Agent context (app, object, record, …)`),options:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Request options (model, temperature, …)`)})),Eu=n(()=>t.z.enum([`pending`,`approved`,`executed`,`failed`,`rejected`])),Du=n(()=>t.z.object({id:t.z.string().describe(`Pending action id`),object_name:t.z.string().describe(`Object the action targets`),action_name:t.z.string().describe(`Action name`),tool_name:t.z.string().describe(`Tool that would execute it`),tool_input:t.z.string().describe(`Serialized tool input`),status:Eu.describe(`Lifecycle status`),result:t.z.string().optional().describe(`Serialized result, once executed`),error:t.z.string().optional().describe(`Failure message, when status is failed`),rejection_reason:t.z.string().optional().describe(`Reason given at rejection`),conversation_id:t.z.string().optional().describe(`Conversation that proposed it`),message_id:t.z.string().optional().describe(`Message that proposed it`),proposed_by:t.z.string().optional().describe(`Actor that proposed it`),decided_by:t.z.string().optional().describe(`Actor that approved or rejected it`),proposed_at:t.z.string().describe(`Proposal timestamp (ISO 8601)`),decided_at:t.z.string().optional().describe(`Decision timestamp (ISO 8601)`)})),Ou=n(()=>t.z.object({status:Eu.optional().describe(`Filter by status`),conversationId:t.z.string().optional().describe(`Filter by proposing conversation`),limit:t.z.number().int().positive().optional().describe(`Max rows (server default 100)`)})),ku=n(()=>t.z.object({items:t.z.array(Du).describe(`Queued actions, newest first`),total:t.z.number().describe(`Number of rows returned (not a total across pages)`)})),Au=n(()=>t.z.object({status:t.z.enum([`executed`,`failed`]).describe(`Outcome of executing the approved action`),result:t.z.unknown().optional().describe(`Tool result, when executed`),error:t.z.string().optional().describe(`Failure reason, when failed`)})),ju=n(()=>t.z.object({status:t.z.literal(`rejected`).describe(`Always "rejected"`),id:t.z.string().describe(`The rejected action id`)})),Mu=n(()=>t.z.object({})),Nu=n(()=>t.z.object({locales:t.z.array(t.z.object({code:t.z.string().describe(`BCP-47 locale code (e.g., en-US, zh-CN)`),label:t.z.string().describe(`Display name of the locale`),isDefault:t.z.boolean().default(!1).describe(`Whether this is the default locale`)})).describe(`Available locales`)})),Pu=n(()=>t.z.object({locale:t.z.string().describe(`BCP-47 locale code`)})),Fu=n(()=>t.z.object({locale:t.z.string().describe(`Locale code`),translations:fs.describe(`Translation data`)})),Iu=n(()=>t.z.object({object:t.z.string().describe(`Object name`),locale:t.z.string().describe(`BCP-47 locale code`)})),Lu=n(()=>t.z.object({object:t.z.string().describe(`Object name`),locale:t.z.string().describe(`Locale code`),labels:t.z.record(t.z.string(),t.z.object({label:t.z.string().describe(`Translated field label`),help:t.z.string().optional().describe(`Translated help text`),options:t.z.record(t.z.string(),t.z.string()).optional().describe(`Translated option labels`)})).describe(`Field labels keyed by field name`)})),Ru=n(()=>t.z.object({version:t.z.string().regex(/^[a-zA-Z0-9_\-\.]+$/).default(`v1`).describe(`API version (e.g., v1, v2, 2024-01)`),basePath:t.z.string().default(`/api`).describe(`Base URL path for API`),apiPath:t.z.string().optional().describe(`Full API path (defaults to {basePath}/{version})`),enableCrud:t.z.boolean().default(!0).describe(`Enable automatic CRUD endpoint generation`),enableMetadata:t.z.boolean().default(!0).describe(`Enable metadata API endpoints`),enableUi:t.z.boolean().default(!0).describe(`Enable UI API endpoints (Views, Menus, Layouts)`),enableBatch:t.z.boolean().default(!0).describe(`Enable batch operation endpoints`),enableDiscovery:t.z.boolean().default(!0).describe(`Enable API discovery endpoint`),enableOpenApi:t.z.boolean().default(!0).describe(`Enable OpenAPI 3.1 spec & docs viewer endpoints`),enableProjectScoping:t.z.boolean().default(!1).describe(`Enable project-scoped routing for data/meta/AI APIs`),projectResolution:t.z.enum([`required`,`optional`,`auto`]).default(`auto`).describe(`Project ID resolution strategy`),requireAuth:p("`api.requireAuth` was removed in @objectstack/spec 17 (#3963). Anonymous access to object data is now always denied — auth is a kernel concern, not a deployment posture. Delete the key. To publish something publicly, declare it: a public form view (`sharing.allowAnonymous`), a share link, or `book.audience: 'public'` — each derives its own narrow authorization instead of opening the whole data plane."),documentation:t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable API documentation`),title:t.z.string().default(`ObjectStack API`).describe(`API documentation title`),description:t.z.string().optional().describe(`API description`),version:t.z.string().optional().describe(`Documentation version`),termsOfService:t.z.string().optional().describe(`Terms of service URL`),contact:t.z.object({name:t.z.string().optional(),url:t.z.string().optional(),email:t.z.string().optional()}).optional(),license:t.z.object({name:t.z.string(),url:t.z.string().optional()}).optional()}).optional().describe(`OpenAPI/Swagger documentation config`),responseFormat:t.z.object({envelope:t.z.boolean().default(!0).describe(`Wrap responses in standard envelope`),includeMetadata:t.z.boolean().default(!0).describe(`Include response metadata (timestamp, requestId)`),includePagination:t.z.boolean().default(!0).describe(`Include pagination info in list responses`)}).optional().describe(`Response format options`)})),zu=t.z.enum([`create`,`read`,`update`,`delete`,`list`]),Bu=n(()=>t.z.object({method:P.describe(`HTTP method`),path:t.z.string().describe(`URL path pattern`),summary:t.z.string().optional().describe(`Operation summary`),description:t.z.string().optional().describe(`Operation description`)})),Vu=n(()=>t.z.object({operations:t.z.object({create:t.z.boolean().default(!0).describe(`Enable create operation`),read:t.z.boolean().default(!0).describe(`Enable read operation`),update:t.z.boolean().default(!0).describe(`Enable update operation`),delete:t.z.boolean().default(!0).describe(`Enable delete operation`),list:t.z.boolean().default(!0).describe(`Enable list operation`)}).optional().describe(`Enable/disable operations`),patterns:t.z.record(zu,Bu.optional()).optional().describe(`Custom URL patterns for operations`),dataPrefix:t.z.string().default(`/data`).describe(`URL prefix for data endpoints`),objectParamStyle:t.z.enum([`path`,`query`]).default(`path`).describe(`How object name is passed (path param or query param)`)})),Hu=n(()=>t.z.object({prefix:t.z.string().default(`/meta`).describe(`URL prefix for metadata endpoints`),enableCache:t.z.boolean().default(!0).describe(`Enable HTTP cache headers (ETag, Last-Modified)`),cacheTtl:t.z.number().int().default(3600).describe(`Cache TTL in seconds`),endpoints:t.z.object({types:t.z.boolean().default(!0).describe(`GET /meta - List all metadata types`),items:t.z.boolean().default(!0).describe(`GET /meta/:type - List items of type`),item:t.z.boolean().default(!0).describe(`GET /meta/:type/:name - Get specific item`),schema:t.z.boolean().default(!0).describe(`GET /meta/:type/:name/schema - Get JSON schema`)}).optional().describe(`Enable/disable specific endpoints`)})),Uu=n(()=>t.z.object({maxBatchSize:t.z.number().int().min(1).max(1e3).default(200).describe(`Maximum records per batch operation`),enableBatchEndpoint:t.z.boolean().default(!0).describe(`Enable POST /data/:object/batch endpoint`),operations:t.z.object({createMany:t.z.boolean().default(!0).describe(`Enable POST /data/:object/createMany`),updateMany:t.z.boolean().default(!0).describe(`Enable POST /data/:object/updateMany`),deleteMany:t.z.boolean().default(!0).describe(`Enable POST /data/:object/deleteMany`),upsertMany:t.z.boolean().default(!0).describe(`Enable POST /data/:object/upsertMany`)}).optional().describe(`Enable/disable specific batch operations`),defaultAtomic:t.z.boolean().default(!0).describe(`Default atomic/transaction mode for batch operations`)})),Wu=n(()=>t.z.object({includeObjects:t.z.array(t.z.string()).optional().describe(`Specific objects to generate routes for (empty = all)`),excludeObjects:t.z.array(t.z.string()).optional().describe(`Objects to exclude from route generation`),nameTransform:t.z.enum([`none`,`plural`,`kebab-case`,`camelCase`]).default(`none`).describe(`Transform object names in URLs`),overrides:t.z.record(t.z.string(),t.z.object({enabled:t.z.boolean().optional().describe(`Enable/disable routes for this object`),basePath:t.z.string().optional().describe(`Custom base path`),operations:t.z.record(zu,t.z.boolean()).optional().describe(`Enable/disable specific operations`)})).optional().describe(`Per-object route customization`)})),Gu=n(()=>t.z.object({api:Ru.optional().describe(`REST API configuration`),crud:Vu.optional().describe(`CRUD endpoints configuration`),metadata:Hu.optional().describe(`Metadata endpoints configuration`),batch:Uu.optional().describe(`Batch endpoints configuration`),routes:Wu.optional().describe(`Route generation configuration`),openApi31:p("`RestServerConfig.openApi31` was removed in @objectstack/spec 17 (#4579, ADR-0049) — no runtime ever read it: the REST server forwards only `api`/`crud`/`metadata`/`batch`/`routes`, and the served /openapi.json is the pre-generated contract enriched with the live server URL and the registered objects, so webhook/callback definitions declared here never appeared in it. Delete the key. Config-driven OpenAPI 3.1 webhooks/callbacks documentation is a new capability and must arrive via the enforce route of ADR-0049 (a new ADR), not by re-declaring the key; for a real outbound webhook use `Webhook` from `@objectstack/spec/automation`.")})),Ku=n(()=>t.z.object({id:t.z.string().describe(`Unique endpoint identifier`),method:P.describe(`HTTP method`),path:t.z.string().describe(`Full URL path`),object:t.z.string().describe(`Object name (snake_case)`),operation:t.z.union([zu,t.z.string()]).describe(`Operation type`),handler:t.z.string().describe(`Handler function identifier`),metadata:t.z.object({summary:t.z.string().optional(),description:t.z.string().optional(),tags:t.z.array(t.z.string()).optional(),deprecated:t.z.boolean().optional()}).optional()})),qu=n(()=>t.z.object({endpoints:t.z.array(Ku).describe(`All generated endpoints`),total:t.z.number().int().describe(`Total number of endpoints`),byObject:t.z.record(t.z.string(),t.z.array(Ku)).optional().describe(`Endpoints grouped by object`),byOperation:t.z.record(t.z.string(),t.z.array(Ku)).optional().describe(`Endpoints grouped by operation`)})),Ju=Object.assign(Ru,{create:e=>e}),Yu=Object.assign(Gu,{create:e=>e}),Xu=n(()=>t.z.object({url:t.z.string().url().describe(`Server base URL`),description:t.z.string().optional().describe(`Server description`),variables:t.z.record(t.z.string(),t.z.object({default:t.z.string(),description:t.z.string().optional(),enum:t.z.array(t.z.string()).optional()})).optional().describe(`URL template variables`)})),Zu=n(()=>t.z.object({type:t.z.enum([`apiKey`,`http`,`oauth2`,`openIdConnect`]).describe(`Security type`),scheme:t.z.string().optional().describe(`HTTP auth scheme (bearer, basic, etc.)`),bearerFormat:t.z.string().optional().describe(`Bearer token format (e.g., JWT)`),name:t.z.string().optional().describe(`API key parameter name`),in:t.z.enum([`header`,`query`,`cookie`]).optional().describe(`API key location`),flows:t.z.object({implicit:t.z.unknown().optional(),password:t.z.unknown().optional(),clientCredentials:t.z.unknown().optional(),authorizationCode:t.z.unknown().optional()}).optional().describe(`OAuth2 flows`),openIdConnectUrl:t.z.string().url().optional().describe(`OpenID Connect discovery URL`),description:t.z.string().optional().describe(`Security scheme description`)})),Qu=n(()=>t.z.object({openapi:t.z.string().default(`3.0.0`).describe(`OpenAPI specification version`),info:t.z.object({title:t.z.string().describe(`API title`),version:t.z.string().describe(`API version`),description:t.z.string().optional().describe(`API description`),termsOfService:t.z.string().url().optional().describe(`Terms of service URL`),contact:t.z.object({name:t.z.string().optional(),url:t.z.string().url().optional(),email:t.z.string().email().optional()}).optional(),license:t.z.object({name:t.z.string(),url:t.z.string().url().optional()}).optional()}).describe(`API metadata`),servers:t.z.array(Xu).optional().default([]).describe(`API servers`),paths:t.z.record(t.z.string(),t.z.unknown()).describe(`API paths and operations`),components:t.z.object({schemas:t.z.record(t.z.string(),t.z.unknown()).optional(),responses:t.z.record(t.z.string(),t.z.unknown()).optional(),parameters:t.z.record(t.z.string(),t.z.unknown()).optional(),examples:t.z.record(t.z.string(),t.z.unknown()).optional(),requestBodies:t.z.record(t.z.string(),t.z.unknown()).optional(),headers:t.z.record(t.z.string(),t.z.unknown()).optional(),securitySchemes:t.z.record(t.z.string(),Zu).optional(),links:t.z.record(t.z.string(),t.z.unknown()).optional(),callbacks:t.z.record(t.z.string(),t.z.unknown()).optional()}).optional().describe(`Reusable components`),security:t.z.array(t.z.record(t.z.string(),t.z.array(t.z.string()))).optional().describe(`Global security requirements`),tags:t.z.array(t.z.object({name:t.z.string(),description:t.z.string().optional(),externalDocs:t.z.object({description:t.z.string().optional(),url:t.z.string().url()}).optional()})).optional().describe(`Tag definitions`),externalDocs:t.z.object({description:t.z.string().optional(),url:t.z.string().url()}).optional().describe(`External documentation`)})),$u=t.z.enum([`swagger-ui`,`redoc`,`rapidoc`,`stoplight`,`scalar`,`graphiql`,`postman`,`custom`]),ed=n(()=>t.z.object({type:$u.describe(`Testing UI implementation`),path:t.z.string().default(`/api-docs`).describe(`URL path for documentation UI`),theme:t.z.enum([`light`,`dark`,`auto`]).default(`light`).describe(`UI color theme`),enableTryItOut:t.z.boolean().default(!0).describe(`Enable interactive API testing`),enableFilter:t.z.boolean().default(!0).describe(`Enable endpoint filtering`),enableCors:t.z.boolean().default(!0).describe(`Enable CORS for browser testing`),defaultModelsExpandDepth:t.z.number().int().min(-1).default(1).describe(`Default expand depth for schemas (-1 = fully expand)`),displayRequestDuration:t.z.boolean().default(!0).describe(`Show request duration`),syntaxHighlighting:t.z.boolean().default(!0).describe(`Enable syntax highlighting`),customCssUrl:t.z.string().url().optional().describe(`Custom CSS stylesheet URL`),customJsUrl:t.z.string().url().optional().describe(`Custom JavaScript URL`),layout:t.z.object({showExtensions:t.z.boolean().default(!1).describe(`Show vendor extensions`),showCommonExtensions:t.z.boolean().default(!1).describe(`Show common extensions`),deepLinking:t.z.boolean().default(!0).describe(`Enable deep linking`),displayOperationId:t.z.boolean().default(!1).describe(`Display operation IDs`),defaultModelRendering:t.z.enum([`example`,`model`]).default(`example`).describe(`Default model rendering mode`),defaultModelsExpandDepth:t.z.number().int().default(1).describe(`Models expand depth`),defaultModelExpandDepth:t.z.number().int().default(1).describe(`Single model expand depth`),docExpansion:t.z.enum([`list`,`full`,`none`]).default(`list`).describe(`Documentation expansion mode`)}).optional().describe(`Layout configuration`)})),td=n(()=>t.z.object({name:t.z.string().describe(`Test request name`),description:t.z.string().optional().describe(`Request description`),method:t.z.enum([`GET`,`POST`,`PUT`,`PATCH`,`DELETE`,`HEAD`,`OPTIONS`]).describe(`HTTP method`),url:t.z.string().describe(`Request URL (can include variables)`),headers:t.z.record(t.z.string(),t.z.string()).optional().default({}).describe(`Request headers`),queryParams:t.z.record(t.z.string(),t.z.union([t.z.string(),t.z.number(),t.z.boolean()])).optional().default({}).describe(`Query parameters`),body:t.z.unknown().optional().describe(`Request body`),variables:t.z.record(t.z.string(),t.z.unknown()).optional().default({}).describe(`Template variables`),expectedResponse:t.z.object({statusCode:t.z.number().int(),body:t.z.unknown().optional()}).optional().describe(`Expected response for validation`)})),nd=n(()=>t.z.object({name:t.z.string().describe(`Collection name`),description:t.z.string().optional().describe(`Collection description`),variables:t.z.record(t.z.string(),t.z.unknown()).optional().default({}).describe(`Shared variables`),requests:t.z.array(td).describe(`Test requests in this collection`),folders:t.z.array(t.z.object({name:t.z.string(),description:t.z.string().optional(),requests:t.z.array(td)})).optional().describe(`Request folders for organization`)})),rd=n(()=>t.z.object({version:t.z.string().describe(`API version`),date:t.z.string().date().describe(`Release date`),changes:t.z.object({added:t.z.array(t.z.string()).optional().default([]).describe(`New features`),changed:t.z.array(t.z.string()).optional().default([]).describe(`Changes`),deprecated:t.z.array(t.z.string()).optional().default([]).describe(`Deprecations`),removed:t.z.array(t.z.string()).optional().default([]).describe(`Removed features`),fixed:t.z.array(t.z.string()).optional().default([]).describe(`Bug fixes`),security:t.z.array(t.z.string()).optional().default([]).describe(`Security fixes`)}).describe(`Version changes`),migrationGuide:t.z.string().optional().describe(`Migration guide URL or text`)})),id=n(()=>t.z.object({language:t.z.string().describe(`Target language/framework (e.g., typescript, python, curl)`),name:t.z.string().describe(`Template name`),template:t.z.string().describe(`Code template with placeholders`),variables:t.z.array(t.z.string()).optional().describe(`Required template variables`)})),ad=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable API documentation`),title:t.z.string().default(`API Documentation`).describe(`Documentation title`),version:t.z.string().describe(`API version`),description:t.z.string().optional().describe(`API description`),servers:t.z.array(Xu).optional().default([]).describe(`API server URLs`),ui:ed.optional().describe(`Testing UI configuration`),generateOpenApi:t.z.boolean().default(!0).describe(`Generate OpenAPI 3.0 specification`),generateTestCollections:t.z.boolean().default(!0).describe(`Generate API test collections`),testCollections:t.z.array(nd).optional().default([]).describe(`Predefined test collections`),changelog:t.z.array(rd).optional().default([]).describe(`API version changelog`),codeTemplates:t.z.array(id).optional().default([]).describe(`Code generation templates`),termsOfService:t.z.string().url().optional().describe(`Terms of service URL`),contact:t.z.object({name:t.z.string().optional(),url:t.z.string().url().optional(),email:t.z.string().email().optional()}).optional().describe(`Contact information`),license:t.z.object({name:t.z.string(),url:t.z.string().url().optional()}).optional().describe(`API license`),externalDocs:t.z.object({description:t.z.string().optional(),url:t.z.string().url()}).optional().describe(`External documentation link`),securitySchemes:t.z.record(t.z.string(),Zu).optional().describe(`Security scheme definitions`),tags:t.z.array(t.z.object({name:t.z.string(),description:t.z.string().optional(),externalDocs:t.z.object({description:t.z.string().optional(),url:t.z.string().url()}).optional()})).optional().describe(`Global tag definitions`)})),od=n(()=>t.z.object({openApiSpec:Qu.optional().describe(`Generated OpenAPI specification`),testCollections:t.z.array(nd).optional().describe(`Generated test collections`),markdown:t.z.string().optional().describe(`Generated markdown documentation`),html:t.z.string().optional().describe(`Generated HTML documentation`),generatedAt:t.z.string().datetime().describe(`Generation timestamp`),sourceApis:t.z.array(t.z.string()).describe(`Source API IDs used for generation`)})),sd=Object.assign(ad,{create:e=>e}),cd=Object.assign(nd,{create:e=>e}),ld=Object.assign(Qu,{create:e=>e}),ud=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`number`,`string`,`boolean`]),dd=t.z.enum([`string`,`number`,`boolean`,`time`,`geo`]),fd=t.z.enum([`second`,`minute`,`hour`,`day`,`week`,`month`,`quarter`,`year`]),pd=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:ud,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()})),md=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:dd,sql:t.z.string().describe(`SQL expression or column reference`),granularities:t.z.array(fd).optional()})),hd=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)`)})),gd=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(),pd).describe(`Quantitative metrics`),dimensions:t.z.record(t.z.string(),md).describe(`Qualitative attributes`),joins:t.z.record(t.z.string(),hd).optional(),refreshKey:t.z.object({every:t.z.string().optional(),sql:t.z.string().optional()}).optional(),public:t.z.boolean().default(!1)})),_d=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:a.optional().describe(`Filtering criteria (canonical Query DSL FilterCondition)`),timeDimensions:t.z.array(t.z.object({dimension:t.z.string(),granularity:fd.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()})),vd=t.z.enum([`/api/v1/analytics/query`,`/api/v1/analytics/meta`,`/api/v1/analytics/sql`]),yd=n(()=>_d.extend({cube:t.z.string().describe(`Target cube name`),query:p("`query` was removed from AnalyticsQueryRequest in @objectstack/spec 17.0.0 (#3878). The { cube, query: {...} } envelope was the dialect of the retired degraded analytics shim (#3891) — the real engine never understood it. Move the query.* fields to the body top level: { cube, measures, dimensions?, where?, timeDimensions?, order?, limit?, offset?, timezone? }."),format:p("`format` was removed from AnalyticsQueryRequest in @objectstack/spec 17.0.0 (#3878). It was never implemented — every response is the JSON envelope. Delete the key; for CSV/XLSX use the export surface instead.")}).strict()),bd=n(()=>j.extend({data:t.z.object({rows:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Result rows`),fields:t.z.array(t.z.object({name:t.z.string(),type:t.z.string()})).describe(`Column metadata`),sql:t.z.string().optional().describe(`Executed SQL (if debug enabled)`)})})),xd=n(()=>t.z.object({cube:t.z.string().optional().describe(`Optional cube name to filter`)})),Sd=n(()=>j.extend({data:t.z.object({cubes:t.z.array(gd).describe(`Available cubes`)})})),Cd=n(()=>j.extend({data:t.z.object({sql:t.z.string(),params:t.z.array(t.z.unknown())})})),wd=t.z.enum([`urlPath`,`header`,`queryParam`,`dateBased`]),Td=t.z.enum([`preview`,`current`,`supported`,`deprecated`,`retired`]),Ed=n(()=>t.z.object({version:t.z.string().describe(`Version identifier (e.g., "v1", "v2beta1", "2025-01-01")`),status:Td.describe(`Lifecycle status of this version`),releasedAt:t.z.string().describe(`Release date (ISO 8601, e.g., "2025-01-15")`),deprecatedAt:t.z.string().optional().describe(`Deprecation date (ISO 8601). Only set for deprecated/retired versions`),sunsetAt:t.z.string().optional().describe(`Sunset date (ISO 8601). After this date, the version returns 410 Gone`),migrationGuide:t.z.string().url().optional().describe(`URL to migration guide for upgrading from this version`),description:t.z.string().optional().describe(`Human-readable description or release notes summary`),breakingChanges:t.z.array(t.z.string()).optional().describe(`List of breaking changes (for preview/new versions)`)})),Dd=n(()=>t.z.object({strategy:wd.default(`urlPath`).describe(`How the API version is specified by clients`),current:t.z.string().describe(`The current/recommended API version identifier`),default:t.z.string().describe(`Fallback version when client does not specify one`),versions:t.z.array(Ed).min(1).describe(`All available API versions with lifecycle metadata`),headerName:t.z.string().default(`ObjectStack-Version`).describe(`HTTP header name for version negotiation (header/dateBased strategies)`),queryParamName:t.z.string().default(`version`).describe(`Query parameter name for version specification (queryParam strategy)`),urlPrefix:t.z.string().default(`/api`).describe(`URL prefix before version segment (urlPath strategy)`),deprecation:t.z.object({warnHeader:t.z.boolean().default(!0).describe(`Include Deprecation header (RFC 8594) in responses`),sunsetHeader:t.z.boolean().default(!0).describe(`Include Sunset header (RFC 8594) with retirement date`),linkHeader:t.z.boolean().default(!0).describe(`Include Link header pointing to migration guide URL`),rejectRetired:t.z.boolean().default(!0).describe(`Return 410 Gone for retired API versions`),warningMessage:t.z.string().optional().describe(`Custom warning message for deprecated version responses`)}).optional().describe(`Deprecation lifecycle behavior`),includeInDiscovery:t.z.boolean().default(!0).describe(`Include version information in the API discovery endpoint`)})),Od=n(()=>t.z.object({current:t.z.string().describe(`Current recommended API version`),requested:t.z.string().optional().describe(`Version requested by the client`),resolved:t.z.string().describe(`Resolved API version for this request`),supported:t.z.array(t.z.string()).describe(`All supported version identifiers`),deprecated:t.z.array(t.z.string()).optional().describe(`Deprecated version identifiers`),versions:t.z.array(Ed).optional().describe(`Full version definitions with lifecycle metadata`)})),kd={strategy:`urlPath`,current:`v1`,default:`v1`,versions:[{version:`v1`,status:`current`,releasedAt:`2025-01-15`,description:`ObjectStack API v1 — Initial stable release`}],deprecation:{warnHeader:!0,sunsetHeader:!0,linkHeader:!0,rejectRetired:!0},includeInDiscovery:!0},Ad=t.z.enum([`local`,`google`,`github`,`microsoft`,`ldap`,`saml`]),jd=n(()=>t.z.object({id:t.z.string().describe(`User ID`),email:t.z.string().email().describe(`Email address`),emailVerified:t.z.boolean().default(!1).describe(`Is email verified?`),name:t.z.string().describe(`Display name`),image:t.z.string().optional().describe(`Avatar URL`),username:t.z.string().optional().describe(`Username (optional)`),roles:t.z.array(t.z.string()).optional().default([]).describe(`Assigned role IDs`),tenantId:t.z.string().optional().describe(`Current tenant ID`),language:t.z.string().default(`en`).describe(`Preferred language`),timezone:t.z.string().optional().describe(`Preferred timezone`),createdAt:t.z.string().datetime().optional(),updatedAt:t.z.string().datetime().optional()})),Md=n(()=>t.z.object({id:t.z.string(),expiresAt:t.z.string().datetime(),token:t.z.string().optional(),ipAddress:t.z.string().optional(),userAgent:t.z.string().optional(),userId:t.z.string()})),Nd=t.z.enum([`email`,`username`,`phone`,`magic-link`,`social`]),Pd=n(()=>t.z.object({type:Nd.default(`email`).describe(`Login method`),email:t.z.string().email().optional().describe(`Required for email/magic-link`),username:t.z.string().optional().describe(`Required for username login`),password:t.z.string().optional().describe(`Required for password login`),provider:t.z.string().optional().describe(`Required for social (google, github)`),redirectTo:t.z.string().optional().describe(`Redirect URL after successful login`)})),Fd=n(()=>t.z.object({email:t.z.string().email(),password:t.z.string(),name:t.z.string(),image:t.z.string().optional()})),Id=n(()=>t.z.object({refreshToken:t.z.string().describe(`Refresh token`)})),Ld=n(()=>j.extend({data:t.z.object({session:Md.describe(`Active Session Info`),user:jd.describe(`Current User Details`),token:t.z.string().optional().describe(`Bearer token if not using cookies`)})})),Rd=n(()=>j.extend({data:jd})),$={signInEmail:`/sign-in/email`,signUpEmail:`/sign-up/email`,signOut:`/sign-out`,getSession:`/get-session`,forgetPassword:`/forget-password`,resetPassword:`/reset-password`,sendVerificationEmail:`/send-verification-email`,verifyEmail:`/verify-email`,twoFactorEnable:`/two-factor/enable`,twoFactorVerify:`/two-factor/verify`,passkeyRegister:`/passkey/register`,passkeyAuthenticate:`/passkey/authenticate`,magicLinkSend:`/magic-link/send`,magicLinkVerify:`/magic-link/verify`,deviceRequest:`/device/request`,deviceToken:`/device/token`,deviceApprove:`/device/approve`},zd=n(()=>t.z.object({signInEmail:t.z.object({method:t.z.literal(`POST`),path:t.z.literal($.signInEmail),description:t.z.literal(`Sign in with email and password`)}),signUpEmail:t.z.object({method:t.z.literal(`POST`),path:t.z.literal($.signUpEmail),description:t.z.literal(`Register new user with email and password`)}),signOut:t.z.object({method:t.z.literal(`POST`),path:t.z.literal($.signOut),description:t.z.literal(`Sign out current user`)}),getSession:t.z.object({method:t.z.literal(`GET`),path:t.z.literal($.getSession),description:t.z.literal(`Get current user session`)}),forgetPassword:t.z.object({method:t.z.literal(`POST`),path:t.z.literal($.forgetPassword),description:t.z.literal(`Request password reset email`)}),resetPassword:t.z.object({method:t.z.literal(`POST`),path:t.z.literal($.resetPassword),description:t.z.literal(`Reset password with token`)}),sendVerificationEmail:t.z.object({method:t.z.literal(`POST`),path:t.z.literal($.sendVerificationEmail),description:t.z.literal(`Send email verification link`)}),verifyEmail:t.z.object({method:t.z.literal(`GET`),path:t.z.literal($.verifyEmail),description:t.z.literal(`Verify email with token`)})})),Bd={login:$.signInEmail,register:$.signUpEmail,logout:$.signOut,me:$.getSession};function Vd(e,t){return`${e.replace(/\/$/,``)}${$[t]}`}var Hd={"/login":$.signInEmail,"/register":$.signUpEmail,"/logout":$.signOut,"/me":$.getSession,"/refresh":$.getSession},Ud=n(()=>t.z.object({id:t.z.string().describe(`Provider ID (e.g., google, github, microsoft, okta)`),name:t.z.string().describe(`Display name (e.g., Google, GitHub)`),enabled:t.z.boolean().describe(`Whether this provider is enabled`),type:t.z.enum([`social`,`oidc`]).default(`social`).describe(`Provider type`)})),Wd=n(()=>t.z.object({enabled:t.z.boolean().describe(`Whether email/password auth is enabled`),disableSignUp:t.z.boolean().optional().describe(`Whether new user registration is disabled`),requireEmailVerification:t.z.boolean().optional().describe(`Whether email verification is required`)})),Gd=n(()=>t.z.object({twoFactor:t.z.boolean().default(!1).describe(`Two-factor authentication enabled`),passkeys:t.z.boolean().default(!1).describe(`Passkey/WebAuthn support enabled`),magicLink:t.z.boolean().default(!1).describe(`Magic link login enabled`),organization:t.z.boolean().default(!1).describe(`Multi-tenant organization support enabled`),ssoEnforced:t.z.boolean().optional().describe(`SSO-only login enforced: the UI hides the local password form + self-registration (a break-glass "use a password" link remains)`),phoneNumber:t.z.boolean().optional().describe(`Phone-number sign-in enabled (phone + password, #2766 V1.5)`),phoneNumberOtp:t.z.boolean().optional().describe(`Phone-number OTP sign-in and self-service password reset available — requires the phoneNumber plugin plus a deliverable SMS service (#2780)`)})),Kd=n(()=>t.z.object({emailPassword:Wd.describe(`Email/password authentication config`),socialProviders:t.z.array(Ud).describe(`Available social/OAuth providers`),features:Gd.describe(`Enabled authentication features`)})),qd=n(()=>t.z.object({code:t.z.string().describe(`Short-lived device code used for polling`),verificationUrl:t.z.string().url().describe(`URL the user should open in a browser`),expiresAt:t.z.string().datetime().describe(`ISO timestamp when the code expires`),interval:t.z.number().default(2).describe(`Recommended polling interval in seconds`)})),Jd=n(()=>t.z.discriminatedUnion(`status`,[t.z.object({status:t.z.literal(`pending`)}),t.z.object({status:t.z.literal(`approved`),token:t.z.string().describe(`Bearer token to store in credentials file`),user:t.z.object({id:t.z.string(),email:t.z.string(),name:t.z.string().optional()})}),t.z.object({status:t.z.literal(`expired`)})])),Yd=n(()=>t.z.enum([`global`,`tenant`,`user`,`session`,`temp`,`cache`,`data`,`logs`,`config`,`public`]).describe(`Storage scope classification`)),Xd=n(()=>t.z.object({path:t.z.string().describe(`File path`),name:t.z.string().describe(`File name`),size:t.z.number().int().describe(`File size in bytes`),mimeType:t.z.string().describe(`MIME type`),lastModified:t.z.string().datetime().describe(`Last modified timestamp`),created:t.z.string().datetime().describe(`Creation timestamp`),etag:t.z.string().optional().describe(`Entity tag`),fileId:t.z.string().optional().describe(`Opaque sys_file id (ADR-0104 D3 file-as-reference)`)})),Zd=n(()=>t.z.enum([`s3`,`azure_blob`,`gcs`,`minio`,`r2`,`spaces`,`wasabi`,`backblaze`,`local`]).describe(`Storage provider type`)),Qd=n(()=>t.z.enum([`private`,`public_read`,`public_read_write`,`authenticated_read`,`bucket_owner_read`,`bucket_owner_full_control`]).describe(`Storage access control level`)),$d=n(()=>t.z.enum([`standard`,`intelligent`,`infrequent_access`,`glacier`,`deep_archive`]).describe(`Storage class/tier for cost optimization`)),ef=n(()=>t.z.enum([`transition`,`delete`,`abort`]).describe(`Lifecycle policy action type`));n(()=>t.z.object({contentType:t.z.string().describe(`MIME type (e.g., image/jpeg, application/pdf)`),contentLength:t.z.number().min(0).describe(`File size in bytes`),contentEncoding:t.z.string().optional().describe(`Content encoding (e.g., gzip)`),contentDisposition:t.z.string().optional().describe(`Content disposition header`),contentLanguage:t.z.string().optional().describe(`Content language`),cacheControl:t.z.string().optional().describe(`Cache control directives`),etag:t.z.string().optional().describe(`Entity tag for versioning/caching`),lastModified:t.z.string().datetime().optional().describe(`Last modification timestamp`),versionId:t.z.string().optional().describe(`Object version identifier`),storageClass:$d.optional().describe(`Storage class/tier`),encryption:t.z.object({algorithm:t.z.string().describe(`Encryption algorithm (e.g., AES256, aws:kms)`),keyId:t.z.string().optional().describe(`KMS key ID if using managed encryption`)}).optional().describe(`Server-side encryption configuration`),custom:t.z.record(t.z.string(),t.z.string()).optional().describe(`Custom user-defined metadata`)})),n(()=>t.z.object({operation:t.z.enum([`get`,`put`,`delete`,`head`]).describe(`Allowed operation`),expiresIn:t.z.number().min(1).max(604800).describe(`Expiration time in seconds (max 7 days)`),contentType:t.z.string().optional().describe(`Required content type for PUT operations`),maxSize:t.z.number().min(0).optional().describe(`Maximum file size in bytes for PUT operations`),responseContentType:t.z.string().optional().describe(`Override content-type for GET operations`),responseContentDisposition:t.z.string().optional().describe(`Override content-disposition for GET operations`)}));var tf=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable multipart uploads`),partSize:t.z.number().min(5242880).max(5368709120).default(10485760).describe(`Part size in bytes (min 5MB, max 5GB)`),maxParts:t.z.number().min(1).max(1e4).default(1e4).describe(`Maximum number of parts (max 10,000)`),threshold:t.z.number().min(0).default(104857600).describe(`File size threshold to trigger multipart upload (bytes)`),maxConcurrent:t.z.number().min(1).max(100).default(4).describe(`Maximum concurrent part uploads`),abortIncompleteAfterDays:t.z.number().min(1).optional().describe(`Auto-abort incomplete uploads after N days`)})),nf=n(()=>t.z.object({acl:Qd.default(`private`).describe(`Default access control level`),allowedOrigins:t.z.array(t.z.string()).optional().describe(`CORS allowed origins`),allowedMethods:t.z.array(t.z.enum([`GET`,`PUT`,`POST`,`DELETE`,`HEAD`])).optional().describe(`CORS allowed HTTP methods`),allowedHeaders:t.z.array(t.z.string()).optional().describe(`CORS allowed headers`),exposeHeaders:t.z.array(t.z.string()).optional().describe(`CORS exposed headers`),maxAge:t.z.number().min(0).optional().describe(`CORS preflight cache duration in seconds`),corsEnabled:t.z.boolean().default(!1).describe(`Enable CORS configuration`),publicAccess:t.z.object({allowPublicRead:t.z.boolean().default(!1).describe(`Allow public read access`),allowPublicWrite:t.z.boolean().default(!1).describe(`Allow public write access`),allowPublicList:t.z.boolean().default(!1).describe(`Allow public bucket listing`)}).optional().describe(`Public access control`),allowedIps:t.z.array(t.z.string()).optional().describe(`Allowed IP addresses/CIDR blocks`),blockedIps:t.z.array(t.z.string()).optional().describe(`Blocked IP addresses/CIDR blocks`)})),rf=n(()=>t.z.object({id:v.describe(`Rule identifier`),enabled:t.z.boolean().default(!0).describe(`Enable this rule`),action:ef.describe(`Action to perform`),prefix:t.z.string().optional().describe(`Object key prefix filter (e.g., "uploads/")`),tags:t.z.record(t.z.string(),t.z.string()).optional().describe(`Object tag filters`),daysAfterCreation:t.z.number().min(0).optional().describe(`Days after object creation`),daysAfterModification:t.z.number().min(0).optional().describe(`Days after last modification`),targetStorageClass:$d.optional().describe(`Target storage class for transition action`)}).refine(e=>!(e.action===`transition`&&!e.targetStorageClass),{message:`targetStorageClass is required when action is "transition"`})),af=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable lifecycle policies`),rules:t.z.array(rf).default([]).describe(`Lifecycle rules`)})),of=n(()=>t.z.object({name:v.describe(`Bucket identifier in ObjectStack (snake_case)`),label:t.z.string().describe(`Display label`),bucketName:t.z.string().describe(`Actual bucket/container name in storage provider`),region:t.z.string().optional().describe(`Storage region (e.g., us-east-1, westus)`),provider:Zd.describe(`Storage provider`),endpoint:t.z.string().optional().describe(`Custom endpoint URL (for S3-compatible providers)`),pathStyle:t.z.boolean().default(!1).describe(`Use path-style URLs (for S3-compatible providers)`),versioning:t.z.boolean().default(!1).describe(`Enable object versioning`),encryption:t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable server-side encryption`),algorithm:t.z.enum([`AES256`,`aws:kms`,`azure:kms`,`gcp:kms`]).default(`AES256`).describe(`Encryption algorithm`),kmsKeyId:t.z.string().optional().describe(`KMS key ID for managed encryption`)}).optional().describe(`Server-side encryption configuration`),accessControl:nf.optional().describe(`Access control configuration`),lifecyclePolicy:af.optional().describe(`Lifecycle policy configuration`),multipartConfig:tf.optional().describe(`Multipart upload configuration`),tags:t.z.record(t.z.string(),t.z.string()).optional().describe(`Bucket tags for organization`),description:t.z.string().optional().describe(`Bucket description`),enabled:t.z.boolean().default(!0).describe(`Enable this bucket`)})),sf=n(()=>t.z.object({accessKeyId:t.z.string().optional().describe(`AWS access key ID or MinIO access key`),secretAccessKey:t.z.string().optional().describe(`AWS secret access key or MinIO secret key`),sessionToken:t.z.string().optional().describe(`AWS session token for temporary credentials`),accountName:t.z.string().optional().describe(`Azure storage account name`),accountKey:t.z.string().optional().describe(`Azure storage account key`),sasToken:t.z.string().optional().describe(`Azure SAS token`),environmentId:t.z.string().optional().describe(`GCP project ID`),credentials:t.z.string().optional().describe(`GCP service account credentials JSON`),endpoint:t.z.string().optional().describe(`Custom endpoint URL`),region:t.z.string().optional().describe(`Default region`),useSSL:t.z.boolean().default(!0).describe(`Use SSL/TLS for connections`),timeout:t.z.number().min(0).optional().describe(`Connection timeout in milliseconds`)})),cf=n(()=>t.z.object({name:v.describe(`Storage configuration identifier`),label:t.z.string().describe(`Display label`),provider:Zd.describe(`Primary storage provider`),scope:Yd.optional().default(`global`).describe(`Storage scope`),connection:sf.describe(`Connection credentials`),buckets:t.z.array(of).default([]).describe(`Configured buckets`),defaultBucket:t.z.string().optional().describe(`Default bucket name for operations`),location:t.z.string().optional().describe(`Root path (local) or base location`),quota:t.z.number().int().positive().optional().describe(`Max size in bytes`),options:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Provider-specific configuration options`),enabled:t.z.boolean().default(!0).describe(`Enable this storage configuration`),description:t.z.string().optional().describe(`Configuration description`)}));cf.parse({name:`aws_s3_storage`,label:`AWS S3 Production Storage`,provider:`s3`,connection:{accessKeyId:"${AWS_ACCESS_KEY_ID}",secretAccessKey:"${AWS_SECRET_ACCESS_KEY}",region:`us-east-1`},buckets:[{name:`user_uploads`,label:`User Uploads`,bucketName:`my-app-user-uploads`,region:`us-east-1`,provider:`s3`,versioning:!0,encryption:{enabled:!0,algorithm:`aws:kms`,kmsKeyId:"${AWS_KMS_KEY_ID}"},accessControl:{acl:`private`,corsEnabled:!0,allowedOrigins:[`https://app.example.com`],allowedMethods:[`GET`,`PUT`,`POST`]},lifecyclePolicy:{enabled:!0,rules:[{id:`archive_old_uploads`,enabled:!0,action:`transition`,daysAfterCreation:90,targetStorageClass:`glacier`}]},multipartConfig:{enabled:!0,partSize:10485760,threshold:104857600,maxConcurrent:4}}],defaultBucket:`user_uploads`,enabled:!0}),cf.parse({name:`minio_local`,label:`MinIO Local Storage`,provider:`minio`,connection:{accessKeyId:`minioadmin`,secretAccessKey:`minioadmin`,endpoint:`http://localhost:9000`,useSSL:!1},buckets:[{name:`development_files`,label:`Development Files`,bucketName:`dev-files`,provider:`minio`,endpoint:`http://localhost:9000`,pathStyle:!0,accessControl:{acl:`private`}}],defaultBucket:`development_files`,enabled:!0}),cf.parse({name:`azure_blob_storage`,label:`Azure Blob Storage`,provider:`azure_blob`,connection:{accountName:`mystorageaccount`,accountKey:"${AZURE_STORAGE_KEY}",endpoint:`https://mystorageaccount.blob.core.windows.net`},buckets:[{name:`media_files`,label:`Media Files`,bucketName:`media`,provider:`azure_blob`,region:`eastus`,accessControl:{acl:`public_read`,publicAccess:{allowPublicRead:!0,allowPublicWrite:!1,allowPublicList:!1}}}],defaultBucket:`media_files`,enabled:!0}),cf.parse({name:`gcs_storage`,label:`Google Cloud Storage`,provider:`gcs`,connection:{environmentId:`my-gcp-project`,credentials:"${GCP_SERVICE_ACCOUNT_JSON}"},buckets:[{name:`backup_storage`,label:`Backup Storage`,bucketName:`my-app-backups`,region:`us-central1`,provider:`gcs`,lifecyclePolicy:{enabled:!0,rules:[{id:`delete_old_backups`,enabled:!0,action:`delete`,daysAfterCreation:30}]}}],defaultBucket:`backup_storage`,enabled:!0});var lf=n(()=>t.z.object({filename:t.z.string().describe(`Original filename`),mimeType:t.z.string().describe(`File MIME type`),size:t.z.number().describe(`File size in bytes`),scope:t.z.string().default(`user`).describe(`Target storage scope (e.g. user, private, public)`),bucket:t.z.string().optional().describe(`Specific bucket override (admin only)`)})),uf=n(()=>t.z.object({fileId:t.z.string().describe(`File ID returned from presigned request`),eTag:t.z.string().optional().describe(`S3 ETag verification`)})),df=n(()=>j.extend({data:t.z.object({uploadUrl:t.z.string().describe(`PUT/POST URL for direct upload`),downloadUrl:t.z.string().optional().describe(`Public/Private preview URL`),fileId:t.z.string().describe(`Temporary File ID`),method:t.z.enum([`PUT`,`POST`]).describe(`HTTP Method to use`),headers:t.z.record(t.z.string(),t.z.string()).optional().describe(`Required headers for upload`),expiresIn:t.z.number().describe(`URL expiry in seconds`)})})),ff=n(()=>j.extend({data:Xd.describe(`Uploaded file metadata`)})),pf=n(()=>j.extend({data:t.z.object({url:t.z.string().describe(`Short-lived signed download URL; may be server-relative`)})})),mf=n(()=>j.extend({data:t.z.object({key:t.z.string().describe(`Storage key the bytes were written to`)})})),hf=n(()=>t.z.object({mode:t.z.enum([`whitelist`,`blacklist`]).describe(`whitelist = only allow listed types, blacklist = block listed types`),mimeTypes:t.z.array(t.z.string()).min(1).describe(`List of MIME types to allow or block (e.g., "image/jpeg", "application/pdf")`),extensions:t.z.array(t.z.string()).optional().describe(`List of file extensions to allow or block (e.g., ".jpg", ".pdf")`),maxFileSize:t.z.number().int().min(1).optional().describe(`Maximum file size in bytes`),minFileSize:t.z.number().int().min(0).optional().describe(`Minimum file size in bytes (e.g., reject empty files)`)})),gf=n(()=>t.z.object({filename:t.z.string().describe(`Original filename`),mimeType:t.z.string().describe(`File MIME type`),totalSize:t.z.number().int().min(1).describe(`Total file size in bytes`),chunkSize:t.z.number().int().min(5242880).default(5242880).describe(`Size of each chunk in bytes (minimum 5MB per S3 spec)`),scope:t.z.string().default(`user`).describe(`Target storage scope`),bucket:t.z.string().optional().describe(`Specific bucket override (admin only)`),metadata:t.z.record(t.z.string(),t.z.string()).optional().describe(`Custom metadata key-value pairs`)})),_f=n(()=>j.extend({data:t.z.object({uploadId:t.z.string().describe(`Multipart upload session ID`),resumeToken:t.z.string().describe(`Opaque token for resuming interrupted uploads`),fileId:t.z.string().describe(`Assigned file ID`),totalChunks:t.z.number().int().min(1).describe(`Expected number of chunks`),chunkSize:t.z.number().int().describe(`Chunk size in bytes`),expiresAt:t.z.string().datetime().describe(`Upload session expiration timestamp`)})})),vf=n(()=>t.z.object({uploadId:t.z.string().describe(`Multipart upload session ID`),chunkIndex:t.z.number().int().min(0).describe(`Zero-based chunk index`),resumeToken:t.z.string().describe(`Resume token from initiate response`)})),yf=n(()=>j.extend({data:t.z.object({chunkIndex:t.z.number().int().describe(`Chunk index that was uploaded`),eTag:t.z.string().describe(`Chunk ETag for multipart completion`),bytesReceived:t.z.number().int().describe(`Bytes received for this chunk`)})})),bf=n(()=>t.z.object({uploadId:t.z.string().describe(`Multipart upload session ID`),parts:t.z.array(t.z.object({chunkIndex:t.z.number().int().describe(`Chunk index`),eTag:t.z.string().describe(`ETag returned from chunk upload`)})).min(1).describe(`Ordered list of uploaded parts for assembly`)})),xf=n(()=>j.extend({data:t.z.object({fileId:t.z.string().describe(`Final file ID`),key:t.z.string().describe(`Storage key/path of the assembled file`),size:t.z.number().int().describe(`Total file size in bytes`),mimeType:t.z.string().describe(`File MIME type`),eTag:t.z.string().optional().describe(`Final ETag of the assembled file`),url:t.z.string().optional().describe(`Download URL for the assembled file`)})})),Sf=n(()=>j.extend({data:t.z.object({uploadId:t.z.string().describe(`Multipart upload session ID`),fileId:t.z.string().describe(`Assigned file ID`),filename:t.z.string().describe(`Original filename`),totalSize:t.z.number().int().describe(`Total file size in bytes`),uploadedSize:t.z.number().int().describe(`Bytes uploaded so far`),totalChunks:t.z.number().int().describe(`Total expected chunks`),uploadedChunks:t.z.number().int().describe(`Number of chunks uploaded`),percentComplete:t.z.number().min(0).max(100).describe(`Upload progress percentage`),status:t.z.enum([`in_progress`,`completing`,`completed`,`failed`,`expired`]).describe(`Current upload session status`),startedAt:t.z.string().datetime().describe(`Upload session start timestamp`),expiresAt:t.z.string().datetime().describe(`Session expiration timestamp`)})})),Cf={getPresignedUrl:{method:`POST`,path:`/api/v1/storage/upload/presigned`,input:lf,output:df},completeUpload:{method:`POST`,path:`/api/v1/storage/upload/complete`,input:uf,output:ff},initiateChunkedUpload:{method:`POST`,path:`/api/v1/storage/upload/chunked`,input:gf,output:_f},uploadChunk:{method:`PUT`,path:`/api/v1/storage/upload/chunked/:uploadId/chunk/:chunkIndex`,input:vf,output:yf},completeChunkedUpload:{method:`POST`,path:`/api/v1/storage/upload/chunked/:uploadId/complete`,input:bf,output:xf},getUploadProgress:{method:`GET`,path:`/api/v1/storage/upload/chunked/:uploadId/progress`,output:Sf},getDownloadUrl:{method:`GET`,path:`/api/v1/storage/files/:fileId/url`,output:pf}},wf=n(()=>t.z.enum([`yaml`,`json`,`typescript`,`javascript`]).describe(`Metadata file format`));n(()=>t.z.object({id:t.z.string().describe(`Unique metadata record identifier`),type:t.z.string().describe(`Metadata type (e.g. "object", "view", "flow")`),name:y.describe(`Machine name (snake_case)`),format:wf.optional().describe(`Source file format`)}).describe(`Base metadata record fields shared across kernel and system`));var Tf=n(()=>t.z.enum([`filesystem`,`memory`,`none`])),Ef=n(()=>t.z.object({datasource:t.z.string().optional().describe(`Datasource name reference for database persistence`),tableName:t.z.string().default(`sys_metadata`).describe(`Database table name for metadata storage`),fallback:Tf.default(`none`).describe(`Fallback strategy when datasource is unavailable`),rootDir:t.z.string().optional().describe(`Root directory path`),formats:t.z.array(wf).default([`typescript`,`json`,`yaml`]).describe(`Enabled formats`),cache:t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable caching`),ttl:t.z.number().int().min(0).default(3600).describe(`Cache TTL in seconds`),maxSize:t.z.number().int().min(0).optional().describe(`Max cache size in bytes`),databaseLoader:t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable DatabaseLoader cache`),maxSize:t.z.number().int().min(0).default(500).describe(`Max cached entries`),ttl:t.z.number().int().min(0).default(6e4).describe(`Cache TTL in milliseconds`)}).optional().describe(`DatabaseLoader read-through cache`)}).optional().describe(`Cache settings`),watch:t.z.boolean().default(!1).describe(`Enable file watching`),watchOptions:t.z.object({ignored:t.z.array(t.z.string()).optional().describe(`Patterns to ignore`),persistent:t.z.boolean().default(!0).describe(`Keep process running`),ignoreInitial:t.z.boolean().default(!0).describe(`Ignore initial add events`)}).optional().describe(`File watcher options`),validation:t.z.object({strict:t.z.boolean().default(!0).describe(`Strict validation`),throwOnError:t.z.boolean().default(!0).describe(`Throw on validation error`)}).optional().describe(`Validation settings`),loaderOptions:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Loader-specific configuration`),persistence:t.z.object({writable:t.z.boolean().default(!0).describe(`Allow base metadata writes via register()`),overlayWritable:t.z.boolean().default(!0).describe(`Allow overlay writes via saveOverlay()`)}).optional().describe(`Persistence write gates`)}));n(()=>t.z.enum([`package`,`admin`,`user`,`migration`,`api`]));var Df=n(()=>t.z.object({path:t.z.string().describe(`JSON path to the changed field`),originalValue:t.z.unknown().optional().describe(`Original value from the package`),currentValue:t.z.unknown().describe(`Current customized value`),changedBy:t.z.string().optional().describe(`User or admin who made this change`),changedAt:t.z.string().datetime().optional().describe(`Timestamp of the change`)})),Of=n(()=>t.z.object({id:t.z.string().describe(`Overlay record ID (UUID)`),baseType:t.z.string().describe(`Metadata type being customized`),baseName:t.z.string().describe(`Metadata name being customized`),packageId:t.z.string().optional().describe(`Package ID that delivered the base metadata`),packageVersion:t.z.string().optional().describe(`Package version when overlay was created`),scope:t.z.enum([`platform`,`user`]).default(`platform`).describe(`Customization scope (platform=admin, user=personal)`),tenantId:t.z.string().optional().describe(`Tenant identifier`),owner:t.z.string().optional().describe(`Owner user ID for user-scope overlays`),patch:t.z.record(t.z.string(),t.z.unknown()).describe(`JSON Merge Patch payload (changed fields only)`),changes:t.z.array(Df).optional().describe(`Field-level change tracking for conflict detection`),active:t.z.boolean().default(!0).describe(`Whether this overlay is active`),createdAt:t.z.string().datetime().optional(),createdBy:t.z.string().optional(),updatedAt:t.z.string().datetime().optional(),updatedBy:t.z.string().optional()})),kf=n(()=>t.z.object({path:t.z.string().describe(`JSON path to the conflicting field`),baseValue:t.z.unknown().describe(`Value in the old package version`),incomingValue:t.z.unknown().describe(`Value in the new package version`),customValue:t.z.unknown().describe(`Customer customized value`),suggestedResolution:t.z.enum([`keep-custom`,`accept-incoming`,`manual`]).describe(`Suggested resolution strategy`),reason:t.z.string().optional().describe(`Explanation for the suggested resolution`)})),Af=n(()=>t.z.object({defaultStrategy:t.z.enum([`keep-custom`,`accept-incoming`,`three-way-merge`]).default(`three-way-merge`).describe(`Default merge strategy`),alwaysAcceptIncoming:t.z.array(t.z.string()).optional().describe(`Field paths that always accept package updates`),alwaysKeepCustom:t.z.array(t.z.string()).optional().describe(`Field paths where customer customizations always win`),autoResolveNonConflicting:t.z.boolean().default(!0).describe(`Auto-resolve changes that do not conflict`)}));n(()=>t.z.object({success:t.z.boolean().describe(`Whether merge completed without unresolved conflicts`),mergedMetadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Merged metadata result`),updatedOverlay:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Updated overlay after merge`),conflicts:t.z.array(kf).optional().describe(`Unresolved merge conflicts`),autoResolved:t.z.array(t.z.object({path:t.z.string(),resolution:t.z.string(),description:t.z.string().optional()})).optional().describe(`Summary of auto-resolved changes`),stats:t.z.object({totalFields:t.z.number().int().min(0).describe(`Total fields evaluated`),unchanged:t.z.number().int().min(0).describe(`Fields with no changes`),autoResolved:t.z.number().int().min(0).describe(`Fields auto-resolved`),conflicts:t.z.number().int().min(0).describe(`Fields with conflicts`)}).optional()}));var jf=n(()=>t.z.object({metadataType:t.z.string().describe(`Metadata type (e.g. "object", "view")`),allowCustomization:t.z.boolean().default(!0),lockedFields:t.z.array(t.z.string()).optional().describe(`Field paths that cannot be customized`),customizableFields:t.z.array(t.z.string()).optional().describe(`Field paths that can be customized (whitelist)`),allowAddFields:t.z.boolean().default(!0).describe(`Whether admins can add new fields to package objects`),allowDeleteFields:t.z.boolean().default(!1).describe(`Whether admins can delete package-delivered fields`)})),Mf=n(()=>t.z.enum(`object.field.hook.seed.mapping.view.page.dashboard.app.action.report.dataset.flow.job.datasource.external_catalog.translation.api.email_template.doc.book.permission.position.agent.tool.skill`.split(`.`))),Nf=t.z.object({type:Mf.describe(`Metadata type identifier`),label:t.z.string().describe(`Display label for the metadata type`),description:t.z.string().optional().describe(`Description of the metadata type`),filePatterns:t.z.array(t.z.string()).describe(`Glob patterns to discover files of this type`),supportsOverlay:t.z.boolean().default(!0).describe(`Whether overlay customization is supported`),allowOrgOverride:t.z.boolean().default(!1).describe(`Allow per-org overlay writes via runtime metadata API`),allowRuntimeCreate:t.z.boolean().default(!0).describe(`Allow runtime creation via API`),supportsVersioning:t.z.boolean().default(!1).describe(`Whether version history is tracked`),executionPinned:t.z.boolean().default(!1).describe(`Transaction rows reference a specific version_hash; history GC is disabled and getByHash() MUST resolve old hashes (ADR-0009)`),loadOrder:t.z.number().int().min(0).default(100).describe(`Loading priority (lower = earlier)`),domain:t.z.enum([`data`,`ui`,`automation`,`system`,`security`,`ai`]).describe(`Protocol domain`),actions:t.z.array(ao).optional().describe(`Declarative type-level actions (e.g. datasource "Test connection"), reusing ActionSchema; merged with plugin-registered actions when emitted`)});n(()=>Nf.superRefine((e,n)=>{e.executionPinned&&!e.supportsVersioning&&n.addIssue({code:t.z.ZodIssueCode.custom,path:[`executionPinned`],message:`executionPinned requires supportsVersioning: true (type '${e.type}')`})}));var Pf=n(()=>t.z.object({types:t.z.array(Mf).optional().describe(`Filter by metadata types`),namespaces:t.z.array(t.z.string()).optional().describe(`Filter by namespaces`),packageId:t.z.string().optional().describe(`Filter by owning package`),search:t.z.string().optional().describe(`Full-text search query`),scope:t.z.enum([`system`,`platform`,`user`]).optional().describe(`Filter by scope`),state:t.z.enum([`draft`,`active`,`archived`,`deprecated`]).optional().describe(`Filter by lifecycle state`),tags:t.z.array(t.z.string()).optional().describe(`Filter by tags`),sortBy:t.z.enum([`name`,`type`,`updatedAt`,`createdAt`]).default(`name`).describe(`Sort field`),sortOrder:t.z.enum([`asc`,`desc`]).default(`asc`).describe(`Sort direction`),page:t.z.number().int().min(1).default(1).describe(`Page number`),pageSize:t.z.number().int().min(1).max(500).default(50).describe(`Items per page`)})),Ff=n(()=>t.z.object({items:t.z.array(t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Item name`),namespace:t.z.string().optional().describe(`Namespace`),label:t.z.string().optional().describe(`Display label`),scope:t.z.enum([`system`,`platform`,`user`]).optional(),state:t.z.enum([`draft`,`active`,`archived`,`deprecated`]).optional(),packageId:t.z.string().optional(),updatedAt:t.z.string().datetime().optional()})).describe(`Matched metadata items`),total:t.z.number().int().min(0).describe(`Total matching items`),page:t.z.number().int().min(1).describe(`Current page`),pageSize:t.z.number().int().min(1).describe(`Page size`)})),If=n(()=>t.z.object({valid:t.z.boolean().describe(`Whether the metadata is valid`),errors:t.z.array(t.z.object({path:t.z.string().describe(`JSON path to the invalid field`),message:t.z.string().describe(`Error description`),code:t.z.string().optional().describe(`Error code`)})).optional().describe(`Validation errors`),warnings:t.z.array(t.z.object({path:t.z.string().describe(`JSON path to the field`),message:t.z.string().describe(`Warning description`)})).optional().describe(`Validation warnings`)})),Lf=n(()=>t.z.object({storage:Ef.describe(`Storage backend configuration`),customizationPolicies:t.z.array(jf).optional().describe(`Default customization policies per type`),mergeStrategy:Af.optional().describe(`Merge strategy for package upgrades`),additionalTypes:t.z.array(Nf.omit({type:!0}).extend({type:t.z.string().describe(`Custom metadata type identifier`)})).optional().describe(`Additional custom metadata types`),enableEvents:t.z.boolean().default(!0).describe(`Emit metadata change events`),validateOnWrite:t.z.boolean().default(!0).describe(`Validate metadata on write`),enableVersioning:t.z.boolean().default(!1).describe(`Track metadata version history`),cacheMaxItems:t.z.number().int().min(0).default(1e4).describe(`Max items in memory cache`),bootstrap:t.z.enum([`eager`,`lazy`,`artifact-only`]).default(`eager`).describe(`How metadata is primed at plugin start (eager / lazy / artifact-only)`)}));n(()=>t.z.object({id:t.z.literal(`com.objectstack.metadata`).describe(`Metadata plugin ID`),name:t.z.literal(`ObjectStack Metadata Service`).describe(`Plugin name`),version:t.z.string().regex(/^\d+\.\d+\.\d+$/).describe(`Plugin version`),type:t.z.literal(`standard`).describe(`Plugin type`),description:t.z.string().default(`Core metadata management service for ObjectStack platform`).describe(`Plugin description`),capabilities:t.z.object({crud:t.z.boolean().default(!0).describe(`Supports metadata CRUD`),query:t.z.boolean().default(!0).describe(`Supports metadata query`),overlay:t.z.boolean().default(!0).describe(`Supports customization overlays`),watch:t.z.boolean().default(!1).describe(`Supports file watching`),importExport:t.z.boolean().default(!0).describe(`Supports import/export`),validation:t.z.boolean().default(!0).describe(`Supports schema validation`),versioning:t.z.boolean().default(!1).describe(`Supports version history`),events:t.z.boolean().default(!0).describe(`Emits metadata events`)}).describe(`Plugin capabilities`),config:Lf.optional().describe(`Plugin configuration`)}));var Rf=n(()=>t.z.object({total:t.z.number().int().min(0).describe(`Total items processed`),succeeded:t.z.number().int().min(0).describe(`Successfully processed`),failed:t.z.number().int().min(0).describe(`Failed items`),errors:t.z.array(t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Item name`),error:t.z.string().describe(`Error message`)})).optional().describe(`Per-item errors`)})),zf=n(()=>t.z.object({sourceType:t.z.string().describe(`Dependent metadata type`),sourceName:t.z.string().describe(`Dependent metadata name`),targetType:t.z.string().describe(`Referenced metadata type`),targetName:t.z.string().describe(`Referenced metadata name`),kind:t.z.enum([`reference`,`extends`,`includes`,`triggers`]).describe(`How the dependency is formed`)})),Bf=n(()=>j.extend({data:Uo.describe(`Full Object Schema`)})),Vf=n(()=>j.extend({data:pc.describe(`Full App Configuration`)})),Hf=n(()=>j.extend({data:t.z.array(t.z.object({name:t.z.string(),label:t.z.string(),icon:t.z.string().optional(),description:t.z.string().optional()})).describe(`List of available concepts (Objects, Apps, Flows)`)})),Uf=n(()=>t.z.object({type:Mf.describe(`Metadata type`),name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Item name (snake_case)`),data:t.z.record(t.z.string(),t.z.unknown()).describe(`Metadata payload`),namespace:t.z.string().optional().describe(`Optional namespace`)})),Wf=n(()=>j.extend({data:t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Item name`),definition:t.z.record(t.z.string(),t.z.unknown()).describe(`Metadata definition payload`)}).describe(`Metadata item`)})),Gf=n(()=>j.extend({data:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Array of metadata definitions`)})),Kf=n(()=>j.extend({data:t.z.array(t.z.string()).describe(`Array of metadata item names`)})),qf=n(()=>j.extend({data:t.z.object({exists:t.z.boolean().describe(`Whether the item exists`)})})),Jf=n(()=>j.extend({data:t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Deleted item name`)})})),Yf=n(()=>Pf.describe(`Metadata query with filtering, sorting, and pagination`)),Xf=n(()=>j.extend({data:Ff.describe(`Paginated query result`)})),Zf=n(()=>t.z.object({items:t.z.array(t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Item name`),data:t.z.record(t.z.string(),t.z.unknown()).describe(`Metadata payload`)})).min(1).describe(`Items to register`),continueOnError:t.z.boolean().default(!1).describe(`Continue on individual failure`),validate:t.z.boolean().default(!0).describe(`Validate before registering`)})),Qf=n(()=>t.z.object({items:t.z.array(t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Item name`)})).min(1).describe(`Items to unregister`)})),$f=n(()=>j.extend({data:Rf.describe(`Bulk operation result`)})),ep=n(()=>j.extend({data:Of.optional().describe(`Overlay definition, undefined if none`)})),tp=n(()=>Of.describe(`Overlay to save`)),np=n(()=>j.extend({data:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Effective metadata with all overlays applied`)})),rp=n(()=>t.z.object({types:t.z.array(t.z.string()).optional().describe(`Filter by metadata types`),namespaces:t.z.array(t.z.string()).optional().describe(`Filter by namespaces`),format:t.z.enum([`json`,`yaml`]).default(`json`).describe(`Export format`)})),ip=n(()=>j.extend({data:t.z.unknown().describe(`Exported metadata bundle`)})),ap=n(()=>t.z.object({data:t.z.unknown().describe(`Metadata bundle to import`),conflictResolution:t.z.enum([`skip`,`overwrite`,`merge`]).default(`skip`).describe(`Conflict resolution strategy`),validate:t.z.boolean().default(!0).describe(`Validate before import`),dryRun:t.z.boolean().default(!1).describe(`Dry run (no save)`)})),op=n(()=>j.extend({data:t.z.object({total:t.z.number().int().min(0),imported:t.z.number().int().min(0),skipped:t.z.number().int().min(0),failed:t.z.number().int().min(0),errors:t.z.array(t.z.object({type:t.z.string(),name:t.z.string(),error:t.z.string()})).optional()}).describe(`Import result`)})),sp=n(()=>t.z.object({type:t.z.string().describe(`Metadata type to validate against`),data:t.z.unknown().describe(`Metadata payload to validate`)})),cp=n(()=>j.extend({data:If.describe(`Validation result`)})),lp=n(()=>j.extend({data:t.z.array(t.z.string()).describe(`Registered metadata type identifiers`)})),up=n(()=>j.extend({data:t.z.object({type:t.z.string().describe(`Metadata type identifier`),label:t.z.string().describe(`Display label`),description:t.z.string().optional().describe(`Description`),filePatterns:t.z.array(t.z.string()).describe(`File glob patterns`),supportsOverlay:t.z.boolean().describe(`Overlay support`),domain:t.z.string().describe(`Protocol domain`),actions:t.z.array(ao).optional().describe(`Declarative type-level actions (buttons) the metadata-admin UI renders for this type`)}).optional().describe(`Type info`)})),dp=n(()=>j.extend({data:t.z.array(zf).describe(`Items this item depends on`)})),fp=n(()=>j.extend({data:t.z.array(zf).describe(`Items that depend on this item`)})),pp=t.z.enum([`metadata`,`data`,`auth`,`file-storage`,`search`,`cache`,`queue`,`automation`,`analytics`,`realtime`,`job`,`notification`,`ai`,`i18n`,`ui`]),mp=n(()=>t.z.enum([`required`,`core`,`optional`]));n(()=>t.z.object({name:pp,enabled:t.z.boolean(),status:t.z.enum([`running`,`stopped`,`degraded`,`initializing`]),version:t.z.string().optional(),provider:t.z.string().optional().describe(`Implementation provider (e.g. "s3" for storage)`),features:t.z.array(t.z.string()).optional().describe(`List of supported sub-features`)})),n(()=>t.z.record(pp,t.z.unknown().describe(`Service Instance implementing the protocol interface`))),n(()=>t.z.object({id:t.z.string(),name:pp,options:t.z.record(t.z.string(),t.z.unknown()).optional()}));var hp=t.z.object({prefix:t.z.string().regex(/^\//).describe(`URL path prefix for routing (e.g. /api/v1/data)`),service:pp.describe(`Target core service name`),authRequired:t.z.boolean().default(!0).describe(`Whether authentication is required`),criticality:mp.default(`optional`).describe(`Service criticality level for unavailability handling`),permissions:t.z.array(t.z.string()).optional().describe(`Required permissions for this route namespace`)}),gp=t.z.object({routes:t.z.array(hp).describe(`Route-to-service mappings`),fallback:t.z.enum([`404`,`proxy`,`custom`]).default(`404`).describe(`Behavior when no route matches`),proxyTarget:t.z.string().url().optional().describe(`Proxy target URL when fallback is "proxy"`)}),_p=t.z.enum([`ROUTE_NOT_FOUND`,`METHOD_NOT_ALLOWED`,`NOT_IMPLEMENTED`,`SERVICE_UNAVAILABLE`]).describe("Route-resolution failure mode emitted in `error.code`"),vp=t.z.object({success:t.z.literal(!1),error:t.z.object({code:t.z.string().describe(`Machine-readable error code (e.g. ROUTE_NOT_FOUND, permission_denied)`),message:t.z.string().describe(`Human-readable error message`),httpStatus:t.z.number().int().optional().describe(`HTTP status code (404, 405, 501, 503, …)`),route:t.z.string().optional().describe(`Requested route path`),service:t.z.string().optional().describe(`Target service name, if resolvable`),hint:t.z.string().optional().describe(`Actionable hint for the developer (e.g., "Install plugin-workflow")`),details:t.z.unknown().optional().describe(`Additional error context`)})});n(()=>t.z.object({method:P.describe(`HTTP method`),path:t.z.string().describe(`URL path pattern`),handler:t.z.string().describe(`Handler identifier or name`),metadata:t.z.object({summary:t.z.string().optional().describe(`Route summary for documentation`),description:t.z.string().optional().describe(`Route description`),tags:t.z.array(t.z.string()).optional().describe(`Tags for grouping`),operationId:t.z.string().optional().describe(`Unique operation identifier`)}).optional(),security:t.z.object({authRequired:t.z.boolean().default(!0).describe(`Require authentication`),permissions:t.z.array(t.z.string()).optional().describe(`Required permissions`),rateLimit:t.z.string().optional().describe(`Rate limit policy override`)}).optional()}));var yp=t.z.enum([`authentication`,`authorization`,`logging`,`validation`,`transformation`,`error`,`custom`]),bp=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Middleware name (snake_case)`),type:yp.describe(`Middleware type`),enabled:t.z.boolean().default(!0).describe(`Whether middleware is enabled`),order:t.z.number().int().default(100).describe(`Execution order priority`),config:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Middleware configuration object`),paths:t.z.object({include:t.z.array(t.z.string()).optional().describe(`Include path patterns (glob)`),exclude:t.z.array(t.z.string()).optional().describe(`Exclude path patterns (glob)`)}).optional().describe(`Path filtering`)})),xp=t.z.enum([`starting`,`started`,`stopping`,`stopped`,`request`,`response`,`error`]);n(()=>t.z.object({type:xp.describe(`Event type`),timestamp:t.z.string().datetime().describe(`Event timestamp (ISO 8601)`),data:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Event-specific data`)})),n(()=>t.z.object({httpVersions:t.z.array(t.z.enum([`1.0`,`1.1`,`2.0`,`3.0`])).default([`1.1`]).describe(`Supported HTTP versions`),websocket:t.z.boolean().default(!1).describe(`WebSocket support`),sse:t.z.boolean().default(!1).describe(`Server-Sent Events support`),serverPush:t.z.boolean().default(!1).describe(`HTTP/2 Server Push support`),streaming:t.z.boolean().default(!0).describe(`Response streaming support`),middleware:t.z.boolean().default(!0).describe(`Middleware chain support`),routeParams:t.z.boolean().default(!0).describe(`URL parameter support (/users/:id)`),compression:t.z.boolean().default(!0).describe(`Built-in compression support`)})),n(()=>t.z.object({state:t.z.enum([`stopped`,`starting`,`running`,`stopping`,`error`]).describe(`Current server state`),uptime:t.z.number().int().optional().describe(`Server uptime in milliseconds`),server:t.z.object({port:t.z.number().int().describe(`Listening port`),host:t.z.string().describe(`Bound host`),url:t.z.string().optional().describe(`Full server URL`)}).optional(),connections:t.z.object({active:t.z.number().int().describe(`Active connections`),total:t.z.number().int().describe(`Total connections handled`)}).optional(),requests:t.z.object({total:t.z.number().int().describe(`Total requests processed`),success:t.z.number().int().describe(`Successful requests`),errors:t.z.number().int().describe(`Failed requests`)}).optional()})),Object.assign(bp,{create:e=>e});var Sp=t.z.enum([`discovery`,`metadata`,`data`,`batch`,`permission`,`analytics`,`automation`,`ui`,`realtime`,`notification`,`ai`,`i18n`]),Cp=n(()=>t.z.enum([`implemented`,`stub`,`planned`])),wp=n(()=>t.z.object({method:P.describe(`HTTP method for this endpoint`),path:t.z.string().describe(`URL path pattern (e.g., /api/v1/data/:object/:id)`),handler:t.z.string().describe(`Protocol method name or handler identifier`),category:Sp.describe(`Route category`),public:t.z.boolean().default(!1).describe(`Is publicly accessible without authentication`),permissions:t.z.array(t.z.string()).optional().describe(`Required permissions (e.g., ["data.read", "object.account.read"])`),summary:t.z.string().optional().describe(`Short description for OpenAPI`),description:t.z.string().optional().describe(`Detailed description for OpenAPI`),tags:t.z.array(t.z.string()).optional().describe(`OpenAPI tags for grouping`),requestSchema:t.z.string().optional().describe(`Request schema name (for validation)`),responseSchema:t.z.string().optional().describe(`Response schema name (for documentation)`),timeout:t.z.number().int().optional().describe(`Request timeout in milliseconds`),rateLimit:t.z.string().optional().describe(`Rate limit policy name`),cacheable:t.z.boolean().default(!1).describe(`Whether response can be cached`),cacheTtl:t.z.number().int().optional().describe(`Cache TTL in seconds`),handlerStatus:Cp.optional().describe(`Handler implementation status: implemented (default if omitted), stub, or planned`)})),Tp=t.z.object({prefix:t.z.string().regex(/^\//).describe(`URL path prefix for this route group`),service:t.z.string().describe(`Core service name (metadata, data, auth, etc.)`),category:Sp.describe(`Primary category for this route group`),methods:t.z.array(t.z.string()).optional().describe(`Protocol method names implemented`),endpoints:t.z.array(wp).optional().describe(`Endpoint definitions`),middleware:t.z.array(bp).optional().describe(`Middleware stack for this route group`),authRequired:t.z.boolean().default(!0).describe(`Whether authentication is required by default`),documentation:t.z.object({title:t.z.string().optional().describe(`Route group title`),description:t.z.string().optional().describe(`Route group description`),tags:t.z.array(t.z.string()).optional().describe(`OpenAPI tags`)}).optional().describe(`Documentation metadata for this route group`)}),Ep=t.z.enum([`strict`,`permissive`,`strip`]),Dp=t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable automatic request validation`),mode:Ep.default(`strict`).describe(`How to handle validation errors`),validateBody:t.z.boolean().default(!0).describe(`Validate request body against schema`),validateQuery:t.z.boolean().default(!0).describe(`Validate query string parameters`),validateParams:t.z.boolean().default(!0).describe(`Validate URL path parameters`),validateHeaders:t.z.boolean().default(!1).describe(`Validate request headers`),includeFieldErrors:t.z.boolean().default(!0).describe(`Include field-level error details in response`),errorPrefix:t.z.string().optional().describe(`Custom prefix for validation error messages`),schemaRegistry:t.z.string().optional().describe(`Schema registry name to use for validation`)}),Op=t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable automatic response envelope wrapping`),includeMetadata:t.z.boolean().default(!0).describe(`Include meta object in responses`),includeTimestamp:t.z.boolean().default(!0).describe(`Include timestamp in response metadata`),includeRequestId:t.z.boolean().default(!0).describe(`Include requestId in response metadata`),includeDuration:t.z.boolean().default(!1).describe(`Include request duration in ms`),includeTraceId:t.z.boolean().default(!1).describe(`Include distributed traceId`),customMetadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional metadata fields to include`),skipIfWrapped:t.z.boolean().default(!0).describe(`Skip wrapping if response already has success field`)}),kp=t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable standardized error handling`),includeStackTrace:t.z.boolean().default(!1).describe(`Include stack traces in error responses`),logErrors:t.z.boolean().default(!0).describe(`Log errors to system logger`),exposeInternalErrors:t.z.boolean().default(!1).describe(`Expose internal error details in responses`),includeRequestId:t.z.boolean().default(!0).describe(`Include requestId in error responses`),includeTimestamp:t.z.boolean().default(!0).describe(`Include timestamp in error responses`),includeDocumentation:t.z.boolean().default(!0).describe(`Include documentation URLs for errors`),documentationBaseUrl:t.z.string().url().optional().describe(`Base URL for error documentation`),customErrorMessages:t.z.record(t.z.string(),t.z.string()).optional().describe(`Custom error messages by error code`),redactFields:t.z.array(t.z.string()).optional().describe(`Field names to redact from error details`)}),Ap=t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable automatic OpenAPI documentation generation`),version:t.z.enum([`3.0.0`,`3.0.1`,`3.0.2`,`3.0.3`,`3.1.0`]).default(`3.0.3`).describe(`OpenAPI specification version`),title:t.z.string().default(`ObjectStack API`).describe(`API title`),description:t.z.string().optional().describe(`API description`),apiVersion:t.z.string().default(`1.0.0`).describe(`API version`),outputPath:t.z.string().default(`/api/docs/openapi.json`).describe(`URL path to serve OpenAPI JSON`),uiPath:t.z.string().default(`/api/docs`).describe(`URL path to serve documentation UI`),uiFramework:t.z.enum([`swagger-ui`,`redoc`,`rapidoc`,`elements`]).default(`swagger-ui`).describe(`Documentation UI framework`),includeInternal:t.z.boolean().default(!1).describe(`Include internal endpoints in documentation`),generateSchemas:t.z.boolean().default(!0).describe(`Auto-generate schemas from Zod definitions`),includeExamples:t.z.boolean().default(!0).describe(`Include request/response examples`),servers:t.z.array(t.z.object({url:t.z.string().describe(`Server URL`),description:t.z.string().optional().describe(`Server description`)})).optional().describe(`Server URLs for API`),contact:t.z.object({name:t.z.string().optional(),url:t.z.string().url().optional(),email:t.z.string().email().optional()}).optional().describe(`API contact information`),license:t.z.object({name:t.z.string().describe(`License name`),url:t.z.string().url().optional().describe(`License URL`)}).optional().describe(`API license information`),securitySchemes:t.z.record(t.z.string(),t.z.object({type:t.z.enum([`apiKey`,`http`,`oauth2`,`openIdConnect`]),scheme:t.z.string().optional(),bearerFormat:t.z.string().optional()})).optional().describe(`Security scheme definitions`)}),jp=t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable REST API plugin`),basePath:t.z.string().default(`/api`).describe(`Base path for all API routes`),version:t.z.string().default(`v1`).describe(`API version identifier`),routes:t.z.array(Tp).describe(`Route registrations`),validation:Dp.optional().describe(`Request validation configuration`),responseEnvelope:Op.optional().describe(`Response envelope configuration`),errorHandling:kp.optional().describe(`Error handling configuration`),openApi:Ap.optional().describe(`OpenAPI documentation configuration`),globalMiddleware:t.z.array(bp).optional().describe(`Global middleware stack`),cors:t.z.object({enabled:t.z.boolean().default(!0),origins:t.z.array(t.z.string()).optional(),methods:t.z.array(P).optional(),credentials:t.z.boolean().default(!0)}).optional().describe(`CORS configuration`),performance:t.z.object({enableCompression:t.z.boolean().default(!0).describe(`Enable response compression`),enableETag:t.z.boolean().default(!0).describe(`Enable ETag generation`),enableCaching:t.z.boolean().default(!0).describe(`Enable HTTP caching`),defaultCacheTtl:t.z.number().int().default(300).describe(`Default cache TTL in seconds`)}).optional().describe(`Performance optimization settings`)}),Mp={prefix:`/api/v1/discovery`,service:`metadata`,category:`discovery`,methods:[`getDiscovery`],authRequired:!1,endpoints:[{method:`GET`,path:``,handler:`getDiscovery`,category:`discovery`,public:!0,summary:`Get API discovery information`,description:`Returns API version, capabilities, and available routes`,tags:[`Discovery`],responseSchema:`GetDiscoveryResponseSchema`,cacheable:!0,cacheTtl:3600}],middleware:[{name:`response_envelope`,type:`transformation`,enabled:!0,order:100}]},Np={prefix:`/api/v1/meta`,service:`metadata`,category:`metadata`,methods:[`getMetaTypes`,`getMetaItems`,`getMetaItem`,`saveMetaItem`],authRequired:!0,endpoints:[{method:`GET`,path:``,handler:`getMetaTypes`,category:`metadata`,public:!1,summary:`List all metadata types`,description:`Returns available metadata types (object, field, view, etc.)`,tags:[`Metadata`],responseSchema:`GetMetaTypesResponseSchema`,cacheable:!0,cacheTtl:3600},{method:`GET`,path:`/:type`,handler:`getMetaItems`,category:`metadata`,public:!1,summary:`List metadata items of a type`,description:`Returns all items of the specified metadata type`,tags:[`Metadata`],responseSchema:`GetMetaItemsResponseSchema`,cacheable:!0,cacheTtl:3600},{method:`GET`,path:`/:type/:name`,handler:`getMetaItem`,category:`metadata`,public:!1,summary:`Get specific metadata item`,description:`Returns a specific metadata item by type and name`,tags:[`Metadata`],responseSchema:`GetMetaItemResponseSchema`,cacheable:!0,cacheTtl:3600},{method:`PUT`,path:`/:type/:name`,handler:`saveMetaItem`,category:`metadata`,public:!1,summary:`Create or update metadata item`,description:`Creates or updates a metadata item`,tags:[`Metadata`],responseSchema:`SaveMetaItemResponseSchema`,permissions:[`metadata.write`],cacheable:!1}],middleware:[{name:`auth`,type:`authentication`,enabled:!0,order:10},{name:`validation`,type:`validation`,enabled:!0,order:20},{name:`response_envelope`,type:`transformation`,enabled:!0,order:100}]},Pp={prefix:`/api/v1/data`,service:`data`,category:`data`,methods:[`findData`,`getData`,`createData`,`updateData`,`deleteData`],authRequired:!0,endpoints:[{method:`GET`,path:`/:object`,handler:`findData`,category:`data`,public:!1,summary:`Query records`,description:`Query records with filtering, sorting, and pagination`,tags:[`Data`],responseSchema:`ListRecordResponseSchema`,permissions:[`data.read`],cacheable:!1},{method:`POST`,path:`/:object/query`,handler:`findData`,category:`data`,public:!1,summary:`Advanced query (QueryAST in body)`,description:`Query records with a structured QueryAST request body (filter, sort, aggregation, expansion)`,tags:[`Data`],requestSchema:`FindDataRequestSchema`,responseSchema:`FindDataResponseSchema`,permissions:[`data.read`],cacheable:!1},{method:`GET`,path:`/:object/:id`,handler:`getData`,category:`data`,public:!1,summary:`Get record by ID`,description:`Retrieve a single record by its ID`,tags:[`Data`],responseSchema:`SingleRecordResponseSchema`,permissions:[`data.read`],cacheable:!1},{method:`POST`,path:`/:object`,handler:`createData`,category:`data`,public:!1,summary:`Create record`,description:`Create a new record`,tags:[`Data`],requestSchema:`CreateDataRequestSchema`,responseSchema:`SingleRecordResponseSchema`,permissions:[`data.create`],cacheable:!1},{method:`PATCH`,path:`/:object/:id`,handler:`updateData`,category:`data`,public:!1,summary:`Update record`,description:`Update an existing record`,tags:[`Data`],requestSchema:`UpdateDataRequestSchema`,responseSchema:`SingleRecordResponseSchema`,permissions:[`data.update`],cacheable:!1},{method:`DELETE`,path:`/:object/:id`,handler:`deleteData`,category:`data`,public:!1,summary:`Delete record`,description:`Delete a record by ID`,tags:[`Data`],responseSchema:`DeleteResponseSchema`,permissions:[`data.delete`],cacheable:!1}],middleware:[{name:`auth`,type:`authentication`,enabled:!0,order:10},{name:`validation`,type:`validation`,enabled:!0,order:20},{name:`response_envelope`,type:`transformation`,enabled:!0,order:100},{name:`error_handler`,type:`error`,enabled:!0,order:200}]},Fp={prefix:`/api/v1/data/:object`,service:`data`,category:`batch`,methods:[`batchData`,`createManyData`,`updateManyData`,`deleteManyData`],authRequired:!0,endpoints:[{method:`POST`,path:`/batch`,handler:`batchData`,category:`batch`,public:!1,summary:`Batch operation`,description:`Execute a batch operation (create, update, upsert, delete)`,tags:[`Batch`],requestSchema:`BatchUpdateRequestSchema`,responseSchema:`BatchUpdateResponseSchema`,permissions:[`data.batch`],timeout:6e4,cacheable:!1},{method:`POST`,path:`/createMany`,handler:`createManyData`,category:`batch`,public:!1,summary:`Batch create`,description:`Create multiple records in a single operation`,tags:[`Batch`],requestSchema:`CreateManyDataRequestSchema`,responseSchema:`BatchUpdateResponseSchema`,permissions:[`data.create`,`data.batch`],timeout:6e4,cacheable:!1},{method:`POST`,path:`/updateMany`,handler:`updateManyData`,category:`batch`,public:!1,summary:`Batch update`,description:`Update multiple records in a single operation`,tags:[`Batch`],requestSchema:`UpdateManyRequestSchema`,responseSchema:`BatchUpdateResponseSchema`,permissions:[`data.update`,`data.batch`],timeout:6e4,cacheable:!1},{method:`POST`,path:`/deleteMany`,handler:`deleteManyData`,category:`batch`,public:!1,summary:`Batch delete`,description:`Delete multiple records in a single operation`,tags:[`Batch`],requestSchema:`DeleteManyRequestSchema`,responseSchema:`BatchUpdateResponseSchema`,permissions:[`data.delete`,`data.batch`],timeout:6e4,cacheable:!1}],middleware:[{name:`auth`,type:`authentication`,enabled:!0,order:10},{name:`validation`,type:`validation`,enabled:!0,order:20},{name:`response_envelope`,type:`transformation`,enabled:!0,order:100},{name:`error_handler`,type:`error`,enabled:!0,order:200}]},Ip={prefix:`/api/v1/notifications`,service:`notification`,category:`notification`,methods:[`listNotifications`,`markNotificationsRead`,`markAllNotificationsRead`],authRequired:!0,endpoints:[{method:`GET`,path:``,handler:`listNotifications`,category:`notification`,public:!1,summary:`List notifications`,description:`Returns paginated list of notifications for the current user`,tags:[`Notifications`],responseSchema:`ListNotificationsResponseSchema`,cacheable:!1},{method:`POST`,path:`/read`,handler:`markNotificationsRead`,category:`notification`,public:!1,summary:`Mark notifications as read`,description:`Marks specific notifications as read by their IDs`,tags:[`Notifications`],requestSchema:`MarkNotificationsReadRequestSchema`,responseSchema:`MarkNotificationsReadResponseSchema`,cacheable:!1},{method:`POST`,path:`/read/all`,handler:`markAllNotificationsRead`,category:`notification`,public:!1,summary:`Mark all notifications as read`,description:`Marks all notifications as read for the current user`,tags:[`Notifications`],responseSchema:`MarkAllNotificationsReadResponseSchema`,cacheable:!1}],middleware:[{name:`auth`,type:`authentication`,enabled:!0,order:10},{name:`validation`,type:`validation`,enabled:!0,order:20},{name:`response_envelope`,type:`transformation`,enabled:!0,order:100}]},Lp={prefix:`/api/v1/i18n`,service:`i18n`,category:`i18n`,methods:[`getLocales`,`getTranslations`,`getFieldLabels`],authRequired:!0,endpoints:[{method:`GET`,path:`/locales`,handler:`getLocales`,category:`i18n`,public:!1,summary:`Get available locales`,description:`Returns all available locales with their metadata`,tags:[`i18n`],responseSchema:`GetLocalesResponseSchema`,cacheable:!0,cacheTtl:86400},{method:`GET`,path:`/translations/:locale`,handler:`getTranslations`,category:`i18n`,public:!1,summary:`Get translations for a locale`,description:`Returns the specified locale's full translation bundle`,tags:[`i18n`],responseSchema:`GetTranslationsResponseSchema`,cacheable:!0,cacheTtl:3600},{method:`GET`,path:`/labels/:object/:locale`,handler:`getFieldLabels`,category:`i18n`,public:!1,summary:`Get translated field labels`,description:`Returns translated field labels, help text, and option labels for an object`,tags:[`i18n`],responseSchema:`GetFieldLabelsResponseSchema`,cacheable:!0,cacheTtl:3600}],middleware:[{name:`auth`,type:`authentication`,enabled:!0,order:10},{name:`response_envelope`,type:`transformation`,enabled:!0,order:100}]},Rp={prefix:`/api/v1/analytics`,service:`analytics`,category:`analytics`,methods:[`analyticsQuery`,`getAnalyticsMeta`],authRequired:!0,endpoints:[{method:`POST`,path:`/query`,handler:`analyticsQuery`,category:`analytics`,public:!1,summary:`Execute analytics query`,description:`Executes a structured analytics query against the semantic layer`,tags:[`Analytics`],requestSchema:`AnalyticsQueryRequestSchema`,responseSchema:`AnalyticsResultResponseSchema`,permissions:[`analytics.query`],timeout:12e4,cacheable:!1},{method:`GET`,path:`/meta`,handler:`getAnalyticsMeta`,category:`analytics`,public:!1,summary:`Get analytics metadata`,description:`Returns available cubes, dimensions, measures, and segments`,tags:[`Analytics`],responseSchema:`AnalyticsMetadataResponseSchema`,cacheable:!0,cacheTtl:3600}],middleware:[{name:`auth`,type:`authentication`,enabled:!0,order:10},{name:`validation`,type:`validation`,enabled:!0,order:20},{name:`response_envelope`,type:`transformation`,enabled:!0,order:100},{name:`error_handler`,type:`error`,enabled:!0,order:200}]},zp={prefix:`/api/v1/automation`,service:`automation`,category:`automation`,methods:[`triggerAutomation`],authRequired:!0,endpoints:[{method:`POST`,path:`/trigger/:name`,handler:`triggerAutomation`,category:`automation`,public:!1,summary:`Trigger automation`,description:`Triggers an automation flow by name (path param). Alias mount: POST /:name/trigger. The body is the flow trigger context ({ recordId?, objectName?, params? }; unknown top-level keys are forwarded as flow params).`,tags:[`Automation`],responseSchema:`AutomationTriggerResponseSchema`,permissions:[`automation.trigger`],timeout:12e4,cacheable:!1},{method:`GET`,path:`/actions`,handler:`getActionDescriptors`,category:`automation`,public:!1,summary:`List automation actions`,description:`Returns the live action/node registry (built-in + plugin-contributed) backing the designer palette and flow validation. Supports ?paradigm, ?source, and ?category filters (ADR-0018).`,tags:[`Automation`],responseSchema:`AutomationActionsResponseSchema`,permissions:[`automation.read`],cacheable:!0}],middleware:[{name:`auth`,type:`authentication`,enabled:!0,order:10},{name:`validation`,type:`validation`,enabled:!0,order:20},{name:`response_envelope`,type:`transformation`,enabled:!0,order:100},{name:`error_handler`,type:`error`,enabled:!0,order:200}]},Bp=Object.assign(jp,{create:e=>e}),Vp=Object.assign(Tp,{create:e=>e});function Hp(){return[Mp,Np,Pp,Fp,Ip,Lp,Rp,zp]}var Up=t.z.object({path:t.z.string().describe(`Full URL path (e.g. /api/v1/analytics/query)`),method:P.describe(`HTTP method (GET, POST, etc.)`),category:Sp.describe(`Route category`),handlerStatus:Cp.describe(`Handler status`),service:t.z.string().describe(`Target service name`),healthCheckPassed:t.z.boolean().optional().describe(`Whether the health check probe succeeded`)}),Wp=t.z.object({timestamp:t.z.string().describe(`ISO 8601 timestamp`),adapter:t.z.string().describe(`Adapter name (e.g. "hono", "express", "nextjs")`),summary:t.z.object({total:t.z.number().int().describe(`Total declared endpoints`),implemented:t.z.number().int().describe(`Endpoints with real handlers`),stub:t.z.number().int().describe(`Endpoints with stub handlers (501)`),planned:t.z.number().int().describe(`Endpoints not yet implemented`)}),entries:t.z.array(Up).describe(`Per-endpoint coverage entries`)}),Gp=n(()=>t.z.enum([`rest`,`odata`])),Kp=n(()=>t.z.object({operator:t.z.string().describe(`Unified DSL operator`),rest:t.z.string().optional().describe(`REST query parameter template`),odata:t.z.string().optional().describe(`OData $filter expression template`)})),qp=n(()=>t.z.object({filterStyle:t.z.enum([`bracket`,`dot`,`flat`,`rsql`]).default(`bracket`).describe(`REST filter parameter encoding style`),pagination:t.z.object({limitParam:t.z.string().default(`limit`).describe(`Page size parameter name`),offsetParam:t.z.string().default(`offset`).describe(`Offset parameter name`),cursorParam:t.z.string().default(`cursor`).describe(`Cursor parameter name`),pageParam:t.z.string().default(`page`).describe(`Page number parameter name`)}).optional().describe(`Pagination parameter name mappings`),sorting:t.z.object({param:t.z.string().default(`sort`).describe(`Sort parameter name`),format:t.z.enum([`comma`,`array`,`pipe`]).default(`comma`).describe(`Sort parameter encoding format`)}).optional().describe(`Sort parameter mapping`),fieldsParam:t.z.string().default(`fields`).describe(`Field selection parameter name`)})),Jp=n(()=>t.z.object({version:t.z.enum([`v2`,`v4`]).default(`v4`).describe(`OData version`),usePrefix:t.z.boolean().default(!0).describe(`Use $ prefix for system query options ($filter vs filter)`),stringFunctions:t.z.array(t.z.enum([`contains`,`startswith`,`endswith`,`tolower`,`toupper`,`trim`,`concat`,`substring`,`length`])).optional().describe(`Supported OData string functions`),expand:t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable $expand support`),maxDepth:t.z.number().int().min(1).default(3).describe(`Maximum expand depth`)}).optional().describe(`$expand configuration`)})),Yp=n(()=>t.z.object({operatorMappings:t.z.array(Kp).optional().describe(`Custom operator mappings`),rest:qp.optional().describe(`REST query adapter configuration`),odata:Jp.optional().describe(`OData query adapter configuration`)})),Xp=t.z.enum([`csv`,`json`,`jsonl`,`xlsx`,`parquet`]),Zp=t.z.enum([`pending`,`processing`,`completed`,`failed`,`cancelled`,`expired`]),Qp=n(()=>t.z.object({object:t.z.string().describe(`Object name to export`),format:Xp.default(`csv`).describe(`Export file format`),fields:t.z.array(t.z.string()).optional().describe(`Specific fields to include (omit for all fields)`),filter:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Filter criteria for records to export`),sort:t.z.array(t.z.object({field:t.z.string().describe(`Field name to sort by`),direction:t.z.enum([`asc`,`desc`]).default(`asc`).describe(`Sort direction`)})).optional().describe(`Sort order for exported records`),limit:t.z.number().int().min(1).optional().describe(`Maximum number of records to export`),includeHeaders:t.z.boolean().default(!0).describe(`Include header row (CSV/XLSX)`),encoding:t.z.string().default(`utf-8`).describe(`Character encoding for the export file`),templateId:t.z.string().optional().describe(`Export template ID for predefined field mappings`)})),$p=n(()=>j.extend({data:t.z.object({jobId:t.z.string().describe(`Export job ID`),status:Zp.describe(`Initial job status`),estimatedRecords:t.z.number().int().optional().describe(`Estimated total records`),createdAt:t.z.string().datetime().describe(`Job creation timestamp`)})})),em=n(()=>j.extend({data:t.z.object({jobId:t.z.string().describe(`Export job ID`),status:Zp.describe(`Current job status`),format:Xp.describe(`Export format`),totalRecords:t.z.number().int().optional().describe(`Total records to export`),processedRecords:t.z.number().int().describe(`Records processed so far`),percentComplete:t.z.number().min(0).max(100).describe(`Export progress percentage`),fileSize:t.z.number().int().optional().describe(`Current file size in bytes`),downloadUrl:t.z.string().optional().describe(`Presigned download URL (available when status is "completed")`),downloadExpiresAt:t.z.string().datetime().optional().describe(`Download URL expiration timestamp`),error:t.z.object({code:t.z.string().describe(`Error code`),message:t.z.string().describe(`Error message`)}).optional().describe(`Error details if job failed`),startedAt:t.z.string().datetime().optional().describe(`Processing start timestamp`),completedAt:t.z.string().datetime().optional().describe(`Completion timestamp`)})})),tm=t.z.enum([`strict`,`lenient`,`dry_run`]),nm=t.z.enum([`skip`,`update`,`create_new`,`fail`]),rm=n(()=>t.z.object({mode:tm.default(`strict`).describe(`Validation mode for the import`),deduplication:t.z.object({strategy:nm.default(`skip`).describe(`How to handle duplicate records`),matchFields:t.z.array(t.z.string()).min(1).describe(`Fields used to identify duplicates (e.g., "email", "external_id")`)}).optional().describe(`Deduplication configuration`),maxErrors:t.z.number().int().min(1).default(100).describe(`Maximum validation errors before aborting`),trimWhitespace:t.z.boolean().default(!0).describe(`Trim leading/trailing whitespace from string fields`),dateFormat:t.z.string().optional().describe(`Expected date format in import data (e.g., "YYYY-MM-DD")`),nullValues:t.z.array(t.z.string()).optional().describe(`Strings to treat as null (e.g., ["", "N/A", "null"])`)})),im=n(()=>j.extend({data:t.z.object({totalRecords:t.z.number().int().describe(`Total records in import file`),validRecords:t.z.number().int().describe(`Records that passed validation`),invalidRecords:t.z.number().int().describe(`Records that failed validation`),duplicateRecords:t.z.number().int().describe(`Duplicate records detected`),errors:t.z.array(t.z.object({row:t.z.number().int().describe(`Row number in the import file`),field:t.z.string().optional().describe(`Field that failed validation`),code:t.z.string().describe(`Validation error code`),message:t.z.string().describe(`Validation error message`)})).describe(`List of validation errors`),preview:t.z.array(t.z.record(t.z.string(),t.z.unknown())).optional().describe(`Preview of first N valid records (for dry_run mode)`)})})),am=n(()=>t.z.object({sourceField:t.z.string().describe(`Field name in the source data (import) or object (export)`),targetField:t.z.string().describe(`Field name in the target object (import) or file column (export)`),targetLabel:t.z.string().optional().describe(`Display label for the target column (export)`),transform:t.z.enum([`none`,`uppercase`,`lowercase`,`trim`,`date_format`,`lookup`]).default(`none`).describe(`Transformation to apply during mapping`),defaultValue:t.z.unknown().optional().describe(`Default value if source field is null/empty`),required:t.z.boolean().default(!1).describe(`Whether this field is required (import validation)`)})),om=n(()=>t.z.object({id:t.z.string().optional().describe(`Template ID (generated on save)`),name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Template machine name (snake_case)`),label:t.z.string().describe(`Human-readable template label`),description:t.z.string().optional().describe(`Template description`),object:t.z.string().describe(`Target object name`),direction:t.z.enum([`import`,`export`,`bidirectional`]).describe(`Template direction`),format:Xp.optional().describe(`Default file format for this template`),mappings:t.z.array(am).min(1).describe(`Field mapping entries`),createdAt:t.z.string().datetime().optional().describe(`Template creation timestamp`),updatedAt:t.z.string().datetime().optional().describe(`Last update timestamp`),createdBy:t.z.string().optional().describe(`User who created the template`)})),sm=t.z.enum([`insert`,`update`,`upsert`]),cm=n(()=>t.z.union([t.z.record(t.z.string(),t.z.string()),t.z.array(am)])),lm=n(()=>t.z.object({format:t.z.enum([`csv`,`json`,`xlsx`]).optional().describe(`Payload shape: csv text, a rows[] array, or a base64 xlsx (inferred when omitted)`),csv:t.z.string().optional().describe(`CSV text (when format = csv)`),rows:t.z.array(t.z.record(t.z.string(),t.z.unknown())).optional().describe(`Row objects (when format = json)`),xlsxBase64:t.z.string().optional().describe(`Base64-encoded .xlsx workbook bytes (when format = xlsx); parsed server-side`),sheet:t.z.union([t.z.string(),t.z.number().int()]).optional().describe(`Worksheet name or 1-based index to read (xlsx; defaults to the first sheet)`),mapping:cm.optional().describe(`Source column → target field mapping`),dryRun:t.z.boolean().default(!1).describe(`Validate + coerce every row without persisting`),writeMode:sm.default(`insert`).describe(`insert / update / upsert semantics`),matchFields:t.z.array(t.z.string()).optional().describe(`Fields that identify an existing record (required for update/upsert)`),runAutomations:t.z.boolean().default(!1).describe(`Fire triggers/hooks for each imported row (off by default for bulk)`),treatAsHistorical:t.z.boolean().default(!1).describe(`Import as established historical facts. Two effects, both off by default so a normal import is unchanged: (1) skip the state_machine rule so mid-lifecycle rows (e.g. already-closed tickets, closed_won deals) are not rejected by initialStates (#3479); and (2) preserve the original audit timeline — keep the supplied created_at / updated_at / updated_by and author-declared business readonly fields (e.g. closed_at, resolved_by) instead of stamping-now / stripping them (#3493). Undoing a historical import mirrors (2): the captured pre-import values are restored verbatim rather than re-stamped (#3556).`),trimWhitespace:t.z.boolean().default(!0).describe(`Trim leading/trailing whitespace from string cells`),nullValues:t.z.array(t.z.string()).optional().describe(`Strings treated as null/blank (besides empty string)`),createMissingOptions:t.z.boolean().default(!1).describe(`Keep unmatched select values instead of failing the row`),skipBlankMatchKey:t.z.boolean().default(!1).describe(`Skip rows whose matchFields are blank (default: upsert creates them, update skips them)`)})),um=n(()=>t.z.object({row:t.z.number().int().describe(`1-based row number in the source data`),ok:t.z.boolean().describe(`Whether the row succeeded`),action:t.z.enum([`created`,`updated`,`skipped`,`failed`]).describe(`What happened to the row`),id:t.z.string().optional().describe(`Record id (created/updated rows)`),field:t.z.string().optional().describe(`Field that caused a coercion/validation error`),code:t.z.string().optional().describe(`Error code (failed rows)`),error:t.z.string().optional().describe(`Human-readable error message (failed rows)`)})),dm=n(()=>t.z.object({object:t.z.string().describe(`Target object name`),dryRun:t.z.boolean().describe(`Whether this was a validate-only pass`),writeMode:sm.describe(`Write mode used`),total:t.z.number().int().describe(`Rows processed`),ok:t.z.number().int().describe(`Rows that succeeded`),errors:t.z.number().int().describe(`Rows that failed`),created:t.z.number().int().describe(`Rows that created a new record`),updated:t.z.number().int().describe(`Rows that updated an existing record`),skipped:t.z.number().int().describe(`Rows skipped (no match in update mode, etc.)`),results:t.z.array(um).describe(`Per-row outcomes`)})),fm=5e4,pm=t.z.enum([`pending`,`running`,`succeeded`,`failed`,`cancelled`]),mm=lm,hm=n(()=>t.z.object({jobId:t.z.string().describe(`Import job id — poll progress/results with this`),object:t.z.string().describe(`Target object name`),status:pm.describe(`Initial job status (usually "pending")`),total:t.z.number().int().describe(`Rows accepted for processing`),createdAt:t.z.string().describe(`Job creation timestamp (ISO 8601)`)})),gm=n(()=>t.z.object({jobId:t.z.string().describe(`Import job id`),object:t.z.string().describe(`Target object name`),status:pm.describe(`Current job status`),dryRun:t.z.boolean().describe(`Whether this is a validate-only pass`),writeMode:sm.describe(`Write mode used`),total:t.z.number().int().describe(`Total rows to process`),processed:t.z.number().int().describe(`Rows processed so far`),created:t.z.number().int().describe(`Rows that created a new record`),updated:t.z.number().int().describe(`Rows that updated an existing record`),skipped:t.z.number().int().describe(`Rows skipped`),errors:t.z.number().int().describe(`Rows that failed`),percentComplete:t.z.number().min(0).max(100).describe(`processed / total as a percentage`),undoable:t.z.boolean().describe(`Whether this job can still be logically rolled back (undo log captured, terminal state, not yet reverted)`),revertedAt:t.z.string().optional().describe(`When the job was undone / rolled back (ISO 8601)`),error:t.z.string().optional().describe(`Fatal error message (when status = failed)`),startedAt:t.z.string().optional().describe(`Processing start timestamp (ISO 8601)`),completedAt:t.z.string().optional().describe(`Completion timestamp (ISO 8601)`),createdAt:t.z.string().describe(`Job creation timestamp (ISO 8601)`)})),_m=n(()=>gm.extend({results:t.z.array(um).describe(`Capped sample of per-row outcomes (failures first)`),resultsTruncated:t.z.boolean().describe("Whether `results` is a capped sample of a larger set")})),vm=n(()=>t.z.object({object:t.z.string().optional().describe(`Filter to one target object`),status:pm.optional().describe(`Filter by job status`),limit:t.z.number().int().min(1).max(200).default(50).describe(`Max rows to return`),offset:t.z.number().int().min(0).default(0).describe(`Pagination offset`)})),ym=n(()=>t.z.object({jobId:t.z.string().describe(`Import job id`),object:t.z.string().describe(`Target object name`),status:pm.describe(`Job status`),total:t.z.number().int().describe(`Total rows`),processed:t.z.number().int().describe(`Rows processed`),created:t.z.number().int().describe(`Rows created`),updated:t.z.number().int().describe(`Rows updated`),skipped:t.z.number().int().describe(`Rows skipped`),errors:t.z.number().int().describe(`Rows failed`),createdAt:t.z.string().describe(`Job creation timestamp (ISO 8601)`),completedAt:t.z.string().optional().describe(`Completion timestamp (ISO 8601)`),undoable:t.z.boolean().describe(`Whether this job can still be logically rolled back`),revertedAt:t.z.string().optional().describe(`When the job was undone / rolled back (ISO 8601)`)})),bm=n(()=>t.z.object({jobs:t.z.array(ym).describe(`Import jobs, newest first`)})),xm=n(()=>t.z.object({success:t.z.boolean().describe(`Whether the undo completed`),jobId:t.z.string().describe(`Import job id`),object:t.z.string().describe(`Target object name`),deleted:t.z.number().int().describe(`Created records deleted`),restored:t.z.number().int().describe(`Updated records restored to pre-import values`),failed:t.z.number().int().describe(`Reversal operations that failed`)})),Sm=n(()=>t.z.object({id:t.z.string().optional().describe(`Scheduled export ID`),name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Schedule name (snake_case)`),label:t.z.string().optional().describe(`Human-readable label`),object:t.z.string().describe(`Object name to export`),format:Xp.default(`csv`).describe(`Export file format`),fields:t.z.array(t.z.string()).optional().describe(`Fields to include`),filter:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Record filter criteria`),templateId:t.z.string().optional().describe(`Export template ID for field mappings`),schedule:t.z.object({cronExpression:oe.describe(`Cron expression for schedule`),timezone:t.z.string().default(`UTC`).describe(`IANA timezone`)}).describe(`Schedule timing configuration`),delivery:t.z.object({method:t.z.enum([`email`,`storage`,`webhook`]).describe(`How to deliver the export file`),recipients:t.z.array(t.z.string()).optional().describe(`Email recipients (for email delivery)`),storagePath:t.z.string().optional().describe(`Storage path (for storage delivery)`),webhookUrl:t.z.string().optional().describe(`Webhook URL (for webhook delivery)`)}).describe(`Export delivery configuration`),enabled:t.z.boolean().default(!0).describe(`Whether the scheduled export is active`),lastRunAt:t.z.string().datetime().optional().describe(`Last execution timestamp`),nextRunAt:t.z.string().datetime().optional().describe(`Next scheduled execution`),createdAt:t.z.string().datetime().optional().describe(`Creation timestamp`),createdBy:t.z.string().optional().describe(`User who created the schedule`)})),Cm=n(()=>t.z.object({jobId:t.z.string().describe(`Export job ID`)})),wm=n(()=>j.extend({data:t.z.object({jobId:t.z.string().describe(`Export job ID`),downloadUrl:t.z.string().describe(`Presigned download URL`),fileName:t.z.string().describe(`Suggested file name`),fileSize:t.z.number().int().describe(`File size in bytes`),format:Xp.describe(`Export file format`),expiresAt:t.z.string().datetime().describe(`Download URL expiration timestamp`),checksum:t.z.string().optional().describe(`File checksum (SHA-256)`)})})),Tm=n(()=>t.z.object({object:t.z.string().optional().describe(`Filter by object name`),status:Zp.optional().describe(`Filter by job status`),limit:t.z.number().int().min(1).max(100).default(20).describe(`Maximum number of jobs to return`),cursor:t.z.string().optional().describe(`Pagination cursor from a previous response`)})),Em=n(()=>t.z.object({jobId:t.z.string().describe(`Export job ID`),object:t.z.string().describe(`Object name that was exported`),status:Zp.describe(`Current job status`),format:Xp.describe(`Export file format`),totalRecords:t.z.number().int().optional().describe(`Total records exported`),fileSize:t.z.number().int().optional().describe(`File size in bytes`),createdAt:t.z.string().datetime().describe(`Job creation timestamp`),completedAt:t.z.string().datetime().optional().describe(`Completion timestamp`),createdBy:t.z.string().optional().describe(`User who initiated the export`)})),Dm=n(()=>j.extend({data:t.z.object({jobs:t.z.array(Em).describe(`List of export jobs`),nextCursor:t.z.string().optional().describe(`Cursor for the next page`),hasMore:t.z.boolean().describe(`Whether more jobs are available`)})})),Om=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Schedule name (snake_case)`),label:t.z.string().optional().describe(`Human-readable label`),object:t.z.string().describe(`Object name to export`),format:Xp.default(`csv`).describe(`Export file format`),fields:t.z.array(t.z.string()).optional().describe(`Fields to include`),filter:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Record filter criteria`),templateId:t.z.string().optional().describe(`Export template ID for field mappings`),schedule:t.z.object({cronExpression:oe.describe(`Cron expression for schedule`),timezone:t.z.string().default(`UTC`).describe(`IANA timezone`)}).describe(`Schedule timing configuration`),delivery:t.z.object({method:t.z.enum([`email`,`storage`,`webhook`]).describe(`How to deliver the export file`),recipients:t.z.array(t.z.string()).optional().describe(`Email recipients (for email delivery)`),storagePath:t.z.string().optional().describe(`Storage path (for storage delivery)`),webhookUrl:t.z.string().optional().describe(`Webhook URL (for webhook delivery)`)}).describe(`Export delivery configuration`)})),km=n(()=>j.extend({data:t.z.object({id:t.z.string().describe(`Scheduled export ID`),name:t.z.string().describe(`Schedule name`),enabled:t.z.boolean().describe(`Whether the schedule is active`),nextRunAt:t.z.string().datetime().optional().describe(`Next scheduled execution`),createdAt:t.z.string().datetime().describe(`Creation timestamp`)})})),Am={createExportJob:{method:`POST`,path:`/api/v1/data/:object/export`,input:Qp,output:$p},getExportJobProgress:{method:`GET`,path:`/api/v1/data/export/:jobId`,input:t.z.object({jobId:t.z.string()}),output:em},getExportJobDownload:{method:`GET`,path:`/api/v1/data/export/:jobId/download`,input:Cm,output:wm},listExportJobs:{method:`GET`,path:`/api/v1/data/export`,input:Tm,output:Dm},scheduleExport:{method:`POST`,path:`/api/v1/data/export/schedules`,input:Om,output:km},cancelExportJob:{method:`POST`,path:`/api/v1/data/export/:jobId/cancel`,input:t.z.object({jobId:t.z.string()}),output:j}},jm={createImportJob:{method:`POST`,path:`/api/v1/data/:object/import/jobs`,input:mm,output:hm},getImportJobProgress:{method:`GET`,path:`/api/v1/data/import/jobs/:jobId`,input:t.z.object({jobId:t.z.string()}),output:gm},getImportJobResults:{method:`GET`,path:`/api/v1/data/import/jobs/:jobId/results`,input:t.z.object({jobId:t.z.string()}),output:_m},listImportJobs:{method:`GET`,path:`/api/v1/data/import/jobs`,input:vm,output:bm},cancelImportJob:{method:`POST`,path:`/api/v1/data/import/jobs/:jobId/cancel`,input:t.z.object({jobId:t.z.string()}),output:j},undoImportJob:{method:`POST`,path:`/api/v1/data/import/jobs/:jobId/undo`,input:t.z.object({jobId:t.z.string()}),output:xm}};function Mm(){return{maxRetries:t.z.number().int().min(0).max(10).default(0).describe(`Retry attempts after the initial one. 0 (the default) means no retry — state a count to opt in.`),backoffMs:t.z.number().int().min(0).default(1e3).describe(`Base delay before the first retry (ms); subsequent delays multiply by backoffMultiplier`),backoffMultiplier:t.z.number().min(1).default(1).describe(`Exponential backoff multiplier; 1 (the default) keeps the delay flat`),maxRetryDelayMs:t.z.number().int().min(0).default(3e4).describe(`Ceiling for a single backoff delay (ms)`),jitter:t.z.boolean().default(!1).describe(`Randomize each delay within [50%, 100%] of its computed value — spreads a thundering herd of simultaneous retries`),retryDelayMs:p("`retryDelayMs` was removed in @objectstack/spec 17.0.0 (#4661, #4964) — the retry policy now has ONE spelling for its base delay across every surface that carries it: `job.retryPolicy`, a `try_catch` node's `retry`, `flow.errorHandling` and an ETL pipeline's `retry`. Rename the key to `backoffMs`; the value (milliseconds before the first retry) is unchanged. `os migrate meta --from 16` rewrites it for you.")}}n(()=>t.z.object(Mm())),t.z.enum([`start`,`end`,`decision`,`assignment`,`loop`,`create_record`,`update_record`,`delete_record`,`get_record`,`http`,`notify`,`script`,`screen`,`wait`,`subflow`,`map`,`connector_action`,`parallel_gateway`,`join_gateway`,`boundary_event`]).options;var Nm=T({surface:`this flow variable`,knownKeys:[`name`,`type`,`isInput`,`isOutput`],aliases:{input:`isInput`,output:`isOutput`},history:`Until #4001 these were dropped silently — the variable still parsed, so a mis-declared input/output contract shipped without a diagnostic.`}),Pm=n(()=>t.z.object({name:t.z.string().describe(`Variable name`),type:t.z.string().describe(`Data type (text, number, boolean, object, list)`),isInput:t.z.boolean().default(!1).describe(`Is input parameter`),isOutput:t.z.boolean().default(!1).describe(`Is output parameter`)},{error:Nm}).strict()),Fm=T({surface:`this flow node`,knownKeys:[`id`,`type`,`label`,`config`,`connectorConfig`,`position`,`timeoutMs`,`inputSchema`,`outputSchema`,`waitEventConfig`,`boundaryConfig`],aliases:{configuration:`config`,settings:`config`,properties:`config`,options:`config`,params:`config`,parameters:`config`},guidance:{inputs:"`inputs` is not a FlowNode key — a node's runtime inputs live under `config` (e.g. `config.inputs` for script/function nodes); `inputSchema` declares their types."},history:`Until #4001 these were dropped silently — the node still parsed, so a mis-placed config shipped as a step that quietly ignored it.`}),Im=n(()=>t.z.object({id:t.z.string().describe(`Node unique ID`),type:t.z.string().min(1).describe(`Action type — a built-in FlowNodeAction id or a plugin-registered node type. Validated against the live action registry at registerFlow() (ADR-0018), not by a closed enum.`),label:t.z.string().describe(`Node label`),config:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Node configuration`),connectorConfig:D({surface:"this connector_action node's `connectorConfig`",aliases:{params:`input`,parameters:`input`,arguments:`input`,payload:`input`},history:"Until #4001 these were dropped silently — the block still parsed, so a whole mapped input map written under another word vanished and the executor dispatched the action with `input ?? {}`: a successful call carrying nothing."},{connectorId:t.z.string().describe(`Registered connector name`),actionId:t.z.string().describe(`Action key declared by the connector`),input:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Mapped inputs for the action`)}).optional(),position:D({surface:"this node's canvas `position`",history:`Until #4001 these were dropped silently — the block still parsed, so a canvas hint written beside x/y (a size, a third coordinate, a designer marker) was discarded, and the round-trip back through the designer could not tell it had ever been written.`},{x:t.z.number(),y:t.z.number()}).optional(),timeoutMs:t.z.number().int().min(0).optional().describe(`Maximum execution time for this node in milliseconds`),inputSchema:t.z.record(t.z.string(),D({surface:`this node input parameter's declaration`,guidance:{optional:"There is no `optional` on an input parameter — the polarity is the other way round. Write `required: false` (which is also the default, so the key can just be dropped); `optional: true` is `required: false`, and `optional: false` is `required: true`."},history:"Until #4001 these were dropped silently — the declaration still parsed, so a parameter constrained under a word we do not declare (`optional: false`) came back UNconstrained: `required` fell to its `false` default, and the engine's pre-execution check (`validateNodeInputSchemas`) then had nothing to require."},{type:t.z.enum([`string`,`number`,`boolean`,`object`,`array`]).describe(`Parameter type`),required:t.z.boolean().default(!1).describe(`Whether the parameter is required`),description:t.z.string().optional().describe(`Parameter description`)})).optional().describe(`Input parameter schema for this node`),outputSchema:p("`flow.nodes[].outputSchema` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it was never validated: the engine does not check node outputs against it, so it documented a contract nothing enforced. Delete the key. Downstream nodes read prior outputs via expressions ({{nodeId.field}}) regardless of any declaration."),waitEventConfig:D({surface:"this wait node's `waitEventConfig`",aliases:{event:`eventType`,signal:`signalName`,duration:`timerDuration`,delay:`timerDuration`},guidance:{timeout:"`wait` has no timeout — nothing has ever failed or resumed a wait on a deadline (#4158 retired the two keys that claimed one). Use `timerDuration`: it accepts a bare number as milliseconds, so `timerDuration: 60000` is a 60s wait."},history:`Until #4001 these were dropped silently — the block still parsed, so a wait node whose resume condition the author spelled slightly wrong waited on nothing.`},{eventType:t.z.enum([`timer`,`signal`,`webhook`,`manual`,`condition`]).describe(`What kind of event resumes the execution`),timerDuration:t.z.string().optional().describe(`ISO 8601 duration (e.g., "PT1H") or wait time for timer events`),signalName:t.z.string().optional().describe(`Named signal or webhook event to wait for`),timeoutMs:p("`waitEventConfig.timeoutMs` was removed in @objectstack/spec 17 (#4158). It documented a timeout guard that never existed: nothing ever failed or resumed a wait on a deadline. Its only reader treated it as the timer DURATION when `timerDuration` was absent, so use `timerDuration` — it accepts a bare number as milliseconds, making `timeoutMs: 60000` and `timerDuration: 60000` the same wait. Stored flows are converted automatically."),onTimeout:p("`waitEventConfig.onTimeout` was removed in @objectstack/spec 17 (#4158). It had no readers at all — no code path ever inspected it, so neither `fail` nor `continue` ever happened. Delete the key. There is no replacement: `wait` has no timeout, and a wait node resumes only when its timer elapses or its signal arrives.")}).optional().describe(`Configuration for wait node event resumption`),boundaryConfig:D({surface:"this boundary event's `boundaryConfig`",aliases:{attachedToRef:`attachedToNodeId`,attachedTo:`attachedToNodeId`,hostNodeId:`attachedToNodeId`,cancelActivity:`interrupting`,event:`eventType`,signal:`signalName`,duration:`timerDuration`},history:"Until #4001 these were dropped silently — the block still parsed, so BPMN's `cancelActivity: false` was discarded and `interrupting` fell to its `true` default: an event the author declared NON-interrupting cancelled the host activity anyway."},{attachedToNodeId:t.z.string().describe(`Host node ID this boundary event monitors`),eventType:t.z.enum([`error`,`timer`,`signal`,`cancel`]).describe(`Boundary event trigger type`),interrupting:t.z.boolean().default(!0).describe(`If true, the host activity is cancelled when this event fires`),errorCode:t.z.string().optional().describe(`Specific error code to catch (empty = catch all errors)`),timerDuration:t.z.string().optional().describe(`ISO 8601 duration for timer boundary events`),signalName:t.z.string().optional().describe(`Named signal to catch`)}).optional().describe(`Configuration for boundary events attached to host nodes`)},{error:Fm}).strict()),Lm=T({surface:`this flow edge`,knownKeys:[`id`,`source`,`target`,`condition`,`type`,`label`,`isDefault`],aliases:{from:`source`,to:`target`,sourceid:`source`,targetid:`target`,expression:`condition`,when:`condition`,guard:`condition`},history:`Until #4001 these were dropped silently — the edge still parsed, so a branch predicate or endpoint the author wrote was quietly ignored.`}),Rm=n(()=>t.z.object({id:t.z.string().describe(`Edge unique ID`),source:t.z.string().describe(`Source Node ID`),target:t.z.string().describe(`Target Node ID`),condition:b.optional().describe(`Predicate (CEL) returning boolean used for branching.`),type:t.z.enum([`default`,`fault`,`conditional`,`back`]).default(`default`).describe(`Connection type: default (normal flow), fault (error path), conditional (expression-guarded), or back (ADR-0044 declared back-edge — traversed normally at run time, but excluded from DAG cycle validation so a revise/rework loop can re-enter an earlier node)`),label:t.z.string().optional().describe(`Label on the connector`),isDefault:t.z.boolean().default(!1).describe("BPMN default flow: traverse this edge only when no sibling conditional edge of the same source node matched. Mutually exclusive with `condition`; at most one per source node.")},{error:Lm}).strict()),zm=T({surface:`this flow`,knownKeys:[`name`,`label`,`description`,`successMessage`,`errorMessage`,`version`,`status`,`template`,`type`,`variables`,`nodes`,`edges`,`active`,`runAs`,`errorHandling`,`protection`,`_lock`,`_lockReason`,`_lockSource`,`_provenance`,`_packageId`,`_packageVersion`,`_lockDocsUrl`],aliases:{steps:`nodes`,connections:`edges`,transitions:`edges`,links:`edges`,trigger:`type`,triggertype:`type`,title:`label`},guidance:{object:"`object` is not a Flow field — a record-change flow binds its object on the START node's `config` (`{ objectName, triggerType, condition }`), not at the flow top level.",objectName:"`objectName` is not a Flow field — it belongs on the START node's `config` (`{ objectName, triggerType, condition }`), not at the flow top level.",schedule:"`schedule` is not a Flow field — a schedule flow declares its cron/interval as `config.schedule` on the START node, not at the flow top level."},history:`Until #4001 these were dropped silently — the flow still parsed, so a trigger binding or config the author wrote was quietly ignored.`}),Bm=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Machine name`),label:t.z.string().describe(`Flow label`),description:t.z.string().optional(),successMessage:t.z.string().optional().describe(`Toast shown when a screen flow completes (defaults to a generic "Done").`),errorMessage:t.z.string().optional().describe(`Toast shown when a screen flow fails (defaults to the raw error).`),version:t.z.number().int().default(1).describe(`Version number`),status:t.z.enum([`draft`,`active`,`obsolete`,`invalid`]).default(`draft`).describe(`Deployment status`),template:p("`flow.template` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no designer or engine path ever read it, so flagging a flow as a template/subflow did nothing. Delete the key. Shared logic is invoked via a subflow NODE referencing the flow by name."),type:t.z.enum([`autolaunched`,`record_change`,`schedule`,`screen`,`api`]).describe(`Flow type`),variables:t.z.array(Pm).optional().describe(`Flow variables`),nodes:t.z.array(Im).describe(`Flow nodes`),edges:t.z.array(Rm).describe(`Flow connections`),active:p("`flow.active` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never had an effect: the engine arms flows from `status`, and `active: false` did NOT stop a flow (worse, the default read as disabled while the engine treated unset as enabled). Delete the key. Use `status: 'obsolete'` (or 'invalid') to unbind and disable a flow, `status: 'active'` to arm it."),runAs:t.z.enum([`system`,`user`]).default(`user`).describe(`Execution identity for the run: system = elevated (bypasses RLS), user = the triggering user (RLS-respecting). A run with no trigger user has no identity to scope to, so under user its data operations are REFUSED — declare system to make the elevation explicit. This covers schedule/time-relative/api triggers AND any record-change flow fired by a write that carried no user.`),errorHandling:D({surface:"this flow's `errorHandling` block",aliases:{initialDelayMs:`backoffMs`,maxDelayMs:`maxRetryDelayMs`,retries:`maxRetries`,attempts:`maxRetries`,onError:`strategy`},guidance:{maxAttempts:"`maxAttempts` is the connector/RetryConfig spelling and INCLUDES the first attempt; flow `errorHandling` counts retries AFTER it. Write `maxRetries: <maxAttempts - 1>` — renaming the key alone would quietly run one attempt fewer than you asked for.",fallback:"There is no fallback node on `errorHandling` (`fallbackNodeId` was removed in 17, #3896 — the engine never read it). Draw a per-node FAULT EDGE from the failing node to the handler node instead.",fallbackNode:"There is no fallback node on `errorHandling` (`fallbackNodeId` was removed in 17, #3896 — the engine never read it). Draw a per-node FAULT EDGE from the failing node to the handler node instead."},history:"Until #4001 these were dropped silently — the block still parsed, so a retry budget or backoff the author configured was replaced by this block's defaults without a word. Since #4964 the retry keys are the converged `RetryPolicySchema` contract, so a spelling learned on `job.retryPolicy` or a `try_catch` node's `retry` is correct here too."},{strategy:t.z.enum([`fail`,`retry`,`continue`]).default(`fail`).describe(`How to handle node execution errors`),...Mm(),maxRetries:Mm().maxRetries.describe(`Retry attempts after the initial one. Read only under strategy: 'retry', which requires >= 1; 0 (the default) means no retry.`),fallbackNodeId:p("`flow.errorHandling.fallbackNodeId` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — the engine routes unrecoverable node errors via per-node fault edges (an edge with condition 'fault'), and never read this key: a fallback configured here silently did not exist. Delete the key and draw a fault edge from the failing node to the handler node instead.")}).superRefine((e,t)=>{e.strategy===`retry`&&e.maxRetries<1&&t.addIssue({code:`custom`,path:[`maxRetries`],message:"`errorHandling.strategy: 'retry'` requires `maxRetries` >= 1 — retrying zero times is exactly `strategy: 'fail'`, so a flow that omits the count (it defaults to 0) or writes 0 never retries. State the attempts explicitly (e.g. `maxRetries: 3`), or use `strategy: 'fail'` if no retry is wanted. Note a retry re-runs the WHOLE flow, so side-effecting nodes run again."})}).optional().describe(`Flow-level error handling configuration`),protection:z.optional().describe(`Package author protection block — lock policy for this flow.`),..._},{error:zm}).strict());n(()=>t.z.object({flowName:t.z.string().describe(`Flow machine name`),version:t.z.number().int().min(1).describe(`Version number`),definition:Bm.describe(`Complete flow definition snapshot`),createdAt:t.z.string().datetime().describe(`When this version was created`),createdBy:t.z.string().optional().describe(`User who created this version`),changeNote:t.z.string().optional().describe(`Description of what changed in this version`)}));var Vm=t.z.enum([`pending`,`running`,`paused`,`completed`,`failed`,`cancelled`,`timed_out`,`retrying`]),Hm=n(()=>t.z.object({selected:t.z.number().int().min(0).optional().describe("Records this node READ or matched (a `get_record` query, a lookup)"),acted:t.z.number().int().min(0).optional().describe(`Records this node WROTE (created / updated / deleted) or effects it dispatched (notifications delivered)`),unmeasuredEffect:t.z.boolean().optional().describe("This execution may have caused an effect the platform cannot count (an external write through a connector). NOT interchangeable with `acted: 0` — it says the count is unknown, not that it is zero.")})),Um=n(()=>t.z.object({nodeId:t.z.string().describe(`Node whose out-edge did not open (the gate)`),edgeId:t.z.string().optional().describe(`Edge whose condition evaluated false`),label:t.z.string().optional().describe(`Edge label, when the flow names its branches`)})),Wm=n(()=>t.z.object({nodeId:t.z.string().describe(`Node ID that was executed`),nodeType:t.z.string().describe(`Node action type (e.g., "decision", "http")`),nodeLabel:t.z.string().optional().describe(`Human-readable node label`),status:t.z.enum([`success`,`failure`,`skipped`]).describe(`Step execution result`),startedAt:t.z.string().datetime().describe(`When the step started`),completedAt:t.z.string().datetime().optional().describe(`When the step completed`),durationMs:t.z.number().int().min(0).optional().describe(`Step execution duration in milliseconds`),input:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Input data passed to the node`),output:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Output data produced by the node`),error:t.z.object({code:t.z.string().describe(`Error code`),message:t.z.string().describe(`Error message`),stack:t.z.string().optional().describe(`Stack trace`)}).optional().describe(`Error details if step failed`),retryAttempt:t.z.number().int().min(0).optional().describe(`Retry attempt number (0 = first try)`),parentNodeId:t.z.string().optional().describe(`Enclosing structured-region container node ID (loop/parallel/try_catch)`),iteration:t.z.number().int().min(0).optional().describe(`Zero-based loop iteration or parallel branch index of the enclosing region`),regionKind:t.z.string().optional().describe(`Region kind the step ran in: loop-body | parallel-branch | try | catch`),metrics:Hm.optional().describe(`Records this step selected / acted on, as reported by the node executor`),skippedBy:Um.optional().describe("The gate that closed, when `status` is `skipped`")})),Gm=n(()=>t.z.object({nodeId:t.z.string().describe(`Node ID`),nodeType:t.z.string().describe(`Node action type (e.g., "get_record", "decision")`),nodeLabel:t.z.string().optional().describe(`Human-readable node label`),status:t.z.enum([`success`,`failure`,`skipped`]).describe("Terminal status of the node across the run — `failure` if any execution failed, else `success` if any succeeded, else `skipped`"),runs:t.z.number().int().min(0).describe(`Times the node executed (loop iterations and parallel branches each count)`),failures:t.z.number().int().min(0).describe(`Executions that failed`),skipped:t.z.number().int().min(0).describe(`Times a closed gate kept this node from running at all`),selected:t.z.number().int().min(0).optional().describe(`Records read across every execution — omitted for a node that reads none`),acted:t.z.number().int().min(0).optional().describe(`Records written / effects dispatched across every execution — omitted for a node that writes none`),unmeasured:t.z.number().int().min(0).optional().describe(`Executions that may have caused an effect the platform cannot count (see ExecutionStepMetrics.unmeasuredEffect)`)})),Km=n(()=>t.z.object({nodeId:t.z.string().describe(`Node whose out-edge did not open (the gate)`),targetNodeId:t.z.string().describe(`Node the closed edge would have run`),edgeId:t.z.string().optional().describe(`Edge whose condition evaluated false`),label:t.z.string().optional().describe(`Edge label, when the flow names its branches`),skipped:t.z.number().int().min(1).describe(`Times this gate evaluated false (once per loop iteration)`)})),qm=n(()=>t.z.object({selected:t.z.number().int().min(0).describe(`Total records read by the run`),acted:t.z.number().int().min(0).describe(`Total records written / effects dispatched by the run`),skipped:t.z.number().int().min(0).describe(`Total node executions a closed gate prevented`),unmeasured:t.z.number().int().min(0).optional().describe(`Total executions that may have caused an effect the platform cannot count. Absent = not tracked (an older run), which is not the same as zero.`),nodes:t.z.array(Gm).describe(`Per-node breakdown, in first-execution order`),gates:t.z.array(Km).describe(`Gates that closed during the run, most-skipped first`),detailOmitted:t.z.boolean().optional().describe('Set when persistence dropped `nodes`/`gates` to keep the stored row bounded — the totals are still exact. Declared so empty arrays are never mistaken for "nothing ran".')})),Jm=n(()=>t.z.object({id:t.z.string().describe(`Execution instance ID`),flowName:t.z.string().describe(`Machine name of the executed flow`),flowVersion:t.z.number().int().optional().describe(`Version of the flow that was executed`),status:Vm.describe(`Current execution status`),trigger:t.z.object({type:t.z.string().describe(`Trigger type (e.g., "record_change", "schedule", "api", "manual")`),recordId:t.z.string().optional().describe(`Triggering record ID`),object:t.z.string().optional().describe(`Triggering object name`),userId:t.z.string().optional().describe(`User who triggered the execution`),metadata:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional trigger context`)}).describe(`What triggered this execution`),steps:t.z.array(Wm).describe(`Ordered list of executed steps`),summary:qm.optional().describe(`Per-run rollup: records selected / acted on, gate skips, per-node status`),variables:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Final state of flow variables`),startedAt:t.z.string().datetime().describe(`Execution start timestamp`),completedAt:t.z.string().datetime().optional().describe(`Execution completion timestamp`),durationMs:t.z.number().int().min(0).optional().describe(`Total execution duration in milliseconds`),runAs:t.z.enum([`system`,`user`]).optional().describe(`Execution context identity`),tenantId:t.z.string().optional().describe(`Tenant ID for multi-tenant isolation`)})),Ym=t.z.enum([`warning`,`error`,`critical`]);n(()=>t.z.object({id:t.z.string().describe(`Error record ID`),executionId:t.z.string().describe(`Parent execution ID`),nodeId:t.z.string().optional().describe(`Node where the error occurred`),severity:Ym.describe(`Error severity level`),code:t.z.string().describe(`Machine-readable error code`),message:t.z.string().describe(`Human-readable error message`),stack:t.z.string().optional().describe(`Stack trace for debugging`),context:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional diagnostic context (input data, config snapshot)`),timestamp:t.z.string().datetime().describe(`When the error occurred`),retryable:t.z.boolean().default(!1).describe(`Whether this error can be retried`),resolvedAt:t.z.string().datetime().optional().describe(`When the error was resolved (e.g., after successful retry)`)})),n(()=>t.z.object({id:t.z.string().describe(`Checkpoint ID`),executionId:t.z.string().describe(`Parent execution ID`),flowName:t.z.string().describe(`Flow machine name`),currentNodeId:t.z.string().describe(`Node ID where execution is paused`),variables:t.z.record(t.z.string(),t.z.unknown()).describe(`Flow variable state at checkpoint`),completedNodeIds:t.z.array(t.z.string()).describe(`List of node IDs already executed`),createdAt:t.z.string().datetime().describe(`Checkpoint creation timestamp`),expiresAt:t.z.string().datetime().optional().describe(`Checkpoint expiration (auto-cleanup)`),reason:t.z.enum([`wait`,`screen_input`,`approval`,`error`,`manual_pause`,`parallel_join`,`boundary_event`]).describe(`Why the execution was checkpointed`)})),n(()=>t.z.object({maxConcurrent:t.z.number().int().min(1).default(1).describe(`Maximum number of concurrent executions allowed`),onConflict:t.z.enum([`queue`,`reject`,`cancel_existing`]).default(`queue`).describe(`queue = enqueue for later, reject = fail immediately, cancel_existing = stop running instance`),lockScope:t.z.enum([`global`,`per_record`,`per_user`]).default(`global`).describe(`Scope of the concurrency lock`),queueTimeoutMs:t.z.number().int().min(0).optional().describe(`Maximum time to wait in queue before timing out (ms)`)})),n(()=>t.z.object({id:t.z.string().describe(`Schedule instance ID`),flowName:t.z.string().describe(`Flow machine name`),cronExpression:oe.describe("Cron expression — cron`0 9 * * MON-FRI`"),timezone:t.z.string().default(`UTC`).describe(`IANA timezone for cron evaluation`),status:t.z.enum([`active`,`paused`,`disabled`,`expired`]).default(`active`).describe(`Current schedule status`),nextRunAt:t.z.string().datetime().optional().describe(`Next scheduled execution timestamp`),lastRunAt:t.z.string().datetime().optional().describe(`Last execution timestamp`),lastExecutionId:t.z.string().optional().describe(`Execution ID of the last run`),lastRunStatus:Vm.optional().describe(`Status of the last run`),totalRuns:t.z.number().int().min(0).default(0).describe(`Total number of executions`),consecutiveFailures:t.z.number().int().min(0).default(0).describe(`Consecutive failed executions`),startDate:t.z.string().datetime().optional().describe(`Schedule effective start date`),endDate:t.z.string().datetime().optional().describe(`Schedule expiration date`),maxRuns:t.z.number().int().min(1).optional().describe(`Maximum total executions before auto-disable`),createdAt:t.z.string().datetime().describe(`Schedule creation timestamp`),updatedAt:t.z.string().datetime().optional().describe(`Last update timestamp`),createdBy:t.z.string().optional().describe(`User who created the schedule`)}));var Xm=n(()=>t.z.object({name:t.z.string().describe(`Flow machine name (snake_case)`)})),Zm=n(()=>Xm.extend({runId:t.z.string().describe(`Execution run ID`)})),Qm=n(()=>t.z.object({status:t.z.enum([`draft`,`active`,`obsolete`,`invalid`]).optional().describe(`Filter by flow status`),type:t.z.enum([`autolaunched`,`record_change`,`schedule`,`screen`,`api`]).optional().describe(`Filter by flow type`),limit:t.z.number().int().min(1).max(100).default(50).describe(`Maximum number of flows to return`),cursor:t.z.string().optional().describe(`Cursor for pagination`)})),$m=n(()=>t.z.object({name:t.z.string().describe(`Flow machine name`),label:t.z.string().describe(`Flow display label`),type:t.z.string().describe(`Flow type`),status:t.z.string().describe(`Flow deployment status`),version:t.z.number().int().describe(`Flow version number`),enabled:t.z.boolean().describe(`Whether the flow is enabled for execution`),nodeCount:t.z.number().int().optional().describe(`Number of nodes in the flow`),lastRunAt:t.z.string().datetime().optional().describe(`Last execution timestamp`)})),eh=n(()=>j.extend({data:t.z.object({flows:t.z.array($m).describe(`Flow summaries`),total:t.z.number().int().optional().describe(`Total matching flows`),nextCursor:t.z.string().optional().describe(`Cursor for the next page`),hasMore:t.z.boolean().describe(`Whether more flows are available`)})})),th=n(()=>Xm),nh=n(()=>j.extend({data:Bm.describe(`Full flow definition`)})),rh=n(()=>Bm),ih=n(()=>j.extend({data:Bm.describe(`The created flow definition`)})),ah=n(()=>Xm.extend({definition:Bm.partial().describe(`Partial flow definition to update`)})),oh=n(()=>j.extend({data:Bm.describe(`The updated flow definition`)})),sh=n(()=>Xm),ch=n(()=>j.extend({data:t.z.object({name:t.z.string().describe(`Name of the deleted flow`),deleted:t.z.boolean().describe(`Whether the flow was deleted`)})})),lh=n(()=>Xm.extend({record:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Record that triggered the automation`),object:t.z.string().optional().describe(`Object name the record belongs to`),event:t.z.string().optional().describe(`Trigger event type`),userId:t.z.string().optional().describe(`User who triggered the automation`),params:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Additional contextual data`)})),uh=n(()=>j.extend({data:t.z.object({success:t.z.boolean().describe(`Whether the automation completed successfully`),output:t.z.unknown().optional().describe(`Output data from the automation`),error:t.z.string().optional().describe(`Error message if execution failed`),durationMs:t.z.number().optional().describe(`Execution duration in milliseconds`)})})),dh=n(()=>Xm.extend({enabled:t.z.boolean().describe(`Whether to enable (true) or disable (false) the flow`)})),fh=n(()=>j.extend({data:t.z.object({name:t.z.string().describe(`Flow name`),enabled:t.z.boolean().describe(`New enabled state`)})})),ph=n(()=>Xm.extend({status:t.z.enum([`pending`,`running`,`paused`,`completed`,`failed`,`cancelled`,`timed_out`,`retrying`]).optional().describe(`Filter by execution status`),limit:t.z.number().int().min(1).max(100).default(20).describe(`Maximum number of runs to return`),cursor:t.z.string().optional().describe(`Cursor for pagination`)})),mh=n(()=>j.extend({data:t.z.object({runs:t.z.array(Jm).describe(`Execution run logs`),total:t.z.number().int().optional().describe(`Total matching runs`),nextCursor:t.z.string().optional().describe(`Cursor for the next page`),hasMore:t.z.boolean().describe(`Whether more runs are available`)})})),hh=n(()=>Zm),gh=n(()=>j.extend({data:Jm.describe(`Full execution log with step details`)})),_h=t.z.enum([`flow_not_found`,`flow_already_exists`,`flow_validation_failed`,`flow_disabled`,`execution_not_found`,`execution_failed`,`execution_timeout`,`node_executor_not_found`,`concurrent_execution_limit`]),vh={listFlows:{method:`GET`,path:`/api/automation`,input:Qm,output:eh},getFlow:{method:`GET`,path:`/api/automation/:name`,input:th,output:nh},createFlow:{method:`POST`,path:`/api/automation`,input:rh,output:ih},updateFlow:{method:`PUT`,path:`/api/automation/:name`,input:ah,output:oh},deleteFlow:{method:`DELETE`,path:`/api/automation/:name`,input:sh,output:ch},triggerFlow:{method:`POST`,path:`/api/automation/:name/trigger`,input:lh,output:uh},toggleFlow:{method:`POST`,path:`/api/automation/:name/toggle`,input:dh,output:fh},listRuns:{method:`GET`,path:`/api/automation/:name/runs`,input:ph,output:mh},getRun:{method:`GET`,path:`/api/automation/:name/runs/:runId`,input:hh,output:gh}},yh=n(()=>t.z.enum([`added`,`modified`,`removed`,`renamed`]).describe(`Type of metadata change between package versions`)),bh=n(()=>t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Metadata name`),changeType:yh.describe(`Category of metadata modification (added, modified, removed, or renamed)`),hasConflict:t.z.boolean().default(!1).describe(`Whether this change may conflict with customizations`),summary:t.z.string().optional().describe(`Human-readable change summary`),previousName:t.z.string().optional().describe(`Previous name if renamed`)}).describe(`Single metadata change between package versions`)),xh=n(()=>t.z.enum([`none`,`low`,`medium`,`high`,`critical`]).describe(`Severity of upgrade impact`)),Sh=n(()=>t.z.object({packageId:t.z.string().describe(`Package identifier`),fromVersion:t.z.string().describe(`Currently installed version`),toVersion:t.z.string().describe(`Target upgrade version`),impactLevel:xh.describe(`Severity assessment from none (seamless) to critical (breaking changes)`),changes:t.z.array(bh).describe(`All metadata changes`),affectedCustomizations:t.z.number().int().min(0).default(0).describe(`Count of customizations that may be affected`),requiresMigration:t.z.boolean().default(!1).describe(`Whether data migration scripts are needed`),migrationScripts:t.z.array(t.z.string()).optional().describe(`Paths to migration scripts`),dependencyUpgrades:t.z.array(t.z.object({packageId:t.z.string(),fromVersion:t.z.string(),toVersion:t.z.string()})).optional().describe(`Dependent packages that also need upgrading`),estimatedDuration:t.z.number().int().min(0).optional().describe(`Estimated upgrade duration in seconds`),summary:t.z.string().optional().describe(`Human-readable upgrade summary`)}).describe(`Upgrade analysis plan generated before execution`));n(()=>t.z.object({id:t.z.string().describe(`Snapshot identifier`),packageId:t.z.string().describe(`Package identifier`),fromVersion:t.z.string().describe(`Version before upgrade`),toVersion:t.z.string().describe(`Target upgrade version`),tenantId:t.z.string().optional().describe(`Tenant identifier`),previousManifest:Z.describe(`Complete manifest of the previous package version`),metadataSnapshot:t.z.array(t.z.object({type:t.z.string(),name:t.z.string(),metadata:t.z.record(t.z.string(),t.z.unknown())})).describe(`Snapshot of all package metadata`),customizationSnapshot:t.z.array(t.z.record(t.z.string(),t.z.unknown())).optional().describe(`Snapshot of customer customizations`),createdAt:t.z.string().datetime().describe(`Snapshot creation timestamp`),expiresAt:t.z.string().datetime().optional().describe(`Snapshot expiry timestamp`)}).describe(`Pre-upgrade state snapshot for rollback capability`)),n(()=>t.z.object({packageId:t.z.string().describe(`Package ID to upgrade`),targetVersion:t.z.string().optional().describe(`Target version (defaults to latest)`),manifest:Z.optional().describe(`New manifest (if installing from local)`),createSnapshot:t.z.boolean().default(!0).describe(`Whether to create a pre-upgrade backup snapshot`),mergeStrategy:t.z.enum([`keep-custom`,`accept-incoming`,`three-way-merge`]).default(`three-way-merge`).describe(`How to handle customer customizations`),dryRun:t.z.boolean().default(!1).describe(`Preview upgrade without making changes`),skipValidation:t.z.boolean().default(!1).describe(`Skip pre-upgrade compatibility checks`)}).describe(`Upgrade package request`));var Ch=n(()=>t.z.enum([`pending`,`analyzing`,`snapshot`,`executing`,`migrating`,`validating`,`completed`,`failed`,`rolling-back`,`rolled-back`]).describe(`Current phase of the upgrade process`));n(()=>t.z.object({success:t.z.boolean().describe(`Whether the upgrade succeeded`),phase:Ch.describe(`Current upgrade phase`),plan:Sh.optional().describe(`Upgrade plan`),snapshotId:t.z.string().optional().describe(`Snapshot ID for rollback`),conflicts:t.z.array(t.z.object({path:t.z.string(),baseValue:t.z.unknown(),incomingValue:t.z.unknown(),customValue:t.z.unknown()})).optional().describe(`Unresolved merge conflicts`),errorMessage:t.z.string().optional().describe(`Error message if upgrade failed`),message:t.z.string().optional().describe(`Human-readable status message`)}).describe(`Upgrade package response`)),n(()=>t.z.object({packageId:t.z.string().describe(`Package ID to rollback`),snapshotId:t.z.string().describe(`Snapshot ID to restore from`),rollbackCustomizations:t.z.boolean().default(!0).describe(`Whether to restore pre-upgrade customizations`)}).describe(`Rollback package request`)),n(()=>t.z.object({success:t.z.boolean().describe(`Whether the rollback succeeded`),restoredVersion:t.z.string().optional().describe(`Version restored to`),message:t.z.string().optional().describe(`Rollback status message`)}).describe(`Rollback package response`));var wh=t.z.enum([`objects`,`views`,`pages`,`flows`,`dashboards`,`permissions`,`agents`,`reports`,`actions`,`translations`,`themes`,`datasets`,`apis`,`triggers`,`workflows`]).describe(`Metadata category within the artifact`),Th=n(()=>t.z.object({path:t.z.string().describe(`Relative file path within the artifact`),size:t.z.number().int().nonnegative().describe(`File size in bytes`),category:wh.optional().describe(`Metadata category this file belongs to`)}).describe(`A single file entry within the artifact`)),Eh=n(()=>t.z.object({algorithm:t.z.enum([`sha256`,`sha384`,`sha512`]).default(`sha256`).describe(`Hash algorithm used for checksums`),files:t.z.record(t.z.string(),t.z.string().regex(/^[a-f0-9]+$/)).describe(`File path to hash value mapping`)}).describe(`Checksum manifest for artifact integrity verification`)),Dh=n(()=>t.z.object({algorithm:t.z.enum([`RSA-SHA256`,`RSA-SHA384`,`RSA-SHA512`,`ECDSA-SHA256`]).default(`RSA-SHA256`).describe(`Signing algorithm used`),publicKeyRef:t.z.string().describe(`Public key reference (URL or fingerprint) for signature verification`),signature:t.z.string().describe(`Base64-encoded digital signature`),signedAt:t.z.string().datetime().optional().describe(`ISO 8601 timestamp of when the artifact was signed`),signedBy:t.z.string().optional().describe(`Identity of the signer (publisher ID or email)`)}).describe(`Digital signature for artifact authenticity verification`)),Oh=n(()=>t.z.object({formatVersion:t.z.string().regex(/^\d+\.\d+$/).default(`1.0`).describe(`Artifact format version (e.g. "1.0")`),packageId:t.z.string().describe(`Package identifier from manifest`),version:t.z.string().describe(`Package version from manifest`),format:t.z.enum([`tgz`,`zip`]).default(`tgz`).describe(`Archive format of the artifact`),size:t.z.number().int().positive().optional().describe(`Total artifact file size in bytes`),builtAt:t.z.string().datetime().describe(`ISO 8601 timestamp of when the artifact was built`),builtWith:t.z.string().optional().describe(`Build tool identifier (e.g. "os-cli@3.2.0")`),files:t.z.array(Th).optional().describe(`List of files contained in the artifact`),metadataCategories:t.z.array(wh).optional().describe(`Metadata categories included in this artifact`),checksums:Eh.optional().describe(`SHA256 checksums for artifact integrity verification`),signature:Dh.optional().describe(`Digital signature for artifact authenticity verification`)}).describe(`Package artifact structure and metadata`)),kh=n(()=>t.z.enum([`private`,`org`,`marketplace`]).describe(`Package visibility: private = owner org only; org = all envs in owner org; marketplace = public registry`)),Ah=n(()=>t.z.string().min(1).describe(`Package category for marketplace discovery (e.g. "crm", "hr", "finance", "devtools")`)),jh=n(()=>t.z.enum([`objectstack`,`partner`,`community`,`private`]).describe(`Package publisher provenance tier`)),Mh=n(()=>t.z.string().regex(/^[a-z]{2,3}(-[A-Z]{2})?$/,`must be a BCP-47 locale (e.g. en, zh, zh-CN)`).describe(`BCP-47 locale tag`)),Nh=n(()=>t.z.object({displayName:t.z.string().min(1).max(128).optional().describe(`Localized display name`),description:t.z.string().max(512).optional().describe(`Localized short description`),readme:t.z.string().optional().describe(`Localized long-form readme (markdown)`),tagline:t.z.string().max(120).optional().describe(`Localized short tagline (marketplace listing only)`),screenshotCaptions:t.z.record(t.z.string(),t.z.string()).optional().describe(`Per-index screenshot caption overrides`)}).describe(`Per-locale overrides for a package listing`)),Ph=n(()=>t.z.record(Mh,Nh).describe(`Locale-keyed overrides; missing keys fall back to base columns`)),Fh=n(()=>t.z.object({id:t.z.string().uuid().describe(`UUID of the package (stable, never reused)`),manifestId:t.z.string().regex(/^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+$/).describe(`Globally unique reverse-domain package identifier (e.g. com.acme.crm)`),ownerOrgId:t.z.string().describe(`Organization ID of the package owner/publisher`),displayName:t.z.string().min(1).max(128).describe(`Display name shown in Studio and Marketplace`),description:t.z.string().max(512).optional().describe(`Short package description`),readme:t.z.string().optional().describe(`Long-form package documentation (markdown)`),visibility:kh.default(`private`),category:Ah.optional(),tags:t.z.array(t.z.string()).optional().describe(`Search and filter tags`),iconUrl:t.z.string().url().optional().describe(`Package icon URL`),homepageUrl:t.z.string().url().optional().describe(`Package homepage URL`),license:t.z.string().optional().describe(`SPDX license identifier (e.g. MIT, Apache-2.0)`),publisher:jh.default(`private`),isStarter:t.z.boolean().default(!1).describe(`If true, surfaces in the Create Project blueprint picker as a starter template`),translations:Ph.optional().describe(`Locale-keyed overrides for display_name / description / readme`),createdAt:t.z.string().datetime().describe(`Creation timestamp (ISO-8601)`),updatedAt:t.z.string().datetime().describe(`Last update timestamp (ISO-8601)`),createdBy:t.z.string().describe(`User ID that created the package`)}));n(()=>t.z.object({manifestId:Fh.shape.manifestId,ownerOrgId:t.z.string().describe(`Owner organization ID`),displayName:Fh.shape.displayName,description:Fh.shape.description,visibility:kh.optional(),category:Ah.optional(),tags:t.z.array(t.z.string()).optional(),iconUrl:t.z.string().url().optional(),homepageUrl:t.z.string().url().optional(),license:t.z.string().optional(),publisher:jh.optional(),isStarter:t.z.boolean().optional(),translations:Ph.optional(),createdBy:t.z.string().describe(`User ID creating the package`)}).describe(`Register a new package in the Control Plane`)),n(()=>t.z.object({displayName:Fh.shape.displayName.optional(),description:Fh.shape.description,readme:Fh.shape.readme,visibility:kh.optional(),category:Ah.optional(),tags:t.z.array(t.z.string()).optional(),iconUrl:t.z.string().url().optional(),homepageUrl:t.z.string().url().optional(),license:t.z.string().optional(),publisher:jh.optional(),isStarter:t.z.boolean().optional(),translations:Ph.optional()}).describe(`Update mutable package metadata`));var Ih=n(()=>t.z.enum([`unverified`,`pending`,`verified`,`trusted`,`partner`]).describe(`Publisher verification status`));n(()=>t.z.object({id:t.z.string().describe(`Publisher ID`),name:t.z.string().describe(`Publisher display name`),type:t.z.enum([`individual`,`organization`]).describe(`Publisher type`),verification:Ih.default(`unverified`).describe(`Publisher verification status`),email:t.z.string().email().optional().describe(`Contact email`),website:t.z.string().url().optional().describe(`Publisher website`),logoUrl:t.z.string().url().optional().describe(`Publisher logo URL`),description:t.z.string().optional().describe(`Publisher description`),registeredAt:t.z.string().datetime().optional().describe(`Publisher registration timestamp`)}).describe(`Developer or organization that publishes packages`));var Lh=n(()=>t.z.object({url:t.z.string().url().describe(`Artifact download URL`),sha256:t.z.string().regex(/^[a-f0-9]{64}$/).describe(`SHA256 checksum`),size:t.z.number().int().positive().describe(`Artifact size in bytes`),format:t.z.enum([`tgz`,`zip`]).default(`tgz`).describe(`Artifact format`),uploadedAt:t.z.string().datetime().describe(`Upload timestamp`)}).describe(`Reference to a downloadable package artifact`));n(()=>t.z.object({downloadUrl:t.z.string().url().describe(`Artifact download URL (may be pre-signed)`),sha256:t.z.string().regex(/^[a-f0-9]{64}$/).describe(`SHA256 checksum for verification`),size:t.z.number().int().positive().describe(`Artifact size in bytes`),format:t.z.enum([`tgz`,`zip`]).describe(`Artifact format`),expiresAt:t.z.string().datetime().optional().describe(`URL expiration timestamp for pre-signed URLs`)}).describe(`Artifact download response with integrity metadata`));var Rh=n(()=>t.z.enum([`crm`,`erp`,`hr`,`finance`,`project`,`collaboration`,`analytics`,`integration`,`automation`,`ai`,`security`,`developer-tools`,`ui-theme`,`storage`,`other`]).describe(`Marketplace package category`)),zh=n(()=>t.z.enum([`draft`,`submitted`,`in-review`,`approved`,`published`,`rejected`,`suspended`,`deprecated`,`unlisted`]).describe(`Marketplace listing status`)),Bh=n(()=>t.z.enum([`free`,`freemium`,`paid`,`subscription`,`usage-based`,`contact-sales`]).describe(`Package pricing model`)),Vh=n(()=>t.z.object({id:t.z.string().describe(`Listing ID (matches package manifest ID)`),packageId:t.z.string().describe(`Package identifier`),packageType:t.z.enum(Ls).default(`app`).describe("Consumer-installable package type (ADR-0019: only `app` is listable)"),publisherId:t.z.string().describe(`Publisher ID`),status:zh.default(`draft`).describe(`Publication state: draft, published, under-review, suspended, deprecated, or unlisted`),name:t.z.string().describe(`Display name`),tagline:t.z.string().max(120).optional().describe(`Short tagline (max 120 chars)`),description:t.z.string().optional().describe(`Full description (Markdown)`),category:Rh.describe(`Package category`),tags:t.z.array(t.z.string()).optional().describe(`Search tags`),iconUrl:t.z.string().url().optional().describe(`Package icon URL`),screenshots:t.z.array(t.z.object({url:t.z.string().url(),caption:t.z.string().optional()})).optional().describe(`Screenshots`),documentationUrl:t.z.string().url().optional().describe(`Documentation URL`),supportUrl:t.z.string().url().optional().describe(`Support URL`),repositoryUrl:t.z.string().url().optional().describe(`Source repository URL`),pricing:Bh.default(`free`).describe(`Pricing model`),priceInCents:t.z.number().int().min(0).optional().describe(`Price in cents (e.g. 999 = $9.99)`),latestVersion:t.z.string().describe(`Latest published version`),minPlatformVersion:t.z.string().optional().describe(`Minimum ObjectStack platform version`),versions:t.z.array(t.z.object({version:t.z.string().describe(`Version string`),releaseDate:t.z.string().datetime().describe(`Release date`),releaseNotes:t.z.string().optional().describe(`Release notes`),minPlatformVersion:t.z.string().optional().describe(`Minimum platform version`),deprecated:t.z.boolean().default(!1).describe(`Whether this version is deprecated`),artifact:Lh.optional().describe(`Downloadable artifact for this version`)})).optional().describe(`Published versions`),stats:t.z.object({totalInstalls:t.z.number().int().min(0).default(0).describe(`Total installs`),activeInstalls:t.z.number().int().min(0).default(0).describe(`Active installs`),averageRating:t.z.number().min(0).max(5).optional().describe(`Average user rating (0-5)`),totalRatings:t.z.number().int().min(0).default(0).describe(`Total ratings count`),totalReviews:t.z.number().int().min(0).default(0).describe(`Total reviews count`)}).optional().describe(`Aggregate marketplace statistics`),publishedAt:t.z.string().datetime().optional().describe(`First published timestamp`),updatedAt:t.z.string().datetime().optional().describe(`Last updated timestamp`),translations:Ph.optional().describe(`Locale-keyed overrides for name / tagline / description / screenshot captions`)}).describe(`Public-facing package listing on the marketplace`));n(()=>t.z.object({id:t.z.string().describe(`Submission ID`),packageId:t.z.string().describe(`Package identifier`),version:t.z.string().describe(`Version being submitted`),publisherId:t.z.string().describe(`Publisher submitting`),status:t.z.enum([`pending`,`scanning`,`in-review`,`changes-requested`,`approved`,`rejected`]).default(`pending`).describe(`Review status`),artifactUrl:t.z.string().describe(`Package artifact URL for review`),releaseNotes:t.z.string().optional().describe(`Release notes for this version`),isNewListing:t.z.boolean().default(!1).describe(`Whether this is a new listing submission`),scanResults:t.z.object({passed:t.z.boolean(),securityScore:t.z.number().min(0).max(100).optional(),compatibilityCheck:t.z.boolean().optional(),issues:t.z.array(t.z.object({severity:t.z.enum([`critical`,`high`,`medium`,`low`,`info`]),message:t.z.string(),file:t.z.string().optional(),line:t.z.number().optional()})).optional()}).optional().describe(`Automated scan results`),reviewerNotes:t.z.string().optional().describe(`Notes from the platform reviewer`),submittedAt:t.z.string().datetime().optional().describe(`Submission timestamp`),reviewedAt:t.z.string().datetime().optional().describe(`Review completion timestamp`)}).describe(`Developer submission of a package version for review`)),n(()=>t.z.object({query:t.z.string().optional().describe(`Full-text search query`),category:Rh.optional().describe(`Filter by category`),tags:t.z.array(t.z.string()).optional().describe(`Filter by tags`),pricing:Bh.optional().describe(`Filter by pricing model`),publisherVerification:Ih.optional().describe(`Filter by publisher verification level`),sortBy:t.z.enum([`relevance`,`popularity`,`rating`,`newest`,`updated`,`name`]).default(`relevance`).describe(`Sort field`),sortDirection:t.z.enum([`asc`,`desc`]).default(`desc`).describe(`Sort direction`),page:t.z.number().int().min(1).default(1).describe(`Page number`),pageSize:t.z.number().int().min(1).max(100).default(20).describe(`Items per page`),platformVersion:t.z.string().optional().describe(`Filter by platform version compatibility`)}).describe(`Marketplace search request`)),n(()=>t.z.object({items:t.z.array(Vh).describe(`Search result listings`),total:t.z.number().int().min(0).describe(`Total matching results`),page:t.z.number().int().min(1).describe(`Current page number`),pageSize:t.z.number().int().min(1).describe(`Items per page`),facets:t.z.object({categories:t.z.array(t.z.object({category:Rh,count:t.z.number().int().min(0)})).optional(),pricing:t.z.array(t.z.object({model:Bh,count:t.z.number().int().min(0)})).optional()}).optional().describe(`Aggregation facets for refining search`)}).describe(`Marketplace search response`)),n(()=>t.z.object({listingId:t.z.string().describe(`Marketplace listing ID`),version:t.z.string().optional().describe(`Version to install`),licenseKey:t.z.string().optional().describe(`License key for paid packages`),settings:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`User-provided settings at install time`),enableOnInstall:t.z.boolean().default(!0).describe(`Whether to enable immediately after install`),artifactRef:Lh.optional().describe(`Artifact reference for direct installation`),tenantId:t.z.string().optional().describe(`Tenant identifier`)}).describe(`Install from marketplace request`)),n(()=>t.z.object({success:t.z.boolean().describe(`Whether installation succeeded`),packageId:t.z.string().optional().describe(`Installed package identifier`),version:t.z.string().optional().describe(`Installed version`),message:t.z.string().optional().describe(`Installation status message`)}).describe(`Install from marketplace response`));var Hh=n(()=>t.z.object({packageId:t.z.string().describe(`Package identifier`)})),Uh=n(()=>t.z.object({status:t.z.enum([`installed`,`disabled`,`installing`,`upgrading`,`uninstalling`,`error`]).optional().describe(`Filter by package status`),enabled:t.z.boolean().optional().describe(`Filter by enabled state`),limit:t.z.number().int().min(1).max(100).default(50).describe(`Maximum number of packages to return`),cursor:t.z.string().optional().describe(`Cursor for pagination`)}).describe(`List installed packages request`)),Wh=n(()=>j.extend({data:t.z.object({packages:t.z.array(Q).describe(`Installed packages`),total:t.z.number().int().optional().describe(`Total matching packages`),nextCursor:t.z.string().optional().describe(`Cursor for the next page`),hasMore:t.z.boolean().describe(`Whether more packages are available`)})}).describe(`List installed packages response`)),Gh=n(()=>Hh),Kh=n(()=>j.extend({data:Q.describe(`Installed package details`)}).describe(`Get installed package response`)),qh=n(()=>t.z.object({manifest:Z.describe(`Package manifest to install`),settings:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`User-provided settings at install time`),enableOnInstall:t.z.boolean().default(!0).describe(`Whether to enable immediately after install`),platformVersion:t.z.string().optional().describe(`Current platform version for compatibility verification`),artifactRef:Lh.optional().describe(`Artifact reference for marketplace installation`)}).describe(`Install package request`)),Jh=n(()=>j.extend({data:t.z.object({package:Q.describe(`Installed package details`),dependencyResolution:Cc.optional().describe(`Dependency resolution result`),namespaceConflicts:t.z.array(t.z.object({type:t.z.literal(`namespace_conflict`).describe(`Error type`),requestedNamespace:t.z.string().describe(`Requested namespace`),conflictingPackageId:t.z.string().describe(`Conflicting package ID`),conflictingPackageName:t.z.string().describe(`Conflicting package name`),suggestion:t.z.string().optional().describe(`Suggested alternative`)})).optional().describe(`Namespace conflicts detected`),message:t.z.string().optional().describe(`Installation status message`)})}).describe(`Install package response`)),Yh=n(()=>t.z.object({packageId:t.z.string().describe(`Package ID to upgrade`),targetVersion:t.z.string().optional().describe(`Target version (defaults to latest)`),manifest:Z.optional().describe(`New manifest for the target version`),createSnapshot:t.z.boolean().default(!0).describe(`Whether to create a pre-upgrade backup snapshot`),mergeStrategy:t.z.enum([`keep-custom`,`accept-incoming`,`three-way-merge`]).default(`three-way-merge`).describe(`How to handle customer customizations`),dryRun:t.z.boolean().default(!1).describe(`Preview upgrade without making changes`),skipValidation:t.z.boolean().default(!1).describe(`Skip pre-upgrade compatibility checks`)}).describe(`Upgrade package request`)),Xh=n(()=>j.extend({data:t.z.object({success:t.z.boolean().describe(`Whether the upgrade succeeded`),phase:t.z.string().describe(`Current upgrade phase`),plan:Sh.optional().describe(`Upgrade plan that was executed`),snapshotId:t.z.string().optional().describe(`Snapshot ID for rollback`),conflicts:t.z.array(t.z.object({path:t.z.string().describe(`Conflict path`),baseValue:t.z.unknown().describe(`Base value`),incomingValue:t.z.unknown().describe(`Incoming value`),customValue:t.z.unknown().describe(`Custom value`)})).optional().describe(`Unresolved merge conflicts`),errorMessage:t.z.string().optional().describe(`Error message if failed`),message:t.z.string().optional().describe(`Human-readable status message`)})}).describe(`Upgrade package response`)),Zh=n(()=>t.z.object({manifest:Z.describe(`Package manifest to resolve dependencies for`),platformVersion:t.z.string().optional().describe(`Current platform version for compatibility filtering`)}).describe(`Resolve dependencies request`)),Qh=n(()=>j.extend({data:Cc.describe(`Dependency resolution result with topological sort`)}).describe(`Resolve dependencies response`)),$h=n(()=>t.z.object({artifact:Oh.describe(`Package artifact metadata`),sha256:t.z.string().regex(/^[a-f0-9]{64}$/).optional().describe(`SHA256 checksum of the uploaded file`),token:t.z.string().optional().describe(`Publisher authentication token`),releaseNotes:t.z.string().optional().describe(`Release notes for this version`)}).describe(`Upload artifact request`)),eg=n(()=>j.extend({data:t.z.object({success:t.z.boolean().describe(`Whether the upload succeeded`),artifactRef:Lh.optional().describe(`Artifact reference in the registry`),submissionId:t.z.string().optional().describe(`Marketplace submission ID for review tracking`),message:t.z.string().optional().describe(`Upload status message`)})}).describe(`Upload artifact response`)),tg=n(()=>Hh.extend({snapshotId:t.z.string().describe(`Snapshot ID to restore from`),rollbackCustomizations:t.z.boolean().default(!0).describe(`Whether to restore pre-upgrade customizations`)}).describe(`Rollback package request`)),ng=n(()=>j.extend({data:t.z.object({success:t.z.boolean().describe(`Whether the rollback succeeded`),restoredVersion:t.z.string().optional().describe(`Restored version`),message:t.z.string().optional().describe(`Rollback status message`)})}).describe(`Rollback package response`)),rg=n(()=>Hh),ig=n(()=>j.extend({data:t.z.object({packageId:t.z.string().describe(`Uninstalled package ID`),success:t.z.boolean().describe(`Whether uninstall succeeded`),message:t.z.string().optional().describe(`Uninstall status message`)})}).describe(`Uninstall package response`)),ag=t.z.enum([`package_not_found`,`package_already_installed`,`version_not_found`,`dependency_conflict`,`namespace_conflict`,`platform_incompatible`,`artifact_invalid`,`checksum_mismatch`,`signature_invalid`,`upgrade_failed`,`rollback_failed`,`snapshot_not_found`,`upload_failed`]),og={listPackages:{method:`GET`,path:`/api/v1/packages`,input:Uh,output:Wh},getPackage:{method:`GET`,path:`/api/v1/packages/:packageId`,input:Gh,output:Kh},installPackage:{method:`POST`,path:`/api/v1/packages/install`,input:qh,output:Jh},upgradePackage:{method:`POST`,path:`/api/v1/packages/upgrade`,input:Yh,output:Xh},resolveDependencies:{method:`POST`,path:`/api/v1/packages/resolve-dependencies`,input:Zh,output:Qh},uploadArtifact:{method:`POST`,path:`/api/v1/packages/upload`,input:$h,output:eg},rollbackPackage:{method:`POST`,path:`/api/v1/packages/:packageId/rollback`,input:tg,output:ng},uninstallPackage:{method:`DELETE`,path:`/api/v1/packages/:packageId`,input:rg,output:ig}};e.AckMessageSchema=On,e.AiAgentCapabilitiesSchema=Su,e.AiAgentChatRequestSchema=Tu,e.AiAgentSummarySchema=Cu,e.AiAgentsResponseSchema=wu,e.AiChatRequestSchema=fu,e.AiChatResponseSchema=pu,e.AiCompleteRequestSchema=mu,e.AiConversationSchema=gu,e.AiMessageSchema=du,e.AiModelsResponseSchema=hu,e.AiPendingActionSchema=Du,e.AiPendingActionStatusSchema=Eu,e.AiStreamChunkSchema=bu,e.AnalyticsEndpoint=vd,e.AnalyticsMetadataResponseSchema=Sd,e.AnalyticsQueryRequestSchema=yd,e.AnalyticsResultResponseSchema=bd,e.AnalyticsSqlResponseSchema=Cd,e.ApiChangelogEntrySchema=rd,e.ApiDocumentationConfig=sd,e.ApiDocumentationConfigSchema=ad,e.ApiEndpoint=dt,e.ApiEndpointSchema=lt,e.ApiErrorSchema=Ve,e.ApiMappingSchema=ct,e.ApiRoutesSchema=Rt,e.ApiTestCollection=cd,e.ApiTestCollectionSchema=nd,e.ApiTestRequestSchema=td,e.ApiTestingUiConfigSchema=ed,e.ApiTestingUiType=$u,e.AppDefinitionResponseSchema=Vf,e.ApproveAiPendingActionResponseSchema=Au,e.AuthEndpointAliases=Bd,e.AuthEndpointPaths=$,e.AuthEndpointSchema=zd,e.AuthFeaturesConfigSchema=Gd,e.AuthProvider=Ad,e.AuthProviderInfoSchema=Ud,e.AutomationActionsResponseSchema=zc,e.AutomationApiContracts=vh,e.AutomationApiErrorCode=_h,e.AutomationFlowPathParamsSchema=Xm,e.AutomationRunPathParamsSchema=Zm,e.AutomationTriggerRequestSchema=Lc,e.AutomationTriggerResponseSchema=Rc,e.BasePresenceSchema=nn,e.BaseResponseSchema=j,e.BatchApiContracts=Ir,e.BatchConfigSchema=Lr,e.BatchDataRequestSchema=pl,e.BatchDataResponseSchema=ml,e.BatchEndpointsConfigSchema=Uu,e.BatchLoadingStrategySchema=tt,e.BatchOperationResultSchema=Nr,e.BatchOperationType=Dr,e.BatchOptionsSchema=kr,e.BatchRecordSchema=Or,e.BatchUpdateRequestSchema=Ar,e.BatchUpdateResponseSchema=Pr,e.BulkDataEventSchema=$t,e.BulkDataEventType=Zt,e.BulkRequestSchema=Ke,e.BulkResponseSchema=Qe,e.CacheControlSchema=Ur,e.CacheDirective=Hr,e.CacheInvalidationRequestSchema=Jr,e.CacheInvalidationResponseSchema=Yr,e.CacheInvalidationTarget=qr,e.CapabilityDescriptorSchema=Wt,e.CheckPermissionRequestSchema=jl,e.CheckPermissionResponseSchema=Ml,e.CodeGenerationTemplateSchema=id,e.CompleteChunkedUploadRequestSchema=bf,e.CompleteChunkedUploadResponseSchema=xf,e.CompleteUploadRequestSchema=uf,e.ConceptListResponseSchema=Hf,e.ConflictResolutionStrategy=zn,e.CreateAiConversationRequestSchema=_u,e.CreateDataRequestSchema=sl,e.CreateDataResponseSchema=cl,e.CreateExportJobRequestSchema=Qp,e.CreateExportJobResponseSchema=$p,e.CreateFlowRequestSchema=rh,e.CreateFlowResponseSchema=ih,e.CreateImportJobRequestSchema=mm,e.CreateImportJobResponseSchema=hm,e.CreateManyDataRequestSchema=hl,e.CreateManyDataResponseSchema=gl,e.CreateRequestSchema=We,e.CreateViewRequestSchema=Tl,e.CreateViewResponseSchema=El,e.CrossObjectBatchDroppedFieldsSchema=Br,e.CrossObjectBatchOperationSchema=Rr,e.CrossObjectBatchRequestSchema=zr,e.CrossObjectBatchResponseSchema=Vr,e.CrudEndpointPatternSchema=Bu,e.CrudEndpointsConfigSchema=Vu,e.CrudOperation=zu,e.CursorMessageSchema=En,e.CursorPositionSchema=vn,e.DEFAULT_ANALYTICS_ROUTES=Rp,e.DEFAULT_AUTOMATION_ROUTES=zp,e.DEFAULT_BATCH_ROUTES=Fp,e.DEFAULT_DATA_CRUD_ROUTES=Pp,e.DEFAULT_DISCOVERY_ROUTES=Mp,e.DEFAULT_I18N_ROUTES=Lp,e.DEFAULT_METADATA_ROUTES=Np,e.DEFAULT_NOTIFICATION_ROUTES=Ip,e.DEFAULT_VERSIONING_CONFIG=kd,e.DataEventSchema=Qt,e.DataEventType=Xt,e.DataLoaderConfigSchema=et,e.DeduplicationStrategy=nm,e.DeleteDataRequestSchema=dl,e.DeleteDataResponseSchema=fl,e.DeleteFlowRequestSchema=sh,e.DeleteFlowResponseSchema=ch,e.DeleteManyDataRequestSchema=yl,e.DeleteManyDataResponseSchema=bl,e.DeleteManyRequestSchema=Fr,e.DeleteMetaItemRequestSchema=Xc,e.DeleteMetaItemResponseSchema=Zc,e.DeleteResponseSchema=$e,e.DeleteViewRequestSchema=kl,e.DeleteViewResponseSchema=Al,e.DeviceRequestResponseSchema=qd,e.DeviceTokenResponseSchema=Jd,e.DisablePackageRequestSchema=Fc,e.DisablePackageResponseSchema=Ic,e.DiscoveryEnvironmentSchema=zt,e.DiscoverySchema=Kt,e.DispatcherConfigSchema=gp,e.DispatcherErrorCode=_p,e.DispatcherErrorResponseSchema=vp,e.DispatcherRouteSchema=hp,e.DocumentStateSchema=xn,e.ERROR_CODE_LEDGER=ze,e.ETagSchema=Wr,e.EditMessageSchema=Dn,e.EditOperationSchema=bn,e.EditOperationType=yn,e.EmailPasswordConfigPublicSchema=Wd,e.EnablePackageRequestSchema=Nc,e.EnablePackageResponseSchema=Pc,e.EndpointMapping=Hd,e.EndpointRegistrySchema=qu,e.EnhancedApiErrorSchema=Le,e.ErrorCategory=ke,e.ErrorCode=A,e.ErrorHandlingConfigSchema=kp,e.ErrorHttpStatusMap=je,e.ErrorMessageSchema=kn,e.ErrorResponseSchema=Re,e.EventMessageSchema=wn,e.EventPatternSchema=fn,e.EventSubscriptionSchema=pn,e.ExportApiContracts=Am,e.ExportFormat=Xp,e.ExportImportTemplateSchema=om,e.ExportJobProgressSchema=em,e.ExportJobStatus=Zp,e.ExportJobSummarySchema=Em,e.ExportRequestSchema=qe,e.FieldErrorCode=Fe,e.FieldErrorSchema=Ie,e.FieldMappingEntrySchema=am,e.FileDownloadUrlResponseSchema=pf,e.FileTypeValidationSchema=hf,e.FileUploadResponseSchema=ff,e.FindDataRequestSchema=nl,e.FindDataResponseSchema=rl,e.FlowSummarySchema=$m,e.GeneratedApiDocumentationSchema=od,e.GeneratedEndpointSchema=Ku,e.GetAnalyticsMetaRequestSchema=xd,e.GetAuthConfigResponseSchema=Kd,e.GetDataRequestSchema=al,e.GetDataResponseSchema=ol,e.GetDiscoveryRequestSchema=Bc,e.GetDiscoveryResponseSchema=Vc,e.GetEffectivePermissionsRequestSchema=Fl,e.GetEffectivePermissionsResponseSchema=Il,e.GetExportJobDownloadRequestSchema=Cm,e.GetExportJobDownloadResponseSchema=wm,e.GetFieldLabelsRequestSchema=Iu,e.GetFieldLabelsResponseSchema=Lu,e.GetFlowRequestSchema=th,e.GetFlowResponseSchema=nh,e.GetInstalledPackageRequestSchema=Gh,e.GetInstalledPackageResponseSchema=Kh,e.GetLocalesRequestSchema=Mu,e.GetLocalesResponseSchema=Nu,e.GetMetaItemCachedRequestSchema=Qc,e.GetMetaItemCachedResponseSchema=$c,e.GetMetaItemRequestSchema=Kc,e.GetMetaItemResponseSchema=qc,e.GetMetaItemsRequestSchema=Wc,e.GetMetaItemsResponseSchema=Gc,e.GetMetaTypesRequestSchema=Hc,e.GetMetaTypesResponseSchema=Uc,e.GetNotificationPreferencesRequestSchema=eu,e.GetNotificationPreferencesResponseSchema=tu,e.GetObjectPermissionsRequestSchema=Nl,e.GetObjectPermissionsResponseSchema=Pl,e.GetPackageRequestSchema=Dc,e.GetPackageResponseSchema=Oc,e.GetPresenceRequestSchema=ql,e.GetPresenceResponseSchema=Jl,e.GetPresignedUrlRequestSchema=lf,e.GetRunRequestSchema=hh,e.GetRunResponseSchema=gh,e.GetTranslationsRequestSchema=Pu,e.GetTranslationsResponseSchema=Fu,e.GetUiViewRequestSchema=el,e.GetUiViewResponseSchema=tl,e.GetViewRequestSchema=Cl,e.GetViewResponseSchema=wl,e.HandlerStatusSchema=Cp,e.HttpFindQueryParamsSchema=il,e.HttpMethod=P,e.HttpStatusErrorCodeMap=Me,e.IMPORT_JOB_MAX_ROWS=fm,e.IdRequestSchema=Xe,e.ImportJobApiContracts=jm,e.ImportJobProgressSchema=gm,e.ImportJobResultsSchema=_m,e.ImportJobStatus=pm,e.ImportJobSummarySchema=ym,e.ImportMappingSchema=cm,e.ImportRequestSchema=lm,e.ImportResponseSchema=dm,e.ImportRowResultSchema=um,e.ImportValidationConfigSchema=rm,e.ImportValidationMode=tm,e.ImportValidationResultSchema=im,e.ImportWriteMode=sm,e.InitiateChunkedUploadRequestSchema=gf,e.InitiateChunkedUploadResponseSchema=_f,e.InstallPackageRequestSchema=kc,e.InstallPackageResponseSchema=Ac,e.ListAiConversationsRequestSchema=vu,e.ListAiConversationsResponseSchema=yu,e.ListAiPendingActionsRequestSchema=Ou,e.ListAiPendingActionsResponseSchema=ku,e.ListExportJobsRequestSchema=Tm,e.ListExportJobsResponseSchema=Dm,e.ListFlowsRequestSchema=Qm,e.ListFlowsResponseSchema=eh,e.ListImportJobsRequestSchema=vm,e.ListImportJobsResponseSchema=bm,e.ListInstalledPackagesRequestSchema=Uh,e.ListInstalledPackagesResponseSchema=Wh,e.ListNotificationsRequestSchema=au,e.ListNotificationsResponseSchema=ou,e.ListPackagesRequestSchema=Tc,e.ListPackagesResponseSchema=Ec,e.ListRecordResponseSchema=Ye,e.ListRunsRequestSchema=ph,e.ListRunsResponseSchema=mh,e.ListViewsRequestSchema=xl,e.ListViewsResponseSchema=Sl,e.LoginRequestSchema=Pd,e.LoginType=Nd,e.MarkAllNotificationsReadRequestSchema=lu,e.MarkAllNotificationsReadResponseSchema=uu,e.MarkNotificationsReadRequestSchema=su,e.MarkNotificationsReadResponseSchema=cu,e.MetadataBulkRegisterRequestSchema=Zf,e.MetadataBulkResponseSchema=$f,e.MetadataBulkUnregisterRequestSchema=Qf,e.MetadataCacheApi=Xr,e.MetadataCacheRequestSchema=Gr,e.MetadataCacheResponseSchema=Kr,e.MetadataDeleteResponseSchema=Jf,e.MetadataDependenciesResponseSchema=dp,e.MetadataDependentsResponseSchema=fp,e.MetadataEffectiveResponseSchema=np,e.MetadataEndpointsConfigSchema=Hu,e.MetadataEventSchema=F,e.MetadataEventType=Yt,e.MetadataExistsResponseSchema=qf,e.MetadataExportRequestSchema=rp,e.MetadataExportResponseSchema=ip,e.MetadataImportRequestSchema=ap,e.MetadataImportResponseSchema=op,e.MetadataItemResponseSchema=Wf,e.MetadataListResponseSchema=Gf,e.MetadataNamesResponseSchema=Kf,e.MetadataOverlayResponseSchema=ep,e.MetadataOverlaySaveRequestSchema=tp,e.MetadataQueryRequestSchema=Yf,e.MetadataQueryResponseSchema=Xf,e.MetadataRegisterRequestSchema=Uf,e.MetadataTypeInfoResponseSchema=up,e.MetadataTypesResponseSchema=lp,e.MetadataValidateRequestSchema=sp,e.MetadataValidateResponseSchema=cp,e.ModificationResultSchema=Ze,e.NotificationPreferencesSchema=$l,e.NotificationSchema=iu,e.OData=qn,e.ODataConfigSchema=Jn,e.ODataErrorSchema=Gn,e.ODataFilterFunctionSchema=Un,e.ODataMetadataSchema=Kn,e.ODataQueryAdapterSchema=Jp,e.ODataQuerySchema=Hn,e.ODataResponseSchema=Wn,e.ObjectDefinitionResponseSchema=Bf,e.OpenApiGenerationConfigSchema=Ap,e.OpenApiSecuritySchemeSchema=Zu,e.OpenApiServerSchema=Xu,e.OpenApiSpec=ld,e.OpenApiSpecSchema=Qu,e.OperatorMappingSchema=Kp,e.PackageApiContracts=og,e.PackageApiErrorCode=ag,e.PackageInstallRequestSchema=qh,e.PackageInstallResponseSchema=Jh,e.PackagePathParamsSchema=Hh,e.PackageRollbackRequestSchema=tg,e.PackageRollbackResponseSchema=ng,e.PackageUpgradeRequestSchema=Yh,e.PackageUpgradeResponseSchema=Xh,e.PingMessageSchema=An,e.PongMessageSchema=jn,e.PresenceMessageSchema=Tn,e.PresenceStateSchema=gn,e.PresenceStatus=en,e.PresenceUpdateSchema=_n,e.PresignedUrlResponseSchema=df,e.QueryAdapterConfigSchema=Yp,e.QueryAdapterTargetSchema=Gp,e.QueryOptimizationConfigSchema=nt,e.REGISTERED_ERROR_CODES=Be,e.RawUploadResponseSchema=mf,e.RealtimeConfigSchema=un,e.RealtimeConnectRequestSchema=Ll,e.RealtimeConnectResponseSchema=Rl,e.RealtimeDisconnectRequestSchema=zl,e.RealtimeDisconnectResponseSchema=Bl,e.RealtimeEventSchema=ln,e.RealtimeEventType=an,e.RealtimePresenceSchema=cn,e.RealtimeRecordAction=tn,e.RealtimeSubscribeRequestSchema=Vl,e.RealtimeSubscribeResponseSchema=Hl,e.RealtimeUnsubscribeRequestSchema=Ul,e.RealtimeUnsubscribeResponseSchema=Wl,e.RecordDataSchema=M,e.RefreshTokenRequestSchema=Id,e.RegisterDeviceRequestSchema=Yl,e.RegisterDeviceResponseSchema=Xl,e.RegisterRequestSchema=Fd,e.RejectAiPendingActionResponseSchema=ju,e.RequestValidationConfigSchema=Dp,e.ResolveDependenciesRequestSchema=Zh,e.ResolveDependenciesResponseSchema=Qh,e.ResponseEnvelopeConfigSchema=Op,e.RestApiConfig=Ju,e.RestApiConfigSchema=Ru,e.RestApiEndpointSchema=wp,e.RestApiPluginConfig=Bp,e.RestApiPluginConfigSchema=jp,e.RestApiRouteCategory=Sp,e.RestApiRouteRegistration=Vp,e.RestApiRouteRegistrationSchema=Tp,e.RestQueryAdapterSchema=qp,e.RestServerConfig=Yu,e.RestServerConfigSchema=Gu,e.RetryStrategy=Pe,e.RouteCategory=Rn,e.RouteCoverageEntrySchema=Up,e.RouteCoverageReportSchema=Wp,e.RouteDefinitionSchema=Bn,e.RouteGenerationConfigSchema=Wu,e.RouteHealthEntrySchema=qt,e.RouteHealthReportSchema=Jt,e.RouterConfigSchema=Vn,e.SERVICE_SELF_INFO_KEY=Ft,e.SaveMetaItemRequestSchema=Jc,e.SaveMetaItemResponseSchema=Yc,e.ScheduleExportRequestSchema=Om,e.ScheduleExportResponseSchema=km,e.ScheduledExportSchema=Sm,e.ServiceInfoSchema=Pt,e.ServiceSelfInfoSchema=It,e.ServiceStatus=Nt,e.SessionResponseSchema=Ld,e.SessionSchema=Md,e.SessionUserSchema=jd,e.SetPresenceRequestSchema=Gl,e.SetPresenceResponseSchema=Kl,e.SimpleCursorPositionSchema=In,e.SimplePresenceStateSchema=Fn,e.SingleRecordResponseSchema=Je,e.StandardApiContracts=N,e.StandardErrorCode=Ae,e.StorageApiContracts=Cf,e.SubscribeMessageSchema=Sn,e.SubscriptionEventSchema=on,e.SubscriptionSchema=sn,e.ToggleFlowRequestSchema=dh,e.ToggleFlowResponseSchema=fh,e.TransportProtocol=rn,e.TriggerFlowRequestSchema=lh,e.TriggerFlowResponseSchema=uh,e.UndoImportJobResponseSchema=xm,e.UninstallPackageApiRequestSchema=rg,e.UninstallPackageApiResponseSchema=ig,e.UninstallPackageRequestSchema=jc,e.UninstallPackageResponseSchema=Mc,e.UnregisterDeviceRequestSchema=Zl,e.UnregisterDeviceResponseSchema=Ql,e.UnsubscribeMessageSchema=Cn,e.UnsubscribeRequestSchema=mn,e.UpdateAiConversationRequestSchema=xu,e.UpdateDataRequestSchema=ll,e.UpdateDataResponseSchema=ul,e.UpdateFlowRequestSchema=ah,e.UpdateFlowResponseSchema=oh,e.UpdateManyDataRequestSchema=_l,e.UpdateManyDataResponseSchema=vl,e.UpdateManyRecordSchema=jr,e.UpdateManyRequestSchema=Mr,e.UpdateNotificationPreferencesRequestSchema=nu,e.UpdateNotificationPreferencesResponseSchema=ru,e.UpdateRequestSchema=Ge,e.UpdateViewRequestSchema=Dl,e.UpdateViewResponseSchema=Ol,e.UploadArtifactRequestSchema=$h,e.UploadArtifactResponseSchema=eg,e.UploadChunkRequestSchema=vf,e.UploadChunkResponseSchema=yf,e.UploadProgressSchema=Sf,e.UserProfileResponseSchema=Rd,e.ValidationMode=Ep,e.VersionDefinitionSchema=Ed,e.VersionNegotiationResponseSchema=Od,e.VersionStatus=Td,e.VersioningConfigSchema=Dd,e.VersioningStrategy=wd,e.WELL_KNOWN_CAPABILITY_KEYS=Ut,e.WebSocketConfigSchema=Nn,e.WebSocketEventSchema=Pn,e.WebSocketMessageSchema=Mn,e.WebSocketMessageType=dn,e.WebSocketPresenceStatus=hn,e.WebSocketServerConfigSchema=Ln,e.WellKnownCapabilitiesSchema=Ht,e.envelopeViolations=Ue,e.getAuthEndpointUrl=Vd,e.getDefaultRouteRegistrations=Hp,e.identityFreeEndpointGateFailure=Ct,e.normalizeEndpointPath=ut,e.readServiceSelfInfo=Lt,e.resolveDiscoveryEnvironment=Vt,e.standardErrorCodeForHttpStatus=Ne,e.validateApiEndpointDeclarations=St})),l=e(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,l=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},u=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!o.call(e,c)&&c!==a&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},d=e=>u(n({},`__esModule`,{value:!0}),e),f={};l(f,{FilterBuilder:()=>g,ObjectStackClient:()=>ae,QueryBuilder:()=>_,RealtimeAPI:()=>h,ScopedProjectClient:()=>b,createFilter:()=>y,createQuery:()=>v}),t.exports=d(f);var ee=s(),p=c(),te=a(),m=c(),h=class{constructor(e,t){this.subscriptions=new Map,this.eventBuffer=[],this._baseUrl=e,this._token=t}subscribeMetadata(e,t,n){let r=`metadata-${e}-${Date.now()}`;return this.subscriptions.set(r,{filter:{type:e,packageId:n?.packageId,eventTypes:[`metadata.${e}.created`,`metadata.${e}.updated`,`metadata.${e}.deleted`]},handler:n=>{if(!n.type.startsWith(`metadata.`))return;let r=m.MetadataEventSchema.safeParse(n.payload);if(!r.success)throw Error(`subscribeMetadata('${e}'): event '${n.type}' payload does not satisfy MetadataEventSchema \u2014 rejecting off-contract event (fix the producer): ${r.error.message}`);t(r.data)}}),this.startPolling(),()=>{this.subscriptions.delete(r),this.subscriptions.size===0&&this.stopPolling()}}subscribeData(e,t,n){let r=`data-${e}-${Date.now()}`;return this.subscriptions.set(r,{filter:{type:e,recordId:n?.recordId,eventTypes:[`data.record.created`,`data.record.updated`,`data.record.deleted`]},handler:r=>{if(!r.type.startsWith(`data.`)||r.object!==e||r.type.startsWith(`data.records.`))return;let i=m.DataEventSchema.safeParse(r.payload);if(!i.success)throw Error(`subscribeData('${e}'): event '${r.type}' payload does not satisfy DataEventSchema \u2014 rejecting off-contract event (fix the producer): ${i.error.message}`);n?.recordId&&i.data.recordId!==n.recordId||t(i.data)}}),this.startPolling(),()=>{this.subscriptions.delete(r),this.subscriptions.size===0&&this.stopPolling()}}subscribeBulkData(e,t){let n=`bulk-data-${e}-${Date.now()}`;return this.subscriptions.set(n,{filter:{type:e,eventTypes:[`data.records.updated`,`data.records.deleted`]},handler:n=>{if(!n.type.startsWith(`data.records.`)||n.object!==e)return;let r=m.BulkDataEventSchema.safeParse(n.payload);if(!r.success)throw Error(`subscribeBulkData('${e}'): event '${n.type}' payload does not satisfy BulkDataEventSchema \u2014 rejecting off-contract event (fix the producer): ${r.error.message}`);t(r.data)}}),this.startPolling(),()=>{this.subscriptions.delete(n),this.subscriptions.size===0&&this.stopPolling()}}emitEvent(e){for(let t of this.subscriptions.values()){let n=!t.filter.type||e.type.includes(t.filter.type)||e.object===t.filter.type,r=!t.filter.eventTypes?.length||t.filter.eventTypes.includes(e.type),i=!t.filter.packageId||e.payload?.packageId===t.filter.packageId;if(n&&r&&i)try{t.handler(e)}catch(e){console.error(`Error in realtime event handler:`,e)}}}startPolling(){this.pollInterval||=setInterval(()=>{for(;this.eventBuffer.length>0;){let e=this.eventBuffer.shift();e&&this.emitEvent(e)}},2e3)}stopPolling(){this.pollInterval&&=(clearInterval(this.pollInterval),void 0)}_bufferEvent(e){this.eventBuffer.push(e)}disconnect(){this.stopPolling(),this.subscriptions.clear(),this.eventBuffer=[]}},g=class{constructor(){this.conditions=[]}equals(e,t){return this.conditions.push([e,`=`,t]),this}notEquals(e,t){return this.conditions.push([e,`!=`,t]),this}greaterThan(e,t){return this.conditions.push([e,`>`,t]),this}greaterThanOrEqual(e,t){return this.conditions.push([e,`>=`,t]),this}lessThan(e,t){return this.conditions.push([e,`<`,t]),this}lessThanOrEqual(e,t){return this.conditions.push([e,`<=`,t]),this}in(e,t){return this.conditions.push([e,`in`,t]),this}notIn(e,t){return this.conditions.push([e,`not_in`,t]),this}like(e,t){return this.conditions.push([e,`like`,t]),this}isNull(e){return this.conditions.push([e,`is_null`,null]),this}isNotNull(e){return this.conditions.push([e,`is_not_null`,null]),this}between(e,t,n){return this.conditions.push([`and`,[e,`>=`,t],[e,`<=`,n]]),this}contains(e,t){return this.conditions.push([e,`like`,`%${t}%`]),this}startsWith(e,t){return this.conditions.push([e,`like`,`${t}%`]),this}endsWith(e,t){return this.conditions.push([e,`like`,`%${t}`]),this}exists(e){return this.conditions.push([e,`is_not_null`,null]),this}build(){if(this.conditions.length===0)throw Error(`Filter builder has no conditions`);return this.conditions.length===1?this.conditions[0]:[`and`,...this.conditions]}getConditions(){return this.conditions}},_=class{constructor(e){this.query={},this._object=e,this.query.object=e}select(...e){return this.query.fields=e,this}where(e){let t=new g;e(t);let n=t.getConditions();return n.length===1?this.query.where=n[0]:n.length>1&&(this.query.where=[`and`,...n]),this}filter(e){return this.query.where=e,this}orderBy(e,t=`asc`){return this.query.orderBy||(this.query.orderBy=[]),this.query.orderBy.push({field:e,order:t}),this}limit(e){return this.query.limit=e,this}skip(e){return this.query.offset=e,this}offset(e){return this.query.offset=e,this}paginate(e,t){return this.query.limit=t,this.query.offset=(e-1)*t,this}groupBy(...e){return this.query.groupBy=e,this}expand(e,t){return this.query.expand||(this.query.expand={}),this.query.expand[e]=t||{},this}search(e,t){return this.query.search={query:e,...t},this}build(){return{object:this._object,...this.query}}getQuery(){return{...this.query}}};function v(e){return new _(e)}function y(){return new g}async function*ne(e){let t=e.body;if(!t)throw Error("Streaming response carried no body — this runtime's fetch does not expose `Response.body`");let n=new TextDecoder,r=``,i=function*(e){r+=e;let t;for(;(t=r.indexOf(`
|
|
32
|
+
`))!==-1;){let e=r.slice(0,t).trim();if(r=r.slice(t+1),!e.startsWith(`data:`))continue;let n=e.slice(5).trim();if(!(!n||n===`[DONE]`))try{yield JSON.parse(n)}catch{}}};if(typeof t.getReader==`function`){let e=t.getReader();try{for(;;){let{done:t,value:r}=await e.read();if(t)break;yield*i(n.decode(r,{stream:!0}))}}finally{e.releaseLock?.()}}else for await(let e of t)yield*i(n.decode(e,{stream:!0}));yield*i(n.decode())}function re(e){return typeof e==`string`&&e?e:typeof e?.message==`string`&&e.message?e.message:`Action failed`}function ie(e){let t=new Set([`success`,`data`,`error`,`code`,`fields`]);return e&&typeof e==`object`&&!Array.isArray(e)&&typeof e.success==`boolean`&&Object.keys(e).every(e=>t.has(e))?e.success===!1?{success:!1,error:re(e.error)}:{success:!0,data:e.data}:{success:!0,data:e}}var ae=class{constructor(e){this.meta={getTypes:async()=>{let e=this.getRoute(`metadata`),t=await this.fetch(`${this.baseUrl}${e}`);return this.unwrapResponse(t)},getItems:async(e,t)=>{let n=this.getRoute(`metadata`),r=new URLSearchParams;t?.packageId&&r.set(`package`,t.packageId);let i=r.toString(),a=`${this.baseUrl}${n}/${e}${i?`?${i}`:``}`,o=await this.fetch(a);return this.unwrapResponse(o)},getItem:async(e,t,n)=>{let r=this.getRoute(`metadata`),i=new URLSearchParams;n?.packageId&&i.set(`package`,n.packageId);let a=i.toString(),o=`${this.baseUrl}${r}/${e}/${t}${a?`?${a}`:``}`,s=await this.fetch(o);return this.unwrapResponse(s)},saveItem:async(e,t,n)=>{let r=this.getRoute(`metadata`),i=await this.fetch(`${this.baseUrl}${r}/${e}/${t}`,{method:`PUT`,body:JSON.stringify(n)});return this.unwrapResponse(i)},deleteItem:async(e,t)=>{let n=this.getRoute(`metadata`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:`DELETE`});return this.unwrapResponse(r)},getHistory:async(e,t,n)=>{let r=this.getRoute(`metadata`),i=new URLSearchParams;n?.sinceSeq!==void 0&&i.set(`sinceSeq`,String(n.sinceSeq)),n?.limit!==void 0&&i.set(`limit`,String(n.limit));let a=i.toString(),o=`${this.baseUrl}${r}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/history${a?`?${a}`:``}`,s=await this.fetch(o);return this.unwrapResponse(s)},getCached:async(e,t)=>{let n=this.getRoute(`metadata`),r={};t?.ifNoneMatch&&(r[`If-None-Match`]=t.ifNoneMatch),t?.ifModifiedSince&&(r[`If-Modified-Since`]=t.ifModifiedSince);let i=await this.fetch(`${this.baseUrl}${n}/object/${e}`,{headers:r});if(i.status===304)return{notModified:!0,etag:t?.ifNoneMatch?{value:t.ifNoneMatch.replace(/^W\/|"/g,``),weak:t.ifNoneMatch.startsWith(`W/`)}:void 0};let a=await i.json(),o=i.headers.get(`ETag`),s=i.headers.get(`Last-Modified`);return{data:a,etag:o?{value:o.replace(/^W\/|"/g,``),weak:o.startsWith(`W/`)}:void 0,lastModified:s||void 0,notModified:!1}},getView:async(e,t=`list`)=>{let n=this.getRoute(`ui`),r=await this.fetch(`${this.baseUrl}${n}/view/${encodeURIComponent(e)}/${t}`);return this.unwrapResponse(r)},getPublished:async(e,t)=>{let n=this.getRoute(`metadata`),r=await this.fetch(`${this.baseUrl}${n}/${e}/${t}/published`);return this.unwrapResponse(r)},listDrafts:async e=>{let t=this.getRoute(`metadata`),n=new URLSearchParams;e?.packageId&&n.set(`packageId`,e.packageId),e?.type&&n.set(`type`,e.type);let r=n.toString(),i=await this.fetch(`${this.baseUrl}${t}/_drafts${r?`?${r}`:``}`);return this.unwrapResponse(i)},migrateStored:async e=>{let t=this.getRoute(`metadata`),n=await this.fetch(`${this.baseUrl}${t}/_migrate-stored`,{method:`POST`,body:JSON.stringify({...e?.apply===!0?{apply:!0}:{},...e?.types&&e.types.length>0?{types:e.types}:{}})});return this.unwrapResponse(n)},getLegalNextStates:async(e,t,n)=>{let r=this.getRoute(`metadata`),i=n===void 0?``:`?from=${encodeURIComponent(n)}`,a=await this.fetch(`${this.baseUrl}${r}/objects/${encodeURIComponent(e)}/state/${encodeURIComponent(t)}${i}`);return this.unwrapResponse(a)},getDiagnostics:async e=>{let t=this.getRoute(`metadata`),n=new URLSearchParams;e?.type&&n.set(`type`,e.type),e?.severity&&n.set(`severity`,e.severity),e?.packageId&&n.set(`package`,e.packageId);let r=n.toString(),i=await this.fetch(`${this.baseUrl}${t}/diagnostics${r?`?${r}`:``}`);return this.unwrapResponse(i)},getReferences:async(e,t)=>{let n=this.getRoute(`metadata`),r=await this.fetch(`${this.baseUrl}${n}/${e}/${t}/references`);return this.unwrapResponse(r)},getBookTree:async(e,t)=>{let n=this.getRoute(`metadata`),r=t?.packageId?`?package=${encodeURIComponent(t.packageId)}`:``,i=await this.fetch(`${this.baseUrl}${n}/book/${encodeURIComponent(e)}/tree${r}`);return this.unwrapResponse(i)},getAudit:async(e,t,n)=>{let r=this.getRoute(`metadata`),i=n?.limit===void 0?``:`?limit=${n.limit}`,a=await this.fetch(`${this.baseUrl}${r}/${e}/${t}/audit${i}`);return this.unwrapResponse(a)},publishItem:async(e,t,n)=>{let r=this.getRoute(`metadata`),i=await this.fetch(`${this.baseUrl}${r}/${e}/${t}/publish`,{method:`POST`,body:JSON.stringify(n?.message?{message:n.message}:{})});return this.unwrapResponse(i)},rollbackItem:async(e,t,n,r)=>{let i=this.getRoute(`metadata`),a=await this.fetch(`${this.baseUrl}${i}/${e}/${t}/rollback`,{method:`POST`,body:JSON.stringify({toVersion:n,...r?.message?{message:r.message}:{}})});return this.unwrapResponse(a)},diffItem:async(e,t,n)=>{let r=this.getRoute(`metadata`),i=new URLSearchParams;n?.from!==void 0&&i.set(`from`,String(n.from)),n?.to!==void 0&&i.set(`to`,String(n.to));let a=i.toString(),o=await this.fetch(`${this.baseUrl}${r}/${e}/${t}/diff${a?`?${a}`:``}`);return this.unwrapResponse(o)}},this.analytics={query:async e=>{let t=this.getRoute(`analytics`);return(await this.fetch(`${this.baseUrl}${t}/query`,{method:`POST`,body:JSON.stringify(e)})).json()},meta:async e=>{let t=this.getRoute(`analytics`),n=e?`?cube=${encodeURIComponent(e)}`:``;return(await this.fetch(`${this.baseUrl}${t}/meta${n}`)).json()},explain:async e=>{let t=this.getRoute(`analytics`);return(await this.fetch(`${this.baseUrl}${t}/sql`,{method:`POST`,body:JSON.stringify(e)})).json()},queryDataset:async e=>{let t=this.getRoute(`analytics`);return(await this.fetch(`${this.baseUrl}${t}/dataset/query`,{method:`POST`,body:JSON.stringify(e)})).json()}},this.email={send:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/email/send`,{method:`POST`,body:JSON.stringify(e)});return this.unwrapResponse(t)}},this.datasources={external:{listTables:async(e,t)=>{let n=t?.schema?`?schema=${encodeURIComponent(t.schema)}`:``,r=await this.fetch(`${this.baseUrl}/api/v1/datasources/${encodeURIComponent(e)}/external/tables${n}`);return this.unwrapResponse(r)},draft:async(e,t,n)=>{let r=await this.fetch(`${this.baseUrl}/api/v1/datasources/${encodeURIComponent(e)}/external/tables/${encodeURIComponent(t)}/draft`,{method:`POST`,body:JSON.stringify(n??{})});return this.unwrapResponse(r)},import:async(e,t,n)=>{let r=await this.fetch(`${this.baseUrl}/api/v1/datasources/${encodeURIComponent(e)}/external/tables/${encodeURIComponent(t)}/import`,{method:`POST`,body:JSON.stringify(n??{})});return this.unwrapResponse(r)},refreshCatalog:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/datasources/${encodeURIComponent(e)}/external/refresh-catalog`,{method:`POST`,body:JSON.stringify({})});return this.unwrapResponse(t)},validate:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/datasources/${encodeURIComponent(e)}/external/validate`,{method:`POST`,body:JSON.stringify({})});return this.unwrapResponse(t)}}},this.packages={list:async e=>{let t=this.getRoute(`packages`),n=new URLSearchParams;e?.status&&n.set(`status`,e.status),e?.type&&n.set(`type`,e.type),e?.enabled!==void 0&&n.set(`enabled`,String(e.enabled));let r=n.toString(),i=`${this.baseUrl}${t}${r?`?`+r:``}`,a=await this.fetch(i);return this.unwrapResponse(a)},get:async e=>{let t=this.getRoute(`packages`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}`);return this.unwrapResponse(n)},install:async(e,t)=>{let n=this.getRoute(`packages`),r=await this.fetch(`${this.baseUrl}${n}`,{method:`POST`,body:JSON.stringify({manifest:e,settings:t?.settings,enableOnInstall:t?.enableOnInstall,...t?.overwrite===void 0?{}:{overwrite:t.overwrite}})});return this.unwrapResponse(r)},uninstall:async e=>{let t=this.getRoute(`packages`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}`,{method:`DELETE`});return this.unwrapResponse(n)},enable:async e=>{let t=this.getRoute(`packages`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}/enable`,{method:`PATCH`});return this.unwrapResponse(n)},disable:async e=>{let t=this.getRoute(`packages`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}/disable`,{method:`PATCH`});return this.unwrapResponse(n)},update:async(e,t)=>{let n=this.getRoute(`packages`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify(t)});return this.unwrapResponse(r)},publish:async(e,t)=>{let n=this.getRoute(`packages`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/publish`,{method:`POST`,body:JSON.stringify(t??{})});return this.unwrapResponse(r)},publishDrafts:async(e,t)=>{let n=this.getRoute(`packages`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/publish-drafts`,{method:`POST`,body:JSON.stringify(t??{})});return this.unwrapResponse(r)},discardDrafts:async(e,t)=>{let n=this.getRoute(`packages`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/discard-drafts`,{method:`POST`,body:JSON.stringify(t??{})});return this.unwrapResponse(r)},listCommits:async e=>{let t=this.getRoute(`packages`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}/commits`);return this.unwrapResponse(n)},revertCommit:async(e,t,n)=>{let r=this.getRoute(`packages`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/commits/${encodeURIComponent(t)}/revert`,{method:`POST`,body:JSON.stringify(n??{})});return this.unwrapResponse(i)},rollback:async(e,t,n)=>{let r=this.getRoute(`packages`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/rollback`,{method:`POST`,body:JSON.stringify({commitId:t,...n??{}})});return this.unwrapResponse(i)},revert:async e=>{let t=this.getRoute(`packages`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}/revert`,{method:`POST`});return this.unwrapResponse(n)},export:async e=>{let t=this.getRoute(`packages`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}/export`);return this.unwrapResponse(n)},adoptOrphans:async(e,t)=>{let n=this.getRoute(`packages`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/adopt-orphans`,{method:`POST`,body:JSON.stringify(t??{})});return this.unwrapResponse(r)},duplicate:async(e,t,n)=>{let r=this.getRoute(`packages`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/duplicate`,{method:`POST`,body:JSON.stringify({targetPackageId:t,...n??{}})});return this.unwrapResponse(i)}},this.projects={list:async e=>{let t=new URLSearchParams;e?.organization_id&&t.set(`organizationId`,e.organization_id),e?.env_type&&t.set(`envType`,e.env_type),e?.status&&t.set(`status`,e.status);let n=t.toString(),r=`${this.baseUrl}/api/v1/cloud/environments${n?`?`+n:``}`,i=await this.fetch(r);return this.unwrapResponse(i)},get:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}`);return this.unwrapResponse(t)},create:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments`,{method:`POST`,body:JSON.stringify(e)});return this.unwrapResponse(t)},update:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify(t)});return this.unwrapResponse(n)},delete:async(e,t)=>{let n=t?.force?`?force=1`:``,r=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}${n}`,{method:`DELETE`});return this.unwrapResponse(r)},activate:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/activate`,{method:`POST`});return this.unwrapResponse(t)},rotateCredential:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/credentials/rotate`,{method:`POST`,body:JSON.stringify({plaintext:t})});return this.unwrapResponse(n)},updateHostname:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/hostname`,{method:`POST`,body:JSON.stringify({hostname:t})});return this.unwrapResponse(n)},updateVisibility:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({visibility:t})});return this.unwrapResponse(n)},listRevisions:async(e,t)=>{let n=new URLSearchParams;t?.limit&&n.set(`limit`,String(t.limit)),t?.cursor&&n.set(`cursor`,t.cursor),t?.branch&&n.set(`branch`,t.branch);let r=n.toString(),i=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/revisions${r?`?${r}`:``}`);return this.unwrapResponse(i)},listBranches:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/branches`);return this.unwrapResponse(t)},renameBranch:async(e,t,n)=>{let r=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/branches/${encodeURIComponent(t)}/rename`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({newName:n})});return this.unwrapResponse(r)},deleteBranch:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/branches/${encodeURIComponent(t)}`,{method:`DELETE`});return this.unwrapResponse(n)},retryProvisioning:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/retry`,{method:`POST`});return this.unwrapResponse(t)},listDrivers:async()=>{let e=await this.fetch(`${this.baseUrl}/api/v1/cloud/drivers`);return this.unwrapResponse(e)},packages:{list:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/packages`);return this.unwrapResponse(t)},install:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/packages`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(n)},get:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/packages/${encodeURIComponent(t)}`);return this.unwrapResponse(n)},enable:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/packages/${encodeURIComponent(t)}/enable`,{method:`PATCH`});return this.unwrapResponse(n)},disable:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/packages/${encodeURIComponent(t)}/disable`,{method:`PATCH`});return this.unwrapResponse(n)},uninstall:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/packages/${encodeURIComponent(t)}`,{method:`DELETE`});return this.unwrapResponse(n)},upgrade:async(e,t,n)=>{let r=await this.fetch(`${this.baseUrl}/api/v1/cloud/environments/${encodeURIComponent(e)}/packages/${encodeURIComponent(t)}/upgrade`,{method:`POST`,body:JSON.stringify({targetVersion:n})});return this.unwrapResponse(r)}}},this.organizations={list:async()=>{let e=this.getRoute(`auth`),t=await(await this.fetch(`${this.baseUrl}${e}/organization/list`)).json();return{organizations:Array.isArray(t)?t:t?.data??[]}},create:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/create`,{method:`POST`,body:JSON.stringify(e)})).json()},update:async(e,t)=>{let n=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${n}/organization/update`,{method:`POST`,body:JSON.stringify({organizationId:e,data:t})})).json()},setActive:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/set-active`,{method:`POST`,body:JSON.stringify({organizationId:e})})).json()},get:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/get-full-organization?organizationId=${encodeURIComponent(e)}`)).json()},listMembers:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/list-members?organizationId=${encodeURIComponent(e)}`)).json()},invite:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/invite-member`,{method:`POST`,body:JSON.stringify(e)})).json()},leave:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/leave`,{method:`POST`,body:JSON.stringify({organizationId:e})})).json()},delete:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/delete`,{method:`POST`,body:JSON.stringify({organizationId:e})})).json()},removeMember:async(e,t)=>{let n=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${n}/organization/remove-member`,{method:`POST`,body:JSON.stringify({memberIdOrEmail:t.memberIdOrEmail,organizationId:e})})).json()},updateMemberRole:async(e,t)=>{let n=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${n}/organization/update-member-role`,{method:`POST`,body:JSON.stringify({memberId:t.memberId,role:t.role,organizationId:e})})).json()},getActiveMember:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/get-active-member?organizationId=${encodeURIComponent(e)}`)).json()},invitations:{list:async e=>{let t=this.getRoute(`auth`),n=await(await this.fetch(`${this.baseUrl}${t}/organization/list-invitations?organizationId=${encodeURIComponent(e)}`)).json();return{invitations:Array.isArray(n)?n:n?.data??n?.invitations??[]}},listMine:async()=>{let e=this.getRoute(`auth`),t=await(await this.fetch(`${this.baseUrl}${e}/organization/list-user-invitations`)).json();return{invitations:Array.isArray(t)?t:t?.data??t?.invitations??[]}},cancel:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/cancel-invitation`,{method:`POST`,body:JSON.stringify({invitationId:e})})).json()},accept:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/accept-invitation`,{method:`POST`,body:JSON.stringify({invitationId:e})})).json()},reject:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/reject-invitation`,{method:`POST`,body:JSON.stringify({invitationId:e})})).json()},resend:async e=>{if(e.id)try{await this.organizations.invitations.cancel(e.id)}catch{}return this.organizations.invite({email:e.email,role:e.role??`member`,organizationId:e.organizationId})}},teams:{list:async e=>{let t=this.getRoute(`auth`),n=await(await this.fetch(`${this.baseUrl}${t}/organization/list-teams?organizationId=${encodeURIComponent(e)}`)).json();return{teams:Array.isArray(n)?n:n?.data??n?.teams??[]}},create:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/create-team`,{method:`POST`,body:JSON.stringify(e)})).json()},update:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/update-team`,{method:`POST`,body:JSON.stringify(e)})).json()},delete:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/remove-team`,{method:`POST`,body:JSON.stringify(e)})).json()},listMembers:async e=>{let t=this.getRoute(`auth`),n=await(await this.fetch(`${this.baseUrl}${t}/organization/list-team-members?teamId=${encodeURIComponent(e)}`)).json();return{members:Array.isArray(n)?n:n?.data??n?.members??[]}},addMember:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/add-team-member`,{method:`POST`,body:JSON.stringify(e)})).json()},removeMember:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/organization/remove-team-member`,{method:`POST`,body:JSON.stringify(e)})).json()}}},this.oauth={applications:{register:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/oauth2/create-client`,{method:`POST`,body:JSON.stringify(e)})).json()},get:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/oauth2/get-client?client_id=${encodeURIComponent(e)}`)).json()},getPublic:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/oauth2/public-client?client_id=${encodeURIComponent(e)}`)).json()},list:async()=>{let e=this.getRoute(`auth`),t=await(await this.fetch(`${this.baseUrl}${e}/oauth2/get-clients`)).json();return{applications:Array.isArray(t)?t:t?.clients??t?.data??[]}},delete:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/oauth2/delete-client`,{method:`POST`,body:JSON.stringify({client_id:e})})).json()}},consent:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/oauth2/consent`,{method:`POST`,body:JSON.stringify(e)})).json()}},this.auth={getConfig:async()=>{let e=this.getRoute(`auth`),t=await this.fetch(`${this.baseUrl}${e}/config`);return this.unwrapResponse(t)},login:async e=>{let t=this.getRoute(`auth`),n=await this.fetch(`${this.baseUrl}${t}/sign-in/email`,{method:`POST`,headers:{Origin:this.baseUrl},body:JSON.stringify(e)}),r=await n.json().catch(()=>({}));if(!n.ok){let e=r?.message||r?.error?.message||`Login failed (HTTP ${n.status})`,t=Error(e);throw r?.code&&(t.code=r.code),t.status=n.status,t}let i=r&&(r.data??(r.token||r.user?{token:r.token,user:r.user}:void 0)),a=i?{...r,data:i}:r;return a.data?.token&&(this.token=a.data.token),a},logout:async()=>{let e=this.getRoute(`auth`);await this.fetch(`${this.baseUrl}${e}/sign-out`,{method:`POST`,headers:{"Content-Type":`application/json`,Origin:this.baseUrl},body:`{}`}),this.token=void 0},me:async()=>{let e=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${e}/get-session`,{headers:{Origin:this.baseUrl}})).json()},register:async e=>{let t=this.getRoute(`auth`),n=await(await this.fetch(`${this.baseUrl}${t}/sign-up/email`,{method:`POST`,headers:{Origin:this.baseUrl},body:JSON.stringify(e)})).json(),r=n&&(n.data??(n.token||n.user?{token:n.token,user:n.user}:void 0)),i=r?{...n,data:r}:n;return i.data?.token&&(this.token=i.data.token),i},signInWithProvider:async(e,t)=>{if(typeof window>`u`)throw Error(`signInWithProvider requires a browser environment`);let n=this.getRoute(`auth`),r=t?.callbackURL??window.location.href,i=t?.type===`oidc`,a=i?`/sign-in/oauth2`:`/sign-in/social`,o=i?{providerId:e,callbackURL:r}:{provider:e,callbackURL:r};t?.errorCallbackURL&&(o.errorCallbackURL=t.errorCallbackURL);let s=await(await this.fetch(`${this.baseUrl}${n}${a}`,{method:`POST`,body:JSON.stringify(o)})).json(),c=s?.url??s?.data?.url;if(c)window.location.assign(c);else throw Error(`signInWithProvider: no redirect URL returned for provider "${e}"`)},refreshToken:async e=>{let t=this.getRoute(`auth`),n=await(await this.fetch(`${this.baseUrl}${t}/get-session`,{method:`GET`})).json();return n.data?.token&&(this.token=n.data.token),n},bootstrapStatus:async()=>{let e=this.getRoute(`auth`),t=await(await this.fetch(`${this.baseUrl}${e}/bootstrap-status`)).json();return{hasOwner:!!(t?.data??t)?.hasOwner}},updateUser:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/update-user`,{method:`POST`,body:JSON.stringify(e)})).json()},changePassword:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/change-password`,{method:`POST`,body:JSON.stringify(e)})).json()},changeEmail:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/change-email`,{method:`POST`,body:JSON.stringify(e)})).json()},sendVerificationEmail:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/send-verification-email`,{method:`POST`,body:JSON.stringify(e)})).json()},verifyEmail:async e=>{let t=this.getRoute(`auth`),n=new URL(`${this.baseUrl}${t}/verify-email`);return n.searchParams.set(`token`,e.token),e.callbackURL&&n.searchParams.set(`callbackURL`,e.callbackURL),(await this.fetch(n.toString())).json()},deleteUser:async e=>{let t=this.getRoute(`auth`),n=await this.fetch(`${this.baseUrl}${t}/delete-user`,{method:`POST`,body:JSON.stringify(e)});return this.token=void 0,n.json()},sessions:{list:async()=>{let e=this.getRoute(`auth`),t=await(await this.fetch(`${this.baseUrl}${e}/list-sessions`)).json();return{sessions:Array.isArray(t)?t:t?.data??t?.sessions??[]}},revoke:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/revoke-session`,{method:`POST`,body:JSON.stringify({token:e})})).json()},revokeOthers:async()=>{let e=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${e}/revoke-other-sessions`,{method:`POST`,body:`{}`})).json()},revokeAll:async()=>{let e=this.getRoute(`auth`),t=await this.fetch(`${this.baseUrl}${e}/revoke-sessions`,{method:`POST`,body:`{}`});return this.token=void 0,t.json()}},twoFactor:{enable:async e=>{let t=this.getRoute(`auth`),n=await(await this.fetch(`${this.baseUrl}${t}/two-factor/enable`,{method:`POST`,body:JSON.stringify(e)})).json();return n?.data??n},verifyTotp:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/two-factor/verify-totp`,{method:`POST`,body:JSON.stringify(e)})).json()},disable:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/two-factor/disable`,{method:`POST`,body:JSON.stringify(e)})).json()},generateBackupCodes:async e=>{let t=this.getRoute(`auth`),n=await(await this.fetch(`${this.baseUrl}${t}/two-factor/generate-backup-codes`,{method:`POST`,body:JSON.stringify(e)})).json();return n?.data??n},verifyBackupCode:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/two-factor/verify-backup-code`,{method:`POST`,body:JSON.stringify(e)})).json()}},accounts:{list:async()=>{let e=this.getRoute(`auth`),t=await(await this.fetch(`${this.baseUrl}${e}/list-accounts`)).json();return{accounts:Array.isArray(t)?t:t?.data??t?.accounts??[]}},unlink:async e=>{let t=this.getRoute(`auth`);return(await this.fetch(`${this.baseUrl}${t}/unlink-account`,{method:`POST`,body:JSON.stringify(e)})).json()},linkSocial:async e=>{let t=this.getRoute(`auth`),n=e.callbackURL??(typeof window<`u`?window.location.href:void 0),r=await(await this.fetch(`${this.baseUrl}${t}/link-social`,{method:`POST`,body:JSON.stringify({provider:e.provider,callbackURL:n})})).json();return r?.data??r}}},this.storage={upload:async(e,t=`user`)=>{let n={filename:e.name,mimeType:e.type,size:e.size,scope:t},r=this.getRoute(`storage`),{data:i}=await(await this.fetch(`${this.baseUrl}${r}/upload/presigned`,{method:`POST`,body:JSON.stringify(n)})).json(),a=await this.fetchImpl(i.uploadUrl,{method:i.method,headers:i.headers,body:e});if(!a.ok)throw Error(`Storage Upload Failed: ${a.statusText}`);let o={fileId:i.fileId},s=await(await this.fetch(`${this.baseUrl}${r}/upload/complete`,{method:`POST`,body:JSON.stringify(o)})).json();return s?.data&&s.data.fileId==null&&(s.data.fileId=i.fileId),s},getDownloadUrl:async e=>{let t=this.getRoute(`storage`),n=await this.fetch(`${this.baseUrl}${t}/files/${e}/url`),{url:r}=await this.unwrapResponse(n);return r},getPresignedUrl:async e=>{let t=this.getRoute(`storage`);return(await this.fetch(`${this.baseUrl}${t}/upload/presigned`,{method:`POST`,body:JSON.stringify(e)})).json()},initChunkedUpload:async e=>{let t=this.getRoute(`storage`);return(await this.fetch(`${this.baseUrl}${t}/upload/chunked`,{method:`POST`,body:JSON.stringify(e)})).json()},uploadPart:async(e,t,n,r)=>{let i=this.getRoute(`storage`);return(await this.fetch(`${this.baseUrl}${i}/upload/chunked/${e}/chunk/${t}`,{method:`PUT`,headers:{"x-resume-token":n},body:r})).json()},completeChunkedUpload:async e=>{let t=this.getRoute(`storage`);return(await this.fetch(`${this.baseUrl}${t}/upload/chunked/${e.uploadId}/complete`,{method:`POST`,body:JSON.stringify(e)})).json()},resumeUpload:async(e,t,n,r)=>{let i=this.getRoute(`storage`),{totalChunks:a,uploadedChunks:o}=(await(await this.fetch(`${this.baseUrl}${i}/upload/chunked/${e}/progress`)).json()).data,s=[],c=t instanceof ArrayBuffer?t:await t.arrayBuffer();for(let t=o;t<a;t++){let i=t*n,a=Math.min(i+n,c.byteLength),o=new Blob([c.slice(i,a)]),l=await this.storage.uploadPart(e,t,r,o);s.push({chunkIndex:t,eTag:l.data.eTag})}return this.storage.completeChunkedUpload({uploadId:e,parts:s})}},this.automation={trigger:async(e,t)=>{let n=this.getRoute(`automation`);return(await this.fetch(`${this.baseUrl}${n}/trigger/${e}`,{method:`POST`,body:JSON.stringify(t)})).json()},list:async()=>{let e=this.getRoute(`automation`),t=await this.fetch(`${this.baseUrl}${e}`);return this.unwrapResponse(t)},get:async e=>{let t=this.getRoute(`automation`),n=await this.fetch(`${this.baseUrl}${t}/${e}`);return this.unwrapResponse(n)},create:async(e,t)=>{let n=this.getRoute(`automation`),r=await this.fetch(`${this.baseUrl}${n}`,{method:`POST`,body:JSON.stringify({name:e,...t})});return this.unwrapResponse(r)},update:async(e,t)=>{let n=this.getRoute(`automation`),r=await this.fetch(`${this.baseUrl}${n}/${e}`,{method:`PUT`,body:JSON.stringify({definition:t})});return this.unwrapResponse(r)},delete:async e=>{let t=this.getRoute(`automation`),n=await this.fetch(`${this.baseUrl}${t}/${e}`,{method:`DELETE`});return this.unwrapResponse(n)},listActions:async e=>{let t=this.getRoute(`automation`),n=new URLSearchParams;e?.paradigm&&n.set(`paradigm`,e.paradigm),e?.source&&n.set(`source`,e.source),e?.category&&n.set(`category`,e.category);let r=n.toString(),i=await this.fetch(`${this.baseUrl}${t}/actions${r?`?${r}`:``}`);return this.unwrapResponse(i)},listConnectors:async e=>{let t=this.getRoute(`automation`),n=e?.type?`?type=${encodeURIComponent(e.type)}`:``,r=await this.fetch(`${this.baseUrl}${t}/connectors${n}`);return this.unwrapResponse(r)},getRuntimeStatus:async()=>{let e=this.getRoute(`automation`),t=await this.fetch(`${this.baseUrl}${e}/_status`);return this.unwrapResponse(t)},toggle:async(e,t)=>{let n=this.getRoute(`automation`),r=await this.fetch(`${this.baseUrl}${n}/${e}/toggle`,{method:`POST`,body:JSON.stringify({enabled:t})});return this.unwrapResponse(r)},runs:{list:async(e,t)=>{let n=this.getRoute(`automation`),r=new URLSearchParams;t?.limit&&r.set(`limit`,String(t.limit)),t?.cursor&&r.set(`cursor`,t.cursor);let i=r.toString(),a=await this.fetch(`${this.baseUrl}${n}/${e}/runs${i?`?${i}`:``}`);return this.unwrapResponse(a)},get:async(e,t)=>{let n=this.getRoute(`automation`),r=await this.fetch(`${this.baseUrl}${n}/${e}/runs/${t}`);return this.unwrapResponse(r)}},getFlow:async e=>{let t=this.getRoute(`automation`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}`);return this.unwrapResponse(n)},execute:async(e,t)=>{let n=this.getRoute(`automation`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/trigger`,{method:`POST`,body:JSON.stringify(t??{})});return this.unwrapResponse(r)},listRuns:async(e,t)=>{let n=this.getRoute(`automation`),r=new URLSearchParams;t?.limit!=null&&r.set(`limit`,String(t.limit)),t?.cursor&&r.set(`cursor`,t.cursor);let i=r.toString(),a=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/runs${i?`?${i}`:``}`);return this.unwrapResponse(a)},getRun:async(e,t)=>{let n=this.getRoute(`automation`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/runs/${encodeURIComponent(t)}`);return this.unwrapResponse(r)},resume:async(e,t,n)=>{let r=this.getRoute(`automation`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/runs/${encodeURIComponent(t)}/resume`,{method:`POST`,body:JSON.stringify(n??{})});return this.unwrapResponse(i)},getScreen:async(e,t)=>{let n=this.getRoute(`automation`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/runs/${encodeURIComponent(t)}/screen`);return this.unwrapResponse(r)}},this.actions={invoke:async(e,t,n)=>{try{let r=await this.fetch(`${this.baseUrl}/api/v1/actions/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:`POST`,body:JSON.stringify({recordId:n?.recordId,params:n?.params??{}})});return ie(await this.unwrapResponse(r))}catch(e){return{success:!1,error:re(e)}}},invokeGlobal:async(e,t)=>this.actions.invoke(`global`,e,t)},this.keys={create:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/keys`,{method:`POST`,body:JSON.stringify({...e?.name==null?{}:{name:e.name},...e?.expiresAt==null?{}:{expires_at:e.expiresAt}})});return this.unwrapResponse(t)}},this.shareLinks={create:async(e,t,n)=>{let r=await this.fetch(`${this.baseUrl}/api/v1/share-links`,{method:`POST`,body:JSON.stringify({object:e,recordId:t,...n??{}})});return this.unwrapResponse(r)},list:async e=>{let t=new URLSearchParams;e?.object&&t.set(`object`,e.object),e?.recordId&&t.set(`recordId`,e.recordId),e?.includeRevoked&&t.set(`includeRevoked`,`true`);let n=t.toString(),r=await this.fetch(`${this.baseUrl}/api/v1/share-links${n?`?${n}`:``}`);return this.unwrapResponse(r)},revoke:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/share-links/${encodeURIComponent(e)}`,{method:`DELETE`});return this.unwrapResponse(t)}},this.security={explain:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/security/explain`,{method:`POST`,body:JSON.stringify(e)});return this.unwrapResponse(t)},describeDelegableScope:async()=>{let e=await this.fetch(`${this.baseUrl}/api/v1/security/my-delegable-scope`);return this.unwrapResponse(e)},suggestedBindings:{list:async e=>{let t=new URLSearchParams;e?.status&&t.set(`status`,e.status),e?.packageId&&t.set(`packageId`,e.packageId);let n=t.toString(),r=await this.fetch(`${this.baseUrl}/api/v1/security/suggested-bindings${n?`?${n}`:``}`);return this.unwrapResponse(r)},confirm:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/security/suggested-bindings/${encodeURIComponent(e)}/confirm`,{method:`POST`});return this.unwrapResponse(t)},dismiss:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/security/suggested-bindings/${encodeURIComponent(e)}/dismiss`,{method:`POST`});return this.unwrapResponse(t)}}},this.approvals={listRequests:async e=>{let t=this.getRoute(`approvals`),n=new URLSearchParams;e?.object&&n.set(`object`,e.object),e?.recordId&&n.set(`recordId`,e.recordId),e?.status&&n.set(`status`,Array.isArray(e.status)?e.status.join(`,`):e.status),e?.approverId&&n.set(`approverId`,Array.isArray(e.approverId)?e.approverId.join(`,`):e.approverId),e?.submitterId&&n.set(`submitterId`,e.submitterId);let r=n.toString(),i=await this.fetch(`${this.baseUrl}${t}/requests${r?`?${r}`:``}`),a=await this.unwrapResponse(i);return Array.isArray(a)?a:a?.data??[]},getRequest:async e=>{let t=this.getRoute(`approvals`),n=await this.fetch(`${this.baseUrl}${t}/requests/${encodeURIComponent(e)}`);return this.unwrapResponse(n)},approve:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/approve`,{method:`POST`,body:JSON.stringify({actorId:t?.actorId,comment:t?.comment,attachments:t?.attachments})});return this.unwrapResponse(r)},reject:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/reject`,{method:`POST`,body:JSON.stringify({actorId:t?.actorId,comment:t?.comment,attachments:t?.attachments})});return this.unwrapResponse(r)},reassign:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/reassign`,{method:`POST`,body:JSON.stringify({to:t.to,from:t.from,actorId:t.actorId,comment:t.comment})});return this.unwrapResponse(r)},recall:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/recall`,{method:`POST`,body:JSON.stringify({actorId:t?.actorId,comment:t?.comment})});return this.unwrapResponse(r)},revise:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/revise`,{method:`POST`,body:JSON.stringify({actorId:t?.actorId,comment:t?.comment})});return this.unwrapResponse(r)},resubmit:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/resubmit`,{method:`POST`,body:JSON.stringify({actorId:t?.actorId,comment:t?.comment})});return this.unwrapResponse(r)},remind:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/remind`,{method:`POST`,body:JSON.stringify({actorId:t?.actorId,comment:t?.comment})});return this.unwrapResponse(r)},requestInfo:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/request-info`,{method:`POST`,body:JSON.stringify({actorId:t?.actorId,comment:t?.comment})});return this.unwrapResponse(r)},comment:async(e,t)=>{let n=this.getRoute(`approvals`),r=await this.fetch(`${this.baseUrl}${n}/requests/${encodeURIComponent(e)}/comment`,{method:`POST`,body:JSON.stringify({actorId:t.actorId,comment:t.comment,attachments:t.attachments})});return this.unwrapResponse(r)},listActions:async e=>{let t=this.getRoute(`approvals`),n=await this.fetch(`${this.baseUrl}${t}/requests/${encodeURIComponent(e)}/actions`),r=await this.unwrapResponse(n);return Array.isArray(r)?r:r?.data??[]}},this.shares={list:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/shares`),i=await this.unwrapResponse(r);return Array.isArray(i)?i:i?.data??[]},grant:async(e,t,n)=>{let r=this.getRoute(`data`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/shares`,{method:`POST`,body:JSON.stringify(n)});return this.unwrapResponse(i)},revoke:async(e,t,n)=>{let r=this.getRoute(`data`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/shares/${encodeURIComponent(n)}`,{method:`DELETE`});return i.status===204?{deleted:!0}:this.unwrapResponse(i)},rules:{list:async e=>{let t=new URLSearchParams;e?.object&&t.set(`object`,e.object),e?.activeOnly!==void 0&&t.set(`activeOnly`,String(e.activeOnly));let n=t.toString(),r=await this.fetch(`${this.baseUrl}/api/v1/sharing/rules${n?`?${n}`:``}`),i=await this.unwrapResponse(r);return Array.isArray(i)?i:i?.data??[]},save:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/sharing/rules`,{method:`POST`,body:JSON.stringify(e)});return this.unwrapResponse(t)},get:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/sharing/rules/${encodeURIComponent(e)}`);return this.unwrapResponse(t)},delete:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/sharing/rules/${encodeURIComponent(e)}`,{method:`DELETE`});return t.status===204?{deleted:!0}:this.unwrapResponse(t)},evaluate:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/sharing/rules/${encodeURIComponent(e)}/evaluate`,{method:`POST`,body:JSON.stringify({})});return this.unwrapResponse(t)}}},this.search=async(e,t)=>{let n=new URLSearchParams;n.set(`q`,e),t?.objects?.length&&n.set(`objects`,t.objects.join(`,`)),t?.limit!==void 0&&n.set(`limit`,String(t.limit)),t?.perObject!==void 0&&n.set(`perObject`,String(t.perObject));let r=await this.fetch(`${this.baseUrl}/api/v1/search?${n.toString()}`);return this.unwrapResponse(r)},this.reports={list:async e=>{let t=new URLSearchParams;e?.object&&t.set(`object`,e.object),e?.ownerId&&t.set(`ownerId`,e.ownerId);let n=t.toString(),r=await this.fetch(`${this.baseUrl}/api/v1/reports${n?`?${n}`:``}`),i=await this.unwrapResponse(r);return Array.isArray(i)?i:i?.data??[]},save:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/reports`,{method:`POST`,body:JSON.stringify(e??{})});return this.unwrapResponse(t)},get:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/reports/${encodeURIComponent(e)}`);return this.unwrapResponse(t)},delete:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/reports/${encodeURIComponent(e)}`,{method:`DELETE`});return t.status===204?{deleted:!0}:this.unwrapResponse(t)},run:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/reports/${encodeURIComponent(e)}/run`,{method:`POST`,body:JSON.stringify({})});return this.unwrapResponse(t)},schedule:async(e,t)=>{let n=await this.fetch(`${this.baseUrl}/api/v1/reports/${encodeURIComponent(e)}/schedule`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(n)},listSchedules:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/reports/${encodeURIComponent(e)}/schedules`),n=await this.unwrapResponse(t);return Array.isArray(n)?n:n?.data??[]},unschedule:async e=>{let t=await this.fetch(`${this.baseUrl}/api/v1/reports/schedules/${encodeURIComponent(e)}`,{method:`DELETE`});return t.status===204?{deleted:!0}:this.unwrapResponse(t)}},this.notifications={list:async e=>{let t=this.getRoute(`notifications`),n=new URLSearchParams;e?.read!==void 0&&n.set(`read`,String(e.read)),e?.type&&n.set(`type`,e.type),e?.limit&&n.set(`limit`,String(e.limit)),e?.cursor&&n.set(`cursor`,e.cursor);let r=n.toString(),i=await this.fetch(`${this.baseUrl}${t}${r?`?${r}`:``}`);return this.unwrapResponse(i)},markRead:async e=>{let t=this.getRoute(`notifications`),n=await this.fetch(`${this.baseUrl}${t}/read`,{method:`POST`,body:JSON.stringify({ids:e})});return this.unwrapResponse(n)},markAllRead:async()=>{let e=this.getRoute(`notifications`),t=await this.fetch(`${this.baseUrl}${e}/read/all`,{method:`POST`});return this.unwrapResponse(t)}},this.ai={chat:async e=>{let t=this.getRoute(`ai`),n=await this.fetch(`${this.baseUrl}${t}/chat`,{method:`POST`,body:JSON.stringify({...e,stream:!1})});return this.unwrapResponse(n)},chatStream:async e=>{let t=this.getRoute(`ai`);return ne(await this.fetch(`${this.baseUrl}${t}/chat`,{method:`POST`,headers:{Accept:`text/event-stream`},body:JSON.stringify({...e,stream:!0})}))},complete:async e=>{let t=this.getRoute(`ai`),n=await this.fetch(`${this.baseUrl}${t}/complete`,{method:`POST`,body:JSON.stringify(e)});return this.unwrapResponse(n)},models:async()=>{let e=this.getRoute(`ai`),t=await this.fetch(`${this.baseUrl}${e}/models`);return this.unwrapResponse(t)},conversations:{create:async e=>{let t=this.getRoute(`ai`),n=await this.fetch(`${this.baseUrl}${t}/conversations`,{method:`POST`,body:JSON.stringify(e??{})});return this.unwrapResponse(n)},list:async e=>{let t=this.getRoute(`ai`),n=new URLSearchParams;e?.agentId&&n.set(`agentId`,e.agentId),e?.limit!==void 0&&n.set(`limit`,String(e.limit)),e?.cursor&&n.set(`cursor`,e.cursor);let r=n.toString(),i=await this.fetch(`${this.baseUrl}${t}/conversations${r?`?${r}`:``}`);return(await this.unwrapResponse(i))?.conversations??[]},get:async e=>{let t=this.getRoute(`ai`),n=await this.fetch(`${this.baseUrl}${t}/conversations/${encodeURIComponent(e)}`);return this.unwrapResponse(n)},update:async(e,t)=>{let n=this.getRoute(`ai`),r=await this.fetch(`${this.baseUrl}${n}/conversations/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify(t)});return this.unwrapResponse(r)},delete:async e=>{let t=this.getRoute(`ai`),n=await this.fetch(`${this.baseUrl}${t}/conversations/${encodeURIComponent(e)}`,{method:`DELETE`});return n.status===204?{deleted:!0}:this.unwrapResponse(n)},addMessage:async(e,t)=>{let n=this.getRoute(`ai`),r=await this.fetch(`${this.baseUrl}${n}/conversations/${encodeURIComponent(e)}/messages`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(r)}},agents:{list:async()=>{let e=this.getRoute(`ai`),t=await this.fetch(`${this.baseUrl}${e}/agents`);return(await this.unwrapResponse(t))?.agents??[]},chat:async(e,t)=>{let n=this.getRoute(`ai`),r=await this.fetch(`${this.baseUrl}${n}/agents/${encodeURIComponent(e)}/chat`,{method:`POST`,body:JSON.stringify({...t,stream:!1})});return this.unwrapResponse(r)},chatStream:async(e,t)=>{let n=this.getRoute(`ai`);return ne(await this.fetch(`${this.baseUrl}${n}/agents/${encodeURIComponent(e)}/chat`,{method:`POST`,headers:{Accept:`text/event-stream`},body:JSON.stringify({...t,stream:!0})}))}},pendingActions:{list:async e=>{let t=this.getRoute(`ai`),n=new URLSearchParams;e?.status&&n.set(`status`,e.status),e?.conversationId&&n.set(`conversationId`,e.conversationId),e?.limit!==void 0&&n.set(`limit`,String(e.limit));let r=n.toString(),i=await this.fetch(`${this.baseUrl}${t}/pending-actions${r?`?${r}`:``}`);return(await this.unwrapResponse(i))?.items??[]},get:async e=>{let t=this.getRoute(`ai`),n=await this.fetch(`${this.baseUrl}${t}/pending-actions/${encodeURIComponent(e)}`);return this.unwrapResponse(n)},approve:async e=>{let t=this.getRoute(`ai`),n=await this.fetch(`${this.baseUrl}${t}/pending-actions/${encodeURIComponent(e)}/approve`,{method:`POST`,body:JSON.stringify({})});return this.unwrapResponse(n)},reject:async(e,t)=>{let n=this.getRoute(`ai`),r=await this.fetch(`${this.baseUrl}${n}/pending-actions/${encodeURIComponent(e)}/reject`,{method:`POST`,body:JSON.stringify(t===void 0?{}:{reason:t})});return this.unwrapResponse(r)}}},this.i18n={getLocales:async()=>{let e=this.getRoute(`i18n`),t=await this.fetch(`${this.baseUrl}${e}/locales`);return this.unwrapResponse(t)},getTranslations:async e=>{let t=this.getRoute(`i18n`),n=await this.fetch(`${this.baseUrl}${t}/translations/${encodeURIComponent(e)}`);return this.unwrapResponse(n)},getFieldLabels:async(e,t)=>{let n=this.getRoute(`i18n`),r=await this.fetch(`${this.baseUrl}${n}/labels/${encodeURIComponent(e)}/${encodeURIComponent(t)}`);return this.unwrapResponse(r)}},this.data={query:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${e}/query`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(r)},find:async(e,t={})=>{let n=this.getRoute(`data`),r=new URLSearchParams,i=t,a={};if(`where`in t||`fields`in t||`orderBy`in t||`offset`in t?(i.where&&(a.filter=i.where),i.fields&&(a.select=i.fields),i.orderBy&&(a.sort=i.orderBy),i.limit!=null&&(a.top=i.limit),i.offset!=null&&(a.skip=i.offset),i.aggregations&&(a.aggregations=i.aggregations),i.groupBy&&(a.groupBy=i.groupBy)):Object.assign(a,t),a.top&&r.set(`top`,a.top.toString()),a.skip&&r.set(`skip`,a.skip.toString()),a.sort)if(Array.isArray(a.sort)&&typeof a.sort[0]==`object`)r.set(`sort`,JSON.stringify(a.sort));else{let e=Array.isArray(a.sort)?a.sort.join(`,`):a.sort;r.set(`sort`,e)}a.select&&r.set(`select`,a.select.join(`,`));let o=a.filter??a.filters;o&&(this.isFilterAST(o)||Array.isArray(o)?r.set(`filter`,JSON.stringify(o)):typeof o==`object`&&o&&Object.entries(o).forEach(([e,t])=>{t!=null&&r.append(e,String(t))})),a.aggregations&&r.set(`aggregations`,JSON.stringify(a.aggregations)),a.groupBy&&r.set(`groupBy`,a.groupBy.join(`,`));let s=await this.fetch(`${this.baseUrl}${n}/${e}?${r.toString()}`);return this.unwrapResponse(s)},get:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${e}/${t}`);return this.unwrapResponse(r)},create:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${e}`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(r)},createMany:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${e}/createMany`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(r)},import:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${e}/import`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(r)},createImportJob:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${e}/import/jobs`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(r)},getImportJobProgress:async e=>{let t=this.getRoute(`data`),n=await this.fetch(`${this.baseUrl}${t}/import/jobs/${encodeURIComponent(e)}`);return this.unwrapResponse(n)},getImportJobResults:async e=>{let t=this.getRoute(`data`),n=await this.fetch(`${this.baseUrl}${t}/import/jobs/${encodeURIComponent(e)}/results`);return this.unwrapResponse(n)},listImportJobs:async(e={})=>{let t=this.getRoute(`data`),n=new URLSearchParams;e.object&&n.set(`object`,e.object),e.status&&n.set(`status`,e.status),e.limit!=null&&n.set(`limit`,String(e.limit)),e.offset!=null&&n.set(`offset`,String(e.offset));let r=n.toString()?`?${n.toString()}`:``,i=await this.fetch(`${this.baseUrl}${t}/import/jobs${r}`);return(await this.unwrapResponse(i)).jobs},cancelImportJob:async e=>{let t=this.getRoute(`data`),n=await this.fetch(`${this.baseUrl}${t}/import/jobs/${encodeURIComponent(e)}/cancel`,{method:`POST`});return this.unwrapResponse(n)},undoImportJob:async e=>{let t=this.getRoute(`data`),n=await this.fetch(`${this.baseUrl}${t}/import/jobs/${encodeURIComponent(e)}/undo`,{method:`POST`});return this.unwrapResponse(n)},update:async(e,t,n,r)=>{let i=this.getRoute(`data`),a={};r?.ifMatch&&(a[`If-Match`]=String(r.ifMatch));let o=await this.fetch(`${this.baseUrl}${i}/${e}/${t}`,{method:`PATCH`,body:JSON.stringify(n),...Object.keys(a).length?{headers:a}:{}});return this.unwrapResponse(o)},batch:async(e,t)=>{let n=this.getRoute(`data`),r=await this.fetch(`${this.baseUrl}${n}/${e}/batch`,{method:`POST`,body:JSON.stringify(t)});return this.unwrapResponse(r)},batchTransaction:async e=>{let t=this.getRoute(`data`).replace(/\/[^/]+\/?$/,``)||`/api/v1`,n={operations:e,atomic:!0},r=await this.fetch(`${this.baseUrl}${t}/batch`,{method:`POST`,body:JSON.stringify(n)});return this.unwrapResponse(r)},updateMany:async(e,t,n)=>{let r=this.getRoute(`data`),i={records:t,options:n},a=await this.fetch(`${this.baseUrl}${r}/${e}/updateMany`,{method:`POST`,body:JSON.stringify(i)});return this.unwrapResponse(a)},delete:async(e,t,n)=>{let r=this.getRoute(`data`),i={};n?.ifMatch&&(i[`If-Match`]=String(n.ifMatch));let a=await this.fetch(`${this.baseUrl}${r}/${e}/${t}`,{method:`DELETE`,...Object.keys(i).length?{headers:i}:{}});return this.unwrapResponse(a)},deleteMany:async(e,t,n)=>{let r=this.getRoute(`data`),i={ids:t,options:n},a=await this.fetch(`${this.baseUrl}${r}/${e}/deleteMany`,{method:`POST`,body:JSON.stringify(i)});return this.unwrapResponse(a)},clone:async(e,t,n)=>{let r=this.getRoute(`data`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/clone`,{method:`POST`,body:JSON.stringify(n?{overrides:n}:{})});return this.unwrapResponse(i)},export:async(e,t)=>{let n=this.getRoute(`data`),r=new URLSearchParams;t?.format&&r.set(`format`,t.format),t?.limit!==void 0&&r.set(`limit`,String(t.limit)),t?.filter!==void 0&&r.set(`filter`,typeof t.filter==`string`?t.filter:JSON.stringify(t.filter)),t?.orderby!==void 0&&r.set(`orderby`,typeof t.orderby==`string`?t.orderby:JSON.stringify(t.orderby)),t?.header!==void 0&&r.set(`header`,String(t.header));let i=r.toString();return this.fetch(`${this.baseUrl}${n}/${encodeURIComponent(e)}/export${i?`?${i}`:``}`)}},this.baseUrl=e.baseUrl.replace(/\/$/,``),this.token=e.token,this.environmentId=e.environmentId,this.locale=e.locale,this.fetchImpl=e.fetch||globalThis.fetch.bind(globalThis),this.logger=e.logger||(0,te.createLogger)({level:e.debug?`debug`:`info`,format:`pretty`}),this.realtimeAPI=new h(this.baseUrl,this.token),this.logger.debug(`ObjectStack client created`,{baseUrl:this.baseUrl})}async connect(){this.logger.debug(`Connecting to ObjectStack server`,{baseUrl:this.baseUrl});try{let e;try{let t=`${this.baseUrl}/api/v1/discovery`;this.logger.debug(`Probing protocol-standard discovery endpoint`,{url:t});let n=await this.fetchImpl(t);if(n.ok){let t=await n.json();e=t.data||t,this.logger.debug(`Discovered via /api/v1/discovery`)}}catch(e){this.logger.debug(`Protocol-standard discovery probe failed`,{error:e.message})}if(!e){let t;try{t=`${new URL(this.baseUrl).origin}/.well-known/objectstack`}catch{t=`/.well-known/objectstack`}this.logger.debug(`Falling back to .well-known discovery`,{url:t});let n=await this.fetchImpl(t);if(!n.ok)throw Error(`Failed to connect to ${t}: ${n.statusText}`);let r=await n.json();e=r.data||r}if(!e)throw Error(`Connection failed: No discovery data returned`);return this.discoveryInfo=e,this.logger.info(`Connected to ObjectStack server`,{version:e.version,apiName:e.apiName,services:e.services}),e}catch(e){throw this.logger.error(`Failed to connect to ObjectStack server`,e,{baseUrl:this.baseUrl}),e}}get capabilities(){let e=this.discoveryInfo?.capabilities;if(!e)return;let t=e,n={};for(let e of p.WELL_KNOWN_CAPABILITY_KEYS){let r=t[e];n[e]=typeof r==`object`&&r?r.enabled===!0:r===!0}return n}project(e){if(!e)throw Error(`[ObjectStack] project(id): environmentId is required`);return new b(this,e)}_baseUrl(){return this.baseUrl}_fetch(e,t){return this.fetch(e,t)}_unwrap(e){return this.unwrapResponse(e)}_isFilterAST(e){return this.isFilterAST(e)}setProjectId(e){this.environmentId=e,this.logger.debug(`Active project changed`,{environmentId:e})}getProjectId(){return this.environmentId}setLocale(e){this.locale=e,this.logger.debug(`Active locale changed`,{locale:e})}getLocale(){return this.locale}get events(){return this.realtimeAPI}isFilterAST(e){return(0,ee.isFilterAST)(e)}async unwrapResponse(e){let t=await e.json();return t&&typeof t.success==`boolean`&&`data`in t?t.data:t}async fetch(e,t={}){this.logger.debug(`HTTP request`,{method:t.method||`GET`,url:e,hasBody:!!t.body});let n={"Content-Type":`application/json`,...t.headers||{}};this.token&&(n.Authorization=`Bearer ${this.token}`),this.environmentId&&(n[`X-Environment-Id`]=this.environmentId),this.locale&&!Object.keys(n).some(e=>e.toLowerCase()===`accept-language`)&&(n[`Accept-Language`]=this.locale);let r=await this.fetchImpl(e,{...t,headers:n});if(this.logger.debug(`HTTP response`,{method:t.method||`GET`,url:e,status:r.status,ok:r.ok}),!r.ok){let n;try{n=await r.json()}catch{n={message:r.statusText}}this.logger.error(`HTTP request failed`,void 0,{method:t.method||`GET`,url:e,status:r.status,error:n});let i=n?.message??n?.error?.message??(typeof n?.error==`string`?n.error:void 0)??r.statusText,a=e=>typeof e==`string`&&e?e:void 0,o=a(n?.code)??a(n?.error?.code),s=Array.isArray(n?.fields)?n.fields:Array.isArray(n?.error?.details?.fields)?n.error.details.fields:void 0,c=Error(i);throw c.code=o,c.category=n?.error?.category,c.httpStatus=r.status,c.retryable=n?.error?.retryable,c.details=n?.details??n?.error?.details??n,s&&(c.fields=s),c}return r}getRoute(e){let t=this.discoveryInfo?.routes;if(t){let n=t[e];if(n)return n}return{data:`/api/v1/data`,metadata:`/api/v1/meta`,discovery:`/api/v1/discovery`,ui:`/api/v1/ui`,auth:`/api/v1/auth`,analytics:`/api/v1/analytics`,storage:`/api/v1/storage`,automation:`/api/v1/automation`,packages:`/api/v1/packages`,realtime:`/api/v1/realtime`,approvals:`/api/v1/approvals`,notifications:`/api/v1/notifications`,ai:`/api/v1/ai`,i18n:`/api/v1/i18n`,mcp:`/api/v1/mcp`}[e]||`/api/v1/${e}`}},b=class{constructor(e,t){this.meta={getTypes:async()=>{let e=await this.parent._fetch(this.url(`/meta`));return this.parent._unwrap(e)},getItems:async(e,t)=>{let n=new URLSearchParams;t?.packageId&&n.set(`package`,t.packageId);let r=n.toString(),i=await this.parent._fetch(this.url(`/meta/${e}${r?`?${r}`:``}`));return this.parent._unwrap(i)},getItem:async(e,t,n)=>{let r=new URLSearchParams;n?.packageId&&r.set(`package`,n.packageId);let i=r.toString(),a=await this.parent._fetch(this.url(`/meta/${e}/${t}${i?`?${i}`:``}`));return this.parent._unwrap(a)},saveItem:async(e,t,n)=>{let r=await this.parent._fetch(this.url(`/meta/${e}/${t}`),{method:`PUT`,body:JSON.stringify(n)});return this.parent._unwrap(r)},deleteItem:async(e,t)=>{let n=await this.parent._fetch(this.url(`/meta/${encodeURIComponent(e)}/${encodeURIComponent(t)}`),{method:`DELETE`});return this.parent._unwrap(n)},getHistory:async(e,t,n)=>{let r=new URLSearchParams;n?.sinceSeq!==void 0&&r.set(`sinceSeq`,String(n.sinceSeq)),n?.limit!==void 0&&r.set(`limit`,String(n.limit));let i=r.toString(),a=await this.parent._fetch(this.url(`/meta/${encodeURIComponent(e)}/${encodeURIComponent(t)}/history${i?`?${i}`:``}`));return this.parent._unwrap(a)}},this.data={query:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}/query`),{method:`POST`,body:JSON.stringify(t)});return this.parent._unwrap(n)},find:async(e,t={})=>{let n=new URLSearchParams,r=t,i={};if(`where`in t||`fields`in t||`orderBy`in t||`offset`in t?(r.where&&(i.filter=r.where),r.fields&&(i.select=r.fields),r.orderBy&&(i.sort=r.orderBy),r.limit!=null&&(i.top=r.limit),r.offset!=null&&(i.skip=r.offset),r.aggregations&&(i.aggregations=r.aggregations),r.groupBy&&(i.groupBy=r.groupBy)):Object.assign(i,t),i.top&&n.set(`top`,i.top.toString()),i.skip&&n.set(`skip`,i.skip.toString()),i.sort)if(Array.isArray(i.sort)&&typeof i.sort[0]==`object`)n.set(`sort`,JSON.stringify(i.sort));else{let e=Array.isArray(i.sort)?i.sort.join(`,`):i.sort;n.set(`sort`,e)}i.select&&n.set(`select`,i.select.join(`,`));let a=i.filter??i.filters;a&&(this.parent._isFilterAST(a)||Array.isArray(a)?n.set(`filter`,JSON.stringify(a)):typeof a==`object`&&a&&Object.entries(a).forEach(([e,t])=>{t!=null&&n.append(e,String(t))})),i.aggregations&&n.set(`aggregations`,JSON.stringify(i.aggregations)),i.groupBy&&n.set(`groupBy`,i.groupBy.join(`,`));let o=n.toString(),s=await this.parent._fetch(this.url(`/data/${e}${o?`?${o}`:``}`));return this.parent._unwrap(s)},get:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}/${t}`));return this.parent._unwrap(n)},create:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}`),{method:`POST`,body:JSON.stringify(t)});return this.parent._unwrap(n)},createMany:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}/createMany`),{method:`POST`,body:JSON.stringify(t)});return this.parent._unwrap(n)},import:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}/import`),{method:`POST`,body:JSON.stringify(t)});return this.parent._unwrap(n)},createImportJob:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}/import/jobs`),{method:`POST`,body:JSON.stringify(t)});return this.parent._unwrap(n)},getImportJobProgress:async e=>{let t=await this.parent._fetch(this.url(`/data/import/jobs/${encodeURIComponent(e)}`));return this.parent._unwrap(t)},getImportJobResults:async e=>{let t=await this.parent._fetch(this.url(`/data/import/jobs/${encodeURIComponent(e)}/results`));return this.parent._unwrap(t)},listImportJobs:async(e={})=>{let t=new URLSearchParams;e.object&&t.set(`object`,e.object),e.status&&t.set(`status`,e.status),e.limit!=null&&t.set(`limit`,String(e.limit)),e.offset!=null&&t.set(`offset`,String(e.offset));let n=t.toString()?`?${t.toString()}`:``,r=await this.parent._fetch(this.url(`/data/import/jobs${n}`));return(await this.parent._unwrap(r)).jobs},cancelImportJob:async e=>{let t=await this.parent._fetch(this.url(`/data/import/jobs/${encodeURIComponent(e)}/cancel`),{method:`POST`});return this.parent._unwrap(t)},undoImportJob:async e=>{let t=await this.parent._fetch(this.url(`/data/import/jobs/${encodeURIComponent(e)}/undo`),{method:`POST`});return this.parent._unwrap(t)},update:async(e,t,n)=>{let r=await this.parent._fetch(this.url(`/data/${e}/${t}`),{method:`PATCH`,body:JSON.stringify(n)});return this.parent._unwrap(r)},batch:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}/batch`),{method:`POST`,body:JSON.stringify(t)});return this.parent._unwrap(n)},batchTransaction:async e=>{let t={operations:e,atomic:!0},n=await this.parent._fetch(this.url(`/batch`),{method:`POST`,body:JSON.stringify(t)});return this.parent._unwrap(n)},updateMany:async(e,t,n)=>{let r={records:t,options:n},i=await this.parent._fetch(this.url(`/data/${e}/updateMany`),{method:`POST`,body:JSON.stringify(r)});return this.parent._unwrap(i)},delete:async(e,t)=>{let n=await this.parent._fetch(this.url(`/data/${e}/${t}`),{method:`DELETE`});return this.parent._unwrap(n)},deleteMany:async(e,t,n)=>{let r={ids:t,options:n},i=await this.parent._fetch(this.url(`/data/${e}/deleteMany`),{method:`POST`,body:JSON.stringify(r)});return this.parent._unwrap(i)}},this.packages={list:async()=>{let e=await this.parent._fetch(this.url(`/packages`));return this.parent._unwrap(e)},get:async(e,t)=>{let n=t?`?version=${encodeURIComponent(t)}`:``,r=await this.parent._fetch(this.url(`/packages/${encodeURIComponent(e)}${n}`));return this.parent._unwrap(r)}},this.automation={getFlow:async e=>{let t=await this.parent._fetch(this.url(`/automation/${encodeURIComponent(e)}`));return this.parent._unwrap(t)},execute:async(e,t)=>{let n=await this.parent._fetch(this.url(`/automation/${encodeURIComponent(e)}/trigger`),{method:`POST`,body:JSON.stringify(t??{})});return this.parent._unwrap(n)},listRuns:async(e,t)=>{let n=new URLSearchParams;t?.limit!=null&&n.set(`limit`,String(t.limit)),t?.cursor&&n.set(`cursor`,t.cursor);let r=n.toString(),i=await this.parent._fetch(this.url(`/automation/${encodeURIComponent(e)}/runs${r?`?${r}`:``}`));return this.parent._unwrap(i)},getRun:async(e,t)=>{let n=await this.parent._fetch(this.url(`/automation/${encodeURIComponent(e)}/runs/${encodeURIComponent(t)}`));return this.parent._unwrap(n)},resume:async(e,t,n)=>{let r=await this.parent._fetch(this.url(`/automation/${encodeURIComponent(e)}/runs/${encodeURIComponent(t)}/resume`),{method:`POST`,body:JSON.stringify(n??{})});return this.parent._unwrap(r)},getScreen:async(e,t)=>{let n=await this.parent._fetch(this.url(`/automation/${encodeURIComponent(e)}/runs/${encodeURIComponent(t)}/screen`));return this.parent._unwrap(n)}},this.parent=e,this.environmentId=t}getProjectId(){return this.environmentId}scope(){return`/api/v1/environments/${encodeURIComponent(this.environmentId)}`}url(e){return`${this.parent._baseUrl()}${this.scope()}${e}`}};0&&(t.exports={FilterBuilder:g,ObjectStackClient:ae,QueryBuilder:_,RealtimeAPI:h,ScopedProjectClient:b,createFilter:y,createQuery:v})}))(),u=class{cache;inflight;maxSize;ttl;stats;constructor(e={}){this.cache=new Map,this.inflight=new Map,this.maxSize=e.maxSize||100,this.ttl=e.ttl||3e5,this.stats={hits:0,misses:0,evictions:0,coalesced:0}}async get(e,t){let n=Date.now(),r=this.cache.get(e);if(r){if(n-r.timestamp<this.ttl)return r.accessCount++,r.lastAccessed=n,this.stats.hits++,this.cache.delete(e),this.cache.set(e,r),r.data;this.cache.delete(e)}let i=this.inflight.get(e);if(i)return this.stats.coalesced++,i;this.stats.misses++;let a=(async()=>{try{let n=await t();return this.set(e,n),n}finally{this.inflight.delete(e)}})();return this.inflight.set(e,a),a}prime(e,t){this.set(e,t)}set(e,t){let n=Date.now();this.cache.size>=this.maxSize&&!this.cache.has(e)&&this.evictLRU(),this.cache.set(e,{data:t,timestamp:n,accessCount:1,lastAccessed:n})}evictLRU(){let e=this.cache.keys().next().value;e!==void 0&&(this.cache.delete(e),this.stats.evictions++)}invalidate(e){e?this.cache.delete(e):this.cache.clear()}clear(){this.cache.clear(),this.inflight.clear(),this.stats={hits:0,misses:0,evictions:0,coalesced:0}}getStats(){let e=this.stats.hits+this.stats.misses,t=e>0?this.stats.hits/e:0;return{size:this.cache.size,maxSize:this.maxSize,hits:this.stats.hits,misses:this.stats.misses,evictions:this.stats.evictions,coalesced:this.stats.coalesced,hitRate:t}}getCachedSync(e){let t=this.cache.get(e);if(t){if(this.ttl>0&&Date.now()-t.timestamp>this.ttl){this.cache.delete(e);return}return this.cache.delete(e),this.cache.set(e,t),this.stats.hits++,t.data}}has(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp>=this.ttl?(this.cache.delete(e),!1):!0:!1}},d=`/meta`,f=`/api/v1`;function ee(e){let t=e.baseUrl.replace(/\/+$/,``),n=e.environmentId?`${f}/environments/${encodeURIComponent(e.environmentId)}${d}`:`${f}${d}`;return/\/api\/v\d+$/i.test(t)?`${t.replace(/\/api\/v\d+$/i,``)}${e.environmentId?`${f}/environments/${encodeURIComponent(e.environmentId)}${d}`:`${f}${d}`}`:`${t}${n}`}async function p(e){let t;try{t=await e.json()}catch{t=await e.text().catch(()=>void 0)}let n=t&&typeof t==`object`?t:void 0,r=n?.error,i=(r&&typeof r==`object`?r.message:r)??n?.message??`Metadata request failed: ${e.status} ${e.statusText}`,a=Error(String(i));a.status=e.status,a.body=t;let o=r&&typeof r==`object`?r.details:void 0,s=o?.issues??(r&&typeof r==`object`?r.issues:void 0)??n?.issues;Array.isArray(s)&&(a.issues=s);let c=o?.code??(r&&typeof r==`object`?r.code:void 0)??n?.code;return c!=null&&(a.code=String(c)),a}var te=class e{base;fetchImpl;headers;previewDrafts;constructor(e){this.base=ee(e),this.fetchImpl=e.fetch??globalThis.fetch.bind(globalThis),this.headers={Accept:`application/json`,...e.headers??{}},this.previewDrafts=e.previewDrafts===!0}withEnvironment(t){return new e({baseUrl:this.base.replace(/\/api\/v\d+(?:\/environments\/[^/]+)?\/meta$/,``).replace(/\/+$/,``),environmentId:t,fetch:this.fetchImpl,headers:this.headers,previewDrafts:this.previewDrafts})}withPreviewDrafts(t){if(t===this.previewDrafts)return this;let n=this.base.match(/\/api\/v\d+\/environments\/([^/]+)\/meta$/);return new e({baseUrl:this.base.replace(/\/api\/v\d+(?:\/environments\/[^/]+)?\/meta$/,``).replace(/\/+$/,``),...n?{environmentId:decodeURIComponent(n[1])}:{},fetch:this.fetchImpl,headers:this.headers,previewDrafts:t})}async listTypes(){let e=await this.fetchImpl(this.base,{method:`GET`,headers:this.headers,cache:`no-store`});if(!e.ok)throw await p(e);let t=await e.json();return Array.isArray(t)?t:t&&Array.isArray(t.entries)?t.entries:t&&Array.isArray(t.items)?t.items:t&&Array.isArray(t.types)?t.types.map(e=>({type:e})):[]}async list(e,t={}){let n=[];t.packageId&&n.push(`package=${encodeURIComponent(t.packageId)}`),this.previewDrafts&&n.push(`preview=draft`);let r=n.length?`?${n.join(`&`)}`:``,i=`${this.base}/${encodeURIComponent(e)}${r}`,a=await this.fetchImpl(i,{method:`GET`,headers:this.headers,cache:`no-store`});if(!a.ok)throw await p(a);let o=await a.json();return Array.isArray(o)?o:o&&Array.isArray(o.items)?o.items:[]}async listDrafts(e={}){let t=[];e.packageId&&t.push(`packageId=${encodeURIComponent(e.packageId)}`),e.type&&t.push(`type=${encodeURIComponent(e.type)}`);let n=t.length?`?${t.join(`&`)}`:``,r=`${this.base}/_drafts${n}`,i=await this.fetchImpl(r,{method:`GET`,headers:this.headers,cache:`no-store`});if(!i.ok)throw await p(i);let a=await i.json();return Array.isArray(a)?a:a?.drafts??a?.data?.drafts??[]}async get(e,t,n={}){let r=[];n.state===`draft`?r.push(`state=draft`):this.previewDrafts&&r.push(`preview=draft`),n.packageId&&r.push(`package=${encodeURIComponent(n.packageId)}`);let i=r.length?`?${r.join(`&`)}`:``,a=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}${i}`,o=await this.fetchImpl(a,{method:`GET`,headers:this.headers,cache:`no-store`});if(o.status===404)return null;if(!o.ok)throw await p(o);return await o.json()}async getDraft(e,t,n={}){return this.get(e,t,{state:`draft`,...n.packageId?{packageId:n.packageId}:{}})}async save(e,t,n,r={}){if(!t||!String(t).trim())throw Error(`MetadataClient.save: name must be non-empty (type="${e}"). The PUT /meta/:type/:name route requires a name segment.`);let i=[];r.force&&i.push(`force=true`),r.mode===`draft`&&i.push(`mode=draft`),r.packageId&&i.push(`package=${encodeURIComponent(r.packageId)}`);let a=i.length?`?${i.join(`&`)}`:``,o=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}${a}`,s={...this.headers,"Content-Type":`application/json`};r.ifMatch&&(s[`If-Match`]=r.ifMatch),r.actor&&(s[`X-Actor`]=r.actor);let c=await this.fetchImpl(o,{method:`PUT`,headers:s,body:JSON.stringify(n)});if(!c.ok)throw await p(c);return await c.json()}async publishDraft(e,t){let n=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/publish`,r=await this.fetchImpl(n,{method:`POST`,headers:{...this.headers,"Content-Type":`application/json`,Accept:`application/json`},body:`{}`});if(!r.ok)throw await p(r);let i=await r.json().catch(()=>({}));return i?.data&&typeof i.data==`object`?i.data:i}async layered(e,t,n={}){let r=n.packageId?`&package=${encodeURIComponent(n.packageId)}`:``,i=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}?layers=true${r}`,a=await this.fetchImpl(i,{method:`GET`,headers:this.headers,cache:`no-store`});if(a.status===404)return{code:null,overlay:null,overlayScope:null,effective:null};if(!a.ok)throw await p(a);let o=await a.json();return o&&(`code`in o||`overlay`in o||`effective`in o)?{code:o.code??null,overlay:o.overlay??null,overlayScope:o.overlayScope??null,effective:o.effective??null,...o._diagnostics?{_diagnostics:o._diagnostics}:{},...o.lock===void 0?{}:{lock:o.lock},...o.lockReason===void 0?{}:{lockReason:o.lockReason},...o.lockSource===void 0?{}:{lockSource:o.lockSource},...o.lockDocsUrl===void 0?{}:{lockDocsUrl:o.lockDocsUrl},...o.provenance===void 0?{}:{provenance:o.provenance},...o.packageId===void 0?{}:{packageId:o.packageId},...o.packageVersion===void 0?{}:{packageVersion:o.packageVersion},...o.editable===void 0?{}:{editable:o.editable},...o.deletable===void 0?{}:{deletable:o.deletable},...o.resettable===void 0?{}:{resettable:o.resettable}}:{code:null,overlay:null,overlayScope:null,effective:o}}async diagnostics(e={}){let t=[];e.type&&t.push(`type=${encodeURIComponent(e.type)}`),e.severity&&t.push(`severity=${encodeURIComponent(e.severity)}`),e.packageId&&t.push(`package=${encodeURIComponent(e.packageId)}`);let n=t.length?`?${t.join(`&`)}`:``,r=`${this.base}/diagnostics${n}`,i=await this.fetchImpl(r,{method:`GET`,headers:this.headers,cache:`no-store`});if(i.status===404)return{entries:[],total:0,scannedTypes:0,scannedItems:0,stats:{}};if(!i.ok)throw await p(i);let a=await i.json();return{entries:Array.isArray(a.entries)?a.entries:[],total:typeof a.total==`number`?a.total:0,scannedTypes:typeof a.scannedTypes==`number`?a.scannedTypes:0,scannedItems:typeof a.scannedItems==`number`?a.scannedItems:0,stats:a.stats&&typeof a.stats==`object`?a.stats:{}}}async references(e,t){let n=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/references`,r=await this.fetchImpl(n,{method:`GET`,headers:this.headers,cache:`no-store`});if(r.status===404)return[];if(!r.ok)throw await p(r);let i=await r.json();return Array.isArray(i)?i:i?.items??[]}async reset(e,t,n={}){let r=n.state===`draft`?`?state=draft`:``,i=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}${r}`,a={...this.headers};n.ifMatch&&(a[`If-Match`]=n.ifMatch),n.actor&&(a[`X-Actor`]=n.actor);let o=await this.fetchImpl(i,{method:`DELETE`,headers:a});if(!o.ok)throw await p(o);return await o.json()}async publish(e,t,n={}){let r=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/publish`,i={...this.headers,"Content-Type":`application/json`};n.actor&&(i[`X-Actor`]=n.actor);let a=await this.fetchImpl(r,{method:`POST`,headers:i,body:JSON.stringify(n.message?{message:n.message}:{})});if(!a.ok)throw await p(a);return await a.json()}async rollback(e,t,n,r={}){let i=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/rollback`,a={...this.headers,"Content-Type":`application/json`};r.actor&&(a[`X-Actor`]=r.actor);let o=await this.fetchImpl(i,{method:`POST`,headers:a,body:JSON.stringify({toVersion:n,...r.message?{message:r.message}:{}})});if(!o.ok)throw await p(o);return await o.json()}async diff(e,t,n,r){let i=new URLSearchParams;n!==void 0&&i.set(`from`,String(n)),r!==void 0&&i.set(`to`,String(r));let a=i.toString(),o=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/diff${a?`?${a}`:``}`,s=await this.fetchImpl(o,{method:`GET`,headers:this.headers,cache:`no-store`});if(!s.ok)throw await p(s);return await s.json()}async history(e,t,n={}){let r=new URLSearchParams;n.sinceSeq!==void 0&&r.set(`sinceSeq`,String(n.sinceSeq)),n.limit!==void 0&&r.set(`limit`,String(n.limit));let i=r.toString(),a=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/history${i?`?${i}`:``}`,o=await this.fetchImpl(a,{method:`GET`,headers:this.headers,cache:`no-store`});if(!o.ok)throw await p(o);return await o.json()}async audit(e,t,n={}){let r=new URLSearchParams;n.limit!==void 0&&r.set(`limit`,String(n.limit));let i=r.toString(),a=`${this.base}/${encodeURIComponent(e)}/${encodeURIComponent(t)}/audit${i?`?${i}`:``}`,o=await this.fetchImpl(a,{method:`GET`,headers:this.headers,cache:`no-store`});if(!o.ok)throw await p(o);return await o.json()}},m=class extends Error{code;statusCode;details;constructor(e,t,n,r){super(e),this.code=t,this.statusCode=n,this.details=r,this.name=`ObjectStackError`,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}toJSON(){return{name:this.name,message:this.message,code:this.code,statusCode:this.statusCode,details:this.details,stack:this.stack}}},h=class extends m{constructor(e,t){super(`Metadata not found for object: ${e}`,`METADATA_NOT_FOUND`,404,{objectName:e,...t}),this.name=`MetadataNotFoundError`}},g=class extends m{successCount;failureCount;errors;constructor(e,t,n,r,i){super(`Bulk ${e} operation failed: ${t} succeeded, ${n} failed`,`BULK_OPERATION_ERROR`,500,{operation:e,successCount:t,failureCount:n,errors:r,...i}),this.successCount=t,this.failureCount=n,this.errors=r,this.name=`BulkOperationError`}getSummary(){let e=this.successCount+this.failureCount,t=e>0?this.failureCount/e:0;return{operation:this.details?.operation,total:e,successful:this.successCount,failed:this.failureCount,failureRate:t,errors:this.errors}}},_=class extends m{url;constructor(e,t,n,r){super(`Connection error: ${e}`,`CONNECTION_ERROR`,r||503,{url:t,...n}),this.url=t,this.name=`ConnectionError`}},v=class extends m{constructor(e=`Authentication failed`,t,n){super(e,`AUTHENTICATION_ERROR`,n||401,t),this.name=`AuthenticationError`}},y=class extends m{field;validationErrors;constructor(e,t,n,r){super(e,`VALIDATION_ERROR`,400,{field:t,validationErrors:n,...r}),this.field=t,this.validationErrors=n,this.name=`ValidationError`}getValidationErrors(){return this.validationErrors||[]}};function ne(e,t){let n=e?.status||e?.statusCode||500,r=e?.message||e?.statusText||`Unknown error`,i={context:t,response:{status:n,data:e?.data,headers:e?.headers}};switch(n){case 401:return new v(r,i,401);case 403:return new v(r,i,403);case 404:return t?.includes(`metadata`)||t?.includes(`schema`)||t?.includes(`getObjectSchema`)?new h(re(t),i):new m(r,`NOT_FOUND`,404,i);case 400:return new y(r,void 0,e?.data?.errors,i);case 503:return new _(r,e?.config?.url,i,503);case 504:return new _(r,e?.config?.url,i,504);default:return new m(r,`UNKNOWN_ERROR`,n,i)}}function re(e){if(!e)return`unknown`;let t=e.match(/\(([^)]+)\)/);return t?t[1]:`unknown`}var ie=`sys_user_preference`;function ae(e){let{dataSource:t,userId:n,key:r,resource:i=ie,onError:a=()=>{}}=e,o=null,s=Promise.resolve(),c=async()=>{let e={$filter:{user_id:n,key:r},$top:1};return((await t.find(i,e))?.data??[]).find(e=>{if(!e)return!1;let t=e.user_id!==void 0&&e.user_id!==n,i=e.key!==void 0&&e.key!==r;return!t&&!i})??null},l=e=>{if(Array.isArray(e))return e;if(typeof e==`string`)try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}return[]},u=async e=>{if(o!==null)try{await t.update(i,o,{value:e});return}catch(e){o=null,a(`save`,e)}let s=await c();if(s&&s.id!==void 0&&s.id!==null){o=s.id,await t.update(i,s.id,{value:e});return}try{let a=(await t.create(i,{user_id:n,key:r,value:e}))?.id;a!=null&&(o=a)}catch(n){let r=await c();if(r&&r.id!==void 0&&r.id!==null){o=r.id,await t.update(i,r.id,{value:e});return}throw n}};return{async load(){try{let e=await c();return e?(e.id!==void 0&&e.id!==null&&(o=e.id),l(e.value)):(o=null,[])}catch(e){return a(`load`,e),[]}},async save(e){let t=s.then(()=>u(e)).catch(e=>{a(`save`,e)});return s=t,t}}}var b={equals:`=`,eq:`=`,"==":`=`,not_equals:`!=`,notequals:`!=`,ne:`!=`,greater_than:`>`,greaterthan:`>`,gt:`>`,greater_than_or_equal:`>=`,greater_than_or_equals:`>=`,greaterthanorequal:`>=`,gte:`>=`,less_than:`<`,lessthan:`<`,lt:`<`,less_than_or_equal:`<=`,less_than_or_equals:`<=`,lessthanorequal:`<=`,lte:`<=`,in:`in`,not_in:`nin`,notin:`nin`,nin:`nin`,contains:`contains`,not_contains:`notcontains`,notcontains:`notcontains`,starts_with:`startswith`,startswith:`startswith`,ends_with:`endswith`,endswith:`endswith`,between:`between`,is_null:`isnull`,isnull:`isnull`,is_not_null:`isnotnull`,isnotnull:`isnotnull`,before:`<`,after:`>`};function oe(e){return typeof e==`string`?b[e.toLowerCase()]??b[e]??e:null}var se=class extends Error{code=`INVALID_FILTER`;httpStatus=400;entry;index;constructor(e,t){let n=JSON.stringify(e)??String(e);super(`Filter entry ${t} is not a usable filter rule (${n}). Expected { field, operator, value } with a non-empty field.`),this.name=`MalformedFilterError`,this.entry=e,this.index=t}};function ce(e){if(!e||typeof e!=`object`)return null;let t=e.field,n=oe(e.operator??e.op??`=`);return!t||!n?null:[String(t),n,e.value]}function le(e){let t=e[0];return e.length>0&&typeof t==`object`&&!!t&&!Array.isArray(t)&&t.field!==void 0}function x(e){let t=e.map((e,t)=>{if(Array.isArray(e))return de(e);let n=ce(e);if(!n)throw new se(e,t);return n});return t.length===1?t[0]:[`and`,...t]}var S=new Set([`and`,`or`]);function ue(e){if(le(e))return x(e);let t=e[0];return typeof t==`string`&&S.has(t.toLowerCase())?[t,...e.slice(1).map(de)]:e.every(e=>Array.isArray(e))?e.map(de):e}function de(e){if(Array.isArray(e))return e.length>0?ue(e):e;if(e&&typeof e==`object`&&e.field!==void 0){let t=ce(e);if(t)return t}return e}function fe(e){if(e!=null){if(Array.isArray(e))return e.length===0?void 0:ue(e);if(typeof e==`object`)return Object.keys(e).length===0?void 0:t(e)}}function pe(e){if(e==null)return;if(typeof e==`string`){let t=e.trim();return t.length>0?t:void 0}let t=(e,t)=>String(t).toLowerCase()===`desc`?`-${e}`:e;if(Array.isArray(e)){let n=e.map(e=>typeof e==`string`?e.trim():t(e.field,e.order)).filter(e=>e.length>0);return n.length>0?n.join(`,`):void 0}if(typeof e==`object`){let n=Object.entries(e).map(([e,n])=>t(e,n));return n.length>0?n.join(`,`):void 0}}var C=new Map;async function me(e,t){let n=e||`<default>`,r=C.get(n);if(r)return r;let i=t().catch(e=>{throw C.delete(n),e});return C.set(n,i),i}function w(e){let t=e?.capabilities;if(!t||typeof t!=`object`)return;let n=t.transactionalBatch;if(typeof n==`boolean`)return n;if(n&&typeof n==`object`&&typeof n.enabled==`boolean`)return n.enabled}function he(e){if(!e||typeof e!=`object`)return!1;let t=e;if(t.httpStatus===404||t.status===404||t.statusCode===404)return!0;let n=typeof t.code==`string`?t.code:``;return i({code:n},[`OBJECT_NOT_FOUND`,`RECORD_NOT_FOUND`])}var ge=class extends Error{code=`ANALYTICS_NOT_INSTALLED`;surface;constructor(e,t){super(`Analytics capability is not installed on this deployment — ${e} is unavailable. Install @objectstack/service-analytics and mount AnalyticsServicePlugin to enable it.`+(t?` (server said: ${t})`:``)),this.name=`AnalyticsNotInstalledError`,this.surface=e}},T=class extends Error{code=`ANALYTICS_QUERY_REJECTED`;serverCode;constructor(e,t){super(`Analytics rejected the query: ${e??`the request body does not match the AnalyticsQuery contract`}`),this.name=`AnalyticsQueryRejectedError`,this.serverCode=t}};function E(e){let t=e??{},n=typeof t.code==`string`?t.code:void 0,r=typeof t.message==`string`?t.message:void 0,i=typeof t.httpStatus==`number`?t.httpStatus:typeof t.status==`number`?t.status:typeof t.statusCode==`number`?t.statusCode:void 0;return n===`VALIDATION_FAILED`||i===400?{kind:`rejected`,code:n,message:r}:i===404||i===501||n===`NOT_IMPLEMENTED`||n===`ROUTE_NOT_FOUND`?{kind:`not-installed`,code:n,message:r}:{kind:`unknown`,code:n,message:r}}var D=class extends Error{code=`CONCURRENT_UPDATE`;httpStatus=409;currentVersion;currentRecord;constructor(e){super(e.message??`Record was modified by another user`),this.name=`ConcurrentUpdateError`,this.currentVersion=e.currentVersion,this.currentRecord=e.currentRecord}};function O(e){if(!e||typeof e!=`object`)return e;let t=e,n=t.details??{};if(t.code===`VALIDATION_FAILED`||t.name===`ValidationError`){let e=Array.isArray(n.fields)?n.fields:Array.isArray(t.fields)?t.fields:[],r=e.map(e=>{let t=e??{},n=typeof t.field==`string`?t.field:void 0;return n?{field:n,message:typeof t.message==`string`&&t.message.trim()?t.message:typeof t.code==`string`?t.code:``}:null}).filter(e=>e!==null);return new y(typeof t.message==`string`?t.message:`Validation failed`,r[0]?.field,r,{fields:e})}return t.code!==`CONCURRENT_UPDATE`&&t.httpStatus!==409||t.code!==`CONCURRENT_UPDATE`?e:new D({currentVersion:typeof n.currentVersion==`string`?n.currentVersion:null,currentRecord:n.currentRecord??null,message:typeof t.message==`string`?t.message:void 0})}function _e(){let e=e=>{if(!e||typeof e!=`object`)return!1;if(e.status===404||e.statusCode===404)return!0;let t=e.error;if(t&&typeof t==`object`){let e=t.code;if(i({code:e},[`OBJECT_NOT_FOUND`,`RECORD_NOT_FOUND`]))return!0}return!1},t={debug:(e,t)=>console.debug(e,t??``),info:(e,t)=>console.info(e,t??``),warn:(e,t)=>console.warn(e,t??``),error:(t,n,r)=>{if(e(r)){console.debug(`[ObjectStack] ${t} (suppressed expected 404)`,r);return}console.error(t,n??``,r??``)},fatal:(e,t,n)=>console.error(e,t??``,n??``),log:(e,...t)=>console.log(e,...t),child:()=>t,withTrace:()=>t};return t}function ve(e){if(typeof e!=`object`||!e)return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(ve).join(`,`)}]`;let t=e;return`{${Object.keys(t).sort().map(e=>`${JSON.stringify(e)}:${ve(t[e])}`).join(`,`)}}`}var ye=class{client;connected=!1;connectPromise=null;metadataCache;connectionState=`disconnected`;connectionStateListeners=[];batchProgressListeners=[];autoReconnect;maxReconnectAttempts;reconnectDelay;reconnectAttempts=0;baseUrl;token;analyticsCapabilityWarned=!1;fetchImpl;inflightFinds=new Map;missingResources=new Set;batchUnsupported=!1;atomicBatchCapability;mutationListeners=new Set;writeWarningListeners=new Set;constructor(e){this.client=new l.ObjectStackClient({...e,logger:_e()}),this.metadataCache=new u(e.cache),this.autoReconnect=e.autoReconnect??!0,this.maxReconnectAttempts=e.maxReconnectAttempts??3,this.reconnectDelay=e.reconnectDelay??1e3,this.baseUrl=e.baseUrl,this.token=e.token,this.fetchImpl=e.fetch||globalThis.fetch.bind(globalThis)}async connect(){if(!this.connected)return this.connectPromise?this.connectPromise:(this.setConnectionState(`connecting`),this.connectPromise=(async()=>{try{let e=this.baseUrl||``,t=e?`${e.replace(/\/$/,``)}/api/v1/discovery`:`/api/v1/discovery`,n=await me(e,async()=>{let e=await this.fetchImpl(t,{method:`GET`,headers:this.token?{Authorization:`Bearer ${this.token}`}:void 0});if(!e.ok)throw Error(`discovery ${e.status} ${e.statusText}`);let n=await e.json();return n&&typeof n.success==`boolean`&&`data`in n?n.data:n});this.client.discoveryInfo=n,this.atomicBatchCapability=w(n),this.connected=!0,this.reconnectAttempts=0,this.setConnectionState(`connected`)}catch(e){let t=new _(e instanceof Error?e.message:`Failed to connect to ObjectStack server`,void 0,{originalError:e});if(this.setConnectionState(`error`,t),this.autoReconnect&&this.reconnectAttempts<this.maxReconnectAttempts)await this.attemptReconnect();else throw t}finally{this.connectPromise=null}})(),this.connectPromise)}async attemptReconnect(){this.reconnectAttempts++,this.setConnectionState(`reconnecting`);let e=this.reconnectDelay*2**(this.reconnectAttempts-1);await new Promise(t=>setTimeout(t,e)),this.connected=!1,await this.connect()}getConnectionState(){return this.connectionState}isConnected(){return this.connected&&this.connectionState===`connected`}onConnectionStateChange(e){return this.connectionStateListeners.push(e),()=>{let t=this.connectionStateListeners.indexOf(e);t>-1&&this.connectionStateListeners.splice(t,1)}}onBatchProgress(e){return this.batchProgressListeners.push(e),()=>{let t=this.batchProgressListeners.indexOf(e);t>-1&&this.batchProgressListeners.splice(t,1)}}setConnectionState(e,t){this.connectionState=e;let n={state:e,timestamp:Date.now(),error:t};this.connectionStateListeners.forEach(e=>{try{e(n)}catch(e){console.error(`Error in connection state listener:`,e)}})}emitBatchProgress(e){this.batchProgressListeners.forEach(t=>{try{t(e)}catch(e){console.error(`Error in batch progress listener:`,e)}})}async find(e,t){if(this.missingResources.has(e))return{data:[],total:0};let n=`${e}::${ve(t)}`,r=this.inflightFinds.get(n);if(r)return r;let i=(async()=>{if(await this.connect(),t?.$expand&&t.$expand.length>0||t?.$search!=null&&String(t.$search).trim()!==``){let n=await this.rawFindWithPopulate(e,t);return this.normalizeQueryResult(n,t)}let n=this.convertQueryParams(t);try{let r=await this.client.data.find(e,n);return this.normalizeQueryResult(r,t)}catch(t){if(he(t))return this.missingResources.add(e),{data:[],total:0};throw t}})();this.inflightFinds.set(n,i);let a=()=>{this.inflightFinds.get(n)===i&&this.inflightFinds.delete(n)};return i.then(a,a),i}async searchAll(e,t){let n=(e??``).trim();if(n===``)return{query:``,hits:[]};await this.connect();let r=new URLSearchParams;r.set(`q`,n),t?.limit!=null&&t.limit>0&&r.set(`limit`,String(t.limit)),t?.objects&&t.objects.length>0&&r.set(`objects`,t.objects.join(`,`));let i=(this.baseUrl||``).replace(/\/$/,``),a=`${i}${/\/api\/v\d+$/i.test(i)?`/search`:`/api/v1/search`}?${r.toString()}`,o={"Content-Type":`application/json`};this.token&&(o.Authorization=`Bearer ${this.token}`);let s=await this.fetchImpl(a,{method:`GET`,headers:o});if(!s.ok){if(s.status===404)return{query:n,hits:[]};let e=await s.json().catch(()=>({message:s.statusText})),t=Error(e?.error?.message||e?.message||s.statusText);throw t.status=s.status,t}let c=await s.json(),l=c&&typeof c==`object`&&typeof c.success==`boolean`&&`data`in c?c.data:c,u=Array.isArray(l?.hits)?l.hits:Array.isArray(l)?l:[],d=[];for(let e of u){if(!e||typeof e!=`object`)continue;let t=e,n=t.object??t.objectName??t.object_name,r=t.id??t.record?.id??t.record?._id;typeof n==`string`&&r!=null&&d.push({object:n,id:String(r),title:typeof t.title==`string`?t.title:void 0,snippet:typeof t.snippet==`string`?t.snippet:void 0,record:t.record&&typeof t.record==`object`?t.record:void 0})}return{query:typeof l?.query==`string`?l.query:n,hits:d}}async findOne(e,t,n){if(await this.connect(),n?.$expand&&n.$expand.length>0)try{let r={...n,$filter:{id:String(t)},$top:1},i=await this.rawFindWithPopulate(e,r);if(Array.isArray(i))return i[0]||null;let a=i;return(a.records||a.value||[])[0]||null}catch(e){if(he(e))return null}try{return(await this.client.data.get(e,String(t))).record}catch(e){if(he(e))return null;throw e}}emitMutation(e){for(let t of this.mutationListeners)try{t(e)}catch(e){console.warn(`ObjectStackAdapter: mutation listener error`,e)}}onMutation(e){return this.mutationListeners.add(e),()=>{this.mutationListeners.delete(e)}}emitWriteWarning(e){for(let t of this.writeWarningListeners)try{t(e)}catch(e){console.warn(`ObjectStackAdapter: write-warning listener error`,e)}}notifyDroppedFields(e,t,n,r){let i=n?.droppedFields;if(!Array.isArray(i)||i.length===0)return;let a=i.filter(e=>!!e&&typeof e==`object`&&Array.isArray(e.fields)&&e.fields.length>0);a.length!==0&&this.emitWriteWarning({operation:e,resource:t,...r===void 0?{}:{id:r},droppedFields:a})}notifyBatchDroppedFields(e,t){let n=t?.droppedFields;if(!(!Array.isArray(n)||n.length===0))for(let t of n){if(!t||typeof t!=`object`)continue;let n=t;if(!Array.isArray(n.fields)||n.fields.length===0)continue;let r=typeof n.index==`number`?e[n.index]:void 0,i=(r?.action??`create`)===`create`?`create`:`update`;this.emitWriteWarning({operation:i,resource:n.object??r?.object??``,...r?.id!==void 0&&r?.id!==null?{id:r.id}:{},droppedFields:[{object:n.object,fields:n.fields,reason:n.reason}]})}}onWriteWarning(e){return this.writeWarningListeners.add(e),()=>{this.writeWarningListeners.delete(e)}}async create(e,t){await this.connect();try{let n=await this.client.data.create(e,t);return this.emitMutation({type:`create`,resource:e,record:{...n.record}}),this.notifyDroppedFields(`create`,e,n,n.record?.id),n.record}catch(e){throw O(e)}}async update(e,t,n,r){await this.connect();try{let i=await this.client.data.update(e,String(t),n,r?.ifMatch?{ifMatch:r.ifMatch}:void 0);return this.emitMutation({type:`update`,resource:e,id:t,record:{...i.record}}),this.notifyDroppedFields(`update`,e,i,t),i.record}catch(e){throw O(e)}}async delete(e,t,n){await this.connect();try{let r=await this.client.data.delete(e,String(t),n?.ifMatch?{ifMatch:n.ifMatch}:void 0);return r.deleted&&this.emitMutation({type:`delete`,resource:e,id:t}),r.deleted}catch(e){throw O(e)}}async bulkUpdate(e,t,n){if(await this.connect(),!t||t.length===0)return 0;let r=t.map(e=>({id:String(e),data:n})),i=t=>(t>0&&this.emitMutation({type:`update`,resource:e}),t),a=this.client.data.updateMany;if(typeof a==`function`)try{let n=await a(e,r,{continueOnError:!0});return n&&typeof n==`object`&&typeof n.succeeded==`number`?i(n.succeeded):i(Array.isArray(n)?n.length:t.length)}catch(e){throw O(e)}let o=0;for(let r of t)try{await this.client.data.update(e,String(r),n),o++}catch{}return i(o)}async bulkDelete(e,t){if(await this.connect(),!t||t.length===0)return 0;let n=t.map(e=>String(e)),r=t=>(t>0&&this.emitMutation({type:`delete`,resource:e}),t),i=this.client.data.deleteMany;if(typeof i==`function`)try{let t=await i(e,n,{continueOnError:!0});return t&&typeof t==`object`&&typeof t.succeeded==`number`?r(t.succeeded):r(Array.isArray(t)?t.length:n.length)}catch(e){throw O(e)}let a=0;for(let t of n)try{await this.client.data.delete(e,t),a++}catch{}return r(a)}async batchTransaction(e){await this.connect();let t=this.atomicBatchCapability===!0;if(!t&&this.batchUnsupported)return n(this,e);try{let t=await this.client.data.batchTransaction(e);return this.emitBatchMutations(e,t?.results),this.notifyBatchDroppedFields(e,t),t}catch(n){let r=this.errorStatusOf(n);if(!t&&this.batchStatusUnsupported(r))return this.fallbackToEmulation(e,r);throw n}}batchStatusUnsupported(e){return e===404||e===405||e===501}errorStatusOf(e){if(!e||typeof e!=`object`)return;let t=e,n=t.httpStatus??t.status??t.statusCode;return typeof n==`number`?n:void 0}fallbackToEmulation(e,t){return this.batchUnsupported||(this.batchUnsupported=!0,console.warn(`ObjectStackAdapter: POST /api/v1/batch unavailable (HTTP ${t??`?`}) — falling back to non-atomic client-side batch emulation. Cross-object saves on this backend are best-effort, not transactional.`)),n(this,e)}emitBatchMutations(e,t){let n=Array.isArray(t)?t:[];e.forEach((e,t)=>{let r=e.action??`create`,i=n[t];r===`create`?this.emitMutation({type:`create`,resource:e.object,record:i}):r===`update`?this.emitMutation({type:`update`,resource:e.object,id:e.id??i?.id??i?._id,record:i}):r===`delete`&&this.emitMutation({type:`delete`,resource:e.object,id:e.id})})}async bulk(e,t,n){if(await this.connect(),!n||n.length===0)return[];let r=n.length,i=0,a=0,o=()=>{this.emitBatchProgress({operation:t,total:r,completed:i,failed:a,percentage:r>0?(i+a)/r*100:0})};try{switch(t){case`create`:{o();let t=await this.client.data.createMany(e,n);return i=t.length,a=r-i,o(),i>0&&this.emitMutation({type:`create`,resource:e}),t}case`delete`:{let t=n.map(e=>e.id).filter(Boolean);if(t.length===0){let e=n.map((e,t)=>({index:t,error:`Missing ID for item at index ${t}`}));throw a=n.length,o(),new g(`delete`,0,n.length,e)}return o(),await this.client.data.deleteMany(e,t),i=t.length,a=r-i,o(),i>0&&this.emitMutation({type:`delete`,resource:e}),[]}case`update`:{if(typeof this.client.data.updateMany==`function`)try{o();let t=this.client.data.updateMany,s=await t(e,n);return i=s.length,a=r-i,o(),i>0&&this.emitMutation({type:`update`,resource:e}),s}catch{}let t=[],s=[];for(let r=0;r<n.length;r++){let c=n[r],l=c.id;if(!l){s.push({index:r,error:`Missing ID`}),a++,o();continue}try{let n=await this.client.data.update(e,String(l),c);t.push(n.record),i++,o()}catch(e){let t=e instanceof Error?e.message:String(e);s.push({index:r,error:t}),a++,o()}}if(i>0&&this.emitMutation({type:`update`,resource:e}),s.length>0)throw new g(`update`,t.length,s.length,s,{resource:e,totalRecords:n.length});return t}default:throw new m(`Unsupported bulk operation: ${t}`,`UNSUPPORTED_OPERATION`,400)}}catch(r){if(o(),r instanceof g||r instanceof m)throw r;let i=r instanceof Error?r.message:String(r),a=n.map((e,t)=>({index:t,error:i}));throw new g(t,0,n.length,a,{resource:e,originalError:r})}}async importRecords(e,t){await this.connect();let n=this.client.data.import;if(typeof n!=`function`)throw new m(`The connected @objectstack/client does not support data.import(). Upgrade the client, or import via a per-row create fallback.`,`UNSUPPORTED_OPERATION`,400);try{return await n.call(this.client.data,e,t)}catch(e){throw O(e)}}importJobApi(){let e=this.client.data;if(typeof e.createImportJob==`function`)return e}async createImportJob(e,t){await this.connect();let n=this.importJobApi();if(!n)throw new m(`The connected @objectstack/client does not support async import jobs (data.createImportJob). Upgrade the client, or use the synchronous importRecords() path.`,`UNSUPPORTED_OPERATION`,400);try{return await n.createImportJob.call(this.client.data,e,t)}catch(e){throw O(e)}}async getImportJobProgress(e){await this.connect();let t=this.importJobApi();if(!t)throw new m(`The connected @objectstack/client does not support async import jobs.`,`UNSUPPORTED_OPERATION`,400);try{return await t.getImportJobProgress.call(this.client.data,e)}catch(e){throw O(e)}}async getImportJobResults(e){await this.connect();let t=this.importJobApi();if(!t)throw new m(`The connected @objectstack/client does not support async import jobs.`,`UNSUPPORTED_OPERATION`,400);try{return await t.getImportJobResults.call(this.client.data,e)}catch(e){throw O(e)}}async listImportJobs(e={}){await this.connect();let t=this.importJobApi();if(!t)throw new m(`The connected @objectstack/client does not support async import jobs.`,`UNSUPPORTED_OPERATION`,400);try{return await t.listImportJobs.call(this.client.data,e)}catch(e){throw O(e)}}async cancelImportJob(e){await this.connect();let t=this.importJobApi();if(!t)throw new m(`The connected @objectstack/client does not support async import jobs.`,`UNSUPPORTED_OPERATION`,400);try{await t.cancelImportJob.call(this.client.data,e)}catch(e){throw O(e)}}async undoImportJob(e){await this.connect();let t=this.importJobApi();if(!t||typeof t.undoImportJob!=`function`)throw new m(`The connected @objectstack/client does not support undoing import jobs (data.undoImportJob).`,`UNSUPPORTED_OPERATION`,400);try{return await t.undoImportJob.call(this.client.data,e)}catch(e){throw O(e)}}normalizeQueryResult(e,t){if(Array.isArray(e))return{data:e,total:e.length,page:1,pageSize:e.length,hasMore:!1};let n=e,r=n.records||n.value||[],i=n.total??n.count??r.length,a=typeof n.hasMore==`boolean`?n.hasMore:t?.$top?r.length===t.$top:!1;return{data:r,total:i,page:t?.$skip&&t.$top?Math.floor(t.$skip/t.$top)+1:1,pageSize:t?.$top,hasMore:a}}async rawFindWithPopulate(e,t){let n=new URLSearchParams;if(t.$expand&&t.$expand.length>0&&n.set(`populate`,t.$expand.join(`,`)),t.$top!==void 0&&n.set(`top`,String(t.$top)),t.$skip!==void 0&&n.set(`skip`,String(t.$skip)),t.$search!=null&&String(t.$search).trim()!==``&&n.set(`search`,String(t.$search).trim()),t.$searchFields&&t.$searchFields.length>0&&n.set(`searchFields`,t.$searchFields.join(`,`)),t.$select&&t.$select.length>0){let e=t.$select.includes(`id`)?t.$select:[`id`,...t.$select];n.set(`select`,e.join(`,`))}let r=pe(t.$orderby);if(r&&n.set(`sort`,r),t.$filter!==void 0&&t.$filter!==null){let e=fe(t.$filter);e!==void 0&&n.set(`filter`,JSON.stringify(e))}let i=this.baseUrl.replace(/\/$/,``),a=n.toString(),o=`${i}${/\/api\/v\d+$/i.test(i)?`/data`:`/api/v1/data`}/${e}${a?`?${a}`:``}`,s={"Content-Type":`application/json`};this.token&&(s.Authorization=`Bearer ${this.token}`);let c=await this.fetchImpl(o,{method:`GET`,headers:s});if(!c.ok){let e=await c.json().catch(()=>({message:c.statusText})),t=Error(e?.error?.message||e?.message||c.statusText);throw t.status=c.status,t}let l=await c.json();return l&&typeof l.success==`boolean`&&`data`in l?l.data:l}async exportDownload(e,t={}){let n=new URLSearchParams,r=t.format===`xlsx`?`xlsx`:t.format===`json`?`json`:`csv`;if(n.set(`format`,r),t.fields&&t.fields.length>0&&n.set(`fields`,t.fields.join(`,`)),t.limit&&t.limit>0&&n.set(`limit`,String(t.limit)),t.includeHeaders===!1&&n.set(`header`,`false`),t.sort&&t.sort.length>0){let e=t.sort.filter(e=>e&&e.field).map(e=>`${e.field}:${e.direction===`desc`?`desc`:`asc`}`).join(`,`);e&&n.set(`orderby`,e)}if(t.filter!==void 0&&t.filter!==null){let e=fe(t.filter);e!==void 0&&n.set(`filter`,JSON.stringify(e))}let i=typeof t.search==`string`?t.search.trim():``;i&&(n.set(`search`,i),t.searchFields&&t.searchFields.length>0&&n.set(`searchFields`,t.searchFields.join(`,`)));let a=this.baseUrl.replace(/\/$/,``),o=`${a}${/\/api\/v\d+$/i.test(a)?`/data`:`/api/v1/data`}/${encodeURIComponent(e)}/export?${n.toString()}`,s={...this.getAuthHeaders()},c=await this.fetchImpl(o,{method:`GET`,headers:s,credentials:`include`});if(!c.ok){let e=await c.json().catch(()=>({message:c.statusText})),t=Error(e?.error?.message||e?.message||c.statusText);throw t.status=c.status,t}return await c.blob()}convertQueryParams(e){if(!e)return{};let n={};e.$select&&(n.select=e.$select.includes(`id`)?e.$select:[`id`,...e.$select]),e.$filter!==void 0&&e.$filter!==null&&((Array.isArray(e.$filter)?e.$filter.length===0:typeof e.$filter==`object`&&Object.keys(e.$filter).length===0)||(n.filters=Array.isArray(e.$filter)?ue(e.$filter):t(e.$filter)));let r=pe(e.$orderby);return r&&(n.sort=r),e.$skip!==void 0&&(n.skip=e.$skip),e.$top!==void 0&&(n.top=e.$top),e.$search!=null&&String(e.$search).trim()!==``&&(n.search=String(e.$search).trim()),e.$searchFields&&e.$searchFields.length>0&&(n.searchFields=e.$searchFields),n}async getObjectSchema(e){await this.connect();try{let t=await this.metadataCache.get(e,()=>this.fetchObjectSchemaFresh(e));return r(t),this.applyFieldWidgetOverrides(e,t),t}catch(t){let n=t;throw he(n)?new h(e,{originalError:t}):t instanceof m?t:ne(n,`getObjectSchema(${e})`)}}applyFieldWidgetOverrides(e,t){let n={sys_permission_set:{object_permissions:`permission-facet-link`,field_permissions:`permission-facet-link`,system_permissions:`permission-facet-link`,row_level_security:`permission-facet-link`,tab_permissions:`permission-facet-link`,admin_scope:`permission-facet-link`}}[e],r=t&&typeof t==`object`?t.fields:null;if(!(!n||!r))for(let[e,t]of Object.entries(n))if(Array.isArray(r)){let n=r.find(t=>t?.name===e);n&&!n.widget&&(n.widget=t)}else{let n=r[e];n&&!n.widget&&(n.widget=t)}}async fetchObjectSchemaFresh(e){let t=(this.baseUrl||``).replace(/\/$/,``),n=`${t}${/\/api\/v\d+$/i.test(t)?`/meta`:`/api/v1/meta`}/object/${encodeURIComponent(e)}`,r={"Content-Type":`application/json`};this.token&&(r.Authorization=`Bearer ${this.token}`);let i=await this.fetchImpl(n,{method:`GET`,headers:r,cache:`no-cache`});if(!i.ok){let e=await i.json().catch(()=>({message:i.statusText})),t=Error(e?.error?.message||e?.message||i.statusText);throw t.status=i.status,t}let a=await i.json(),o=a&&typeof a==`object`&&`success`in a&&`data`in a?a.data:a;return o&&typeof o==`object`&&`item`in o?o.item:o}async getObjects(){try{await this.connect();let e=(this.baseUrl||``).replace(/\/$/,``),t=`${e}${/\/api\/v\d+$/i.test(e)?`/meta`:`/api/v1/meta`}/object`,n={"Content-Type":`application/json`};this.token&&(n.Authorization=`Bearer ${this.token}`);let r=await this.fetchImpl(t,{method:`GET`,headers:n});if(!r.ok)return[];let i=await r.json(),a=i&&typeof i==`object`&&`success`in i&&`data`in i?i.data:i;return(Array.isArray(a)?a:Array.isArray(a?.items)?a.items:[]).map(e=>({name:String(e?.name??``),label:e?.label==null?void 0:String(e.label)})).filter(e=>e.name)}catch{return[]}}getClient(){return this.client}async getDiscovery(){try{return await this.connect(),this.client.discoveryInfo||null}catch{return null}}async listViewOverrides(e){await this.connect();try{let t=`view-overrides:${e}`;return await this.metadataCache.get(t,async()=>{let t=await this.client.meta.getItems(e),n=Array.isArray(t?.items)?t.items:[],r={};for(let e of n){if(!e||typeof e!=`object`)continue;let t=e.name??e.id??e._name;typeof t==`string`&&t&&(r[t]=e)}return r})}catch{return{}}}async getView(e,t){await this.connect();try{let n=`view:${e}:${t}`;return await this.metadataCache.get(n,async()=>{let e=await this.client.meta.getItem(`view`,t);return e&&e.item?e.item:e??null})}catch{return null}}async updateViewConfig(e,t,n){await this.connect();let r={...n||{},object:n?.object||e,name:t},i=await this.client.meta.saveItem(`view`,t,r),a=`view:${e}:${t}`;return this.metadataCache.invalidate?.(a),this.metadataCache.invalidate?.(`view-overrides:${e}`),this.metadataCache.invalidate?.(`views:${e}`),i&&i.item?i.item:i??void 0}async listViews(e,t){await this.connect();try{let n;if(t?.previewDrafts){let e=await this.metadataClient().withPreviewDrafts(!0).list(`view`);n=Array.isArray(e)?e:[]}else{let e=await this.client.meta.getItems(`view`);n=Array.isArray(e?.items)?e.items:Array.isArray(e)?e:[]}let r=new Set([`form`,`detail`]);return n.filter(t=>{if(!t)return!1;let n=t.list??t;if((n?.data?.object??n?.object??n?.objectName)!==e)return!1;let i=t.viewKind??n?.viewKind;return!(i&&r.has(i))}).map(e=>{let t=e.list??e,n=e._draft===!0||t?._draft===!0;return t&&t.config&&typeof t.config==`object`?{...t.config,name:t.name??t.config.name,label:t.label??t.config.label,isDefault:!!t.isDefault,...n?{_draft:!0}:{}}:n?{...t,_draft:!0}:t})}catch(e){return console.warn(`[OBJECTSTACKDataSource] listViews failed:`,e),[]}}metadataClient(){return new te({baseUrl:this.baseUrl,fetch:this.fetchImpl,...this.token?{headers:{Authorization:`Bearer ${this.token}`}}:{}})}async listImportMappings(e){await this.connect();try{let t=await this.client.meta.getItems(`mapping`);return(Array.isArray(t?.items)?t.items:Array.isArray(t)?t:[]).filter(t=>t&&t.targetObject===e)}catch(e){return console.warn(`[OBJECTSTACKDataSource] listImportMappings failed:`,e),[]}}async createView(e,t){await this.connect();let n=String(t?.name||``).trim();if(!n){let r=String(t?.label||e||`view`).toLowerCase().replace(/[^a-z0-9_]+/g,`_`).replace(/^_+|_+$/g,``).slice(0,40);(!r||/^[0-9]/.test(r))&&(r=r?`view_${r}`:`view`);let i=Date.now().toString(36);n=`${r}_${i}`}let r={...t,name:n,object:t?.object||e,data:t?.data||{provider:`object`,object:e}},i=await this.client.meta.saveItem(`view`,n,r);return this.metadataCache.invalidate?.(`views:${e}`),i&&i.item?i.item:r}async updateView(e,t,n){await this.connect();let r={};try{let e=await this.client.meta.getItem(`view`,t);r=e&&(e.item||e)||{},r?.list&&(r=r.list)}catch{}let i={...r,...n,name:t,object:r?.object||r?.data?.object||e},a=await this.client.meta.saveItem(`view`,t,i);return this.metadataCache.invalidate?.(`views:${e}`),this.metadataCache.invalidate?.(`view:${e}:${t}`),a&&a.item?a.item:i}async deleteView(e,t){await this.connect();let n=await this.client.meta.deleteItem(`view`,t);return this.metadataCache.invalidate?.(`views:${e}`),this.metadataCache.invalidate?.(`view:${e}:${t}`),{deleted:!!(n?.deleted??n?.reset??!0)}}async getApp(e){await this.connect();try{let t=`app:${e}`;return await this.metadataCache.get(t,async()=>{let t=await this.client.meta.getItem(`apps`,e);return t&&t.item?t.item:t??null})}catch{return null}}async getPage(e){await this.connect();try{let t=`page:${e}`;return await this.metadataCache.get(t,async()=>{let t=await this.client.meta.getItem(`pages`,e);return t&&t.item?t.item:t??null})}catch{return null}}async updateDashboard(e,t){await this.connect();let n=await this.client.meta.saveItem(`dashboard`,e,t);return this.metadataCache.invalidate?.(`dashboards`),this.metadataCache.invalidate?.(`dashboard:${e}`),n&&n.item?n.item:n??void 0}async aggregate(e,t){if(await this.connect(),t!=null&&(Array.isArray(t.groupBy)||Array.isArray(t.aggregations)||t.where!==void 0)){let n={};Array.isArray(t.groupBy)&&(n.groupBy=t.groupBy),Array.isArray(t.aggregations)&&(n.aggregations=t.aggregations),t.where!==void 0&&(n.where=t.where),typeof t.limit==`number`&&(n.limit=t.limit);let r=await this.client.data.query(e,n);return Array.isArray(r)?r:Array.isArray(r?.records)?r.records:Array.isArray(r?.data)?r.data:[]}try{let n=t.function===`count`?`count`:`${t.field}_${t.function}`,r=this.aggregateValueKey(t),i={cube:e,measures:[n],dimensions:t.groupBy&&t.groupBy!==`_all`?[t.groupBy]:[]};t.filter&&(i.where=t.filter);let a=await this.client.analytics.query(i),o=Array.isArray(a)?a:a?.rows&&Array.isArray(a.rows)?a.rows:a?.data&&Array.isArray(a.data)?a.data:a?.data?.rows&&Array.isArray(a.data.rows)?a.data.rows:a?.results&&Array.isArray(a.results)?a.results:[];return o.length>0&&o.every(e=>e==null||!(n in e&&e[n]!=null||r in e&&e[r]!=null))?await this.aggregateViaFind(e,t):o.map(e=>{let t={...e};return n!==r&&n in t&&(t[r]=t[n],delete t[n]),t})}catch(n){let r=E(n);if(r.kind===`rejected`)throw new T(r.message,r.code);return r.kind===`not-installed`&&this.warnAnalyticsCapabilityOnce(r.message),await this.aggregateViaFind(e,t)}}async aggregateViaFind(e,t){let n=(await this.find(e,t.filter?{$filter:t.filter}:void 0)).data||[];return n.length===0?[]:this.aggregateClientSide(n,t)}warnAnalyticsCapabilityOnce(e){this.analyticsCapabilityWarned||(this.analyticsCapabilityWarned=!0,console.warn(`[OBJECTSTACKDataSource] analytics capability unavailable — aggregating client-side from a scoped find(). Numbers stay correct but the semantic layer (cubes, joins, server-side rollups) is off. Install @objectstack/service-analytics to enable it.`+(e?` Server said: ${e}`:``)))}async queryDataset(e,t){await this.connect();let n=`${(this.baseUrl||``).replace(/\/$/,``)}/api/v1/analytics/dataset/query`,r=typeof window<`u`&&new URLSearchParams(window.location.search).get(`preview`)===`draft`,i=typeof e==`string`?{datasetName:e,selection:t,...r?{previewDrafts:!0}:{}}:{dataset:e,selection:t,...r?{previewDrafts:!0}:{}},a=await this.fetchImpl(n,{method:`POST`,headers:{"Content-Type":`application/json`,...this.token?{Authorization:`Bearer ${this.token}`}:{}},body:JSON.stringify(i)});if(!a.ok){let e=``;try{let t=await a.json();e=t?.message||t?.error||JSON.stringify(t)}catch{}throw a.status===501||a.status===404?new ge(`POST /analytics/dataset/query`,e||void 0):Error(`Dataset query failed: ${a.status} ${a.statusText}${e?` — ${e}`:``}`)}let o=await a.json(),s=o&&typeof o==`object`&&`success`in o&&`data`in o?o.data:o;return{rows:Array.isArray(s?.rows)?s.rows:Array.isArray(s)?s:[],fields:Array.isArray(s?.fields)?s.fields:[],object:typeof s?.object==`string`?s.object:void 0,dimensionFields:s?.dimensionFields&&typeof s.dimensionFields==`object`?s.dimensionFields:void 0,drillRawRows:Array.isArray(s?.drillRawRows)?s.drillRawRows:void 0,totals:Array.isArray(s?.totals)?s.totals:void 0}}aggregateValueKey(e){return e.field||e.function||`count`}aggregateClientSide(e,t){let{field:n,function:r,groupBy:i}=t,a=this.aggregateValueKey(t),o={};for(let t of e){let e=String(t[i]??`Unknown`);o[e]||(o[e]=[]),o[e].push(t)}return Object.entries(o).map(([e,t])=>{let o=n?t.map(e=>Number(e[n])||0):[],s;switch(r){case`count`:s=t.length;break;case`avg`:s=o.length>0?o.reduce((e,t)=>e+t,0)/o.length:0;break;case`min`:s=o.length>0?Math.min(...o):0;break;case`max`:s=o.length>0?Math.max(...o):0;break;default:s=o.reduce((e,t)=>e+t,0)}return{[i]:e,[a]:s}})}async getItems(e,t){return await this.connect(),await Promise.all(t.map(async t=>{let n=`${e}:${t}`;return this.metadataCache.get(n,async()=>{let n=await this.client.meta.getItem(e,t);return n&&n.item?n.item:n})}))}getCached(e){return this.metadataCache.getCachedSync(e)}getCacheStats(){return this.metadataCache.getStats()}invalidateCache(e){this.metadataCache.invalidate(e)}clearCache(){this.metadataCache.clear()}async uploadFile(e,t,n){await this.connect();let r=new FormData;r.append(`file`,t),n?.recordId&&r.append(`recordId`,n.recordId),n?.fieldName&&r.append(`fieldName`,n.fieldName),n?.metadata&&r.append(`metadata`,JSON.stringify(n.metadata));let i=`${this.baseUrl}/api/data/${encodeURIComponent(e)}/upload`,a=await fetch(i,{method:`POST`,body:r,headers:{...this.getAuthHeaders()}});if(!a.ok)throw new m((await a.json().catch(()=>({message:a.statusText}))).message||`Upload failed with status ${a.status}`,`UPLOAD_ERROR`,a.status);return a.json()}async uploadFiles(e,t,n){await this.connect();let r=new FormData;t.forEach((e,t)=>{r.append(`files`,e,e.name||`file-${t}`)}),n?.recordId&&r.append(`recordId`,n.recordId),n?.fieldName&&r.append(`fieldName`,n.fieldName),n?.metadata&&r.append(`metadata`,JSON.stringify(n.metadata));let i=`${this.baseUrl}/api/data/${encodeURIComponent(e)}/upload`,a=await fetch(i,{method:`POST`,body:r,headers:{...this.getAuthHeaders()}});if(!a.ok)throw new m((await a.json().catch(()=>({message:a.statusText}))).message||`Upload failed with status ${a.status}`,`UPLOAD_ERROR`,a.status);return a.json()}async cancelPendingApproval(e,t){await this.connect();let n=`${this.baseUrl}/api/v1/approvals/requests?recordId=${encodeURIComponent(t)}&object=${encodeURIComponent(e)}`,r=await this.fetchImpl(n,{method:`GET`,headers:{"Content-Type":`application/json`,...this.getAuthHeaders()}});if(!r.ok)throw new m(`Failed to look up approval requests (status ${r.status})`,`APPROVAL_LOOKUP_FAILED`,r.status);let i=await r.json().catch(()=>({})),a=(Array.isArray(i)?i:i?.data??[]).find(e=>e?.status===`pending`||e?.status===`in_approval`);if(!a?.id)throw new m(`No pending approval request found for this record`,`NO_PENDING_REQUEST`,404);let o=`${this.baseUrl}/api/v1/approvals/requests/${encodeURIComponent(a.id)}/recall`,s=await this.fetchImpl(o,{method:`POST`,headers:{"Content-Type":`application/json`,...this.getAuthHeaders()},body:JSON.stringify({})});if(!s.ok){let e=await s.json().catch(()=>({}));throw new m(e?.error||e?.message||`Recall failed with status ${s.status}`,e?.code||`APPROVAL_RECALL_FAILED`,s.status)}let c=await s.json().catch(()=>({}));return{requestId:a.id,status:c?.data?.request?.status??`recalled`}}getAuthHeaders(){let e={};return this.token&&(e.Authorization=`Bearer ${this.token}`),e}};export{ae as n,te as r,ye as t};
|