@objectstack/console 17.0.0 → 17.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/CHANGELOG.md +452 -0
  2. package/dist/.objectstack-injection.json +13 -0
  3. package/dist/.objectui-sha +1 -1
  4. package/dist/assets/AdapterProvider-gULVLpjV.js +3 -0
  5. package/dist/assets/AiPendingActionsPage-CyG11hX9.js +1 -0
  6. package/dist/assets/ApiConsolePage-DYuOp_W4.js +1 -0
  7. package/dist/assets/AppDocsIndex-BXkNskk1.js +1 -0
  8. package/dist/assets/AppManagementPage-BvSxDdA_.js +1 -0
  9. package/dist/assets/ApprovalsInboxPage-oep3a-Ek.js +1 -0
  10. package/dist/assets/AuditLogPage-BZZ6tzHu.js +1 -0
  11. package/dist/assets/ComponentNavView-Cq4wkNUa.js +1 -0
  12. package/dist/assets/DashboardView-C23ZCS2S.js +1 -0
  13. package/dist/assets/{DeveloperHubPage-DVKVm5k0.js → DeveloperHubPage-KEpKc45V.js} +1 -1
  14. package/dist/assets/DocPage-Y4rWCZ3E.js +1 -0
  15. package/dist/assets/{DocShell-C1VQpTIJ.js → DocShell-DMJHUgE5.js} +1 -1
  16. package/dist/assets/DocsIndex-Bb5OtPb3.js +1 -0
  17. package/dist/assets/DocsLayout-CoIVTMH_.js +1 -0
  18. package/dist/assets/DocsSlug-BARWHmXg.js +1 -0
  19. package/dist/assets/{ExpressionProvider-qmd0nVCn.js → ExpressionProvider-vGLngw8h.js} +1 -1
  20. package/dist/assets/FlowRunsPage-BeGa9_ge.js +1 -0
  21. package/dist/assets/{IntegrationsPage-Cq4mWRFh.js → IntegrationsPage-DTXA-Nne.js} +2 -2
  22. package/dist/assets/InterfaceListPage-BMvedZyV.js +1 -0
  23. package/dist/assets/{ManagedByBadge-DgsrLolr.js → ManagedByBadge-mKmG0hP7.js} +1 -1
  24. package/dist/assets/MarketplaceAccessDenied-BBMyNu2w.js +1 -0
  25. package/dist/assets/{MarketplaceInstalledPage-CRe2BiM2.js → MarketplaceInstalledPage-B4qrvb7w.js} +1 -1
  26. package/dist/assets/MarketplacePackagePage-BuVfVeBj.js +4 -0
  27. package/dist/assets/MarketplacePage-Cmltk5nG.js +1 -0
  28. package/dist/assets/{MetadataInspector-qQ85bFun.js → MetadataInspector-kVAu8vlh.js} +1 -1
  29. package/dist/assets/MetadataProvider-DyFZSNqq.js +1 -0
  30. package/dist/assets/{MonacoImpl-DStuouLX.js → MonacoImpl-Cu_-ISwm.js} +1 -1
  31. package/dist/assets/ObjectDataPage-BKHEYwXA.js +1 -0
  32. package/dist/assets/PageView-CTqS-VD9.js +1 -0
  33. package/dist/assets/ProfilePage-CBUxXn5a.js +1 -0
  34. package/dist/assets/PublicFormsPage-B8Dk8fky.js +1 -0
  35. package/dist/assets/RecordDetailView-BBNqsNy9.js +11 -0
  36. package/dist/assets/RecordFormPage-CeUmmc_n.js +1 -0
  37. package/dist/assets/ReportDefaultInspector-CRjDi2Er.js +3 -0
  38. package/dist/assets/ReportView-Cwi_Po4H.js +2 -0
  39. package/dist/assets/SearchResultsPage-Cg0oq2by.js +1 -0
  40. package/dist/assets/SettingsHub-B5_S9YgI.js +1 -0
  41. package/dist/assets/SettingsView-Csi1awf-.js +1 -0
  42. package/dist/assets/SystemHubPage-CnDri9oU.js +1 -0
  43. package/dist/assets/{abnfDiagram-N423BO3Z-Ck9FUrgJ.js → abnfDiagram-N423BO3Z-DfpQlDUF.js} +1 -1
  44. package/dist/assets/{architectureDiagram-T3A2C74G-DJbnVK1q.js → architectureDiagram-T3A2C74G-Ej_4n3NG.js} +1 -1
  45. package/dist/assets/{assistantBus-DNogw1P-.js → assistantBus-DNH-fDWN.js} +1 -1
  46. package/dist/assets/{blockDiagram-VBNYF7ZC-Qtci47Jq.js → blockDiagram-VBNYF7ZC-l_P_W7_Y.js} +1 -1
  47. package/dist/assets/{c4Diagram-5PPSVZJV-DC9Uk9FW.js → c4Diagram-5PPSVZJV-CE82HAlO.js} +1 -1
  48. package/dist/assets/channel-DowAYf9b.js +1 -0
  49. package/dist/assets/{chunk-2GRJ4B5K-C6KsYuNR.js → chunk-2GRJ4B5K-D1if-ThW.js} +1 -1
  50. package/dist/assets/chunk-3NCLNEKW-Z5ckM4mG.js +1 -0
  51. package/dist/assets/{chunk-4I5QYGJK-CPsvNPUx.js → chunk-4I5QYGJK-DlrWrdEa.js} +1 -1
  52. package/dist/assets/{chunk-5RXB4S5H-CU_v2umt.js → chunk-5RXB4S5H-JwFhdddt.js} +1 -1
  53. package/dist/assets/{chunk-6Q2QTUOP-C_q0JPmG.js → chunk-6Q2QTUOP-C2vvuHlO.js} +1 -1
  54. package/dist/assets/{chunk-7Z6QIM7H-jM3JGv9o.js → chunk-7Z6QIM7H-m6s_oalL.js} +1 -1
  55. package/dist/assets/{chunk-GF5L2VYU-Dp_0e4Vj.js → chunk-GF5L2VYU-Dgjjn2FR.js} +1 -1
  56. package/dist/assets/{chunk-I66GZJ75-CLtbCU_E.js → chunk-I66GZJ75-BsY3mBMx.js} +1 -1
  57. package/dist/assets/{chunk-J7OUQ5F2-C4uAdkrD.js → chunk-J7OUQ5F2-Cl4FNR_k.js} +1 -1
  58. package/dist/assets/{chunk-JQJVKLGR-BlTMFaN6.js → chunk-JQJVKLGR-BApWxqMA.js} +1 -1
  59. package/dist/assets/{chunk-KBJHAD2P-BJzwVqKy.js → chunk-KBJHAD2P-DI4-lUt-.js} +1 -1
  60. package/dist/assets/{chunk-NSK5VX7P-B7tNpEbR.js → chunk-NSK5VX7P-BBTxIP6Z.js} +1 -1
  61. package/dist/assets/{chunk-QR6OTTB3-B3mQWEI2.js → chunk-QR6OTTB3-DJcD7xr-.js} +1 -1
  62. package/dist/assets/{chunk-RYQCIY6F-B3DAS_Q-.js → chunk-RYQCIY6F-CnMsR_qh.js} +1 -1
  63. package/dist/assets/{chunk-UBXNYLIW-Cqb7MpFH.js → chunk-UBXNYLIW-B7z1tp3V.js} +1 -1
  64. package/dist/assets/{chunk-W5SLKNZC-DWOVkEVc.js → chunk-W5SLKNZC-BnMc5i0B.js} +1 -1
  65. package/dist/assets/{chunk-WRU74C26-DR5g8owc.js → chunk-WRU74C26-MrzCPX2E.js} +1 -1
  66. package/dist/assets/chunk-XXDRQBXY-NKBlW2Dm.js +1 -0
  67. package/dist/assets/classDiagram-JCYQIIEL-C4ADaKBz.js +1 -0
  68. package/dist/assets/classDiagram-v2-OCEON4UE-C4ADaKBz.js +1 -0
  69. package/dist/assets/{cose-bilkent-JH36ORCC-CcXrYRrs.js → cose-bilkent-JH36ORCC-XP-DnSP5.js} +1 -1
  70. package/dist/assets/{createDerive-C1PaRnFZ.js → createDerive-B3AGnDaY.js} +1 -1
  71. package/dist/assets/{cynefinDiagram-MW4NZA55-DuPIOMPB.js → cynefinDiagram-MW4NZA55-B8MvpqXe.js} +1 -1
  72. package/dist/assets/{dagre-VZM6K2ZE-CHbs07zF.js → dagre-VZM6K2ZE-B5E8-xuM.js} +1 -1
  73. package/dist/assets/{diagram-7IWD3JNH-sPS-Y-CP.js → diagram-7IWD3JNH-Xj62y5BF.js} +1 -1
  74. package/dist/assets/{diagram-B4RE2ZJO-C4Essr7L.js → diagram-B4RE2ZJO-mI-iOCGl.js} +1 -1
  75. package/dist/assets/{diagram-LBJQPF4R-CluEJ_Yg.js → diagram-LBJQPF4R-BMTSoZch.js} +1 -1
  76. package/dist/assets/{diagram-Q27KOJAE-D4lem9jQ.js → diagram-Q27KOJAE-B98Knrnh.js} +1 -1
  77. package/dist/assets/{diagram-UB23O5K3-Bfj6mHJD.js → diagram-UB23O5K3-bseKIzhv.js} +1 -1
  78. package/dist/assets/{dist-D3VfqzjO.js → dist-BK-OswHQ.js} +1 -1
  79. package/dist/assets/dist-Ck19TqqJ.js +5 -0
  80. package/dist/assets/{ebnfDiagram-BXEA7PRR-BKXyHLd_.js → ebnfDiagram-BXEA7PRR-Bgo10FP1.js} +1 -1
  81. package/dist/assets/{erDiagram-JOGREHBK-B6_uGYAF.js → erDiagram-JOGREHBK-BU4b8mUv.js} +1 -1
  82. package/dist/assets/flowDiagram-UKHOOZJN-BDHHPApJ.js +1 -0
  83. package/dist/assets/framework-BwfIhdyz.js +55 -0
  84. package/dist/assets/{ganttDiagram-PKOTCBZU-Cip5kKH4.js → ganttDiagram-PKOTCBZU-CrmKcYGt.js} +1 -1
  85. package/dist/assets/{getIcon-QmYxLBSb.js → getIcon-1ZXs1v-a.js} +1 -1
  86. package/dist/assets/{gitGraphDiagram-DS77QQ5N-CF75OjHf.js → gitGraphDiagram-DS77QQ5N-COu0mOui.js} +1 -1
  87. package/dist/assets/{highlighted-body-OFNGDK62-BPV_Giyg.js → highlighted-body-OFNGDK62-CnGKNo0r.js} +1 -1
  88. package/dist/assets/i18n-rra-09wp.js +9 -0
  89. package/dist/assets/index-BLepsDd_.js +19 -0
  90. package/dist/assets/index-D26gl3rg.css +2 -0
  91. package/dist/assets/{infoDiagram-6WML65LV-IbyJxsv4.js → infoDiagram-6WML65LV-BT0Q6MIs.js} +1 -1
  92. package/dist/assets/infrastructure-BCTDJsqi.js +3 -0
  93. package/dist/assets/{ishikawaDiagram-WSZJBQD7-D8FhFMwb.js → ishikawaDiagram-WSZJBQD7-kvPjMvBP.js} +1 -1
  94. package/dist/assets/{journeyDiagram-NVQOT4AX-C1y_DqRe.js → journeyDiagram-NVQOT4AX-DhXy7wxt.js} +1 -1
  95. package/dist/assets/{kanban-definition-27J2QSJJ-DIUOavva.js → kanban-definition-27J2QSJJ-CFDavpZY.js} +1 -1
  96. package/dist/assets/maplibre-gl-CrDadnl3.js +801 -0
  97. package/dist/assets/maplibre-gl-shared.mjs +2 -2
  98. package/dist/assets/maplibre-gl-worker.mjs +2 -2
  99. package/dist/assets/mermaid-GHXKKRXX-CR9PcY0X.js +1 -0
  100. package/dist/assets/{mermaid-parser.core-BbBeSajF.js → mermaid-parser.core-Dd2B8Ckv.js} +1 -1
  101. package/dist/assets/{mermaid.core-Dc9p2r4P.js → mermaid.core-BwiBFu_S.js} +2 -2
  102. package/dist/assets/metadata-admin-BE9_-F_f.js +25 -0
  103. package/dist/assets/{mindmap-definition-FAOFIHXS-TIsZfgu-.js → mindmap-definition-FAOFIHXS-ITGoV4nW.js} +1 -1
  104. package/dist/assets/{pegDiagram-VL7TDLO6-BrUvPfjL.js → pegDiagram-VL7TDLO6-BoRu9yvl.js} +1 -1
  105. package/dist/assets/{pieDiagram-7S7Q4E2Y-BNPIri0N.js → pieDiagram-7S7Q4E2Y-DVsM9krU.js} +1 -1
  106. package/dist/assets/plugin-calendar-BfY9ZunQ.js +1 -0
  107. package/dist/assets/plugin-charts-CmWL7Og-.js +7 -0
  108. package/dist/assets/plugin-chatbot-mxoQfkdx.js +120 -0
  109. package/dist/assets/plugin-dashboard-CzbAW1Rz.js +6 -0
  110. package/dist/assets/plugin-form-ItAwTFz-.js +1 -0
  111. package/dist/assets/plugin-gantt-DF5W5xkN.js +64 -0
  112. package/dist/assets/plugin-grid-B42Photo.js +9 -0
  113. package/dist/assets/plugin-kanban-Dh3HIJIm.js +1 -0
  114. package/dist/assets/plugin-map-C1wSLqlB.js +1 -0
  115. package/dist/assets/plugin-map-DSnsEFKn.css +1 -0
  116. package/dist/assets/{plugin-markdown-CbQeAjXv.js → plugin-markdown-DNllWgPM.js} +1 -1
  117. package/dist/assets/plugin-report-yfOfZPQg.js +59 -0
  118. package/dist/assets/plugin-timeline-BpuaaqBd.js +1 -0
  119. package/dist/assets/plugin-tree-BrXE50se.js +1 -0
  120. package/dist/assets/plugin-view-Jc0rkk7A.js +1 -0
  121. package/dist/assets/plugins-views-cOiN-mPq.js +4 -0
  122. package/dist/assets/{quadrantDiagram-CIZ2JOQS-BpL1Kl6d.js → quadrantDiagram-CIZ2JOQS-C4VzXHnp.js} +1 -1
  123. package/dist/assets/{railroadDiagram-AXF67PYL-CY1JovP6.js → railroadDiagram-AXF67PYL-DqZ3yKWv.js} +1 -1
  124. package/dist/assets/{requirementDiagram-LRYGKXZP-TRTGy9-6.js → requirementDiagram-LRYGKXZP-BeH0P3vD.js} +1 -1
  125. package/dist/assets/{runtime-metadata-persistence-DDZN-tZg.js → runtime-metadata-persistence-DTOJpVmd.js} +1 -1
  126. package/dist/assets/{sankeyDiagram-W5VNT64P-Hj-Un0bp.js → sankeyDiagram-W5VNT64P-Bu_tPh-A.js} +1 -1
  127. package/dist/assets/{sequenceDiagram-SI44F4Z6-iGYyf5AF.js → sequenceDiagram-SI44F4Z6-BWEuLn1a.js} +1 -1
  128. package/dist/assets/{skeletons-BWrJAbfN.js → skeletons-BwA1TSR2.js} +1 -1
  129. package/dist/assets/src-BLbFBP_B.js +1 -0
  130. package/dist/assets/{src-DwpgXgLE.js → src-CY2xhbXR.js} +1 -1
  131. package/dist/assets/{src-0qbDl74X.js → src-CvicUdp3.js} +1 -1
  132. package/dist/assets/src-DhAd4aY4.js +2 -0
  133. package/dist/assets/{stateDiagram-OKZ733FA-B-kn5M6g.js → stateDiagram-OKZ733FA-Cp7aDYsZ.js} +1 -1
  134. package/dist/assets/stateDiagram-v2-UEYNNEHI-DaTg8C5m.js +1 -0
  135. package/dist/assets/{swimlanes-SLNWSIFB-sV1QkjXA.js → swimlanes-SLNWSIFB-wrx1JN6o.js} +1 -1
  136. package/dist/assets/swimlanesDiagram-ULZ7WXOC-Bqz9GVuM.js +8 -0
  137. package/dist/assets/{timeline-definition-Z64GVDOM-DMClsS2j.js → timeline-definition-Z64GVDOM-BcUiJfLU.js} +1 -1
  138. package/dist/assets/ui-components-Dwq5utCl.js +42 -0
  139. package/dist/assets/ui-layout-DPFlQaQp.js +1 -0
  140. package/dist/assets/use-book-data-CZc8MJsb.js +1 -0
  141. package/dist/assets/useActionModal-DYiSBx1G.js +1 -0
  142. package/dist/assets/useOpenRecordList-DOZu_JZX.js +1 -0
  143. package/dist/assets/usePackageL10n-D91-102Q.js +1 -0
  144. package/dist/assets/{useSettingsLabel-Bl5L3RqQ.js → useSettingsLabel-CeZ36S4g.js} +1 -1
  145. package/dist/assets/{utils-L-_x2yPF.js → utils-CJ4UwXMF.js} +1 -1
  146. package/dist/assets/{vendor-charts-DAI87uet.js → vendor-charts-BEGSmcjR.js} +3 -3
  147. package/dist/assets/{vendor-dndkit-CQdzTF9d.js → vendor-dndkit-CkJ59XFL.js} +1 -1
  148. package/dist/assets/{vendor-i18n-DeMInx63.js → vendor-i18n-Cpia2wlg.js} +1 -1
  149. package/dist/assets/{vendor-icons-core-B25E_7o5.js → vendor-icons-core-Bi9GWsvI.js} +1 -1
  150. package/dist/assets/{vendor-markdown-DjBjpmKk.js → vendor-markdown-C_Ip9E_I.js} +2 -2
  151. package/dist/assets/vendor-objectstack-B1R3ym-9.js +264 -0
  152. package/dist/assets/{vendor-radix-D1dussIM.js → vendor-radix-DFmVRiEf.js} +1 -1
  153. package/dist/assets/{vendor-react-BgOXCBVK.js → vendor-react-CsWFRkED.js} +1 -1
  154. package/dist/assets/vendor-sentry-B2ojA7qm.js +501 -0
  155. package/dist/assets/vendor-ui-utils-BFw4cGI6.js +1 -0
  156. package/dist/assets/vendor-zod-r9lyeyrU.js +64 -0
  157. package/dist/assets/{vennDiagram-T6HMQDX7-CrP23lgd.js → vennDiagram-T6HMQDX7-BKJsL5fS.js} +1 -1
  158. package/dist/assets/{wardleyDiagram-T6FBY63Y-DSw6poZ6.js → wardleyDiagram-T6FBY63Y-CZ0aMbYX.js} +1 -1
  159. package/dist/assets/{xychartDiagram-ELKLHX3M-BVUFqBDL.js → xychartDiagram-ELKLHX3M-BpK2RmQ_.js} +1 -1
  160. package/dist/eager-closure.json +277 -0
  161. package/dist/index.html +56 -16
  162. package/package.json +1 -1
  163. package/dist/assets/AdapterProvider-BpWMSLQH.js +0 -3
  164. package/dist/assets/AiPendingActionsPage-DAJUEqyC.js +0 -1
  165. package/dist/assets/ApiConsolePage-CgXbOsFC.js +0 -1
  166. package/dist/assets/AppDocsIndex-BgaIthca.js +0 -1
  167. package/dist/assets/AppManagementPage-BvGPskyf.js +0 -1
  168. package/dist/assets/ApprovalsInboxPage-CxmrNrwP.js +0 -1
  169. package/dist/assets/AuditLogPage-JahfQFnX.js +0 -1
  170. package/dist/assets/ComponentNavView-DjiNAGys.js +0 -1
  171. package/dist/assets/CreateViewDialog-CUvjCA1o.js +0 -1
  172. package/dist/assets/DashboardView-Cr-Q-16_.js +0 -1
  173. package/dist/assets/FlowRunsPage-DL7MhL_U.js +0 -1
  174. package/dist/assets/InterfaceListPage-CfhSyYAw.js +0 -1
  175. package/dist/assets/MarketplaceAccessDenied-t8A0k9OX.js +0 -1
  176. package/dist/assets/MarketplacePackagePage-XSdk80Dd.js +0 -4
  177. package/dist/assets/MarketplacePage-CZjDbg5G.js +0 -1
  178. package/dist/assets/MetadataProvider-CnYsadFP.js +0 -1
  179. package/dist/assets/ObjectDataPage-D9kCSxvN.js +0 -1
  180. package/dist/assets/PageView-q1XSwpVo.js +0 -1
  181. package/dist/assets/ProfilePage-DeDhni58.js +0 -1
  182. package/dist/assets/PublicFormsPage-BX6YXY8w.js +0 -1
  183. package/dist/assets/RecordDetailView-DrVbrbaN.js +0 -9
  184. package/dist/assets/RecordFormPage-Bs9wX-M6.js +0 -1
  185. package/dist/assets/ReportDefaultInspector-BbbhDn34.js +0 -3
  186. package/dist/assets/ReportView-D_soBKL6.js +0 -2
  187. package/dist/assets/SearchResultsPage--Beqyte8.js +0 -1
  188. package/dist/assets/SettingsHub-BozLt7dt.js +0 -1
  189. package/dist/assets/SettingsView-CC3o9IGe.js +0 -1
  190. package/dist/assets/SystemHubPage-CBdrX4bx.js +0 -1
  191. package/dist/assets/channel-dlPH8oK4.js +0 -1
  192. package/dist/assets/chunk-3NCLNEKW-CHvXlKAW.js +0 -1
  193. package/dist/assets/chunk-XXDRQBXY-BLRqgrvV.js +0 -1
  194. package/dist/assets/classDiagram-JCYQIIEL-ghx-FrtR.js +0 -1
  195. package/dist/assets/classDiagram-v2-OCEON4UE-ghx-FrtR.js +0 -1
  196. package/dist/assets/componentRegistry-ByxoJqMW.js +0 -1
  197. package/dist/assets/data-adapter-yS4exRPT.js +0 -24
  198. package/dist/assets/flowDiagram-UKHOOZJN-6YBsanbO.js +0 -1
  199. package/dist/assets/framework-B8ndNKrd.js +0 -38
  200. package/dist/assets/i18n-DLOdKEiB.js +0 -9
  201. package/dist/assets/index-DaeqUnH6.js +0 -2
  202. package/dist/assets/index-gaeYmjTV.css +0 -2
  203. package/dist/assets/infrastructure-ChmEYj6c.js +0 -3
  204. package/dist/assets/maplibre-gl-DPzMTNDD.js +0 -801
  205. package/dist/assets/mermaid-GHXKKRXX-BrwYiPsC.js +0 -1
  206. package/dist/assets/metadata-admin-DqAvOmNf.js +0 -25
  207. package/dist/assets/plugin-calendar-CQVTjox_.js +0 -1
  208. package/dist/assets/plugin-charts-CBUIhVeW.js +0 -7
  209. package/dist/assets/plugin-chatbot-DsLGdfGx.js +0 -120
  210. package/dist/assets/plugin-dashboard-fdM1jm2j.js +0 -6
  211. package/dist/assets/plugin-form-Bv0Hi0E6.js +0 -1
  212. package/dist/assets/plugin-gantt-CRJpVrrP.js +0 -63
  213. package/dist/assets/plugin-grid-gHcTrjs3.js +0 -8
  214. package/dist/assets/plugin-kanban-CNm7DssD.js +0 -1
  215. package/dist/assets/plugin-map-5lRITB8H.css +0 -1
  216. package/dist/assets/plugin-map-TrYBEx8q.js +0 -1
  217. package/dist/assets/plugin-report-Bg1oh9SG.js +0 -59
  218. package/dist/assets/plugin-timeline-B30kCAGi.js +0 -1
  219. package/dist/assets/plugin-tree-Br5XanqO.js +0 -1
  220. package/dist/assets/plugin-view-CgDs-8T5.js +0 -1
  221. package/dist/assets/plugins-views-BxwTmeut.js +0 -4
  222. package/dist/assets/src-BBKXMp-o.js +0 -19
  223. package/dist/assets/src-CVuJHohL.js +0 -1
  224. package/dist/assets/src-leh_hyM1.js +0 -2
  225. package/dist/assets/stateDiagram-v2-UEYNNEHI-CHYANMPw.js +0 -1
  226. package/dist/assets/swimlanesDiagram-ULZ7WXOC-CBFvMN71.js +0 -8
  227. package/dist/assets/ui-components-mPgY5chB.js +0 -42
  228. package/dist/assets/ui-layout-CRcyxP_X.js +0 -1
  229. package/dist/assets/use-book-data-B2KPEJjv.js +0 -1
  230. package/dist/assets/useOpenRecordList-ovuRzPa2.js +0 -1
  231. package/dist/assets/usePackageL10n-9fP2GgDK.js +0 -1
  232. package/dist/assets/vendor-objectstack-DneBps14.js +0 -155
  233. package/dist/assets/vendor-sentry-DlmtNsBO.js +0 -501
  234. package/dist/assets/vendor-ui-utils-BGw4RtYu.js +0 -1
  235. package/dist/assets/vendor-zod-CBDIIwrA.js +0 -65
@@ -1,24 +0,0 @@
1
- import{t as e}from"./rolldown-runtime-C0FnF6B9.js";import{Bn as t,En as n,Vt as r,t as i,wr as a,zn as o}from"./framework-B8ndNKrd.js";import{t as s}from"./vendor-zod-CBDIIwrA.js";var c=e((e=>{var t=s(),n=[`string`,`number`,`bigint`,`boolean`,`null`,`Date`],r=`a string, number, bigint, boolean, null or Date`,i=2n**53n;function a(e){if(e===null)return!0;switch(typeof e){case`string`:case`number`:case`bigint`:case`boolean`:return!0;default:return e instanceof Date}}var o=new Set([`$eq`,`$ne`,`$gt`,`$gte`,`$lt`,`$lte`,`$contains`,`$notContains`,`$startsWith`,`$endsWith`,`$icontains`,`$like`,`$ilike`,`$null`,`$exists`]),c=new Set([`$in`,`$nin`,`$between`]);function l(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function u(e){return l(e)&&typeof e.$field==`string`}function d(e){if(e===null)return`null`;if(e===void 0)return`undefined`;if(Array.isArray(e))return`an array`;let t=typeof e;if(t===`function`)return`a function`;if(t===`symbol`)return`a Symbol`;if(t!==`object`)return`a ${t}`;let n=e.constructor;return n?.name&&n.name!==`Object`?`a ${n.name} instance`:`a plain object`}function f(e){let t;try{t=typeof e==`bigint`?`${e}n`:typeof e==`symbol`||typeof e==`function`?String(e):JSON.stringify(e)??String(e)}catch{t=String(e)}return t.length>40?`${t.slice(0,39)}\u2026`:t}function p(e,t){let n=Error(`${e?`${e}: `:``}${t}`);return n.code=`INVALID_FILTER`,n.status=400,n}var ee=`The filter was NOT applied, and an unapplied filter would have returned the UNFILTERED result set.`;function m(e,t){return p(e,`Filter comparand at ${t} is undefined. { key: undefined } cannot be told apart from an omitted key, yet the two mean OPPOSITE things (a predicate vs no constraint) \u2014 one backend even encoded it as MATCH EVERYTHING. Write null for the null predicate, or omit the key. A comparison value must be ${r}. `+ee)}function te(e,t,n){return p(e,`Filter comparand at ${t} is ${d(n)} (${f(n)}), which no driver can compare. A comparison value must be ${r}. Refusing rather than guessing: the backends disagreed on this input (crash / zero rows / silently edited query). ${ee}`)}function ne(e,t,n){return p(e,`Filter comparand at ${t} is the bigint ${f(n)}, whose magnitude exceeds 2^53 \u2014 it has no exact JS-number form, so a comparison built on it would silently answer the wrong rows on double-storing backends. Compare within \xB12^53, or store and compare the value as a string. A comparison value must be ${r}. ${ee}`)}function re(e,t,n){return n===void 0?{kind:`refuse`,error:m(e,t)}:typeof n==`bigint`?n<=i&&n>=-i?{kind:`narrow`,value:Number(n)}:{kind:`refuse`,error:ne(e,t,n)}:a(n)||Array.isArray(n)||u(n)?{kind:`keep`}:{kind:`refuse`,error:te(e,t,n)}}function h(e,t,n=`where`){if(!l(e))return e;let r;for(let[i,a]of Object.entries(e)){let o=`${n}.${i}`,s=a;if(i===`$and`||i===`$or`){if(Array.isArray(a)){let e;a.forEach((n,r)=>{let i=h(n,t,`${o}[${r}]`);i!==n&&(e??=[...a],e[r]=i)}),e&&(s=e)}}else i===`$not`?s=h(a,t,o):i.startsWith(`$`)||(s=ie(t,o,a));s!==a&&(r??={...e},r[i]=s)}return r??e}function ie(e,t,n){if(l(n)){if(u(n)||!Object.keys(n).some(e=>e.startsWith(`$`)))return n;let r;for(let[i,a]of Object.entries(n)){let s=a;if(o.has(i))s=ae(re(e,`${t}.${i}`,a),a);else if(c.has(i)&&Array.isArray(a)){let n;a.forEach((r,o)=>{let s=re(e,`${t}.${i}[${o}]`,r);if(s.kind===`refuse`)throw s.error;s.kind===`narrow`&&(n??=[...a],n[o]=s.value)}),n&&(s=n)}s!==a&&(r??={...n},r[i]=s)}return r??n}return ae(re(e,t,n),n)}function ae(e,t){if(e.kind===`refuse`)throw e.error;return e.kind===`narrow`?e.value:t}function g(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 _=g(()=>t.z.object({$field:t.z.string().describe(`Field Reference/Column Name`)})),oe=g(()=>t.z.object({$eq:t.z.any().optional(),$ne:t.z.any().optional()})),v=`Comparand is a number, a Date, a string, or a { $field } reference. STRING is the form the platform itself produces: the date-macro resolver returns only strings ("{current_year_start}" -> "2026-01-01"), and the guaranteed spellings are an ISO calendar day (YYYY-MM-DD), a UTC ISO-8601 instant, or a wall-clock time of day (HH:MM[:SS[.fff]]) for a Field.time column. Those are ASCII and fixed-width, so lexicographic order IS chronological order and every backend agrees; the driver reconciles the comparand with the column (a bare calendar day used as an upper bound becomes the half-open next-day boundary). Ordering NON-temporal text is permitted but NOT promised: the order is the backend collation's (byte-wise on SQLite, the database locale on Postgres, UTF-16 code units in the JS matchers), and those coincide only for ASCII.`,se=g(()=>t.z.object({$gt:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional().describe(`Greater than. ${v}`),$gte:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional().describe(`Greater than or equal to. ${v}`),$lt:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional().describe(`Less than. ${v}`),$lte:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional().describe(`Less than or equal to. ${v}`)}));function ce(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&`$field`in e}function le(e){return`A { "$field": \u2026 } reference is not a valid ${e}. No evaluation path resolves a field reference inside a list: the in-memory evaluator (matchesFilter) leaves the list unresolved and compares the raw reference OBJECT, so it silently matches nothing, and both SQL drivers refuse the position with INVALID_FILTER / 400. Write a literal value here, or move the reference to a scalar comparison operator ($eq/$ne/$gt/$gte/$lt/$lte), whose WHOLE comparand a { $field } reference may be. Ruled 2026-08-11 on #7596: declared = enforced (ADR-0049).`}var ue=e=>t.z.array(t.z.any()).superRefine((t,n)=>{t.forEach((t,r)=>{ce(t)&&n.addIssue({code:`custom`,path:[r],message:le(`${e} member at index ${r}`)})})}),de=`Membership list. Members are literal values of any type the column stores. A { $field } reference is NOT a member shape: no backend resolves one inside a list (#7596) — put it in a scalar comparison ($eq/$ne/$gt/$gte/$lt/$lte) instead.`,fe=g(()=>t.z.object({$in:ue(`$in`).optional().describe(de),$nin:ue(`$nin`).optional().describe(de)})),pe=`Closed interval [min, max]. Each endpoint is a number, a Date, or a string. A { $field } reference is NOT an endpoint shape: no backend resolves one inside a list (#7596) — put it in a scalar comparison ($gt/$gte/$lt/$lte), which does compile to a column-to-column bound. STRING is the form the platform itself produces: the date-macro resolver walks INTO arrays, so { $between: ["{current_year_start}", "{current_year_end}"] } resolves to two strings. The guaranteed spellings are an ISO calendar day (YYYY-MM-DD), a UTC ISO-8601 instant, or a wall-clock time of day (HH:MM[:SS[.fff]]) for a Field.time column; those are ASCII and fixed-width, so lexicographic order IS chronological order and every backend agrees. The driver reconciles each endpoint with the column independently (a bare calendar day used as the MAX becomes the half-open next-day boundary). Ranging over NON-temporal text is permitted but NOT promised: the order is the backend collation's, and those coincide only for ASCII.`,me=e=>t.z.union([t.z.number(),t.z.date(),t.z.string()],{error:t=>ce(t.input)?le(`$between endpoint at index ${e}`):void 0}),he=g(()=>t.z.object({$between:t.z.tuple([me(0),me(1)]).optional().describe(`Between (inclusive). ${pe}`)})),y=g(()=>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 it; #5702 lowered it on the SQL family (driver-sql, driver-sqlite-wasm, driver-turso on both transports); #6520 lowered it on every JS evaluation face, so it is portable across every backend the platform ships.]`),$like:t.z.string().optional().describe('Whole-string pattern match with CALLER-bound wildcards: "%" matches any sequence (including empty), "_" matches exactly one character, and a backslash escapes the character after it ("\\%", "\\_", "\\\\") so it matches literally. The pattern must cover the WHOLE value — a pattern with no wildcards is an exact comparison, NOT a substring search; write $contains for containment. A pattern ending in a lone unpaired backslash is refused (INVALID_FILTER). Comparison is case-SENSITIVE, same contract as $contains (#4706 Q2 = A); $ilike is the case-insensitive twin. [#7536. Answered by the SQL family (driver-sql, driver-sqlite-wasm, driver-turso on both transports), by driver-memory and by @objectstack/formula. driver-mongodb, objectql `having` and service-analytics REFUSE it in the INVALID_FILTER envelope rather than approximating it — see FILTER_OPERATORS for why it is staged out of that allowlist.]'),$ilike:t.z.string().optional().describe(`Whole-string pattern match like $like — "%" / "_" wildcards bound by the caller, backslash escapes — but ignoring ASCII case (A-Z against a-z) and ONLY ASCII case: "café" does NOT match "CAFÉ", the same #4706 Q1 = A boundary $icontains declares, because SQLite's fold is ASCII-only and three of the five backends are SQLite underneath. [#7536; staged with $like — see FILTER_OPERATORS.]`)})),b=65,x=90,S=32;function ge(e){let t=``;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t+=r>=b&&r<=x?String.fromCharCode(r+S):e[n]}return t}function _e(e,t){return ge(e).includes(ge(t))}function ve(e){let t=``;for(let n=0;n<e.length;n++){let r=e[n],i=e.charCodeAt(n);i>=b&&i<=x?t+=`[${r}${String.fromCharCode(i+S)}]`:i>=b+S&&i<=x+S?t+=`[${String.fromCharCode(i-S)}${r}]`:t+=/[\\^$.*+?()[\]{}|/]/.test(r)?`\\${r}`:r}return t}function C(e){let t=0;for(let n=e.length-1;n>=0&&e[n]===`\\`;n--)t++;return t%2==1}function ye(e,t=!1){if(C(e))throw Error(`LIKE pattern ${JSON.stringify(e)} ends with a lone unpaired backslash; write "\\\\\\\\" to match a literal backslash.`);let n=`^`;for(let r=0;r<e.length;r++){let i=e[r],a=!1;if(i===`\\`&&(i=e[++r],a=!0),!a&&i===`%`){n+=`[\\s\\S]*`;continue}if(!a&&i===`_`){n+=`[\\s\\S]`;continue}let o=i.charCodeAt(0);t&&o>=b&&o<=x?n+=`[${i}${String.fromCharCode(o+S)}]`:t&&o>=b+S&&o<=x+S?n+=`[${String.fromCharCode(o-S)}${i}]`:n+=/[\\^$.*+?()[\]{}|/]/.test(i)?`\\${i}`:i}return`${n}$`}function be(e,t,n=!1){return new RegExp(ye(t,n)).test(e)}function xe(e){if(C(e))throw Error(`LIKE pattern ${JSON.stringify(e)} ends with a lone unpaired backslash; write "\\\\\\\\" to match a literal backslash.`);let t=e=>/[*?[]/.test(e)?`[${e}]`:e,n=``;for(let r=0;r<e.length;r++){let i=e[r];if(i===`\\`){n+=t(e[++r]);continue}if(i===`%`){n+=`*`;continue}if(i===`_`){n+=`?`;continue}n+=t(i)}return n}var Se=g(()=>t.z.object({$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),Ce=g(()=>t.z.object({$eq:t.z.any().optional(),$ne:t.z.any().optional(),$gt:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional(),$gte:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional(),$lt:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional(),$lte:t.z.union([t.z.number(),t.z.date(),t.z.string(),_]).optional(),$in:ue(`$in`).optional().describe(de),$nin:ue(`$nin`).optional().describe(de),$between:t.z.tuple([me(0),me(1)]).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(),$like:t.z.string().optional(),$ilike:t.z.string().optional(),$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),w=t.z.lazy(()=>t.z.record(t.z.string(),t.z.unknown()).and(t.z.object({$and:t.z.array(w).optional(),$or:t.z.array(w).optional(),$not:w.optional()}))),we=g(()=>t.z.object({where:w.optional()})),Te=[`$and`,`$or`,`$not`];function Ee(e,t){return`Not a valid ${e} \u2014 ${t&&typeof t==`object`&&!Array.isArray(t)?`got an object with key(s) ${Object.keys(t).map(e=>JSON.stringify(e)).join(`, `)}`:`got ${Array.isArray(t)?`an array`:t===null?`null`:typeof t}`}. A ${e} is either a FIELD CONDITION ({ "field": { "$op": value } }, whose keys are field names and whose operator map must satisfy FieldOperatorsSchema \u2014 comparand shapes included), or a nested LOGICAL GROUP carrying only ${Te.join(` / `)} and nothing else. Ruled on #7711: declared = enforced (ADR-0049).`}var T=()=>t.z.record(t.z.string(),Ce).refine(e=>!Object.keys(e).some(e=>e.startsWith(`$`)),{message:`A field condition's keys are field names, never $-prefixed operators (#7711).`,abort:!0}),De=e=>t.z.union([T(),Oe],{error:t=>Ee(e,t.input)}),Oe=t.z.lazy(()=>t.z.object({$and:t.z.array(De(`$and member`)).optional(),$or:t.z.array(De(`$or member`)).optional(),$not:De(`$not operand`).optional()}).strict()),ke={"=":`$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:`$like`,ilike:`$ilike`,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 Ae(e){return ke[e]}var je=new Set(Object.keys(ke)),Me={$eq:`=`,$ne:`!=`,$gt:`>`,$gte:`>=`,$lt:`<`,$lte:`<=`,$in:`in`,$nin:`nin`,$contains:`contains`,$notContains:`not_contains`,$startsWith:`starts_with`,$endsWith:`ends_with`,$between:`between`,$like:`like`,$ilike:`ilike`};function Ne(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`;let n=Ae(t);return n?Me[n]??t:t}function Pe(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=>Pe(e));if(e.length>=2&&typeof e[1]==`string`)return je.has(e[1].toLowerCase())}return e.every(e=>Pe(e))?e.length>0:!1}function Fe(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:typeof e.$field==`string`}function Ie(e){let[t,n,r]=e,i=n.toLowerCase();if(i===`=`||i===`==`||i===`equals`||i===`eq`)return Fe(r)?{[t]:{$eq:r}}:{[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=Ae(i);return a?{[t]:{[a]:r}}:{[t]:{[`$${i}`]:r}}}function Le(e){let t=Re(e);return t===void 0?void 0:h(t)}function Re(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=>Re(e)).filter(Boolean);return r.length===0?void 0:r.length===1?r[0]:{[n]:r}}if(e.length>=2&&typeof t==`string`)return Ie(e);if(e.every(e=>Array.isArray(e))){let t=e.map(e=>Re(e)).filter(Boolean);return t.length===0?void 0:t.length===1?t[0]:{$and:t}}}var ze=[`and`,`or`],Be=t.z.string().min(1).refine(e=>!ze.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]].`}),Ve=t.z.string().refine(e=>je.has(e.toLowerCase()),{error:e=>`Unknown filter operator '${String(e.input)}'. Recognised operators: ${[...je].sort().join(`, `)}.`}),He=t.z.string().refine(e=>ze.includes(e.toLowerCase()),{message:`A logical group opens with 'and' or 'or'.`}),Ue=t.z.lazy(()=>t.z.union([t.z.tuple([Be,Ve,t.z.unknown()]),t.z.tuple([Be,Ve]),t.z.tuple([He,Ue],Ue),t.z.array(Ue).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).`)),We=[`$eq`,`$ne`,`$gt`,`$gte`,`$lt`,`$lte`,`$in`,`$nin`,`$between`,`$contains`,`$notContains`,`$startsWith`,`$endsWith`,`$icontains`,`$null`,`$exists`],Ge=[`$and`,`$or`,`$not`],Ke=[...We,...Ge],qe=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 E(e){return t.z.never({error:()=>e}).optional().describe(`[REMOVED] ${e}`)}function Je(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}}var Ye={surface:`this view/page schema`,history:`Before ADR-0089 D3a these were dropped silently, shipping inert metadata; a mis-layered or stale key is now a loud parse error.`,guidanceSets:[{name:`VISIBILITY_KEY_PATTERN`,keys:/vis|conceal|hidden|show.?when/i,examples:[`visibleWhenn`,`visibleIf`,`hiddenWhen`,`conceal`,`showWhen`],prescription:"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."}]},Xe=[`disabled`,`disabledWhen`,`readonly`,`readOnly`,`readonlyWhen`,`editable`],Ze={name:`EDITABILITY_BOUNDARY_KEYS`,keys:Xe,prescription:"Editability is a FIELD-level concern. This shape gates VISIBILITY only — a deliberate boundary, not a missing key (#7887): a section / page component has no read-only semantics of its own to enforce. Write `readonly: true` (or the conditional `readonlyWhen` predicate) on the form field(s) inside it instead; to hide the whole section or component, use `visibleWhen`."},Qe={name:`SELECT_OPTION_EDITABILITY_BOUNDARY_KEYS`,keys:Xe,prescription:"Editability is not a per-OPTION concern — a deliberate boundary, not a missing key (#8201): an option declares WHICH value may be picked and WHEN it is offered, and nothing in the field pipeline reads a per-option enabled/disabled flag today (the select and radio widgets treat the FIELD-level state as the single authority), so a key here would be metadata the renderer never honours (ADR-0049). To withdraw ONE option, give it the per-option `visibleWhen` predicate — the one `*When` surface that also binds `current_user` (ADR-0068), so an option can be withheld per record or per role, and the rule validator refuses a write of a value whose predicate is false. To freeze the WHOLE picker, write `readonly: true` (or the conditional `readonlyWhen` predicate) on the field that owns these options. If a shown-but-unselectable option ever earns a reader, that is a spec decision to ask for — not a key to write here."},$e={...Ye,guidanceSets:[...Ye.guidanceSets??[],Ze]},et=t.z.enum([`none`,`no-overlay`,`no-delete`,`full`]),tt=t.z.enum([`artifact`,`package`,`env-forced`]),nt=t.z.enum([`package`,`org`,`env-forced`]),D={_lock:et.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:tt.optional().describe(`Layer that set _lock (artifact | package | env-forced).`),_provenance:nt.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.`)},rt=g(()=>t.z.string().min(2,{message:`System identifier must be at least 2 characters`}).regex(/^[a-z][a-z0-9_.]*$/,{message:`System identifier must be lowercase, starting with a letter, and may contain letters, numbers, underscores, or dots (e.g., "user_profile" or "order.created")`}).describe(`System identifier (lowercase with underscores or dots)`)),O=g(()=>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)`));g(()=>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 it=t.z.enum([`cel`,`cron`,`template`]),at=t.z.object({rationale:t.z.string().optional(),generatedBy:t.z.string().optional()}),ot=t.z.object({dialect:it,source:t.z.string().min(1).optional(),ast:t.z.unknown().optional(),meta:at.optional()}).refine(e=>e.source!==void 0||e.ast!==void 0,{message:"Expression requires at least one of `source` or `ast`"}),k=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cel`,source:e})),ot]);t.z.union([t.z.string().min(1).transform(e=>({dialect:`cron`,source:e})),ot]);var st=t.z.union([t.z.string().min(1).transform(e=>({dialect:`template`,source:e})),ot]),ct=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.`}}),lt=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`."}}),ut=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).`}}),dt=Object.freeze([`onEnable`,`functions`]);function ft(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function pt(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:Ln(s,o,3,1)[0]);a.push({path:`${i}.${s}`,surface:r,key:s,...c?{suggestion:c}:{},...e?.why?{guidance:e.why}:{}})}}function mt(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 ht=new Set([`YYYY`,`YY`,`MM`,`DD`,`YYYYMMDD`]);function gt(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):ht.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 _t(e){return e.some(e=>e.kind===`date`||e.kind===`field`)}function vt(e,t=4){let n=e.find(e=>e.kind===`seq`);return n&&n.kind===`seq`?n.width:t}function A(e){return e.filter(e=>e.kind===`field`).map(e=>e.field)}function yt(e,t){let n=[];for(let r of A(e)){let e=t?t[r]:void 0;(e==null||e===``)&&!n.includes(r)&&n.push(r)}return n}function bt(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 xt(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``}}var St=`{0000}`;function Ct(e){let t=e?.autonumberFormat;if(typeof t==`string`&&t)return t;let n=e?.format;return typeof n==`string`&&n?n:St}function wt(e){let{tokens:t,seq:n,record:r,now:i,timezone:a}=e,o=bt(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=xt(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=_t(t)?s:``,d=l===null?`${s}${n}`:`${s}${String(n).padStart(l,`0`)}${c}`;return{prefix:s,suffix:c,scope:u,value:d}}function Tt(e,t,n){if(t===``&&n===``||t&&!e.startsWith(t))return;let r=e.slice(t.length);n&&r.endsWith(n)&&(r=r.slice(0,r.length-n.length));let i=r.match(/^\d+/);if(!i)return;let a=parseInt(i[0],10);return Number.isFinite(a)?a:void 0}var j=`NOW()`,M=`current_user`,Et=[j,M],Dt={"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 Ot(e){return typeof e==`string`&&/^now\(\)$/i.test(e.trim())}function kt(e){return e===M}function At(e){return Ot(e)||kt(e)}function jt(e){return At(e)&&!Ot(e)}var Mt={USER:`sys_user`},Nt={OWNER_ID:`owner_id`,OWNING_BUSINESS_UNIT_ID:`owning_business_unit_id`,ORGANIZATION_ID:`organization_id`},Pt=new Set([`text`,`textarea`,`email`,`url`,`phone`,`password`,`secret`,`markdown`,`html`,`richtext`,`code`,`color`,`signature`,`qrcode`]),Ft=new Set([`number`,`currency`,`percent`,`rating`,`slider`,`progress`,`summary`]),It=new Set([`boolean`,`toggle`]),Lt=new Set([`date`]),Rt=new Set([`datetime`]),zt=new Set([`time`]),Bt=new Set([`select`,`radio`]),Vt=new Set([`multiselect`,`checkboxes`,`tags`]),Ht=new Set([`lookup`,`master_detail`,`user`,`tree`]),Ut=new Map([[`user`,Mt.USER]]);function Wt(e){if(!e||typeof e!=`object`)return;let{type:t,reference:n}=e;if(!(typeof t!=`string`||!Ht.has(t)))return typeof n==`string`&&n?n:Ut.get(t)}var Gt=new Set([`image`,`file`,`avatar`,`video`,`audio`]);function Kt(e){return typeof e==`string`&&/^[A-Za-z0-9_-]{1,64}$/.test(e)}var qt=`__rawFileValues`,Jt=new Set([`json`,`composite`,`repeater`,`record`,`location`,`address`,`vector`]),Yt=new Set([`formula`,`summary`,`autonumber`]),Xt=new Set([`select`,`radio`,`lookup`,`user`,`file`,`image`]);function Zt(e){return Vt.has(e.type)?!0:Xt.has(e.type)&&e.multiple===!0}var Qt=g(()=>t.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,`expected YYYY-MM-DD (calendar day, not an instant)`)),$t=g(()=>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)`)),en=g(()=>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)`)),tn=g(()=>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`)})),N=g(()=>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`)})),nn=N,rn=g(()=>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()})),P=g(()=>t.z.string().regex(/^[A-Za-z0-9_-]{1,64}$/,`Expected an opaque sys_file id`)),an=g(()=>t.z.union([t.z.string().min(1),rn])),on=/^\s*[[{]/,sn=g(()=>t.z.string().min(1).refine(e=>!on.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 cn(e){return Array.isArray(e.options)?e.options.map(e=>String(typeof e==`object`&&e?e.value:e)):[]}function ln(e,n=`stored`){let r=e.type,i=(()=>{if(Pt.has(r))return t.z.string();if(Ft.has(r))return t.z.number().finite();if(It.has(r))return t.z.boolean();if(Lt.has(r))return Qt;if(Rt.has(r))return $t;if(zt.has(r))return en;if(Bt.has(r)||Vt.has(r)){let n=cn(e);return n.length>0?t.z.enum(n):t.z.string()}return Ht.has(r)?n===`expanded`?t.z.union([sn,t.z.record(t.z.string(),t.z.unknown())]):sn:Gt.has(r)?n===`expanded`?t.z.union([P,rn]):P:r===`location`?tn:r===`address`?nn: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 Zt(e)?t.z.array(i):i}function un(e){return typeof e==`object`&&!!e&&!!e.dialect&&typeof e.source==`string`}function dn(e){return un(e)?`expression`:At(e)?`token`:`literal`}function fn(e,t){let n=ln(e,`stored`).safeParse(t);return n.success?{ok:!0}:{ok:!1,detail:n.error.issues[0]?.message??`invalid value`}}var pn=new Set([`datetime`,`date`,`time`]);function mn(e,t){if(!At(t))return null;let n=Ot(t)?j:M,r=e.name??`<unnamed>`;if(Zt(e))return`Field "${r}" (${e.type}, multi-value): the default ${JSON.stringify(t)} is the runtime token \`${n}\`, which resolves to a single scalar \u2014 the engine's insert-time resolution assigns one value (applyFieldDefaults) and a physical column DEFAULT is one value; neither produces the array a multi-value field stores. Make the field single-valued, or write a literal array default.`;if(n===j)return pn.has(e.type)?null:`Field "${r}" (${e.type}): the default ${JSON.stringify(t)} is the runtime token \`NOW()\` \u2014 the insert-time clock, resolved by the engine and by the SQL column DEFAULT into a temporal stored form \u2014 and a \`${e.type}\` field has no such form. It is legal only on \`datetime\`, \`date\`, or \`time\`. Use one of those temporal types, or write a literal value this field can store. (Before this gate the engine silently intercepted the token even here and stored an ISO instant \u2014 an interception nobody chose; it is refused instead.)`;if(e.type===`user`||e.type===`lookup`&&e.reference===Mt.USER)return null;let i=e.type===`lookup`?` (this lookup targets ${e.reference?`\`${e.reference}\``:`no declared object`}, not \`sys_user\`)`:``;return`Field "${r}" (${e.type}): the default ${JSON.stringify(t)} is the runtime token \`current_user\` \u2014 resolved by the engine to the acting user's \`sys_user.id\` at insert time \u2014 and a \`${e.type}\` field cannot hold one${i}. It is legal only on a \`user\` field or a \`lookup\` with \`reference: 'sys_user'\` (#4560 records what happens when that id lands anywhere else). Use one of those, or write a literal record id.`}var hn={currentuser:M,"current-user":M,"current user":M,"{current_user}":M,current_user_id:M,"{current_user_id}":M,now:j,"{now}":j,current_datetime:j,current_time:j};function gn(e){if(typeof e!=`string`)return;let t=e.trim().toLowerCase();if(!At(e))return hn[t]}var _n={AED:2,AFN:0,ALL:0,AMD:2,ANG:2,AOA:2,ARS:2,AUD:2,AWG:2,AZN:2,BAM:2,BBD:2,BDT:2,BGN:2,BHD:3,BIF:0,BMD:2,BND:2,BOB:2,BRL:2,BSD:2,BTN:2,BWP:2,BYN:2,BZD:2,CAD:2,CDF:2,CHF:2,CLP:0,CNY:2,COP:0,CRC:2,CUC:2,CUP:2,CVE:2,CZK:2,DJF:0,DKK:2,DOP:2,DZD:2,EGP:2,ERN:2,ETB:2,EUR:2,FJD:2,FKP:2,GBP:2,GEL:2,GHS:2,GIP:2,GMD:2,GNF:0,GTQ:2,GYD:2,HKD:2,HNL:2,HRK:2,HTG:2,HUF:0,IDR:0,ILS:2,INR:2,IQD:0,IRR:0,ISK:0,JMD:2,JOD:3,JPY:0,KES:2,KGS:2,KHR:2,KMF:0,KPW:0,KRW:0,KWD:3,KYD:2,KZT:2,LAK:0,LBP:0,LKR:2,LRD:2,LSL:2,LYD:3,MAD:2,MDL:2,MGA:0,MKD:2,MMK:0,MNT:2,MOP:2,MRU:2,MUR:2,MVR:2,MWK:2,MXN:2,MYR:2,MZN:2,NAD:2,NGN:2,NIO:2,NOK:2,NPR:2,NZD:2,OMR:3,PAB:2,PEN:2,PGK:2,PHP:2,PKR:0,PLN:2,PYG:0,QAR:2,RON:2,RSD:2,RUB:2,RWF:0,SAR:2,SBD:2,SCR:2,SDG:2,SEK:2,SGD:2,SHP:2,SLE:2,SLL:0,SOS:0,SRD:2,SSP:2,STN:2,SVC:2,SYP:0,SZL:2,THB:2,TJS:2,TMT:2,TND:3,TOP:2,TRY:2,TTD:2,TWD:2,TZS:2,UAH:2,UGX:0,USD:2,UYU:2,UZS:2,VES:2,VND:0,VUV:0,WST:2,XAF:0,XCD:2,XCG:2,XDR:2,XOF:0,XPF:0,XSU:2,YER:0,ZAR:2,ZMW:2,ZWG:2,ZWL:2};function vn(e){return _n[e.toUpperCase()]}function F(e,t){let n=vn(e);if(n!==void 0&&n!==t)return`currency ${e.toUpperCase()} has ${n} fraction digits; \`precision: ${t}\` contradicts it \u2014 the amount would render minor-unit digits the currency does not have, or drop digits it does (ISO 4217 / CLDR currencyData). Declare \`precision: ${n}\`, or omit \`precision\` and let renderers derive the width from the currency. Codes outside CLDR (crypto/custom) are not checked, and a field in \`dynamic\` currencyMode has no single currency to check against.`}var yn=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(`.`)),bn=new Set([`autonumber`]),xn=`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.`,Sn=g(()=>I({surface:`this select option`,history:xn,aliases:{text:`label`,name:`label`,title:`label`,key:`value`,id:`value`,isDefault:`default`,selected:`default`,colour:`color`,visible:`visibleWhen`,showWhen:`visibleWhen`},guidanceSets:[Qe]},{label:t.z.string().describe(`Display label (human-readable, any case allowed)`),value:rt.describe(`Stored value (lowercase machine identifier)`),color:t.z.string().optional().describe(`Color code for badges/charts`),default:t.z.boolean().optional().describe(`Is default option`),visibleWhen:k.optional().describe("Per-option visibility predicate (CEL) — option is offered only when TRUE (else omitted). Env: the live `record` plus the host predicate scope, which binds `current_user` — wider than field-level visibleWhen, which has no `current_user`. e.g. P`record.country == 'cn'` or P`'admin' in current_user.positions`")})),Cn=g(()=>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`)})),wn=g(()=>I({surface:`this currency configuration`,history:xn,aliases:{decimals:`precision`,scale:`precision`,mode:`currencyMode`,currency:`defaultCurrency`,code:`defaultCurrency`,isoCode:`defaultCurrency`}},{precision:t.z.number().int().min(0).max(10).optional().meta({description:`Decimal precision (default: 2)`,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)`)}).superRefine((e,t)=>{if(e.precision===void 0||e.currencyMode!==`fixed`)return;let n=F(e.defaultCurrency,e.precision);n!==void 0&&t.addIssue({code:`custom`,path:[`precision`],message:n})}).overwrite(e=>({precision:e.precision??2,currencyMode:e.currencyMode,defaultCurrency:e.defaultCurrency}))),Tn=g(()=>t.z.object({value:t.z.number().describe(`Monetary amount`),currency:t.z.string().length(3).describe(`Currency code (ISO 4217)`)})),En=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).`:``}`},Dn=g(()=>t.z.union([t.z.boolean(),t.z.literal(`global`),t.z.literal(`organization`)],{error:En}));function On(e){return e===`global`}function kn(e){return e===!0||e===`global`||e===`organization`}function An(e){return e===`organization`}function jn(){let e={},t={};for(let[n,r]of Object.entries(ct))r.to?e[n]=r.to:r.why&&(t[n]=r.why);return{aliases:e,guidance:t}}var Mn=g(()=>I({surface:`this field`,history:xn,aliases:{...jn().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`,showWhen:`visibleWhen`,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:{...jn().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).",visible:"`visible` is not a field key, and which key you want depends on the form: a static boolean is `hidden` — INVERTED, so `visible: false` is `hidden: true` — while a per-record CEL predicate is `visibleWhen` (shown only when TRUE). Its siblings are `readonlyWhen` and `requiredWhen`."}},{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:yn.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:Dn.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 applied on INSERT when the field is omitted or null (`''` is a real value, not absence). Three legal shapes (#7127), discriminated in the engine's own order: a CEL Expression envelope `{ dialect: 'cel', source: 'today()' }` (accepted structurally; result type is a runtime concern); a runtime TOKEN — `NOW()` on `datetime`/`date`/`time` only, `current_user` on `user` or `lookup` with `reference: 'sys_user'` only, neither on a multi-value field; or a LITERAL, which must satisfy this field's own stored value contract (ADR-0104 D1 `valueSchemaFor`). Anything else is refused at parse time with a prescriptive message."),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`),useGrouping:t.z.boolean().optional().describe("Digit-grouping presentation hint for `number` fields (#7768) — maps to `Intl.NumberFormat`'s `useGrouping`. Absent = renderer decides (interim heuristic today, locale default eventually); `false` = author opts out of grouping (e.g. a year or other ordinal/identifier integer); `true` = author pins grouping on."),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(Sn).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(),I({surface:`this lookup column`,history:xn,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(I({surface:`this lookup filter`,history:xn,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(),I({surface:`this dependsOn entry`,history:xn,aliases:{name:`field`,fieldName:`field`,local:`field`,remote:`param`,remoteField:`param`,key:`param`}},{field:t.z.string(),param:t.z.string().optional()})])).optional().describe("Declares that this field's available values depend on the value of other field(s) on the same record — the form gates the field until they are set and re-evaluates as they change. For `lookup`/`master_detail` it scopes the candidate query (string = same local/remote key; {field,param} when the remote filter key differs — the {field,param} form is lookup-only). For `select`/`multiselect`/`radio` the actual per-option rule lives in each option's `visibleWhen`; list the referenced fields here (string form) so the option list gates and refreshes with the parent."),allowCreate:t.z.boolean().optional().describe(`Allow inline quick-create from the record picker: when no match exists the user can create a record from the typed text (optimistic dataSource.create with the display field). Best for simple objects whose only required field is the display field.`),expression:k.optional().describe("Formula expression (CEL). e.g. F`record.amount * 0.1`"),returnType:t.z.enum([`number`,`text`,`boolean`,`date`]).optional().describe(`Inferred value type of a formula field (number/text/boolean/date)`),summaryOperations:I({surface:`this roll-up summary`,history:xn,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:w.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:wn.optional().describe(`Configuration for currency field type`),dimensions:t.z.number().int().min(1).max(1e4).optional().describe(`Vector dimensionality (e.g., 1536 for OpenAI embeddings)`),trackHistory:t.z.boolean().optional().describe(`Render this field's value changes as human-readable entries on the record activity timeline (ADR-0052 §5b). Opt-in per field.`),group:t.z.string().optional().describe(`Field group name for organizing fields in forms and layouts (e.g., "contact_info", "billing", "system")`),visibleWhen:k.optional().describe("Predicate (CEL) — field is shown only when TRUE (else hidden). e.g. P`record.type == 'invoice'`"),readonlyWhen:k.optional().describe("Predicate (CEL) — field is read-only when TRUE. e.g. P`record.status == 'paid'`"),requiredWhen:k.optional().describe("Predicate (CEL) — field is required when TRUE. The only slot; the `conditionalRequired` alias was removed in protocol 17 (#3855)."),conditionalRequired:E("`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 existing sources 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`),internal:t.z.boolean().optional().describe("[#7728] Never return this field's value on the generic data path — the engine OMITS the key from `find`/`findOne` results, the 201 create body and the by-id update body, on the default projection AND when a client names the field in `?select=`. Storage, filtering and indexing are untouched, so a server-side verifier can still match on the column and a purpose-built mint route can still return the value once at creation. The read protection for ADR-0100's third credential channel (auth-subsystem one-way hashes on `text` columns). Omission, not masking: a mask signals 'a value is set', which carries no information on a `required` column."),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 on BOTH paths: `isSystem` writes (seed replay, migration). Exempt on the UPDATE path ONLY: an opt-in "historical" import (`preserveAudit`, #3493) — which admits a whitelist (the audit/timestamp family plus author-declared business `readonly` fields). On INSERT the exemption does NOT apply (#6640): a non-system create that requests `preserveAudit` still has its readonly fields stripped, and is warned loudly that the exemption is UPDATE-only — replaying archival readonly facts on create requires a system context. 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().meta({description:"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). Omitted on an `autonumber` field ⇒ the contract default `{0000}` (#6555).",default:St}),externalId:t.z.boolean().default(!1).describe(`Is external ID for upsert operations`),...D}).superRefine((e,t)=>{if(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)."}),e.type===`currency`&&e.precision!==void 0&&e.currencyConfig?.currencyMode===`fixed`){let n=F(e.currencyConfig.defaultCurrency,e.precision);n!==void 0&&t.addIssue({code:`custom`,path:[`precision`],message:n})}let n=e.defaultValue;if(n==null)return;let r=JSON.stringify(n)??String(n),i=dn(n);if(i===`expression`)return;if(i===`token`){let r=mn({type:e.type,multiple:e.multiple,options:e.options,name:e.name,reference:e.reference},n);r!==null&&t.addIssue({code:`custom`,path:[`defaultValue`],message:r});return}let a=fn({type:e.type,multiple:e.multiple,options:e.options},n);if(!a.ok){let i=gn(n),o=i===void 0?``:` Did you mean the runtime token \`${i}\`? Near-miss spellings are never accepted as tokens (a genuinely-intended literal must stay storable) \u2014 write the exact token, or a valid literal.`;t.addIssue({code:`custom`,path:[`defaultValue`],message:`Field "${e.name??`<unnamed>`}" (${e.type}): the default ${r} cannot satisfy this field's own stored value contract \u2014 ${a.detail??`invalid value`}. The engine stores a literal default VERBATIM at insert (applyFieldDefaults), so this would seed data the field type cannot hold, surfacing far from the cause. Write the default in the field's stored value shape, or use one of the other legal shapes: a runtime token (\`NOW()\` on \`datetime\`/\`date\`/\`time\`; \`current_user\` on \`user\` or \`lookup\` with \`reference: 'sys_user'\`) or a CEL Expression envelope ({ dialect: 'cel', source: '\u2026' }).${o}`})}})),Nn={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,readonly:!0}),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})},Pn=e=>e.toLowerCase().replace(/[_\-\s]/g,``);function Fn(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 In=e=>e.toLowerCase().replace(/[-\s]/g,`_`);function Ln(e,t,n=3,r=3){let i=In(e);return t.map(t=>({value:t,distance:Fn(i,In(t)),cased:Fn(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 Rn(e,t){return e.keys instanceof RegExp?t.search(e.keys)!==-1:e.keys.includes(t)}function zn(e){let{surface:t,knownKeys:n,guidance:r={},guidanceSets:i=[],history:a}=e,o={};for(let[t,n]of Object.entries(e.aliases??{}))o[Pn(t)]=n;return e=>{if(e.code!==`unrecognized_keys`)return;let s=e.keys??[],c=[],l=[],u=new Set;for(let e of s){let t=r[e];if(t){l.push(t);continue}let a=i.find(t=>Rn(t,e));if(a){u.has(a)||(u.add(a),l.push(a.prescription));continue}let s=Math.max(2,Math.floor(e.length/3)),d=o[Pn(e)]??Ln(e,n,s,1)[0];d&&d!==e&&c.push(`\`${e}\` \u2192 \`${d}\``)}let d=`Unrecognized key(s) on ${t}: ${s.map(e=>`\`${e}\``).join(`, `)}.`;return c.length&&(d+=` Did you mean ${c.join(`, `)}?`),l.length&&(d+=`
2
- ${l.map(e=>` \u2022 ${e}`).join(`
3
- `)}`),`${d} ${a}`}}function Bn(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 Bn(n.innerType,t+1);default:return!1}}function Vn(){let e=Vn;return e.list??=[]}function Hn(e,t){let{surface:n,history:r,aliases:i,guidance:a,guidanceSets:o,extraKeys:s=[],retiredForms:c}=e,l;return Vn().push({options:e,shape:t}),e=>{if(c&&e.code===`invalid_type`){let t=typeof e.input==`string`?c[e.input]:void 0;if(t)return t}return(l??=zn({surface:n,knownKeys:[...Object.keys(t).filter(e=>!Bn(t[e])),...s],history:r,aliases:i,guidance:a,guidanceSets:o}))(e)}}function I(e,n){return t.z.object(n,{error:Hn(e,n)}).strict()}var Un=g(()=>I({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`)})),Wn=" was removed from `AggregationFunction` in @objectstack/spec 17 (#6188, ADR-0049 enforce-or-remove) — no SQL backend ever compiled it. `SqlDriver.mapAggregateFunc` and `RemoteTransport.aggregate` each lower the same set of functions and refuse the rest, and the v1 dataset runtime had to subtract this one by name to stop it reaching a `COUNT(*)` fallback that returns a row count in place of the value asked for. On the backend family this platform targets it was a declaration that could only fail. ",Gn="There is no replacement in the query vocabulary: read the rows with an ordinary `fields` query and shape them in the caller, or model the roll-up as a stored field. It returns only WITH a portable lowering — ADR-0049's enforce leg, implementation first. Run `os migrate meta --from 16` to rewrite existing sources automatically.",Kn="`array_agg`"+Wn+`Delete the aggregation, or the dataset measure that declared it. `+Gn,qn="`string_agg`"+Wn+"Its dialect divergence is the widest of the family — the delimiter is a second argument in PostgreSQL, a `SEPARATOR` clause in MySQL and a differently-named function in SQL Server — so there was never one shape to lower it to. Delete the aggregation, or the dataset measure that declared it. "+Gn,Jn=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`],{error:e=>{if(e.input===`array_agg`)return Kn;if(e.input===`string_agg`)return qn}}),Yn=t.z.enum([`day`,`week`,`month`,`quarter`,`year`]),Xn=g(()=>t.z.union([t.z.string(),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:Yn.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`)})])),Zn="`query.aggregations[].distinct` was removed in @objectstack/spec 17 (#6815, ADR-0049) — exactly ONE of the six faces that read an aggregation honoured it. The objectql in-memory fallback deduplicated the values before applying the function, while `driver-sql`, `driver-turso`, `driver-mongodb`, `driver-memory` and the service-analytics SQL builder all ignored it — so `{ function: 'sum', field: 'amount', distinct: true }` answered a DEDUPLICATED sum when the engine fell back in memory and an ordinary sum on every SQL datasource: one query, two numbers, chosen by which backend happened to serve it. Both answers are plausible, so nothing surfaced the divergence. Delete the key. For a deduplicated COUNT the live spelling is the `count_distinct` aggregation function, which every SQL face compiles to `COUNT(DISTINCT field)` (#6409) and the in-memory fallback computes identically. `SUM(DISTINCT …)` / `AVG(DISTINCT …)` get no replacement: no backend ever computed them here, and a per-row measure that needs deduplicating is a modelling problem to fix in the data, not a flag on the read.",Qn=g(()=>t.z.object({function:Jn.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (optional for COUNT(*))`),alias:t.z.string().describe(`Result column alias`),distinct:E(Zn),filter:w.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.")})),$n="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 data with `expand` — `expand: { owner_id: { object: 'user', fields: ['name'] } }` — whose nested query names the related columns you want. A dotted `fields` path is NOT the replacement: no driver ever resolved one and the ingress refuses it (`400 INVALID_FIELD`, #7532). Keep the foreign-key column in your own projection (`fields: ['title', 'owner_id']`) — the relation is carried by that key, so projecting it away leaves expansion nothing to resolve. `alias` has no replacement here; an aliased projection is an `aggregations` or `windowFunctions` entry, which carry their own `alias`.",er=t.z.string({error:e=>e.code===`invalid_type`&&typeof e.input==`object`&&e.input!==null&&!Array.isArray(e.input)?$n:void 0}),tr="`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_id: { object: 'user', fields: ['name'] } }` — which the engine resolves via batch $in queries, and whose nested query selects the related record's own columns. Keep the foreign key in your own projection (`fields: ['title', 'owner_id']`): the relation is carried by that column, so projecting it away leaves expansion nothing to resolve. A dotted `fields` path is NOT a replacement — no driver ever resolved one and the ingress refuses it (`400 INVALID_FIELD`, #7532).",nr='`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.',rr="`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.",ir="`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`.",ar=g(()=>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).`)})),or=t.z.object({object:t.z.string().describe(`Object name (e.g. account)`),fields:t.z.array(er).optional().describe("Fields to retrieve — names of the queried object's OWN columns. A dotted path (`owner.name`) is not a projection: no driver resolves one, and the ingress refuses it with `400 INVALID_FIELD` (#7532). Related data is read with `expand`, whose nested QueryAST both filters (`where`) and selects (`fields`) the related record's columns. The projection must RETAIN the foreign-key column: `fields: ['title']` with `expand: 'project_id'` resolves nothing, because the relation is carried by that key — add `'project_id'` and it works. Where the value is wanted on the queried object itself, denormalise it onto that object (a stored field, written when the source changes), the same remedy the sort axis prescribes (#6924)."),where:w.optional().describe(`Filtering criteria (WHERE)`),search:t.z.union([t.z.string(),ar]).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(Un).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:E(nr),joins:E(tr),aggregations:t.z.array(Qn).optional().describe(`Aggregation functions`),groupBy:t.z.array(Xn).optional().describe("GROUP BY targets (strings or `{field, dateGranularity?}` objects for date bucketing)"),having:w.optional().describe(`HAVING — filter over the AGGREGATED rows (aggregation aliases + groupBy projections); applied engine-side after aggregation`),windowFunctions:E(ir),distinct:E(rr)}),sr=g(()=>or.extend({expand:t.z.lazy(()=>t.z.record(t.z.string(),sr)).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.")})),cr=[{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`}],lr=[{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.`}];function ur(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function dr(e,t={}){return pr(e,t,t.path??``)}function fr(e,t,n={}){return mr(e,t,n,n.path??``)}function pr(e,t,n){let r=!1,i=!1;for(let[a,o]of Object.entries(e)){let e=mr(a,o,t,n);e===`false`?r=!0:e===`clause`&&(i=!0)}return r?`false`:i?`clause`:`true`}function mr(e,t,n,r){let i=r?`${r}.${e}`:e;if(e===`$and`||e===`$or`){if(n.assertNodeList?.(t,e,i),!Array.isArray(t))return`clause`;let r=!1,a=!1,o=!1;return t.forEach((e,t)=>{let s=`${i}[${t}]`;n.assertNode?.(e,s);let c=ur(e)?pr(e,n,s):`clause`;c===`true`?r=!0:c===`false`?a=!0:o=!0}),e===`$and`?a?`false`:o?`clause`:`true`:r?`true`:o?`clause`:`false`}if(e===`$not`){if(n.assertNode?.(t,i),!ur(t))return`clause`;let e=pr(t,n,i);return e===`true`?`false`:e===`false`?`true`:`clause`}return n.classifyKey?.(e,t,i)??`clause`}var hr=Symbol.for(`objectstack.filter.subtreeProvenance`);function gr(e,t){if(typeof e!=`object`||!e||t!==`author`&&t!==`policy`||_r(e)!==null)return e;try{Object.defineProperty(e,hr,{value:t,enumerable:!1,writable:!1,configurable:!1})}catch{}return e}function _r(e){if(e===null||typeof e!=`object`&&typeof e!=`function`)return null;let t=e[hr];return t===`author`||t===`policy`?t:null}function vr(e,t){if(typeof e!=`object`||!e||typeof t!=`object`||!t)return null;let n=new Set,r=new Set,i=(e,a)=>{if(typeof e!=`object`||!e||r.has(e))return;let o=_r(e)??a;if(e===t){n.add(o);return}if(yr(e)){if(r.add(e),Array.isArray(e))for(let t of e)i(t,o);else for(let t of Object.values(e))i(t,o);r.delete(e)}};return i(e,null),n.size===1?n.values().next().value??null:null}function yr(e){if(Array.isArray(e))return!0;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var br=[{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`}],xr=[{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. SQLite's LIKE folds ASCII — the defect #6518 replaced with GLOB on the SQLite dialects; a JS backend's equivalent is a RegExp carrying the `i` flag, which #6682 took off the last two. A backend returning both here has regressed to one of them."},{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 used to emit, and the one \`$icontains\` replaces one-for-one. #5710 flipped that producer before any backend enrolled this case (re-verified 2026-08, #6993). "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.`}],Sr=[{id:`1`,qty:100,label:`alpha`,active:!0,note:null},{id:`2`,qty:250,label:`beta`,active:!1,note:`kept`}],Cr=class{constructor(e=100){this.v=e}},wr=[{name:`string compiles and matches — operator form`,filter:()=>({label:{$eq:`beta`}}),verdict:`matches`,expected:[`2`]},{name:`number compiles and matches — the #7956 control cell`,filter:()=>({qty:{$eq:100}}),verdict:`matches`,expected:[`1`],note:`The matrix's control: this row returning on every driver is what made its zeros real answers.`},{name:`bigint compiles and matches — the crash cell, dead (#7872)`,filter:()=>({qty:{$eq:BigInt(100)}}),verdict:`matches`,expected:[`1`],note:`driver-memory answered this exact filter with a raw mingo TypeError out of Query.compile; the door narrows the bigint to its exact number, so no driver path sees a bigint at all.`},{name:`bigint compiles and matches — implicit-equality form`,filter:()=>({qty:BigInt(250)}),verdict:`matches`,expected:[`2`]},{name:`bigint compiles and matches — as an $in member`,filter:()=>({qty:{$in:[BigInt(100),999]}}),verdict:`matches`,expected:[`1`],note:`$in/$nin members are comparands in their own right (#5234) — the door narrows each.`},{name:`boolean compiles and matches — implicit-equality form`,filter:()=>({active:!0}),verdict:`matches`,expected:[`1`]},{name:`null compiles and matches — the declared null predicate`,filter:()=>({note:null}),verdict:`matches`,expected:[`1`],note:`null IS a comparand and IS the null predicate (#6050's untouched half) — the door must not confuse it with undefined.`},{name:`Date compiles — row agreement is temporal-conformance's subject`,filter:()=>({label:{$gte:new Date(`2020-01-01T00:00:00.000Z`)}}),verdict:`compiles`,note:`A Date comparand must pass the door and execute everywhere; what it MATCHES against a stored text/date column legitimately differs per storage form (ADR-0053), so no row set is asserted here.`},{name:`undefined is refused — operator form`,filter:()=>({qty:{$eq:void 0}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`undefined`,r]},{name:`undefined is refused — implicit-equality form (the mongo silent-edit worst cell, dead)`,filter:()=>({qty:void 0}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`undefined`,`null`],note:`Measured on the wire: {qty: undefined} BSON-encoded to {} — MATCH EVERYTHING, the one cell that returned MORE data rather than less. It is also the one refused value that arrives by accident ({owner: someVar} with someVar unset), so the message carries the null/omit prescription.`},{name:`undefined is refused — as an $in member`,filter:()=>({qty:{$in:[100,void 0]}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`$in[1]`]},{name:`a function is refused`,filter:()=>({qty:{$eq:(()=>1)}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`a function`,r]},{name:`a Symbol is refused`,filter:()=>({qty:{$eq:Symbol(`x`)}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`a Symbol`,r]},{name:`a Map is refused`,filter:()=>({qty:{$eq:new Map}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`a Map instance`,r]},{name:`a class instance is refused`,filter:()=>({qty:{$eq:new Cr}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`instance`,r]},{name:`a class instance is refused — implicit-equality form`,filter:()=>({qty:new Cr}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`instance`],note:`On the wire this encoded to {qty: {"v":100}} — a document match the author never wrote.`},{name:`a plain object in a scalar slot is refused`,filter:()=>({qty:{$eq:{v:100}}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`a plain object`,r],note:`The SQL family already refused this ("cannot be bound"); the door makes the answer uniform instead of deep-equality-on-two-drivers, refusal-on-three.`},{name:`a bigint beyond ±2^53 is refused — precision loss must not answer silently`,filter:()=>({qty:{$eq:BigInt(2)**BigInt(53)+BigInt(1)}}),verdict:`door-refusal`,code:`INVALID_FILTER`,mustMention:[`2^53`,r]}],Tr=`2026-07-28T12:00:00.000Z`,Er=[{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`}],Dr=[{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."}],Or=[{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`}],kr=[{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.`}],Ar=[{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`}],jr=[{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}],Mr=[{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}],Nr=Ar.map(e=>e.id),Pr=[{name:`limit 0 returns no records`,query:{limit:0},expectedRowCount:0},{name:`limit 0 with an explicit offset 0 returns no records`,query:{limit:0,offset:0},expectedRowCount:0},{name:`limit 0 past the first page still returns no records`,query:{limit:0,offset:5},expectedRowCount:0},{name:`control — limit 2 returns two records`,query:{limit:2},expectedRowCount:2},{name:`control — offset 0 alone does not truncate`,query:{offset:0},expectedRowCount:Ar.length},{name:`control — no limit returns every record`,query:{},expectedRowCount:Ar.length}],Fr=[{id:`1`,region:`west`,stage:`won`,score:10},{id:`2`,region:`west`,stage:`won`,score:20},{id:`3`,region:`west`,stage:`lost`,score:30},{id:`4`,region:`west`,stage:null,score:40},{id:`5`,region:`east`,stage:`won`,score:50},{id:`6`,region:`east`,stage:null,score:60}],Ir=[{name:`count(*) counts rows, nulls included`,function:`count`,expected:[{group:null,value:6}]},{name:`count(stage) counts non-null values, duplicates included`,function:`count`,field:`stage`,expected:[{group:null,value:4}],note:`The neighbour count_distinct must NOT equal: dedup is the difference.`},{name:`count_distinct(stage) counts distinct NON-NULL values`,function:`count_distinct`,field:`stage`,expected:[{group:null,value:2}],note:"#6409: `won` twice collapses to one and the two nulls contribute nothing — 4 means the dedup was dropped, 3 means NULL was counted as a value, 6 means the lowering fell through to count(*)."},{name:`count_distinct over an all-distinct non-null column equals the row count`,function:`count_distinct`,field:`score`,expected:[{group:null,value:6}],note:`The control for the case above: with nothing to dedup and no nulls, count_distinct and count agree — so the previous case cannot be passed by a lowering that always subtracts something.`},{name:`sum(score)`,function:`sum`,field:`score`,expected:[{group:null,value:210}]},{name:`avg(score)`,function:`avg`,field:`score`,expected:[{group:null,value:35}]},{name:`min(score)`,function:`min`,field:`score`,expected:[{group:null,value:10}]},{name:`max(score)`,function:`max`,field:`score`,expected:[{group:null,value:60}]},{name:`count_distinct(stage) grouped by region`,function:`count_distinct`,field:`stage`,groupBy:`region`,expected:[{group:`east`,value:1},{group:`west`,value:2}],note:`The two groups disagree on purpose — an aggregate computed over the whole table and repeated per group would answer 2/2, and the ungrouped case above cannot see that.`},{name:`count(stage) grouped by region`,function:`count`,field:`stage`,groupBy:`region`,expected:[{group:`east`,value:1},{group:`west`,value:3}],note:"The grouped neighbour: `west` is 3 here and 2 above."},{name:`count(*) grouped by region`,function:`count`,groupBy:`region`,expected:[{group:`east`,value:2},{group:`west`,value:4}]},{name:`sum(score) grouped by region`,function:`sum`,field:`score`,groupBy:`region`,expected:[{group:`east`,value:110},{group:`west`,value:100}]},{name:`groupBy alias renames the projected group column`,function:`count`,groupBy:`region`,groupByAlias:`bucket`,expected:[{group:`east`,value:2},{group:`west`,value:4}],note:"#6401: the VALUES are the `count(*) grouped by region` case verbatim — only the key moves. A face that ignores `alias` returns the same two numbers under `region`, so this case can only fail on the KEY, which is the whole point: every wrong answer here is a valid query returning plausible rows. `bucket` is deliberately not a column on the fixture, so a face that GROUPED BY the alias instead of projecting under it errors rather than coincidentally agreeing."},{name:`groupBy alias equal to the field name is a no-op`,function:`sum`,field:`score`,groupBy:`region`,groupByAlias:`region`,expected:[{group:`east`,value:110},{group:`west`,value:100}],note:'#6401: the degenerate alias. Its twin above cannot see a face that emits `"region" AS "region"` and breaks on the self-rename, and a face that special-cases `alias === field` needs the case that exercises the special case.'}],Lr=[`today`,`yesterday`,`tomorrow`,`now`],L=[`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`],Rr=[`week_start`,`week_end`,`month_start`,`month_end`,`quarter_start`,`quarter_end`,`year_start`,`year_end`],zr=[...Lr,...L,...Rr],Br=/^(\d+)_(minutes?|hours?|days?|weeks?|months?|years?)_(ago|from_now)$/,Vr=[`minute`,`hour`,`day`,`week`,`month`,`year`];function Hr(e){return zr.includes(e)||Br.test(e)}function Ur(e){let t=e.match(Br);if(!t)return null;let n=t[2].replace(/s$/,``);return{n:parseInt(t[1],10),unit:n,direction:t[3]}}var Wr=t.z.string().refine(Hr,{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: `+Vr.join(`, `)}),Gr=/^\$?\{([a-zA-Z0-9_]+)\}$/,Kr=t.z.string().refine(e=>{let t=e.match(Gr);return!!t&&Hr(t[1])},{message:`Not a recognised {date-macro} placeholder`}),qr={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 Jr(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 Xr(new Date(Date.UTC(r,i-1,a)))===t?Xr(new Date(Date.UTC(r,i-1,a+1))):null}function Yr(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 Jr(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 Xr(e){return`${String(e.getUTCFullYear()).padStart(4,`0`)}-${String(e.getUTCMonth()+1).padStart(2,`0`)}-${String(e.getUTCDate()).padStart(2,`0`)}`}var Zr=[`current_user_id`,`current_org_id`];function Qr(e){return Zr.includes(e)}var $r=Gr,ei=/^\$?\{([^{}]+)\}$/,ti=t.z.string().refine(Qr,{message:`Unknown context token. Must be one of: ${Zr.join(`, `)}`}),ni=t.z.string().refine(e=>{let t=e.match($r);return!!t&&Qr(t[1])},{message:`Not a recognised {context-token} placeholder`}),ri={current_user_id:"The signed-in user's id (`sys_user.id`).",current_org_id:`The active organization id.`},ii={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 ai(e){return Qr(e)||Hr(e)}function oi(e){if(typeof e!=`string`)return null;let t=e.match(ei);if(!t)return null;let n=t[1];return Qr(n)?{kind:`context`,token:n}:Hr(n)?{kind:`date-macro`,token:n}:{kind:`unknown`,token:n,suggestion:ii[n.toLowerCase()]}}var si={name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique rule name (snake_case)`),label:t.z.string().optional().describe(`Human-readable label for the rule listing`),description:t.z.string().optional().describe(`Administrative notes explaining the business reason`),active:t.z.boolean().default(!0),events:t.z.array(t.z.enum([`insert`,`update`])).default([`insert`,`update`]).describe("Write contexts the rule runs on. `delete` is intentionally absent — the evaluator only runs on the insert/update write path; guard deletions with a `beforeDelete` lifecycle hook"),priority:t.z.number().int().min(0).max(9999).default(100).describe(`Execution priority (lower runs first, default: 100)`),tags:t.z.array(t.z.string()).optional().describe(`Categorization tags (e.g., "compliance", "billing")`),severity:t.z.enum([`error`,`warning`,`info`]).default(`error`),message:t.z.string().describe(`Error message to display to the user`),...D},ci=g(()=>I({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`}},{...si,type:t.z.literal(`script`),condition:k.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),li=g(()=>I({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`}},{...si,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.")})),ui=g(()=>I({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`}},{...si,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),di=g(()=>I({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`}},{...si,type:t.z.literal(`cross_field`),condition:k.describe("Predicate (CEL) comparing fields. e.g. P`record.end_date > record.start_date`"),fields:t.z.array(t.z.string()).describe(`Fields involved. Only fields[0] is read (labels which field the violation attaches to); the rest are advisory. Shares script’s evaluation path.`)})),fi=g(()=>I({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`}},{...si,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`)})),pi=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[ci,li,ui,di,fi,mi])),mi=g(()=>I({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`}},{...si,type:t.z.literal(`conditional`),when:k.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:pi.describe(`Validation rule to apply when condition is true`),otherwise:pi.optional().describe(`Validation rule to apply when condition is false`)}));function hi(e){return e!=null&&(typeof e!=`string`||e.trim()!==``)}g(()=>t.z.object({userId:t.z.string().optional().describe(`Invoking user id (absent when the call carries no user)`),organizationId:t.z.string().optional().describe(`Active organization id (blessed developer-facing name; absent when the call is org-less)`),positions:t.z.array(t.z.string()).optional().describe('Position names held by the caller (ADR-0090 D3 vocabulary; the value of `ExecutionContext.positions`, whose schema comment reads "Formerly `roles`") — the CANONICAL spelling at this boundary and the key an action body should read. Within the #5613 deprecation window `buildActionSession()` emits the same array under both this key and the deprecated `roles`, so migrating is a change of key and nothing else; `roles` is then removed on the v11 session-alias removal path (#3280 deprecate → #3290 remove: one window, then gone). Never gate PRIVILEGE on this array — ask the security service, which evaluates capability grants, placements and the derived posture (ADR-0095), never a position-name string comparison.'),roles:t.z.array(t.z.string()).optional().describe('DEPRECATED alias of `positions` — the same caller position names under the one spelling ADR-0090 D3 forbids (the value is `ExecutionContext.positions`, "Formerly `roles`"). Read `positions` instead: within the #5613 deprecation window `buildActionSession()` emits both keys with identical values, so migrating is a change of key and nothing else. The migration prescription and its acceptance criteria are the ADR-0087 semantic migration `action-session-roles-to-positions`; removal follows the v11 session-alias removal path (#3280 deprecated → #3290 removed). Never gate PRIVILEGE on this array — ask the security service, which evaluates capability grants, placements and the derived posture (ADR-0095), never a role-name string comparison.')}).describe("Action-body `ctx.session` — the caller identity an action body reads (runtime shape, never authored)"));var gi=/^(default|[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*)$/,_i=g(()=>t.z.record(t.z.string().regex(gi,"an inline label map is keyed by BCP-47 locale tags (`en`, `zh-CN`, …) or `default` — not by `key`/`defaultValue`, which was the retired key-reference form (#5055) and resolves to nothing"),t.z.string()).describe(`Inline locale map: BCP-47 tag → translated string`)),R=g(()=>t.z.union([t.z.string(),_i]).describe(`Display label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time`)),vi=`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.`,yi=g(()=>I({surface:`these ARIA attributes`,history:vi,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:R.optional().describe(`Accessible label for screen readers (WAI-ARIA aria-label). Plain string, or an inline locale map — no translation-bundle slot addresses this key, so a plain string is announced in the source language.`),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`)),bi='`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 existing sources automatically.',z=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?bi:void 0}),xi='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.',Si=I({surface:`this expression (L1) hook body`,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${xi}`,timeoutMs:`\`timeoutMs\` ${xi}`,memoryMb:`\`memoryMb\` ${xi}`},history:`Until #4001 these were dropped silently.`},{language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)}).describe(`L1 expression body — pure formula, no IO`),Ci=I({surface:`this sandboxed JS (L2) hook body`,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.`},{language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(z).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)`)}).describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),wi=t.z.discriminatedUnion(`language`,[Si,Ci]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),Ti={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.`},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).`}}},Ei=Object.keys(Ti);function Di(e){return`features.${e} ${Ti[e].semantics===`opt-in`?`== true`:`!= false`}`}function Oi(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=Di(n),a=r.visible;return a===void 0||a===!0?{...r,visible:{dialect:`cel`,source:i}}:a===!1?(t.addIssue({code:`custom`,path:[`requiresFeature`],message:"`requiresFeature` cannot compose with `visible: false` — the literal already hides this unconditionally, so the feature gate can never take effect. Drop `requiresFeature` to keep it hidden, or drop `visible: false` to let the flag decide."}),r):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 ki={referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},Ai="`color` is a per-option key of a FIELD's option list (`SelectOptionSchema` in `data/field.zod.ts`), read where a STORED value is displayed — the grid cell and the detail badge. An action param's options are never rendered that way: the dialog builds an INPUT from them, submits the picked value and discards the list, so no renderer would read `color` here even if this shape declared it (#5016 measured this). Drop the key — to colour the value once it is stored, declare the option list on the FIELD.",ji=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 and no widget reads. An action param's options are \`{ label, value, visibleWhen }\`; drop the key.`,Mi=g(()=>I({surface:`this action param`,aliases:ki,history:`Until #3405 these were dropped silently — the param still parsed, so a mis-spelled config shipped as a control that quietly ignored it.`},{name:t.z.string().optional(),field:O.optional(),objectOverride:O.optional(),label:R.optional(),type:yn.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(I({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`,visible:`visibleWhen`,showWhen:`visibleWhen`},guidance:{color:Ai,icon:ji(`icon`),disabled:ji(`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:R,value:t.z.string(),visibleWhen:k.optional().describe("Per-option visibility predicate (CEL) — option is offered only when TRUE (else omitted). Same env as the field-level per-option visibleWhen (record + current_user). e.g. P`record.tier == 'gold'`")})).optional(),placeholder:t.z.string().optional(),helpText:t.z.string().optional(),defaultValue:t.z.unknown().optional(),multiple:t.z.boolean().optional().describe(`Allow multiple values (array value shape); mirrors FieldSchema.multiple.`),accept:t.z.array(t.z.string()).optional().describe(`Accepted upload types (MIME types / extensions) for file/image params.`),maxSize:t.z.number().int().positive().optional().describe(`Max upload size in bytes for file/image params.`),reference:O.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:k.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(Ei).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")}).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.`}).superRefine((e,t)=>{if(!hi(e.defaultValue)||!e.type)return;let n={type:e.type,multiple:e.multiple,options:e.options},r=fn(n,e.defaultValue);if(r.ok||e.field&&e.multiple===void 0&&Xt.has(e.type)&&fn({...n,multiple:!Zt(n)},e.defaultValue).ok)return;let i=r.detail??`invalid value`,a=e.name??e.field??`<unnamed>`;t.addIssue({code:`custom`,path:[`defaultValue`],message:`Action param "${a}" (${e.type}): the default ${JSON.stringify(e.defaultValue)} cannot satisfy this param's own value contract \u2014 ${i}. The dialog would PREFILL this value and the submit would then be refused with that same message (ADR-0104 D2), for a field the user never touched \u2014 so the 400 names the param but not this default, which is the real cause. Write the default in the param's declared value shape, or drop \`defaultValue\`.`})}).transform((e,t)=>Oi(e,t))),Ni=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),Pi=new Set(Ni.options.filter(e=>e!==`script`)),Fi="`global_nav` was removed from `ACTION_LOCATIONS` in @objectstack/spec 17 (#6888, ADR-0049 enforce-or-remove) — no running-app surface ever rendered it. The console command palette (`⌘K`) builds its groups from nav items, objects, dashboards, pages, reports, recent items and record search; it reads no action metadata at all, so an action declaring this location never reached a user. The only thing that DID draw it was the Studio designer, which previewed a command-palette frame for a surface the product does not have — an authoring tool teaching authors to write dead metadata (ADR-0078). Place the action on a location a renderer serves (`list_toolbar`, `list_item`, `record_header`, `record_more`, `record_related`, `record_section`), or — for an action that deliberately has no UI home, such as an object-less one invoked over REST/MCP/AI — declare it headless with `locations: []`, which keeps its capability gate, param contract and audit trail. Run `os migrate meta --from 16` to rewrite existing sources automatically.",Ii=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`],{error:e=>e.input===`global_nav`?Fi:void 0}),Li=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),Ri=`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.`,zi=I({surface:`this action's AI exposure block`,history:Ri,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:Li.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),I({surface:`this AI parameter hint`,history:Ri,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.`)}),Bi=t.z.union([t.z.boolean(),k]),Vi=()=>I({surface:`this action`,history:Ri,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:O.describe(`Machine name (lowercase snake_case)`),label:R.describe(`Display label`),description:R.optional().describe("Explanatory line shown under the title in the action's param dialog. Carries the confirm question for an action that collects params (one dialog, not two — #7278). Not the LLM-facing `ai.description`."),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(Ii).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:Ni.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:wi.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:E("`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 existing sources automatically."),params:t.z.array(Mi,{error:e=>e.code===`invalid_type`&&e.input!==null&&typeof e.input==`object`&&!Array.isArray(e.input)?"`params` is the parameter DEFINITION array (fields collected from the user before the action runs), not a values map. For a `type:'api'` action's static request body — including `{{page.<var>}}` tokens — use `bodyExtra: { … }` instead (#5777). For a `type:'url'` action there is nowhere to move it to, by decision: put static values straight into the `target` string (`${param.X}` interpolates a value collected by the params dialog, `${ctx.X}` one from the action context), and open a new tab with `openIn: 'new-tab'`. The url-side readings of an object `params` — a static `${param.X}` scope, and `params.newTab` — are RETIRED, not renamed (#6828). Expected an array of ActionParam, received an object.":void 0}).optional().describe("Input parameters required from user — an ActionParam[] DEFINITION array, never a payload map (a static request body goes in `bodyExtra`)."),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:R.optional().describe("Confirmation message before execution. On a registered action, pairing this with a non-empty `params` is refused (#7428) — that opens a second dialog for one decision; put the question on `description` instead. Correct on a param-LESS action, where the confirm is the only dialog there is."),successMessage:R.optional().describe(`Success message to show after execution`),errorMessage:R.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:I({surface:`this result dialog`,history:Ri,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:R.optional(),description:R.optional(),acknowledge:R.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(I({surface:`this result dialog field`,history:Ri,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:R.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:Bi.optional().describe("Visibility predicate — `true`/`false` literal, CEL string, or `{dialect, source}` envelope. The action is offered when it evaluates TRUE. Omit = always visible."),requiresFeature:t.z.enum(Ei).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:Bi.optional().describe("Disabled predicate — `true`/`false` literal, CEL string, or `{dialect, source}` envelope. The action is shown but refused when it evaluates TRUE. Omit = never disabled."),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:E("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),bulkEnabled:E("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),ai:zi.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`),I({surface:`this body shape`,history:Ri,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('Static request-body fields for a type:"api" action, merged last (overrides user params). `{{page.<var>}}` tokens are resolved by the runtime. This — not `params` — is where a payload goes.'),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:yi.optional().describe(`ARIA accessibility attributes`),...D}),Hi=g(()=>Vi().refine(e=>!(Pi.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`]}).refine(e=>!(e.confirmText!=null&&Array.isArray(e.params)&&e.params.length>0),{message:"An action that declares `confirmText` beside a non-empty `params` shows the user TWO dialogs for one decision — the confirm, then the param prompt, with nothing sent until the second. Carry the confirm question in the action's top-level `description` instead (it renders under the param dialog's title) and drop `confirmText`: one condition, one wording, one dialog (#7278). Not `ai.description` — that is the LLM-facing tool contract. `confirmText` stays correct for a param-LESS action, where the confirm IS the only dialog, and for a view's `bulkActionDefs`, where the pair renders one dialog by that schema's own contract.",path:[`confirmText`]}).transform((e,t)=>Oi(e,t)));function Ui(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}g(()=>t.z.preprocess(Ui,Vi().pick({type:!0,name:!0,label:!0,target:!0,openIn:!0,method:!0,params:!0,bodyExtra:!0,confirmText:!0,successMessage:!0,errorMessage:!0,refreshAfter:!0,opensInNewTab:!0}).partial({name:!0,label:!0}).refine(e=>!(Pi.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 Wi=t.z.object({lock:et.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(),Gi=g(()=>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`])),Ki=g(()=>I({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:R.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)})),qi=g(()=>I({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:R.optional().describe(`Series display label`),type:Gi.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`)})),Ji=g(()=>I({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:R.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),Yi=g(()=>I({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`)}));g(()=>I({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`)})),g(()=>I({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:Gi,title:R.optional().describe(`Chart title`),subtitle:R.optional().describe(`Chart subtitle`),description:R.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:Ki.optional().describe(`X-Axis configuration`),yAxis:t.z.array(Ki).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(qi).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(Ji).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:Yi.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:yi.optional().describe(`ARIA accessibility attributes`)}));var Xi=g(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),Zi=g(()=>t.z.union([t.z.string().describe(`Field to group by`),I({surface:`this chart groupBy`,history:"Until #5583 an undeclared key inside the structured groupBy was dropped at parse — `dateGranularty` for `dateGranularity` cost the date bucketing silently, and the chart drew one point per raw timestamp.",aliases:{granularity:`dateGranularity`,bucket:`dateGranularity`,name:`field`,as:`alias`,label:`alias`},guidance:{function:"`function` belongs on the aggregate, not inside `groupBy` — write `aggregate: { function, field, groupBy: { field, dateGranularity } }`.",groupBy:"You are already inside `groupBy` — the structured form is `{ field, dateGranularity?, alias? }`, not a nested `groupBy`."}},{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")})]));g(()=>I({surface:`this chart aggregate`,history:"Until #5583 an undeclared aggregate key was dropped at parse — `groupby` for `groupBy` degraded the chart to a single ungrouped point, and `fn` for `function` fell back to the default, both with `build`/`validate` fully green.",aliases:{fn:`function`,agg:`function`,aggregation:`function`,measure:`field`,dimension:`groupBy`,category:`groupBy`},guidance:{dateGranularity:'`dateGranularity` goes INSIDE `groupBy`, not beside it — write `groupBy: { field: "<date field>", dateGranularity: "month" }`.',alias:"`alias` renames the GROUP column and lives inside the structured `groupBy` node. The measure column is named after `field` (or the literal `count` for a fieldless count) and is not renameable here — see `chartAggregateResultKeys` in `./chart-aggregate.ts`.",filter:"`filter` is a prop on the chart itself (`<ObjectChart filter={…}>`), not part of the aggregate.",objectName:"`objectName` is the chart's own prop — the aggregate runs against it and does not name it again.",measures:"An inline aggregate is SINGLE-MEASURE by design (one `function` over one `field`); two measures would collide on the result column name. Multi-measure is the dataset path's job — bind `dataset` + `values` instead (ADR-0021 Level B, see `./chart-aggregate.ts`)."}},{field:t.z.string().optional().describe(`Field to aggregate — required for sum/avg/min/max, optional for count`),function:Xi.describe(`Aggregation function`),groupBy:Zi.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 Qi=`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.`,$i=g(()=>I({surface:`this sharing config`,history:Qi,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`)})),ea=t.z.enum([`update`,`delete`,`custom`]),ta=t.z.enum([`perRecord`,`aggregate`]),na=g(()=>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:yn.describe(`Field widget to render, from the standard field-type vocabulary (text/number/select/lookup/date/…).`),required:t.z.boolean().optional().describe(`Blocks the Confirm button until a value is present.`),default:t.z.unknown().optional().describe("Value applied when the dialog opens. (An ActionParam spells this `defaultValue`.)"),options:t.z.array(t.z.object({label:t.z.string().describe(`Option label (plain string — not i18n-resolved on this path).`),value:t.z.union([t.z.string(),t.z.number(),t.z.boolean()]).describe(`Stored value.`)}).passthrough()).optional().describe("Static options for select-style widgets. Each entry is `{ label, value }` plus any extra widget config — the entry is open (`.passthrough()`) because the renderer forwards unknown option keys to the field widget, which reads `color` / `icon` / `disabled` / `visibleWhen` beyond the declared pair."),object:O.optional().describe("Target object for a `lookup` widget. (An ActionParam spells this `reference`.)"),labelField:t.z.string().optional().describe("Related-object field used as the option label for a `lookup` widget (defaults to name/full_name/email/id)."),multiple:t.z.boolean().optional().describe(`Allow picking multiple values — the param value becomes an array and is written to the patch as-is.`),placeholder:t.z.string().optional().describe(`Placeholder text.`)}).passthrough()),ra=g(()=>I({surface:`this bulk action definition`,aliases:{action:`name`,actionname:`name`,title:`label`,op:`operation`,mode:`execution`,confirm:`confirmText`,confirmmessage:`confirmText`,limit:`maxRecords`,max:`maxRecords`,batch:`batchSize`,permissions:`requiredPermissions`,capabilities:`requiredPermissions`,requiresPermissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`,acl:`requiredPermissions`},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)."},{name:O.describe(`Stable identifier — the audit-log action key, and (for an aggregate def) the name of the object action to dispatch.`),label:t.z.string().optional().describe("Button + dialog-header text. Plain string: an authored def is not i18n-resolved (declare a real action and name it in `bulkActions` to get localization)."),icon:t.z.string().optional().describe(`Lucide icon name (e.g. "user-check", "trash-2").`),variant:t.z.enum([`primary`,`secondary`,`danger`,`ghost`,`outline`]).optional().describe(`Visual treatment of the button.`),operation:ea.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:ta.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(na).optional().describe(`Inputs collected once before the run. Omit to skip the params step and go straight to confirm.`),confirmText:t.z.string().optional().describe(`Confirmation text shown above the affected-record summary.`),confirmLabel:t.z.string().optional().describe(`Custom Confirm button label (default: "Run").`),visible:k.optional().describe("Eligibility predicate (CEL) — a string or a `{dialect, source}` envelope, i.e. `action.visible` without its boolean-literal arm (#5970): a per-record predicate has nothing to say as a constant. 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."),requiredPermissions:t.z.array(t.z.string()).optional().describe("[ADR-0066 D4] Capability gate on the button, `action.requiredPermissions` semantics verbatim: absent or empty always passes, several are AND-ed, and a client that cannot resolve the caller's capabilities fails OPEN (the server stays the authority). This key exists for INLINE defs — notably the `update`/`delete` data-plane forms, which dispatch no action and so have nothing to inherit a gate from; a def promoted from `bulkActions: ['<name>']` (or an aggregate def naming a declared action) inherits the action's own declaration instead. On a data-plane def the gate governs visibility only — the write itself is still authorized by the data API's object permissions and server hooks."),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.`)}).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`."})})),ia=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."),aa=g(()=>t.z.enum([`GET`,`POST`,`PUT`,`PATCH`,`DELETE`]).describe("HTTP methods a view data source may request — the subset of `HttpMethod` without `HEAD`/`OPTIONS`.")),oa=g(()=>t.z.object({url:t.z.string().describe(`API endpoint URL`),method:aa.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`)}));g(()=>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(ia).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`)})),g(()=>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`)})),g(()=>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 B=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,sa=g(()=>t.z.discriminatedUnion(`provider`,[I({surface:"this `object` data source",history:B,aliases:{objectName:`object`}},{provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),I({surface:"this `api` data source",history:B,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:oa.optional().describe(`Configuration for fetching data`),write:oa.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),I({surface:"this `value` data source",history:B,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`)}),I({surface:"this `schema` data source",history:B,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.`)})])),ca=[`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`],la=[`in`,`not_in`],ua=[`between`],da={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 fa(e){return typeof e!=`string`||ca.includes(e)?e:da[e]??da[e.toLowerCase()]??e}var pa=[`id`],ma=[`filter`,`sort`],ha=12,ga="`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 _a(e,t,n){if(n>ha||!e||typeof e!=`object`)return e;if(Array.isArray(e)){let r=!1,i=e.map(e=>{let i=_a(e,t,n+1);return i!==e&&(r=!0),i});return r?i:e}let r=e,i;if(t)for(let e of pa)e in r&&(i??={...r},delete i[e]);for(let[e,t]of Object.entries(i??r)){let a=_a(t,ma.includes(e),n+1);a!==t&&(i??={...r},i[e]=a)}return i??e}function va(e){return _a(e,!1,0)}function ya(e){return e===null?`null`:e===void 0?`no value`:Array.isArray(e)?`an array of ${e.length}`:`a ${typeof e}`}function ba(e){if(e===void 0)return`(omitted)`;let t;try{t=JSON.stringify(e)??String(e)}catch{t=String(e)}return t.length>40?`${t.slice(0,39)}\u2026`:t}function xa(e,t){let n=e.operator,r=e.value,i=typeof e.field==`string`?e.field:`<field>`,a=la.includes(n),o=ua.includes(n);if(a){if(Array.isArray(r))return;t.addIssue({code:`custom`,path:[`value`],message:`Operator "${n}" on field "${i}" requires an ARRAY of values. Received ${ya(r)} (${ba(r)}). "${n}" tests membership of a list \u2014 write ${r===void 0?`["…"]`:ba([r])} for a single value, or use ${n===`in`?`"equals"`:`"not_equals"`} to compare against it. An empty list [] is allowed and is a real predicate. This is refused at authoring time because the query path refuses it too (400 INVALID_FILTER, #5869).`});return}o&&(Array.isArray(r)&&r.length===2||t.addIssue({code:`custom`,path:[`value`],message:`Operator "${n}" on field "${i}" requires a [min, max] value array. Received ${ya(r)} (${ba(r)}). A range needs exactly two bounds, in order. This is refused at authoring time because the query path refuses it too (400 INVALID_FILTER, #5869).`}))}var Sa=g(()=>I({surface:`this filter rule`,history:B,guidance:{id:ga}},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(fa,t.z.enum(ca)).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. The accepted SHAPE depends on the operator: `in` / `not_in` take an array (any length, including []), `between` takes exactly [min, max], every other operator takes a scalar. The unary operators (is_empty / is_not_empty / is_null / is_not_null) take their direction from the operator name and ignore this key.")}).superRefine(xa).describe(`View filter rule`)),Ca=g(()=>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`)),wa=g(()=>I({surface:`this column summary configuration`,history:B},{type:Ca.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),Ta=g(()=>I({surface:`this column prefix`,history:B},{field:t.z.string().describe(`Field whose value renders before the cell value`),type:t.z.enum([`badge`,`text`]).default(`text`).describe(`How the prefix value is rendered`)}).describe(`Compound-cell prefix configuration`)),Ea=g(()=>I({surface:`this list column`,history:B},{field:t.z.string().describe(`Field name (snake_case)`),label:R.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([Ca,wa]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:Ta.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`)})),Da=g(()=>I({surface:`this selection configuration`,history:B},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),Oa=g(()=>I({surface:`this pagination configuration`,history:B},{pageSize:t.z.number().int().positive().default(25).describe(`Number of records per page`),pageSizeOptions:t.z.array(t.z.number().int().positive()).optional().describe(`Available page size options`)})),V=g(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),ka=g(()=>I({surface:`this grouping field`,history:B},{field:t.z.string().describe(`Field name to group by`),order:t.z.enum([`asc`,`desc`]).default(`asc`).describe(`Group sort order`),collapsed:t.z.boolean().default(!1).describe(`Collapse groups by default`)})),Aa=g(()=>I({surface:`this grouping configuration`,history:B},{fields:t.z.array(ka).min(1).describe(`Fields to group by, in nesting order — the first entry is the outermost group and each later entry nests one level deeper (at least one field)`)}).describe(`Record grouping configuration`)),ja=g(()=>I({surface:`this gallery configuration`,history:B},{coverField:t.z.string().optional().describe(`Attachment/image field to display as card cover`),coverFit:t.z.enum([`cover`,`contain`]).default(`cover`).describe(`Image fit mode for card cover`),cardSize:t.z.enum([`small`,`medium`,`large`]).default(`medium`).describe(`Card size in gallery view`),titleField:t.z.string().optional().describe(`Field to display as card title`),visibleFields:t.z.array(t.z.string()).optional().describe(`Fields to display on card body`)}).describe(`Gallery/card view configuration`)),Ma=g(()=>I({surface:`this timeline configuration`,history:B},{startDateField:t.z.string().describe(`Field for timeline item start date`),endDateField:t.z.string().optional().describe(`Field for timeline item end date`),titleField:t.z.string().describe(`Field to display as timeline item title`),groupByField:t.z.string().optional().describe(`Field to group timeline rows`),colorField:t.z.string().optional().describe(`Field to determine item color`),scale:t.z.enum([`hour`,`day`,`week`,`month`,`quarter`,`year`]).default(`week`).describe(`Default timeline scale`)}).describe(`Timeline view configuration`)),Na=g(()=>I({surface:`this view sharing`,history:B},{type:t.z.enum([`personal`,`collaborative`]).default(`collaborative`).describe(`View ownership type`),lockedBy:t.z.string().optional().describe(`User who locked the view configuration`)}).describe(`View sharing and access configuration`)),Pa=g(()=>I({surface:`this row color configuration`,history:B},{field:t.z.string().describe(`Field to derive color from (typically a select/status field)`),colors:t.z.record(t.z.string(),t.z.string()).optional().describe(`Map of field value to color (hex/token)`)}).describe(`Row color configuration based on field values`)),Fa=g(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),Ia=g(()=>I({surface:`this user actions configuration`,history:B},{sort:t.z.boolean().default(!0).describe(`Allow users to sort records`),search:t.z.boolean().default(!0).describe(`Allow users to search records`),filter:t.z.boolean().default(!0).describe(`Allow users to filter records`),refresh:t.z.boolean().default(!0).describe(`Allow users to reload the view data from the backend without a full page reload`),rowHeight:t.z.boolean().default(!0).describe(`Allow users to toggle row height/density`),addRecordForm:t.z.boolean().default(!1).describe(`Add records through a form instead of inline`),editInline:t.z.boolean().default(!1).describe(`Allow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in.`),buttons:t.z.array(t.z.string()).optional().describe(`Custom action button IDs to show in the toolbar`)}).describe(`User action toggles for the view toolbar`)),La=g(()=>I({surface:`this appearance configuration`,history:B},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array(Fa).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),Ra=g(()=>I({surface:`this view tab`,history:B},{name:O.describe(`Tab identifier (snake_case)`),label:R.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(Sa).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`)),za=g(()=>I({surface:`this user filter field`,history:B},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:R.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(I({surface:`this user filter option`,history:B,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:R.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`)),Ba=g(()=>I({surface:`these user filters`,history:B},{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(za).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(Ra).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("Let end users add their own tab after the presets (tabs element): the affordance asks for a name and snapshots the filters currently applied as a new tab. SESSION-SCOPED — an added tab lives only for the current mount, is never written back as metadata (ADR-0047), and carries a remove control the authored presets do not. Page lists only — object views use `listViews` for named presets")}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),Va=g(()=>I({surface:`this add record configuration`,history:B},{enabled:t.z.boolean().default(!0).describe(`Show the add record entry point`),position:t.z.enum([`top`,`bottom`,`both`]).default(`bottom`).describe(`Position of the add record button`),mode:t.z.enum([`inline`,`form`,`modal`]).default(`inline`).describe(`How to add a new record`),formView:t.z.string().optional().describe(`Named form view to use when mode is "form" or "modal"`)}).describe(`Add record entry point configuration`)),Ha=g(()=>I({surface:`this kanban configuration`,history:B},{groupByField:t.z.string().describe(`Field to group columns by (usually status/select)`),summarizeField:t.z.string().optional().describe(`Field to sum at top of column (e.g. amount)`),columns:t.z.array(t.z.string()).describe(`Fields to show on cards`)})),Ua=g(()=>I({surface:`this list chart configuration`,history:B},{chartType:Gi.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:O.describe(`Dataset name to bind (ADR-0021)`),dimensions:t.z.array(t.z.string()).optional().describe(`Dimension names — X/group/split`),values:t.z.array(t.z.string()).min(1).describe(`Measure names — Y (at least one)`)}).describe(`List chart view configuration`)),H=g(()=>I({surface:`this calendar configuration`,history:B},{startDateField:t.z.string().describe(`Field providing the event start date/time`),endDateField:t.z.string().optional().describe(`Field providing the event end date/time (defaults to a single-day event)`),titleField:t.z.string().describe(`Field displayed as the event title`),colorField:t.z.string().optional().describe(`Field whose value determines the event color`)})),Wa=g(()=>I({surface:`this gantt quick filter`,history:B},{field:t.z.string().describe(`Record field / dot-path the dimension filters on`),label:t.z.string().optional().describe(`Trigger label (falls back to the field label)`),options:t.z.array(t.z.union([t.z.string(),I({surface:`this gantt quick-filter option`,history:B,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`)})),Ga=g(()=>I({surface:`this gantt configuration`,history:B},{startDateField:t.z.string().describe(`Field providing the task start date`),endDateField:t.z.string().describe(`Field providing the task end date`),titleField:t.z.string().describe(`Field displayed as the task title`),progressField:t.z.string().optional().describe(`Field providing the task completion percentage`),dependenciesField:t.z.string().optional().describe(`Field listing the task's predecessor (dependency) record ids`),colorField:t.z.string().optional().describe(`Field that drives the bar color`),parentField:t.z.string().optional().describe(`Field holding the parent task id (builds the summary → step tree)`),typeField:t.z.string().optional().describe(`Field whose value maps to task/summary/milestone`),baselineStartField:t.z.string().optional().describe(`Baseline (planned) start field`),baselineEndField:t.z.string().optional().describe(`Baseline (planned) end field`),groupByField:t.z.string().optional().describe(`Field to group leaf tasks by (synthesized summary rows)`),resourceView:t.z.boolean().optional().describe(`Render a per-resource workload histogram instead of the timeline`),assigneeField:t.z.string().optional().describe(`Resource field to bucket load by (resource view)`),effortField:t.z.string().optional().describe(`Per-task load units (resource view; default 1)`),capacity:t.z.number().optional().describe(`Per-resource capacity ceiling; loads above this flag overload`),tooltipFields:t.z.array(t.z.union([t.z.string(),I({surface:`this gantt tooltip field`,history:B,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(Wa).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()),Ka=g(()=>I({surface:`this tree configuration`,history:B},{parentField:t.z.string().optional().describe(`Single-parent pointer field (auto-detected from the object schema when omitted)`),labelField:t.z.string().optional().describe(`Field rendered indented in the first column (defaults to "name")`),fields:t.z.array(t.z.string()).optional().describe(`Additional fields rendered as flat columns alongside the label`),defaultExpandedDepth:t.z.number().int().min(0).optional().describe(`Initial expansion depth (0 = roots only; omit = expand all)`)}).passthrough()),qa=g(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),Ja=g(()=>I({surface:`this navigation configuration`,history:B},{mode:qa.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.')})),Ya="'pdf' was removed from `view.exportOptions` formats in @objectstack/spec 17.0.0 (#8010; PDF export itself was declined as #1301 NOT_PLANNED) — no renderer has ever produced a PDF export: ObjectGrid dropped the declared format from the export menu with only a runtime console.warn, so authoring it was a parse-clean no-op. Delete the value; the surviving formats are 'csv', 'xlsx' and 'json'. Run `os migrate meta --from 16` to rewrite existing sources automatically.",Xa=t.z.enum([`csv`,`xlsx`,`json`],{error:e=>e.input===`pdf`?Ya:void 0}),Za=I({surface:`this export options block`,history:B},{formats:t.z.array(Xa).optional().describe(`Formats offered in the export menu (default: ['csv', 'json']). XLSX is delivered by the server stream only.`),maxRecords:t.z.number().int().nonnegative().optional().describe(`Maximum number of records to export; 0 or absent = unlimited`),includeHeaders:t.z.boolean().optional().describe(`Include column headers in the exported file (default true)`),fileNamePrefix:t.z.string().optional().describe(`Download file name prefix — replaces the object label and suppresses the view label in the generated file name`),streaming:t.z.boolean().optional().describe(`Set false to force the client-side export path (csv/json only) instead of the server stream`)}),Qa=e=>{let t=e.input;return(Array.isArray(t)?t.includes(`pdf`):t&&typeof t==`object`&&Array.isArray(t.formats)&&t.formats.includes(`pdf`))?Ya:void 0},$a=g(()=>I({surface:`this list view`,history:B},{name:O.optional().describe(`Internal view name (lowercase snake_case)`),label:R.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:sa.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(Ea)]).describe(`Fields to display as columns`),filter:t.z.array(Sa).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(I({surface:`this sort entry`,history:B,aliases:{direction:`order`},guidance:{id:ga}},{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:Ba.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`),compactToolbar:t.z.boolean().optional().describe(`Collapse Group/Color/Density/Hide-fields into a single View settings popover`),selection:Da.optional().describe(`Row selection configuration`),navigation:Ja.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:Oa.optional().describe(`Pagination configuration`),kanban:Ha.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:H.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:Ga.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:ja.optional(),timeline:Ma.optional(),chart:Ua.optional(),tree:Ka.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:R.optional().describe(`View description for documentation/tooltips`),sharing:Na.optional().describe(`View sharing and access configuration`),rowHeight:V.optional().describe(`Row height / density setting`),grouping:Aa.optional().describe(`Group records by one or more fields`),rowColor:Pa.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(ra).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}`."),conditionalFormatting:t.z.array(I({surface:`this conditional formatting rule`,history:B,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:k.describe(`Predicate (CEL) to evaluate.`),style:t.z.record(t.z.string(),t.z.string()).describe(`CSS styles to apply when condition is true`)})).optional().describe(`Conditional formatting rules for list rows`),inlineEdit:t.z.boolean().optional().describe(`Allow inline editing of records directly in the list view`),exportOptions:t.z.union([t.z.array(Xa).transform(e=>({formats:e})),Za],{error:Qa}).optional().describe("Export configuration for the list toolbar export menu: `{ formats?, maxRecords?, includeHeaders?, fileNamePrefix?, streaming? }`. A bare format array is the legacy spelling and lifts to `{ formats: [...] }` at parse."),userActions:Ia.optional().describe(`User action toggles for the view toolbar`),appearance:La.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(Ra).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:Va.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:I({surface:`this empty state`,history:B,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:R.optional(),message:R.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:yi.optional().describe(`ARIA accessibility attributes for the list view`),responsive:E("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),performance:E("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),striped:E("`view.striped` was removed in @objectstack/spec 17.0.0 (#7176, ADR-0049 enforce-or-remove) — every measured reader only copied it forward and no renderer ever applied it, so authoring it was a parse-clean no-op. There is no authorable striped-rows switch; delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically."),bordered:E("`view.bordered` was removed in @objectstack/spec 17.0.0 (#7176, ADR-0049 enforce-or-remove) — every measured reader only copied it forward and no renderer ever applied it (the grid frame is the renderer's own constant, not authorable). Delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically."),virtualScroll:E("`view.virtualScroll` was removed in @objectstack/spec 17.0.0 (#7176, ADR-0049 enforce-or-remove) — every measured reader only copied it forward and no grid ever virtualized off it; authoring it was a parse-clean no-op. Delete the key; large datasets page via `pagination`. Run `os migrate meta --from 16` to rewrite existing sources automatically.")})),eo=g(()=>I({surface:`this public picker configuration`,history:B},{displayFields:t.z.array(t.z.string()).min(1).max(5).optional().describe("Fields projected into each picker result (with `id`); the visitor's search matches `contains` on the first entry. At most 5 (the route projects no more); omitted → ['name']."),maxResults:t.z.number().int().min(1).max(50).optional().describe(`Maximum rows a lookup returns (default 20, hard ceiling 50 — the route clamps; anonymous visitors cannot paginate past it).`),filter:t.z.array(Sa).optional().describe("Static pre-filter rows ANDed ahead of the visitor's search (e.g. only active records are searchable). Same `{ field, operator, value }` dialect as list-view filters."),object:t.z.string().optional().describe("Referenced-object override for the picker search; omitted → resolved from the field definition (`referenceTo`).")}).describe(`Public-lookup opt-in: enables GET /forms/:slug/lookup/:field for this field on an anonymous public form (without it the route answers 403 LOOKUP_NOT_PUBLIC).`)),to=g(()=>{let e={field:t.z.string().describe(`Field name (snake_case)`),type:yn.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(Sn).optional().describe(`Options for select/multiselect/radio/checkboxes fields`),reference:t.z.string().optional().describe(`Target object name for lookup/master_detail fields`),publicPicker:eo.optional().describe(`Opt this field into the anonymous public-form lookup picker (GET /forms/:slug/lookup/:field). Without it the route answers 403 LOOKUP_NOT_PUBLIC and the field is stripped from the rendered public form.`),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:R.optional().describe(`Display label override`),placeholder:R.optional().describe(`Placeholder text`),helpText:R.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:I({surface:`this record key field`,history:B,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:R.optional().describe(`Display label for the key column`),placeholder:R.optional().describe(`Placeholder when entering a new key`),helpText:R.optional().describe(`Help text under the key input`),regex:t.z.string().optional().describe(`JS regex source string the key must match (no flags)`),immutable:t.z.boolean().default(!0).describe(`If true, the key is read-only after creation`)}).optional().describe(`Key column config for record-typed fields`),dependsOn:t.z.string().optional().describe(`Parent field name for cascading`),visibleWhen:k.optional().describe("Visibility predicate (CEL) — field shown only when TRUE. Root: `record` (+ `previous`, `parent`) in runtime forms, or `data` in metadata forms. No `current_user` at field level — it is unbound here and the predicate would fault open (per-option `visibleWhen` is the surface that binds it). Inside a repeater `data` is the ROW, but it is still spelled `data` — a bare identifier is unbound and faults open too. e.g. P`record.priority == 'urgent'`"),visibleOn:k.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Normalized to `visibleWhen` at parse."),disclosure:t.z.enum([`inline`,`popover`]).optional().describe(`Composite rendering: inline bordered box (default) or a summary line + gear popover (progressive disclosure).`)};return t.z.object(e,{error:Hn({...Ye,surface:`this form field`,extraKeys:[`fields`],aliases:{disabled:`readonly`}},e)})}),no=g(()=>to.extend({fields:t.z.array(t.z.lazy(()=>no)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(Je)),ro=g(()=>I({...$e,surface:`this form section`},{name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:R.optional(),description:t.z.string().optional().describe(`Optional description rendered under the section header.`),collapsible:t.z.boolean().default(!1),collapsed:t.z.boolean().default(!1),visibleWhen:k.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record` (+ `previous`, `parent`) in runtime forms, or `data` in metadata forms. No `current_user` at section level — it is unbound here and the predicate would fault open."),visibleOn:k.optional().describe("[DEPRECATED → `visibleWhen`] Visibility predicate (CEL). Hides the whole section when false. Normalized to `visibleWhen` at parse."),columns:t.z.union([t.z.enum([`1`,`2`,`3`,`4`]),t.z.literal(1),t.z.literal(2),t.z.literal(3),t.z.literal(4)]).default(1).transform(e=>typeof e==`string`?parseInt(e):e),pane:t.z.enum([`primary`,`secondary`]).optional().describe(`Split pane this section renders in (split forms only; a parse error elsewhere). Omitted → first section 'primary', others 'secondary'.`),fields:t.z.array(t.z.union([t.z.string(),no]))}).transform(Je)),io=g(()=>I({surface:`this form button configuration`,history:B},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:R.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict());function ao(e){if(e.groups===void 0)return e;let{groups:t,...n}=e;return n.sections===void 0?{...n,sections:t}:n}var oo=`ruled 2026-08-11 on #7496`,so=/\{\{record\.[a-z_][a-z0-9_]*\}\}/g,co=/^[a-z][a-z0-9+.-]*:/i,lo=/[\s\u0000-\u001f\u007f]/;function uo(e){if(e===``)return`A \`redirect\` submit behavior needs a \`url\` \u2014 an empty string is not a destination. Write the in-app path the submitter should land on, e.g. \`/thanks\` (${oo}).`;if(co.test(e))return`\`submitBehavior.url\` accepts a RELATIVE path only, and this is an absolute URL (${oo}). A post-submit redirect that can leave the app is an open redirect, so the scheme form is refused at the authoring door rather than sanitized at the renderer. Write the in-app path instead \u2014 \`/thanks\`, not \`https://example.com/thanks\`. To send the browser OUT of the app deliberately, that is an app navigation item (\`{ type: 'url', url }\`), which is declared for external addresses.`;if(e.startsWith(`//`))return`\`submitBehavior.url\` accepts a RELATIVE path only, and a leading \`//\` is protocol-relative \u2014 the browser reads \`//example.com/thanks\` as ANOTHER ORIGIN despite the leading slash (${oo}). Use a single leading slash for an in-app path; for a deliberate external link use an app navigation item (\`{ type: 'url', url }\`).`;if(e.includes(`\\`))return`\`submitBehavior.url\` must not contain a backslash \u2014 browsers normalise \`\\\` to \`/\` while resolving, so \`/\\example.com\` navigates off-origin exactly like \`//example.com\` and would walk straight past the relative-only rule (${oo}). Write the path with forward slashes; percent-encode a backslash that is genuinely part of a path segment (\`%5C\`).`;if(lo.test(e))return`\`submitBehavior.url\` must not contain whitespace or control characters \u2014 browsers strip them before resolving, so a leading one hides what the address really starts with and defeats the relative-only rule (${oo}). Percent-encode a space that belongs in the path (\`%20\`).`;let t=e.replace(so,``);if(t.includes(`{`)||t.includes(`}`))return`\`submitBehavior.url\` interpolates ONLY declared record fields, spelled \`{{record.field_name}}\` \u2014 \`${t.match(/\{\{?[^{}]*\}?\}?/)?.[0]??`{`}\` is not that shape (${oo}). The record just submitted is the whole scope a post-submit redirect has, and the field segment takes the same lowercase snake_case grammar fields are declared under. Every interpolated value is URL-escaped when the redirect is built, so a token is a value in the path or query \u2014 never a way to add path structure.`;if(!e.startsWith(`/`))return`\`submitBehavior.url\` must start with \`/\` \u2014 a document-relative path like \`thanks\` resolves against whichever console route the form happened to be opened from, so one form lands in different places depending on how it was reached (${oo}). Write the rooted in-app path: \`/thanks\`.`}var fo=g(()=>I({surface:`this form view`,history:B},{type:t.z.enum([`simple`,`tabbed`,`wizard`,`split`,`drawer`,`modal`]).default(`simple`),layout:t.z.enum([`vertical`,`horizontal`,`inline`,`grid`]).optional().describe(`Field layout direction`),columns:t.z.number().int().min(1).optional().describe(`Number of columns for the form body`),title:t.z.string().optional().describe(`Form title`),description:t.z.string().optional().describe(`Form description`),defaultTab:t.z.string().optional().describe(`Initially active tab (tabbed forms)`),tabPosition:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Tab strip position (tabbed forms)`),allowSkip:t.z.boolean().optional().describe(`Allow skipping steps (wizard forms)`),showStepIndicator:t.z.boolean().optional().describe(`Show the step indicator (wizard forms)`),splitDirection:t.z.enum([`horizontal`,`vertical`]).optional().describe(`Split orientation (split forms)`),splitSize:t.z.number().optional().describe(`Primary split panel size, % (split forms)`),splitResizable:t.z.boolean().optional().describe(`Whether the split is resizable (split forms)`),drawerSide:t.z.enum([`top`,`bottom`,`left`,`right`]).optional().describe(`Drawer side (drawer forms)`),drawerWidth:t.z.string().optional().describe(`[DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it.`),modalSize:t.z.enum([`sm`,`default`,`lg`,`xl`,`full`]).optional().describe(`Modal size (modal forms)`),data:sa.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(ro).optional(),groups:t.z.array(ro).optional().describe("[LEGACY ALIAS → `sections`] Accepted for back-compat and folded onto `sections` at parse; `sections` wins when both are present. Prefer `sections`."),subforms:t.z.array(I({surface:`this subform`,history:B,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:E("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),sharing:$i.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.discriminatedUnion(`kind`,[I({surface:"this `thank-you` submit behavior",history:B,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()}),I({surface:"this `redirect` submit behavior",history:B,aliases:{delay:`delayMs`,delayMS:`delayMs`,timeout:`delayMs`,to:`url`,href:`url`,target:`url`}},{kind:t.z.literal(`redirect`),url:t.z.string().superRefine((e,t)=>{let n=uo(e);n&&t.addIssue({code:`custom`,message:n})}).describe("Where the browser goes after a successful submit. Ruled 2026-08-11 (#7496): (1) RELATIVE paths only — it must start with `/`, and absolute or protocol-relative URLs are refused, which is what closes the open-redirect face; (2) interpolation ONLY from declared record fields, spelled `{{record.field_name}}`, and every interpolated value is URL-escaped when the redirect is built; (3) a verbatim redirect on the resolved relative path is the intended consumption. To send the browser OUT of the app, use an app navigation item (`{ type: 'url', url }`) instead."),delayMs:t.z.number().int().min(0).optional()}),I({surface:"this `continue` submit behavior",history:B,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`)}),I({surface:"this `next-record` submit behavior",history:B,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. On the `redirect` arm, `url` is relative-only and interpolates only declared record fields as `{{record.field_name}}`, URL-escaped (ruled 2026-08-11, #7496)."),buttons:t.z.object({submit:io.optional().describe(`Submit button`),cancel:io.optional().describe(`Cancel button`),reset:io.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:E("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically.")}).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.`})})}).overwrite(ao)),po=g(()=>I({surface:`these object user filters`,history:B,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."}},{...Ba.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.')})),mo=g(()=>$a.omit({userFilters:!0}).extend({userFilters:po.optional()})),ho="Wrap it: `defineView({ list: { type, data, columns, … } })`, or name it — `defineView({ listViews: { my_view: { … } } })`.",go=g(()=>I({surface:`this view container`,history:B,guidance:Object.fromEntries([`type`,`columns`,`data`,`viewKind`,`filters`,`sort`].map(e=>[e,`\`${e}\` belongs to a single VIEW, not to the container. ${ho} 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:R.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:mo.optional(),form:fo.optional(),listViews:t.z.record(t.z.string(),mo).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),fo).optional().describe(`Additional named form views`),protection:Wi.optional().describe(`Package author protection block — lock policy for this view.`),...D})),_o=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>`."),vo=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),yo=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function bo(){return{name:_o,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:R.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:vo.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:Wi.optional().describe(`Package author protection block — lock policy for this view.`),...D}}function xo(e,n){return{viewKind:t.z.literal(e),config:n,...bo()}}var So={surface:`this view item`,history:B,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."}};g(()=>t.z.discriminatedUnion(`viewKind`,[I(So,xo(`list`,$a.describe(`List-family view configuration.`))),I(So,xo(`form`,fo.describe(`Form view configuration.`)))]));function Co(){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 wo=g(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({...xo(`list`,$a.describe(`List-family view configuration.`)),...Co()}).strip(),t.z.object({...xo(`form`,fo.describe(`Form view configuration.`)),...Co()}).strip()])),To='This inline view config names no `object`, so the saved row could never be served: `GET /meta/view?object=…` and the view switcher match stored views on `object` + `viewKind`, and a row missing them is registered yet renders nowhere. Bind it — add `object: "<object_name>"` and `viewKind: "list" | "form"` — or save a ViewItem record (`{ name, object, viewKind, config: { … } }`), or make it a container. '+ho,Eo='This inline view config names no `viewKind`, so the saved row could never be served: `GET /meta/view?object=…` and the view switcher match stored views on `object` + `viewKind`, and a row missing them is registered yet renders nowhere. Bind it — add `viewKind: "list" | "form"` alongside `object` — or save a ViewItem record (`{ name, object, viewKind, config: { … } }`), or make it a container. '+ho;function Do(){return{name:t.z.string().optional().describe(`Save name / qualified view id (stamped by the write path).`),object:t.z.string({error:e=>e.input===void 0?To:void 0}).describe("Bound object name — REQUIRED on an inline view config (#7741): the object-bound read paths (`GET /meta/view?object=`, the view switcher) match on `object` + `viewKind`, so an unbound row can never be served. Inherited from the shadowed entry on personalization PUTs (#2555)."),viewKind:t.z.enum(yo.options,{error:e=>e.input===void 0?Eo:void 0}).describe("View family — REQUIRED on an inline view config (#7741): half of the `object` + `viewKind` pair the object-bound read paths match on. Inherited from the shadowed entry on personalization PUTs (#2555)."),label:R.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:vo.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:Wi.optional(),...D,config:t.z.undefined().optional(),list:t.z.undefined().optional(),form:t.z.undefined().optional(),listViews:t.z.undefined().optional(),formViews:t.z.undefined().optional()}}function Oo(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)}var ko=new Set([`name`,`viewKind`,`object`,`label`]);function Ao(e,t,n=0){let r=e?._zod?.def;if(!(!r||n>6)){if(r.type===`object`){for(let e of Object.keys(r.shape??{}))t.add(e);return}if(r.type===`union`){for(let e of r.options??[])Ao(e,t,n+1);return}for(let e of[`innerType`,`in`,`out`,`schema`])r[e]&&Ao(r[e],t,n+1)}}function jo(e){if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=zo();return Object.keys(e).some(e=>t.has(e))}function Mo(e,t){if(typeof e!=`object`||!e||Array.isArray(e)||jo(e))return!0;let n=Object.keys(e),r=n.filter(e=>ko.has(e)),i=n.filter(e=>!ko.has(e)),a=(e,t=5)=>`${e.slice(0,t).map(e=>`\`${e}\``).join(`, `)}${e.length>t?`, …`:``}`;return t.addIssue({code:`custom`,path:[],message:"Not a `view` body: no recognized `view` key. Expected at least one of a container slot (`list` / `form` / `listViews` / `formViews`), a ViewItem record (`viewKind` + `config`), or an inline view config (`type`, `columns`, `sections`, `filter`, …). "+(n.length===0?"Received `{}`.":`Received `)+(i.length>0?`unrecognized ${i.length===1?`key`:`keys`} ${a(i)}`:``)+(i.length>0&&r.length>0?`, and `:``)+(r.length>0?`only identity fields (${a(r)}) \u2014 these say which view this attaches to, not what the view is, and the write path stamps them itself`:``)+(n.length===0?``:`.`)}),!1}var No=g(()=>go.refine(Oo,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."})),Po=g(()=>$a.extend(Do()).strip()),Fo=g(()=>fo.extend(Do()).strip()),Io=[`viewItem`,`container`,`listOverlay`,`formOverlay`],Lo={viewItem:wo,container:No,listOverlay:Po,formOverlay:Fo},Ro;function zo(){if(!Ro){let e=new Set;for(let t of Io)Ao(Lo[t],e);for(let t of ko)e.delete(t);Ro=e}return Ro}function Bo(e){let t=(e._zod?.def?.shape)?.type?._zod?.values;return new Set([...t??[]].filter(e=>typeof e==`string`))}function Vo(e){if(typeof e!=`object`||!e||Array.isArray(e))return null;let t=e;if(t.config!==void 0)return`viewItem`;if(t.list!==void 0||t.form!==void 0||t.listViews!==void 0||t.formViews!==void 0)return`container`;if(t.viewKind===`form`)return`formOverlay`;if(t.viewKind===`list`)return`listOverlay`;if(typeof t.type==`string`){if(Bo(fo).has(t.type))return`formOverlay`;if(Bo($a).has(t.type))return`listOverlay`}return null}function Ho(e,t,n){return{code:`invalid_type`,expected:`object`,input:n,path:[],message:`Not the \`${e}\` branch \u2014 this body reads as \`${t}\`, so that branch carries the diagnosis.`}}function Uo(){let e=new t.z.core.$ZodCheck({check:`custom`,when:()=>!0});return e._zod.check=e=>{if(e.issues.length===0)return;let t=Vo(e.value);if(t!==null)for(let n=0;n<e.issues.length;n+=1){let r=e.issues[n];r?.code!==`invalid_union`||!Array.isArray(r.errors)||r.errors.length===Io.length&&(e.issues[n]={...e.issues[n],errors:r.errors.map((n,r)=>{let i=Io[r];return i===t?n:[Ho(i,t,e.value)]})})}},e}g(()=>{let e=Io.map(e=>Lo[e]);return t.z.preprocess((e,n)=>Mo(e,n)?va(e):t.z.NEVER,t.z.union(e).check(Uo()))});function Wo(e){let{schemaId:t,...n}=e;return fo.parse({...n,data:{provider:`schema`,schemaId:t}})}var Go=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),U=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],Ko={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"},qo=[`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],Jo=t.z.enum(qo),Yo=new Set(U),Xo=new Set;function Zo(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&Yo.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&Yo.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return Xo.has(i)||(Xo.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}\`: ${Ko[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 Qo=I({surface:"`enable`",history:"Until this shape was closed an unknown flag was dropped without a word — the object shipped as if the author had never written it (#1535); `enable` is a closed vocabulary in which every flag carries an enforcement contract (#2707).",guidance:{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 existing sources 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 existing sources automatically."}},{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=>Zo(e),t.z.array(Go)).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`)}),$o=g(()=>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:Dn.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:E("`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 existing sources automatically."),partial:E("`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 existing sources automatically.")})),es={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."},ts="The two supported tenancy modes are: database-per-tenant = environment-level deployment (no object config); row-level isolation = `tenancy.enabled` + `tenancy.tenantField`.",ns=g(()=>I({surface:"`tenancy`",history:ts,guidance:es},{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).")}));function rs(e){return e?.tenancy?.enabled===!1}var is=g(()=>I({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).`)})),as=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(),os=t.z.union([t.z.array(t.z.string()),as]),ss=t.z.enum([`record`,`audit`,`telemetry`,`transient`,`event`]),cs=/^\d+(h|d|w|y)$/,ls=e=>t.z.string().regex(cs,`${e} must be a duration literal like '6h', '14d', '12w' or '7y'`),us=g(()=>I({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:ss.describe(`Persistence contract: record (business truth, permanent) | audit (compliance ledger) | telemetry (high-freq log) | transient (ephemeral state) | event (bus messages).`),retention:I({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:ls(`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:I({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:ls(`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:I({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 takes its window from `shards` × `unit`, not from an age you name — reclaimed by DROPping the oldest shard whole on SQLite, by an equivalent age-based reap elsewhere. Set the window with `shards`/`unit`, or use `retention` instead of rotation."}},{strategy:t.z.literal(`rotation`).describe("Time-shard the table. The retained window (`shards` × `unit`) is the same on every dialect; the reclamation is not — SQLite DROPs the oldest shard whole (O(1) reclaim), other dialects reap that same window by age from `created_at`."),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:I({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:ls(`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:ls(`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`})})),ds=g(()=>I({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.")})),fs=I({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)`),ps=I({surface:`this row CRUD override`,history:`This shape has been closed since objectui#2614, so the key was never silently dropped — until #7832 the rejection just could not tell you which key to write instead.`,aliases:{showWhen:`visibleWhen`},guidance:{visible:"`visible` is the CUSTOM row-action spelling (`actions[].visible`), where one key takes either form. This override splits them: write `enabled: false` for the object-level on/off, or `visibleWhen: <CEL over record.*>` for a per-record predicate (FALSE hides that row's button).",disabled:"`disabled` is the CUSTOM row-action spelling (`actions[].disabled`). The per-record form here is `disabledWhen: <CEL over record.*>` (TRUE renders that row's button disabled); there is no boolean `disabled` — switch the affordance off with `enabled: false`."}},{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:k.optional().describe(`CEL predicate over the record in scope (row record for edit/delete, host record for a related-list create/import toolbar); false → hide the button. Fail-closed.`),disabledWhen:k.optional().describe(`CEL predicate over the record in scope (row record for edit/delete, host record for a related-list create/import toolbar); true → render the button disabled. Fail-soft.`)}).describe(`Boolean-or-predicates override for a built-in CRUD affordance.`),ms="`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 WRITABLE affordances — create, edit, delete and exportCsv (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. CSV `import` is deliberately NOT in that default (#4671): it stays opt-in per object via `userActions: { import: true }`, which is what a v16 `system` object already resolved to. Run `os migrate meta --from 16` to rewrite existing sources automatically.",hs={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."},gs=I({surface:`this object`,aliases:{capabilities:`enable`,features:`enable`},guidance:hs,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."},{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`?ms: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`,`business_unit`,`org`,`none`],{error:"`ownership` is the record-ownership model — one of 'user' (default) | 'business_unit' | '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 plus owning_business_unit_id) | business_unit (unit-owned: owning_business_unit_id only, no owner_id) | org | none (no per-record owner, neither anchor). Distinct from the package own/extend contribution kind.`),userActions:I({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.union([t.z.boolean(),ps]).optional().describe(`Show generic "New" button. Boolean, or an object adding visibleWhen/disabledWhen CEL predicates evaluated once per toolbar against the record in scope (the host record on a related list).`),import:t.z.union([t.z.boolean(),ps]).optional().describe(`Show CSV import wizard entry. Boolean, or an object adding visibleWhen/disabledWhen CEL predicates evaluated once per toolbar against the record in scope (the host record on a related list).`),edit:t.z.union([t.z.boolean(),ps]).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(),ps]).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),I({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: `'user'` (or omitted) injects it, while `'org'` and `'none'` BOTH skip it and no `owner_id` is injected at all — `'org'` for an org-wide catalog (Dataverse-style), `'none'` for a junction/link table. `'business_unit'` skips it too, for a different reason: that tier is owned by an org UNIT rather than a person, so it carries `owning_business_unit_id` and deliberately no `owner_id` (ADR-0117 D1). `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 the ownership anchors (`owner_id` and `owning_business_unit_id`) are 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:fs.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")`}),Mn).describe(`Field definitions map. Keys must be snake_case identifiers.`),indexes:t.z.array($o).optional().describe(`Database performance indexes`),fieldGroups:t.z.array(ds).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:ns.optional().describe(`Multi-tenancy configuration for SaaS applications`),access:is.optional().describe(`[ADR-0066 D2] Object exposure posture (public-by-default vs private secure-by-default).`),requiredPermissions:os.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:us.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(pi).optional().describe(`Object-level validation rules`),activityMilestones:t.z.array(I({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:st.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(),mo).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. Entries must name a STORED column: a virtual `formula` field is computed on read and materializes no column, so searching it can never match and it is refused (#6674) — mirror the value onto a stored text field and declare that."),enable:Qo.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:I({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(Hi).optional().describe(`Actions associated with this object (auto-populated from top-level actions via objectName)`),protection:Wi.optional().describe(`Package author protection block — lock policy for this object.`),...D});function _s(e){return e.split(`_`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function vs(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 ys(e,t){let n,r=1/0;for(let i of t){let t=vs(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 bs(e,t,n){let r=typeof e==`string`&&e.length>0?e:`<unnamed>`,i=t.map(e=>{let t=hs[e];if(t)return` \u2022 ${t}`;let r=ys(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(`, `)}.
7
- These keys would previously have been stripped silently at build, shipping dead metadata with no diagnostic (ADR-0032 "no silent failure", issue #1535).
8
-
9
- ${i.join(`
10
- `)}
11
-
12
- Remove the unknown key(s), fix the typo, or move the logic to a supported mechanism.`)}var xs=new Set;function Ss(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>`;xs.has(i)||(xs.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 Cs(e,t,n){if(t!==`system-data`)return;let r=Os({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 already grants create, edit, delete and exportCsv, so \`userActions\` is for NARROWING those (#3355). The one verb it does not grant is CSV \`import\`, which is opt-in per object (#4671).`)}function ws(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 Ts(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 Es=g(()=>{let e=gs.parse.bind(gs),t=gs.safeParse.bind(gs);return Object.assign(gs,{parse(t,n){return e(Ts(ws(t)),n)},safeParse(e,n){return t(Ts(ws(e)),n)},create:e=>{let t=e,n=Object.keys(gs.shape),r=Object.keys(t).filter(e=>!n.includes(e));if(r.length>0)throw bs(t.name,r,n);Ss(t.name,t.fields,t.managedBy),Cs(t.name,t.managedBy,t.userActions);let i={...t,label:t.label??_s(t.name)};return gs.parse(i)}})}),Ds={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:!1,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 Os(e){let t=Ds[e?.managedBy??`platform`]??Ds.platform,n=e?.userActions??{},r=ks(n.create,t.create),i=ks(n.import,t.import),a=ks(n.edit,t.edit),o=ks(n.delete,t.delete),s={create:r.enabled,import:i.enabled,edit:a.enabled,delete:o.enabled,exportCsv:n.exportCsv??t.exportCsv};return r.predicates&&(s.createPredicates=r.predicates),i.predicates&&(s.importPredicates=i.predicates),a.predicates&&(s.editPredicates=a.predicates),o.predicates&&(s.deletePredicates=o.predicates),s}function ks(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 As=t.z.enum([`own`,`extend`,`overlay`]),js=g(()=>I({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(),Mn).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(pi).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)`)}));function Ms(e){return js.parse(e)}var Ns=[`get`,`list`,`create`,`update`,`delete`,`bulk`],Ps=qo,Fs=new Set(Ns),Is=new Set(U);function Ls(e){return Fs.has(e)}function Rs(e){return Is.has(e)}var zs={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}},Bs={get:`get`,query:`list`,find:`list`,list:`list`,create:`create`,update:`update`,delete:`delete`,bulk:`bulk`,upsert:`upsert`,aggregate:`aggregate`,history:`history`,search:`search`,restore:`restore`,purge:`purge`,import:`import`,export:`export`};function Vs(e,t,n,r){let i=zs[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 Hs(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 U)Vs(e,t,n,r)&&i.add(e);return i}function Us(e,t){let n=t?.userExportAllowed!==!1,r=e??{},i=r.apiMethods;if(i==null){let e=new Set(Ns);return{mode:`unrestricted`,primitives:e,operations:Hs(`unrestricted`,e,r,n),userExportAllowed:n}}let a=Array.isArray(i)?new Set(i.map(e=>String(e)).filter(Ls)):new Set;return a.size===0?{mode:`deny-all`,primitives:new Set,operations:new Set,userExportAllowed:n}:{mode:`restricted`,primitives:a,operations:Hs(`restricted`,a,r,n),userExportAllowed:n}}function Ws(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:Ws(e,n.bulkChild,{writeMode:n.writeMode});if(Ls(t))return r||e.primitives.has(t);if(Rs(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 Gs(e){return qo.filter(t=>e.operations.has(t))}function Ks(e,t,n){if(!e)return null;if(e.apiEnabled===!1)return`api-disabled`;let r=Us(e);return r.mode===`unrestricted`||Ws(r,t,n)?null:`method-not-allowed`}function qs(e,t,n){return Ks(e,t,n)===null}var Js=Object.freeze({create:`create`,update:`edit`,upsert:`edit`,delete:`delete`,purge:`delete`});function Ys(e){if(!e||typeof e!=`object`)return[];let t=e;if(t.managedBy==null)return[];let n=t.enable?.apiMethods;if(!Array.isArray(n)||n.length===0)return[];let r=Os(e),i=[];for(let[e,t]of n.entries()){if(typeof t!=`string`)continue;let n=Js[t];n&&!r[n]&&i.push({verb:t,needs:n,index:e})}return i}function Xs(e){return`advertises generic write verb(s) [${e.map(e=>e.verb).join(`, `)}] in enable.apiMethods that its resolved affordances do not permit (needs userActions ${[...new Set(e.map(e=>e.needs))].join(`/`)}) \u2014 see ADR-0092 / ADR-0103.`}var Zs=`••••••••`,Qs=new Set([`true`,`t`,`yes`,`y`,`1`,`on`,`是`,`对`,`✓`,`√`]),$s=new Set([`false`,`f`,`no`,`n`,`0`,`off`,`否`,`错`,`✗`,`×`]),ec=new Set([...Ht,`reference`]),tc="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: '*'`.",nc=t.z.enum([`beforeFind`,`afterFind`,`beforeInsert`,`afterInsert`,`beforeUpdate`,`afterUpdate`,`beforeDelete`,`afterDelete`]),rc=g(()=>I({surface:`this hook`,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.`},{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:tc}).describe(`Target object(s)`),events:t.z.array(nc).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:wi.optional().describe(`Hook body — expression (L1) or sandboxed JS (L2)`),priority:t.z.number().default(100).describe(`Execution priority`),async:t.z.boolean().default(!1).describe(`Run specifically as fire-and-forget`),condition:k.optional().describe('Predicate (CEL); hook runs only when TRUE. e.g. P`record.status == "closed" && record.amount > 1000`'),description:t.z.string().optional().describe(`Human-readable description of what this hook does`),retryPolicy:I({surface:`this hook's retryPolicy`,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`."},{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`)}).optional().describe(`Retry policy for failed hook executions`),timeout:t.z.number().optional().describe(`Maximum execution time in milliseconds before the hook is aborted`),onError:t.z.enum([`abort`,`log`]).default(`abort`).describe(`Error handling strategy`),...D})),ic=g(()=>t.z.object({id:t.z.string().optional().describe(`Unique execution ID for tracing`),object:t.z.string(),event:nc,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`),dispatch:t.z.object({mode:t.z.enum([`record`,`per-row`]).describe(`'record' = this call is the caller's whole write; 'per-row' = one of N dispatches for one write`),index:t.z.number().int().nonnegative().describe(`0-based position in the per-row fan-out; always 0 when mode is "record"`),scope:t.z.record(t.z.string(),t.z.unknown()).describe(`Scratch shared by every dispatch of one caller write, across both phases (same object identity)`)}).optional().describe(`How this hook call relates to the caller's write (engine-produced; #6966)`),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. tailoring a message, or branching a business rule the hook runs through its own `ctx.api` channel. 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. A hook context carries no `services` key, so the sharing service cannot be called from one either — the sharing gates already ran inside the engine before the hook chain."),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:E("`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 (IScopedContext — `object(name)` + `transaction(cb)`)"),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 ac(e){return rc.parse(e)}var oc=[{event:`beforeUpdate`,phase:`before`,contextKeys:[`id`,`data`,`options`,`previous`],payloadScope:`batch`,delivered:!0,engineDeliveryIssue:5574},{event:`beforeDelete`,phase:`before`,contextKeys:[`id`,`options`,`previous`],payloadScope:`none`,delivered:!0,engineDeliveryIssue:5574},{event:`afterUpdate`,phase:`after`,contextKeys:[`id`,`data`,`options`,`previous`,`result`],payloadScope:`batch`,delivered:!0,engineDeliveryIssue:5038},{event:`afterDelete`,phase:`after`,contextKeys:[`id`,`options`,`previous`],payloadScope:`none`,delivered:!0,engineDeliveryIssue:5038}],sc=1e4,cc=`ERR_BULK_PER_ROW_HOOK_LIMIT`;function lc(e){let{object:t,event:n,matched:r}=e,i=sc;return r<=i?{kind:`ok`,matched:r,limit:i}:{kind:`refused`,code:cc,object:t,event:n,matched:r,limit:i,message:`Refusing the bulk write on '${t}': it matches ${r} rows, and '${n}' hooks are contracted to fire PER ROW on a predicate write (ADR-0058, bulk-write addendum), which is over the ${i}-row ceiling for one write. Nothing was written. Narrow the predicate so the batch matches fewer rows (paginate the write), or remove the '${n}' hook from this object. The write is NOT silently downgraded to one hook call for the batch \u2014 that would skip the hook for ${r-1} rows without saying so.`}}var uc=`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.`,dc='`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.',fc="`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.",pc="`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.",mc={extractQuery:dc,query:dc,errorPolicy:fc,onError:fc,errorHandling:fc,errorMode:fc,skipErrors:fc,batchSize:pc,batch:pc,chunkSize:pc},hc=t.z.enum([`none`,`constant`,`lookup`,`split`,`join`,`javascript`,`map`]),gc=g(()=>I({surface:`this field mapping`,history:uc,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:hc.default(`none`),params:I({surface:`this transform’s params`,history:uc,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()})),_c=g(()=>I({surface:`this mapping`,history:uc,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",...mc}},{name:O.describe(`Mapping unique name (lowercase snake_case)`),label:t.z.string().optional(),sourceFormat:t.z.enum([`csv`,`json`,`xml`,`sql`]).default(`csv`),targetObject:t.z.string().describe(`Target Object Name`),fieldMapping:t.z.array(gc),mode:t.z.enum([`insert`,`update`,`upsert`]).default(`insert`),upsertKey:t.z.array(t.z.string()).optional().describe(`Fields to match for upsert (e.g. email)`),...D}));function vc(e){return _c.parse(e)}var yc=t.z.enum([`read`,`create`,`update`,`delete`,`transfer`,`restore`,`purge`,`export`]),bc=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.`),xc=g(()=>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.`)})),Sc=g(()=>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(xc).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.`)})),Cc=g(()=>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:Sc.optional().describe(`Row-level determination for the specific record under explanation; set only for record-grained requests.`)})),wc=200;g(()=>t.z.object({object:t.z.string(),operation:yc,recordId:t.z.string().optional().describe(`Optional id of one concrete record to explain at row granularity; omitted = object-level (pre-C2) request. Mutually exclusive with recordIds.`),recordIds:t.z.array(t.z.string()).min(1).max(wc).optional().describe(`Batch of record ids (1–200) to answer at row granularity in one round trip; records[i] answers recordIds[i]. Mutually exclusive with recordId.`),userId:t.z.string().optional()}).superRefine((e,t)=>{e.recordId!==void 0&&e.recordIds!==void 0&&t.addIssue({code:`custom`,path:[`recordIds`],message:`recordId and recordIds are mutually exclusive — send one record as recordId, or the batch as recordIds, never both.`})}));var Tc=g(()=>t.z.object({recordId:t.z.string().describe(`The concrete record id this verdict is about (echoes the request recordId or recordIds[i]).`),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); omitted for a missing record.`)}));g(()=>t.z.object({allowed:t.z.boolean(),object:t.z.string(),operation:yc,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:bc.optional()}),layers:t.z.array(Cc),readFilter:t.z.unknown().optional(),record:Tc.optional().describe(`Row-level verdict for the specific record; set only for singular record-grained requests.`),records:t.z.array(Tc).optional().describe(`Per-record verdicts for a batch request — records[i] answers recordIds[i]; set only when the request carried recordIds.`)}));var Ec=g(()=>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()}));g(()=>t.z.object({version:t.z.literal(1).default(1),entries:t.z.array(Ec).default([])}));var Dc=g(()=>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:bc.optional(),authGate:t.z.object({code:t.z.string(),message:t.z.string()}).optional().describe("ADR-0069 authentication-policy gate: present only while the principal is blocked from protected resources until they remediate (expired password, enforced MFA), absent for every healthy session. `code` is the stable machine code the client branches on (PASSWORD_EXPIRED / MFA_REQUIRED) and `message` is what the blocked user reads; both are required because the transport seam renders them as the 403 body. AUTHENTICATION, not authorization — it suspends access entirely rather than narrowing it, and nothing in the permission/RLS path reads it, while the allow-listed remediation endpoints stay reachable. Server-constructed only, never client-supplied; a guest/anonymous principal never carries one."),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().describe('Historical import: preserve the ORIGINAL audit timeline for this write instead of stamping it "now" (#3493). Opt-in and server-constructed only, never client-supplied. On the UPDATE path it admits a whitelist — the audit/timestamp family (created_at / created_by / updated_at / updated_by) plus author-declared business `readonly` fields — while platform-managed `system` columns (tenancy, generated) stay stripped. On INSERT the exemption does NOT apply (#6640): a create is stripped earlier, at the DataProtocol ingress, whose only exemption is `context.isSystem`, so a non-system create carrying `preserveAudit` still has those fields stripped and is warned (WARN) that the exemption is UPDATE-only — replaying archival readonly facts on create requires a system context. Permissions / RLS / field-level security are unaffected.'),oauthScopes:t.z.array(t.z.string()).optional(),accessToken:t.z.string().optional(),transaction:t.z.unknown().optional(),traceId:t.z.string().optional()})),Oc=g(()=>t.z.union([t.z.record(t.z.string(),t.z.unknown()),w]).describe(`Data Engine query filter conditions`)),kc=g(()=>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(Un)]).describe(`Sort order definition`)),W=g(()=>t.z.object({context:Dc.partial().optional()})),Ac=g(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),w]).optional(),fields:t.z.array(er).optional(),orderBy:t.z.array(Un).optional(),limit:t.z.number().optional(),offset:t.z.number().optional(),top:t.z.number().optional(),cursor:E(nr),search:t.z.union([t.z.string(),ar]).optional(),searchFields:t.z.array(t.z.string()).optional(),expand:t.z.lazy(()=>t.z.record(t.z.string(),sr)).optional(),distinct:E(rr)}).describe(`QueryAST-aligned query options for IDataEngine.find() operations`)),jc=g(()=>W.extend({filter:Oc.optional(),select:t.z.array(t.z.string()).optional(),sort:kc.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`)),Mc=g(()=>W.extend({returning:t.z.boolean().default(!0).optional()}).describe(`Options for DataEngine.insert operations`)),Nc="`update.options.upsert` was removed in @objectstack/spec 17 (#8057, ADR-0049) — it was declared and allowlisted but never implemented: no engine or driver path ever read it, so `{ upsert: true }` was accepted and silently dropped and the update stayed a plain update. Delete the key. Express create-if-absent explicitly: a by-id update whose id names no row throws RECORD_NOT_FOUND (#7867's not-found gate) rather than inserting, so read the row first (`findOne`) and call `insert` or `update` on what you find. A first-class upsert, if ever built, must reconcile with that gate by design rather than through this silent flag.",Pc=g(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),w]).optional(),upsert:E(Nc),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.update operations`)),Fc=g(()=>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`,`primary_key`]).describe(`Why the fields were dropped: static readonly (#2948), a TRUE readonlyWhen predicate (#3042), or the primary-key strip of a payload id the engine ruled is not an identifier (#6437)`)}).describe(`A write-path strip event: caller-supplied fields legally dropped from the payload (#3407)`)),Ic=g(()=>W.extend({filter:Oc.optional(),upsert:E(Nc),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.update operations`)),Lc=g(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),w]).optional(),multi:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.delete operations`)),Rc=g(()=>W.extend({filter:Oc.optional(),multi:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.delete operations`)),zc=g(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),w]).optional(),groupBy:t.z.array(Xn).optional().describe("GROUP BY targets (strings or `{field, dateGranularity?}` objects for date bucketing)"),aggregations:t.z.array(Qn).optional(),having:w.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`)),Bc=g(()=>W.extend({filter:Oc.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`)),Vc=g(()=>W.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),w]).optional()}).describe(`QueryAST-aligned options for DataEngine.count operations`)),Hc=g(()=>W.extend({filter:Oc.optional()}).describe(`Options for DataEngine.count operations`)),Uc=g(()=>t.z.object({find:t.z.function().input(t.z.tuple([t.z.string(),Ac.optional()])).output(t.z.promise(t.z.array(t.z.unknown()))),findOne:t.z.function().input(t.z.tuple([t.z.string(),Ac.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()))]),Mc.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()),Pc.optional()])).output(t.z.promise(t.z.unknown())),delete:t.z.function().input(t.z.tuple([t.z.string(),Lc.optional()])).output(t.z.promise(t.z.unknown())),count:t.z.function().input(t.z.tuple([t.z.string(),Vc.optional()])).output(t.z.promise(t.z.number())),aggregate:t.z.function().input(t.z.tuple([t.z.string(),zc])).output(t.z.promise(t.z.array(t.z.unknown())))}).describe(`Standard Data Engine Contract`)),Wc=[{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 Gc(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 Kc=Wc.filter(e=>e.canonical===`where`);function qc(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 Jc={filter:Oc.optional()};function Yc(e,t){let n={...e};return Gc(n,Kc,e=>t.addIssue(qc(e))),n}function Xc(e,t){let n={...e};return Gc(n,Wc,e=>t.addIssue(qc(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 Zc=Ac.extend({...Jc,select:t.z.array(t.z.string()).optional(),sort:kc.optional(),skip:t.z.number().int().min(0).optional(),populate:t.z.array(t.z.string()).optional()}).transform((e,t)=>Xc(e,t)),Qc=g(()=>t.z.object({method:t.z.literal(`find`),object:t.z.string(),query:Zc.optional()})),$c=g(()=>t.z.object({method:t.z.literal(`findOne`),object:t.z.string(),query:Zc.optional()})),el=g(()=>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:Mc.optional()})),tl=g(()=>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:Pc.extend(Jc).transform((e,t)=>Yc(e,t)).optional()})),nl=g(()=>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:Lc.extend(Jc).transform((e,t)=>Yc(e,t)).optional()})),rl=g(()=>t.z.object({method:t.z.literal(`count`),object:t.z.string(),query:Vc.extend(Jc).transform((e,t)=>Yc(e,t)).optional()})),il=g(()=>t.z.object({method:t.z.literal(`aggregate`),object:t.z.string(),query:zc.extend(Jc).transform((e,t)=>Yc(e,t))})),al=g(()=>t.z.object({method:t.z.literal(`execute`),command:t.z.unknown(),options:t.z.record(t.z.string(),t.z.unknown()).optional()})),G=g(()=>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()),w]).optional(),fields:t.z.array(t.z.string()).optional(),limit:t.z.number().int().default(5).optional(),threshold:t.z.number().optional()})),ol=g(()=>t.z.discriminatedUnion(`method`,[Qc,$c,el,tl,nl,rl,il,al,G]).describe(`Virtual ObjectQL Request Protocol`)),sl=t.z.enum([`asc`,`desc`]).describe(`Sort order direction`);g(()=>t.z.object({field:t.z.string().describe(`Field name to sort by`),order:sl.describe(`Sort direction`)}).describe(`Sort field and direction pair`)),t.z.enum([`insert`,`update`,`delete`,`upsert`]).describe(`Data mutation event types`);var cl=t.z.enum([`read_uncommitted`,`read_committed`,`repeatable_read`,`serializable`,`snapshot`]).describe(`Transaction isolation levels (snake_case standard)`),K=g(()=>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)`)})),q=(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.`,ll=g(()=>t.z.object({queryDateGranularity:t.z.record(Yn,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:E(q(`create`,"CRUD is not optional for a driver: `create`/`find`/`findOne`/`update`/`delete` are REQUIRED `IDataDriver` methods and the engine calls them unconditionally.")),read:E(q(`read`,"CRUD is not optional for a driver: reads go through the REQUIRED `find`/`findOne`/`count` methods, called unconditionally.")),update:E(q(`update`,"CRUD is not optional for a driver: `update`/`upsert` are REQUIRED `IDataDriver` methods, called unconditionally.")),delete:E(q(`delete`,"CRUD is not optional for a driver: `delete` is a REQUIRED `IDataDriver` method, called unconditionally.")),bulkCreate:E(q(`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:E(q(`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:E(q(`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:E(q(`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:E(q(`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:E(q(`isolationLevels`,"Isolation is requested per transaction via `beginTransaction({ isolationLevel })`; no planner ever consulted this list to decide anything.")),queryFilters:E(q(`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:E(q(`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:E(q(`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:E(q(`queryAggregations`,"Aggregate pushdown is decided by `typeof driver.aggregate === 'function'` plus `queryDateGranularity` (engine aggregate dispatch) — never by this bit.")),queryWindowFunctions:E(q(`queryWindowFunctions`,`ObjectQL never plans window functions through a driver, so there was nothing for the bit to switch on.`)),querySubqueries:E(q(`querySubqueries`,`ObjectQL never plans subqueries through a driver, so there was nothing for the bit to switch on.`)),queryCTE:E(q(`queryCTE`,`ObjectQL never plans Common Table Expressions through a driver, so there was nothing for the bit to switch on.`)),joins:E(q(`joins`,"Related data is resolved by the engine (lookup expansion over `find()`), not by driver-side JOIN planning — no code consulted the bit.")),fullTextSearch:E(q(`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:E(q(`jsonQuery`,`No engine path ever branched on driver-side JSON querying.`)),geospatialQuery:E(q(`geospatialQuery`,`No geospatial query path exists in the platform — declaring the bit advertised a capability nothing delivers.`)),streaming:E("`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:E(q(`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:E(q(`arrayFields`,"Field-type handling is negotiated per object at `syncSchema` time by the driver itself; no engine path consulted the bit.")),vectorSearch:E(q(`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:E(q(`schemaSync`,"Schema sync is gated on METHOD PRESENCE — `typeof driver.syncSchema === 'function'` (engine and ObjectQL plugin init).")),migrations:E(q(`migrations`,`No migration engine ever consulted it.`)),indexes:E(q(`indexes`,"Declared indexes are materialised by the driver itself during schema sync (`SqlDriver.syncDeclaredIndexes`); no engine path consulted the bit.")),connectionPooling:E(q(`connectionPooling`,"Pooling is configured via `poolConfig` and owned by the driver; `getPoolStats` is duck-typed where monitoring wants it. Nothing consulted the bit.")),preparedStatements:E(q(`preparedStatements`,"Parameterised execution is an implementation detail of the driver (`execute(command, parameters)`); nothing consulted the bit.")),queryCache:E(q(`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."))})),ul=g(()=>t.z.object({name:t.z.string().describe(`Driver unique name`),version:t.z.string().describe(`Driver version`),supports:ll,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(),K.optional()])).output(t.z.promise(t.z.unknown())).describe(`Execute raw command`),find:t.z.function().input(t.z.tuple([t.z.string(),sr,K.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(),sr,K.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()),K.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()),K.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(),K.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()),K.optional()])).output(t.z.promise(t.z.boolean())).describe(`Delete record`),count:t.z.function().input(t.z.tuple([t.z.string(),sr.optional(),K.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())),K.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())})),K.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())),K.optional()])).output(t.z.promise(t.z.void())),updateMany:t.z.function().input(t.z.tuple([t.z.string(),sr,t.z.record(t.z.string(),t.z.unknown()),K.optional()])).output(t.z.promise(t.z.number())).optional(),deleteMany:t.z.function().input(t.z.tuple([t.z.string(),sr,K.optional()])).output(t.z.promise(t.z.number())).optional(),beginTransaction:t.z.function().input(t.z.tuple([t.z.object({isolationLevel:cl.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(),K.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()})),K.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(),K.optional()])).output(t.z.promise(t.z.void())),explain:t.z.function().input(t.z.tuple([t.z.string(),sr,K.optional()])).output(t.z.promise(t.z.unknown())).optional()})),dl=g(()=>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`)})),fl=g(()=>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:ll.describe(`Driver capability flags`),connectionString:t.z.string().optional().describe(`Database connection string (driver-specific format)`),poolConfig:dl.optional().describe(`Connection pool configuration`)})),pl=g(()=>t.z.enum([`postgresql`,`mysql`,`sqlite`,`mssql`,`oracle`,`mariadb`])),ml=g(()=>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)`)})),hl=g(()=>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`})),gl=g(()=>fl.extend({type:t.z.literal(`sql`).describe(`Driver type must be "sql"`),dialect:pl.describe(`SQL database dialect`),dataTypeMapping:ml.describe(`SQL data type mapping configuration`),ssl:t.z.boolean().default(!1).describe(`Enable SSL/TLS connection`),sslConfig:hl.optional().describe(`SSL/TLS configuration (required when ssl is true)`)}).refine(e=>!(e.ssl&&!e.sslConfig),{message:`sslConfig is required when ssl is true`})),_l={text:`TEXT`,number:`REAL`,boolean:`INTEGER`,date:`TEXT`,datetime:`TEXT`,json:`TEXT`,uuid:`TEXT`,binary:`BLOB`},vl={supportsAddColumn:!0,supportsRenameColumn:!0,supportsDropColumn:!0,supportsModifyColumn:!1,supportsAddConstraint:!1,rebuildStrategy:`create_copy_drop_rename`},yl=g(()=>t.z.enum([`mongodb`,`couchdb`,`dynamodb`,`cassandra`,`redis`,`elasticsearch`,`neo4j`,`orientdb`])),bl=g(()=>t.z.enum([`find`,`findOne`,`insert`,`update`,`delete`,`aggregate`,`mapReduce`,`count`,`distinct`,`createIndex`,`dropIndex`])),xl=g(()=>t.z.enum([`all`,`quorum`,`one`,`local_quorum`,`each_quorum`,`eventual`])),Sl=g(()=>t.z.enum([`single`,`compound`,`unique`,`text`,`geospatial`,`hashed`,`ttl`,`sparse`])),Cl=g(()=>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`)})),wl=g(()=>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`)})),Tl=g(()=>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`)})),El=g(()=>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`)})),Dl=g(()=>fl.extend({type:t.z.literal(`nosql`).describe(`Driver type must be "nosql"`),databaseType:yl.describe(`Specific NoSQL database type`),dataTypeMapping:El.describe(`NoSQL data type mapping configuration`),consistency:xl.optional().describe(`Consistency level for operations`),replication:wl.optional().describe(`Replication configuration`),sharding:Cl.optional().describe(`Sharding configuration`),schemaValidation:Tl.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`)})),Ol=g(()=>t.z.object({consistency:xl.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`)})),kl=g(()=>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`)})),Al=g(()=>t.z.object({collection:t.z.string().describe(`Collection/table name`),stages:t.z.array(kl).describe(`Aggregation pipeline stages`),options:Ol.optional().describe(`Query options`)})),jl=g(()=>t.z.object({name:t.z.string().describe(`Index name`),type:Sl.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`)})),Ml=g(()=>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)`)})),Nl=t.z.enum([`insert`,`update`,`upsert`,`replace`,`ignore`]),Pl=g(()=>I({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:Nl.default(`upsert`).describe(`Conflict resolution strategy`),env:t.z.array(t.z.enum([`prod`,`dev`,`test`])).default([`prod`,`dev`,`test`]).describe(`Applicable environments`),records:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Data records`),...D}));function Fl(e,t){return Pl.parse({...t,object:e.name})}var Il=Wo({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:`data.type in ['text','textarea','email','url','phone','password','markdown','html','richtext']`},{field:`minLength`,type:`number`,helpText:`Min characters`,visibleWhen:`data.type in ['text','textarea','email','url','phone','password','markdown','html','richtext']`},{field:`min`,type:`number`,helpText:`Minimum value`,visibleWhen:`data.type in ['number','currency','percent','rating','slider','progress']`},{field:`max`,type:`number`,helpText:`Maximum value`,visibleWhen:`data.type in ['number','currency','percent','rating','slider','progress']`},{field:`precision`,type:`number`,helpText:`Total digits`,visibleWhen:`data.type in ['number','currency','percent']`},{field:`scale`,type:`number`,helpText:`Decimal places`,visibleWhen:`data.type in ['number','currency','percent']`},{field:`options`,type:`repeater`,helpText:`Available choices`,visibleWhen:`data.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:`data.type in ['lookup','master_detail','tree']`},{field:`lookupFilters`,widget:`json`,helpText:`Filter rules applied to the picker ({field, operator, value})`,visibleWhen:`data.type in ['lookup','master_detail']`},{field:`deleteBehavior`,type:`select`,helpText:`What happens when the referenced record is deleted`,visibleWhen:`data.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:`data.type in ['lookup']`},{field:`expression`,type:`code`,language:`expression`,helpText:`CEL formula expression`,visibleWhen:`data.type == 'formula'`},{field:`returnType`,type:`select`,helpText:`Result type for formulas`,visibleWhen:`data.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:`data.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:`data.type == 'autonumber'`},{field:`language`,type:`text`,helpText:`Editor language (e.g. sql, javascript)`,visibleWhen:`data.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)`}]}]}]}),Ll=Wo({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`}]}]}),Rl=Wo({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)`}]}]}]}),zl=g(()=>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`)),Bl=g(()=>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(zl).describe(`Field-level reference details`)}).describe(`Object node in the seed data dependency graph`)),Vl=g(()=>t.z.object({nodes:t.z.array(Bl).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`)),Hl=g(()=>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`)),Ul=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`),Wl=g(()=>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:Nl.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:Ul.optional().describe(`Identity bound to os.user / os.org when resolving CEL seed values`)}).describe(`Seed data loader configuration`)),Gl=g(()=>t.z.object({object:t.z.string().describe(`Object that was loaded`),mode:Nl.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(Hl).default([]).describe(`Reference resolution errors`)}).describe(`Result of loading a single dataset`)),Kl=g(()=>t.z.object({success:t.z.boolean().describe(`Overall success status`),dryRun:t.z.boolean().describe(`Whether this was a dry-run`),dependencyGraph:Vl.describe(`Object dependency graph`),results:t.z.array(Gl).describe(`Per-object load results`),errors:t.z.array(Hl).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`)),ql=g(()=>t.z.object({seeds:t.z.array(Pl).min(1).describe(`Seeds to load`),config:Wl.default(()=>Wl.parse({})).describe(`Loader configuration`)}).describe(`Seed loader request with datasets and configuration`)),Jl=g(()=>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`)})),Yl=g(()=>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`)})),Xl=g(()=>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`)})),Zl=g(()=>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(Jl).describe(`Version history`),majorVersion:t.z.number().describe(`Major version`),minorVersion:t.z.number().describe(`Minor version`)}).optional().describe(`Version control`),template:Yl.optional().describe(`Document template`),eSignature:Xl.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`)})),J=t.z.enum([`off`,`safe`]).describe(`Dev-only non-destructive schema self-heal (#2186)`),Ql="`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.",$l="`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).",eu=t.z.boolean().describe("Enable TLS. Certificates go in the datasource-level `ssl` block."),Y="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.",X=e=>`\`${e}\` is a credential and is not accepted inline in driver config (#7990): the datasource is persisted whole into \`sys_metadata\`, which is served back by the ordinary data API, so an inline credential lands in cleartext at rest. Bind the secret instead: the Setup \u2192 Datasources connection form's secret field hands it to the datasource secret binder, which encrypts it into \`sys_secret\` and stores only an opaque handle at \`external.credentialsRef\` \u2014 or reference the secrets store directly with \`external.credentialsRef\`. The resolved secret is injected at connect time and always wins over anything embedded in \`config\`.`,tu=e=>`this \`${e}\` embeds a password in its userinfo (\`user:password@host\`) and is not accepted at publish (#8082): the datasource is persisted whole into \`sys_metadata\`, which is served back by the ordinary data API, so a URL-embedded credential lands in cleartext at rest exactly like an inline \`password\` (#7990). Keep the authored URL credential-free (a bare username, \`user@host\`, is fine) and bind the secret instead: the Setup \u2192 Datasources connection form's secret field hands it to the datasource secret binder, which encrypts it into \`sys_secret\` and stores only an opaque handle at \`external.credentialsRef\` \u2014 or reference the secrets store directly with \`external.credentialsRef\`. The resolved secret is injected at connect time and wins over anything embedded in the URL. Do NOT substitute a \`\${\u2026}\` placeholder into the URL: placeholders in authored metadata are resolved by nothing and reach the database client verbatim (#8078, measured), and are themselves refused at publish (#8336). Runtime-environment DSNs (\`OS_DATABASE_URL\` and friends) do not pass through this publish door and are unaffected.`;function nu(e){let t=/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.exec(e);if(!t)return;let n=e.slice(t[0].length),r=n.search(/[/?#]/),i=r===-1?n:n.slice(0,r),a=i.lastIndexOf(`@`);if(a===-1)return;let o=i.slice(0,a),s=o.indexOf(`:`);if(s===-1)return;let c=o.slice(s+1);return c.length>0?c:void 0}function ru(e,t){return e.superRefine((e,n)=>{typeof e==`string`&&nu(e)!==void 0&&n.addIssue({code:`custom`,message:tu(t)})})}var iu=e=>`this \`${e}\` contains a \`\${\u2026}\` placeholder, and placeholders are not resolved here (#8336): nothing in the platform substitutes \`\${\u2026}\` in authored datasource config \u2014 placeholders in authored metadata are resolved by nothing, are stored verbatim in \`sys_metadata\`, and reach the database client verbatim (#8078, measured), so the connection fails (or connects somewhere unintended) with no error naming the unresolved placeholder. Write the literal value instead. For secret material, bind it: the Setup \u2192 Datasources connection form's secret field hands it to the datasource secret binder, which encrypts it into \`sys_secret\` and stores only an opaque handle at \`external.credentialsRef\` \u2014 the resolved secret is injected at connect time. For environment-driven connections, configure the runtime environment itself: \`OS_DATABASE_URL\` and friends are translated into driver config by the boot hosts and never pass through this publish door, so they are unaffected.`;function au(e){return/\$\{[^}]*\}/.test(e)}function Z(e,t){return e.superRefine((e,n)=>{typeof e==`string`&&au(e)&&n.addIssue({code:`custom`,message:iu(t)})})}function ou(e,t){return e.superRefine((e,n)=>{for(let r of su(e))n.addIssue({code:`custom`,path:r,message:iu([t,...r].join(`.`))})})}function su(e,t=[]){return typeof e==`string`?au(e)?[[...t]]:[]:Array.isArray(e)?e.flatMap((e,n)=>su(e,[...t,n])):typeof e==`object`&&e?Object.entries(e).flatMap(([e,n])=>su(n,[...t,e])):[]}function cu(e,n){return t.z.never({error:()=>X(e)}).optional().describe("Set through the connection form's secret field or `external.credentialsRef` — encrypted into `sys_secret`, never stored in `config` (#7990)").meta({title:n,format:`password`})}var lu={target:`draft-2020-12`,io:`input`,unrepresentable:`any`};function uu(e){let n;return()=>(n===void 0&&(n=t.z.toJSONSchema(e,lu)),n)}var du="Until #4410 nothing parsed `datasource.config` at all, so an unrecognised key here was accepted in silence and the requested persistence mode came up on its defaults instead.",fu=g(()=>I({surface:`this memory datasource's custom persistence adapter`,history:du},{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`)),pu=g(()=>t.z.enum([`file`,`local`,`auto`]).describe(`Persistence backend type`)),mu=g(()=>I({surface:`this memory datasource's file persistence config`,history:du},{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`)),hu=g(()=>I({surface:`this memory datasource's localStorage persistence config`,history:du},{type:t.z.literal(`local`),key:t.z.string().optional().describe(`localStorage key for persisted data`)}).describe(`localStorage persistence configuration`)),gu=g(()=>I({surface:`this memory datasource's custom-adapter persistence config`,history:du},{adapter:fu}).describe(`Custom adapter persistence configuration`)),_u=g(()=>I({surface:`this memory datasource's auto-detect persistence config`,history:du},{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`)),vu=g(()=>t.z.union([pu,mu,hu,_u,gu]).describe(`Persistence configuration for the memory driver`)),yu=g(()=>I({surface:`this memory datasource's config`,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:Ql,readOnly:$l},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."},{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:vu.or(t.z.literal(!1)).default(!1).describe(`Persistence configuration (opt-in; defaults to pure in-memory)`)}).describe(`Memory Driver Connection Configuration`)),bu=uu(yu),xu={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 bu()}},Su=g(()=>I({surface:`this mongo datasource's config`,aliases:{uri:`url`,connectionstring:`url`,dsn:`url`,hostname:`host`,server:`host`,dbname:`database`,db:`database`,user:`username`,authdb:`authSource`,authdatabase:`authSource`,replicaset:`options`},guidance:{passwd:X(`passwd`),pwd:X(`pwd`),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:Ql,readOnly:$l,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."},{url:Z(ru(t.z.string(),`url`),`url`).optional().describe(`Connection URI (supersedes the discrete fields; must not embed a password — bind the secret instead)`).meta({title:`Connection URI`}),database:Z(t.z.string().min(1),`database`).optional().describe(`Database name`).meta({title:`Database`}),host:Z(t.z.string(),`host`).default(`localhost`).describe(`Host address`).meta({title:`Host`}),port:t.z.number().int().default(27017).describe(`Port number`).meta({title:`Port`}),username:Z(t.z.string(),`username`).optional().describe(`Authentication user`).meta({title:`User`}),password:cu(`password`,`Password`),authSource:Z(t.z.string(),`authSource`).optional().describe(`Authentication database`).meta({title:`Auth source`}),options:ou(t.z.record(t.z.string(),t.z.unknown()),`options`).optional().describe(`Extra MongoClient options (replicaSet, tls, timeouts, …)`)}).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."})})),Q=uu(Su),Cu={id:`mongodb`,label:`MongoDB`,description:`Official MongoDB Driver for ObjectStack. Supports rich queries, aggregation, and atomic updates.`,icon:`database`,get configSchema(){return Q()}},wu=g(()=>I({surface:`this mysql datasource's config`,aliases:{hostname:`host`,server:`host`,dbname:`database`,db:`database`,schema:`database`,user:`username`,connectionstring:`url`,dsn:`url`,uri:`url`,sslmode:`ssl`,tls:`ssl`,usessl:`ssl`},guidance:{passwd:X(`passwd`),pwd:X(`pwd`),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:Ql,readOnly:$l,ca:Y,cert:Y,key:Y,rejectUnauthorized:Y,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."},{url:Z(ru(t.z.string(),`url`),`url`).optional().describe(`Connection URI (supersedes the discrete fields; must not embed a password — bind the secret instead)`).meta({title:`Connection URL`}),host:Z(t.z.string(),`host`).default(`localhost`).describe(`Host address`).meta({title:`Host`}),port:t.z.number().int().default(3306).describe(`Port number`).meta({title:`Port`}),database:Z(t.z.string(),`database`).optional().describe(`Database name`).meta({title:`Database`}),username:Z(t.z.string(),`username`).optional().describe(`Authentication user`).meta({title:`User`}),password:cu(`password`,`Password`),ssl:eu.optional().meta({title:`Use SSL/TLS`}),autoMigrate:J.optional()}).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."})})),Tu=uu(wu),Eu=(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.)`,Du=g(()=>I({surface:`this postgres datasource's config`,aliases:{hostname:`host`,server:`host`,dbname:`database`,db:`database`,user:`username`,connectionstring:`url`,dsn:`url`,uri:`url`,searchpath:`schema`,applicationname:`applicationName`,statementtimeout:`statementTimeout`,sslmode:`ssl`,tls:`ssl`,usessl:`ssl`},guidance:{passwd:X(`passwd`),pwd:X(`pwd`),pool:Eu(`pool`,`max`),min:Eu(`min`,`min`),max:Eu(`max`,`max`),idleTimeoutMillis:Eu(`idleTimeoutMillis`,`idleTimeoutMillis`),connectionTimeoutMillis:Eu(`connectionTimeoutMillis`,`connectionTimeoutMillis`),schemaMode:Ql,readOnly:$l,ca:Y,cert:Y,key:Y,rejectUnauthorized:Y},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."},{url:Z(ru(t.z.string(),`url`),`url`).optional().describe(`Connection URI (supersedes the discrete fields; must not embed a password — bind the secret instead)`).meta({title:`Connection URL`}),host:Z(t.z.string(),`host`).default(`localhost`).describe(`Host address`).meta({title:`Host`}),port:t.z.number().int().default(5432).describe(`Port number`).meta({title:`Port`}),database:Z(t.z.string(),`database`).optional().describe(`Database name`).meta({title:`Database`}),username:Z(t.z.string(),`username`).optional().describe(`Authentication user`).meta({title:`User`}),password:cu(`password`,`Password`),ssl:eu.optional().meta({title:`Use SSL/TLS`}),schema:Z(t.z.string(),`schema`).default(`public`).describe(`Default schema (knex searchPath)`).meta({title:`Schema`}),applicationName:Z(t.z.string(),`applicationName`).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:J.optional()}).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."})})),Ou=uu(Du),ku={file:`filename`,filepath:`filename`,path:`filename`,database:`filename`,db:`filename`,url:`filename`,connectionstring:`filename`},Au="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.",ju="`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'`.",Mu=g(()=>I({surface:`this sqlite datasource's config`,aliases:ku,guidance:{schemaMode:Ql,readOnly:$l,memory:ju,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:Au},{filename:Z(t.z.string(),`filename`).default(`:memory:`).describe(`Database file path, or ":memory:" for an ephemeral database`).meta({title:`Filename`}),autoMigrate:J.optional()}).describe(`SQLite connection configuration`)),Nu=uu(Mu),Pu=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`),Fu=g(()=>I({surface:`this sqlite-wasm datasource's config`,aliases:ku,guidance:{schemaMode:Ql,readOnly:$l,memory:ju,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:Au},{filename:Z(t.z.string(),`filename`).default(`:memory:`).describe(`Database file path, or ":memory:" for an ephemeral database`).meta({title:`Filename`}),persist:Pu.optional().meta({title:`Persist mode`})}).describe(`SQLite (WASM) connection configuration`)),Iu=uu(Fu),Lu=t.z.enum([`local`,`replica`,`remote`]).describe("Force a transport mode instead of inferring it from `url`"),Ru=g(()=>I({surface:`this turso datasource's config`,aliases:{uri:`url`,connectionstring:`url`,dsn:`url`,database:`url`,databaseurl:`url`,syncinterval:`sync`},guidance:{token:X(`token`),jwt:X(`jwt`),auth_token:X(`auth_token`),authtoken:X(`authtoken`),pool:"`pool` is not driver config — libSQL sizes remote concurrency with `concurrency`, and every driver's pooling block lives next to `driver` on the datasource itself.",schemaMode:Ql,readOnly:$l,filename:'`filename` is the sqlite spelling. A libSQL local database is still named by `url` — use `url: "file:./data/objectstack.db"`.'},history:'Until #6345 a turso `config` was validated against nothing at all: the driver ships in an optional package, so it was not a builtin and `validateDriverConfig` answered "{ known: false }" for it. A misspelled `token:` was therefore accepted in silence and the connection was attempted unauthenticated.'},{url:Z(ru(t.z.string().min(1),`url`),`url`).describe(`libSQL endpoint or local file: a remote libsql/https Turso URL, a file path, or :memory:`).meta({title:`Database URL`}),authToken:cu(`authToken`,`Auth token`),encryptionKey:Z(t.z.string(),`encryptionKey`).optional().describe(`AES-256 encryption key for the local database file (local/replica modes)`).meta({title:`Encryption key`,format:`password`}),concurrency:t.z.number().int().positive().optional().describe(`Maximum concurrent requests to the remote database`).meta({title:`Concurrency`}),syncUrl:Z(ru(t.z.string(),`syncUrl`),`syncUrl`).optional().describe(`Remote sync URL for embedded-replica mode: a libsql or https Turso endpoint`).meta({title:`Sync URL`}),sync:t.z.strictObject({intervalSeconds:t.z.number().int().nonnegative().optional().describe(`Periodic sync interval in seconds (0 = manual only)`),onConnect:t.z.boolean().optional().describe(`Sync immediately on connect`)}).optional().describe("Embedded-replica sync configuration (requires `syncUrl`)"),timeout:t.z.number().int().positive().optional().describe(`Operation timeout in milliseconds for remote operations`).meta({title:`Timeout (ms)`}),mode:Lu.optional().meta({title:`Transport mode`})}).describe(`Turso / libSQL Connection Configuration`).superRefine((e,t)=>{e.sync&&!e.syncUrl&&t.addIssue({code:`custom`,path:[`sync`],message:"`sync` configures embedded-replica syncing, which only runs when `syncUrl` names the remote to replicate from. Set `syncUrl`, or remove `sync` — on its own it configures nothing."})})),zu=uu(Ru),Bu={id:`turso`,label:`Turso / libSQL`,description:`libSQL driver for ObjectStack — remote Turso databases, local files, and embedded replicas. Ships in the optional @objectstack/driver-turso package.`,icon:`database`,get configSchema(){return zu()}},Vu=[{id:`memory`,aliases:[`memory`,`mingo`,`in-memory`],contractOnlyAliases:[`inmemory`],hasLocalDefault:!0},{id:`sqlite`,aliases:[`sqlite`,`sql`],contractOnlyAliases:[`sqlite3`,`better-sqlite3`],hasLocalDefault:!0},{id:`sqlite-wasm`,aliases:[`sqlite-wasm`,`wasm-sqlite`,`wasm`],hasLocalDefault:!0},{id:`postgres`,aliases:[`postgres`,`postgresql`,`pg`],hasLocalDefault:!1},{id:`mysql`,aliases:[`mysql`,`mysql2`],contractOnlyAliases:[`mariadb`],hasLocalDefault:!1},{id:`mongodb`,aliases:[`mongodb`,`mongo`],hasLocalDefault:!1},{id:`turso`,aliases:[`turso`,`libsql`],hasLocalDefault:!1}],Hu=Vu,Uu=Vu.map(e=>e.id),Wu=Object.freeze(Object.fromEntries(Hu.flatMap(e=>[...e.aliases,...e.contractOnlyAliases??[]].map(t=>[t,e.id])))),Gu=Object.freeze(Hu.flatMap(e=>[...e.aliases]));function Ku(e){if(typeof e==`string`)return Wu[e.trim().toLowerCase()]}var qu=Object.freeze(Object.fromEntries(Hu.flatMap(e=>e.aliases.map(t=>[t,e.id]))));function Ju(e){if(typeof e==`string`)return qu[e.trim().toLowerCase()]}var Yu=Object.freeze(Gu.filter(e=>Ju(e)===e)),Xu=Object.freeze(Object.fromEntries(Hu.map(e=>[e.id,e.hasLocalDefault])));function Zu(e){let t=Ku(e);return!t||Xu[t]}var Qu={memory:yu,sqlite:Mu,"sqlite-wasm":Fu,postgres:Du,mysql:wu,mongodb:Su,turso:Ru};function $u(e){let t=Ku(e);return t?Qu[t]:void 0}var ed={memory:bu,sqlite:Nu,"sqlite-wasm":Iu,postgres:Ou,mysql:Tu,mongodb:Q,turso:zu};function td(e){return ed[e]()}function nd(e,t){let n=$u(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 rd="`datasource.capabilities` was removed in @objectstack/spec 17.0.0 (#4583, ADR-0049) — all eleven flags were declared, strict-guarded and read by nobody. ",id={capabilities:rd+"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 existing sources automatically.",readOnly:rd+"`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 no read-only gate at all, so delete the key rather than trusting it. #4584 settled that this stays so ON PURPOSE: grant the connection SELECT-only at the database (`GRANT SELECT`), which no direct connection, migration or DDL can talk past — an application-layer flag holds in the ObjectQL path only, and one that looks like a boundary without being one is worse than none."},ad={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 rewrite existing sources automatically.',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 rewrite existing sources automatically.',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 rewrite existing sources automatically.",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 rewrite existing sources automatically."},od=(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\`).`,sd="`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 existing sources automatically.",cd=t.z.string().describe(`Underlying driver identifier`),ld=g(()=>I({surface:`this driver definition`,aliases:{name:`id`,driver:`id`,title:`label`,config:`configSchema`,schema:`configSchema`},guidance:{capabilities:id.capabilities,capability:id.capabilities},history:`Until #4001 these were dropped silently — the driver still registered.`},{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`)})),ud=t.z.enum([`managed`,`external`,`validate-only`]).describe(`Schema ownership mode`),dd=I({surface:`this datasource's external settings`,aliases:{schemas:`allowedSchemas`,allowedschema:`allowedSchemas`,writable:`allowWrites`,allowwrite:`allowWrites`,credentials:`credentialsRef`,secretref:`credentialsRef`,timeoutms:`queryTimeoutMs`,querytimeout:`queryTimeoutMs`},guidance:{label:ad.externalLabel,requirePermission:ad.externalRequirePermission,permission:ad.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.`},{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:I({surface:`this datasource's external validation policy`,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.`},{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.`)}).default({onMismatch:`fail`,checkOnBoot:!0}).describe(`Boot/drift validation policy`),credentialsRef:t.z.string().optional().describe("Reference into the secrets store; never inline credentials. Valid in every schemaMode — the one `external` key a managed datasource may carry (#8153)."),queryTimeoutMs:t.z.number().default(3e4).describe(`Hard cap on per-query execution time.`)}).describe(`External datasource settings: federation policy (schemaMode != "managed") plus the secrets-store credentials reference (valid in every schemaMode)`);function fd(e,t,n,r){let i=nd(t,n);if(i.known)for(let t of i.issues)e.addIssue({code:`custom`,path:[...r,...t.path],message:t.message})}var pd=g(()=>I({surface:`this datasource`,aliases:{type:`driver`,connection:`config`,connectionconfig:`config`,options:`config`,enabled:`active`,pooling:`pool`,mode:`schemaMode`,schema_mode:`schemaMode`,federation:`external`,tls:`ssl`},guidance:{host:od(`host`),port:od(`port`),database:od(`database`),user:od(`user`,`username`),username:od(`username`),filename:od(`filename`),url:od(`url`),connectionString:od(`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:sd,replicas:sd,capabilities:id.capabilities,readOnly:id.readOnly,retryPolicy:ad.retryPolicy,retry:ad.retryPolicy,healthCheck:ad.healthCheck,healthcheck:ad.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.`},{name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Unique datasource identifier`),label:t.z.string().optional().describe(`Display label`),driver:cd.describe(`Underlying driver type`),config:t.z.record(t.z.string(),t.z.unknown()).describe(`Driver specific configuration`),pool:I({surface:`this datasource's pool config`,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`."},{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`)}).optional().describe(`Connection pool settings`),ssl:I({surface:`this datasource's ssl config`,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.`},{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)`)}).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:ud.default(`managed`),external:dd.optional(),origin:t.z.enum([`code`,`runtime`]).default(`code`).describe(`Datasource provenance (server-managed, read-only)`),...D}).superRefine((e,t)=>{if(fd(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){let n=hd(e.external);n.length>0&&t.addIssue({code:`custom`,path:[`external`],message:`'external' settings only apply when schemaMode != 'managed'. A managed datasource may carry 'external.credentialsRef' (and only it) \u2014 remove: ${n.join(`, `)}.`})}})),md;function hd(e){let t=md??=dd.parse({});return Object.keys(e).filter(e=>e!==`credentialsRef`).filter(n=>!gd(e[n],t[n])).sort()}function gd(e,t){if(e===t)return!0;if(typeof e!=`object`||typeof t!=`object`||e===null||t===null)return!1;if(Array.isArray(e)||Array.isArray(t))return Array.isArray(e)&&Array.isArray(t)&&e.length===t.length&&e.every((e,n)=>gd(e,t[n]));let n=Object.keys(e),r=Object.keys(t);return n.length===r.length&&n.every(n=>gd(e[n],t[n]))}function _d(e){return pd.parse(e)}var vd=[`password`,`authToken`],yd=[`passwd`,`pwd`,`token`,`jwt`,`auth_token`,`authtoken`],bd={turso:[`encryptionKey`]};function xd(e){let t=e;for(let e=0;t&&e<10;e+=1){let e=t.def??t._def,n=e?.type;if(!n)return;if(n===`optional`||n==="default"||n===`nullable`||n===`readonly`){t=e.innerType;continue}return n}}function Sd(e){let t;try{let n=$u(e)?.shape;t=typeof n==`function`?n():n}catch{return[]}return t?Object.entries(t).filter(([,e])=>xd(e)===`never`).map(([e])=>e):[]}function Cd(e){let t=Sd(e),n=t.length>0?t:[...vd],r=typeof e==`string`?bd[e]??[]:[];return[...new Set([...n,...yd,...r])]}var wd=/^([a-z][a-z0-9+.\-]*:\/\/)([^/?#@:]*)(:[^/?#]*)@/i;function Td(e){return e.replace(wd,(e,t,n)=>`${t}${n}@`)}function Ed(e,t){if(!t||typeof t!=`object`)return{config:{},redactedKeys:[]};let n=new Set(Cd(e)),r={},i=[];for(let[e,a]of Object.entries(t)){if(n.has(e)){a!==void 0&&i.push(e);continue}if(typeof a==`string`){let t=Td(a);if(t!==a){r[e]=t,i.push(e);continue}}r[e]=a}return{config:r,redactedKeys:i.sort()}}var Dd={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`}},Od={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`},kd={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 Ad(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?Dd[t]:void 0;return i&&i[n]?i[n]:Od[n]?Od[n]:`unknown`}function jd(e,t){let n=Ad(e,t);if(n!==`unknown`)return kd[n].suggested}function Md(e,t,n){let r=kd[Ad(e,n)];return r.exact.includes(t)?!0:r.lossy.includes(t)?`lossy`:!1}var Nd=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`)}),Pd=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(Nd).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`)}),Fd=g(()=>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(Pd).describe(`Snapshotted remote tables.`)})),Id=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`number`,`string`,`boolean`]),Ld=t.z.enum([`string`,`number`,`boolean`,`time`,`geo`]),Rd=t.z.enum([`second`,`minute`,`hour`,`day`,`week`,`month`,`quarter`,`year`]),zd=g(()=>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:Id,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()})),Bd=g(()=>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:Ld,sql:t.z.string().describe(`SQL expression or column reference`),granularities:t.z.array(Rd).optional()})),Vd=g(()=>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)`)})),Hd=g(()=>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(),zd).describe(`Quantitative metrics`),dimensions:t.z.record(t.z.string(),Bd).describe(`Qualitative attributes`),joins:t.z.record(t.z.string(),Vd).optional(),refreshKey:t.z.object({every:t.z.string().optional(),sql:t.z.string().optional()}).optional(),public:t.z.boolean().default(!1)})),Ud=g(()=>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:w.optional().describe(`Filtering criteria (canonical Query DSL FilterCondition)`),timeDimensions:t.z.array(t.z.object({dimension:t.z.string(),granularity:Rd.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 Wd(e){return Hd.parse(e)}var Gd=new Set([`number`,`currency`,`percent`]);function Kd(e){return e===`percent`?`avg`:`sum`}function qd(e,t){return!(t!==`percent`||e!==`sum`&&e!==`count_distinct`)}function Jd(e){return e===`count`||e===`count_distinct`||e===`sum`?0:void 0}function Yd(e){if(e?.type===`percent`)return typeof e.max==`number`&&e.max>1?`whole`:`fraction`}var Xd=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(`.`)),Zd=new Set([`text`,`textarea`,`email`,`url`,`markdown`,`html`,`richtext`]),Qd=Zd;function $d(e){if(!e)return!1;let t=e.type;return t?t===`formula`?(e.returnType??e.valueType)===`text`:!Xd.has(t)&&Zd.has(t):!1}var ef=new Set([`name`,`title`,`subject`,`label`,`full_name`,`display_name`]),tf=[`_name`,`_title`],nf=[`name_`];function rf(e){return ef.has(e.toLowerCase())}function af(e){let t=e.toLowerCase();return ef.has(t)?!1:tf.some(e=>t.endsWith(e))||nf.some(e=>t.startsWith(e))}function of(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&&$d(e[r]))return r;for(let n of t)if(af(n)&&$d(e[n]))return n;for(let n of t)if(!rf(n)&&$d(e[n]))return n}function sf(e){return e?(e.nameField??e.displayNameField)||of(e.fields):void 0}function cf(e){return e==null||typeof e==`string`&&e.trim()===``}function lf(e,t,n){let r=t??{},i=n?.viewTitleField??sf(e),a=i?r[i]:void 0;return cf(a)?`Record #${r.id??r._id??``}`.trimEnd():String(a)}function uf(e,t){let n=sf(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 df(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=of(e.fields);return n?{status:`derived`,field:n}:{status:`none`}}var ff=new Set([`text`,`email`,`phone`,`url`,`autonumber`,`textarea`,`markdown`]),pf=new Set([`select`,`status`]),mf=new Set([`id`,`_id`,`created`,`modified`,`created_at`,`updated_at`,`created_by`,`updated_by`,`owner_id`,`organization_id`,`space`,`company_id`]),hf=new Set([`json`,`object`,`grid`,`image`,`file`,`avatar`,`vector`,`location`,`geometry`,`secret`,`password`,`encrypted`,`boolean`,`lookup`,`master_detail`]),gf=new Set([`formula`]);function _f(e){return!!e&&typeof e.type==`string`&&gf.has(e.type)}function vf(e,t){let n=Object.keys(e).filter(t=>{if(mf.has(t))return!1;let n=e[t];if(!n||n.hidden)return!1;let r=n.type;return!r||hf.has(r)?!1:ff.has(r)||pf.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 yf(e){let t=e.fields||{},n=e.searchableFields?.filter(e=>t[e]&&!_f(t[e]));return n&&n.length>0?{allowed:n,source:`declared`}:{allowed:vf(t,e.displayField),source:`auto`}}function bf(e){let{allowed:t}=yf(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 xf=Object.freeze([`created_at`,`created_by`,`updated_at`,`updated_by`]),Sf=new Set([...xf,`organization_id`,`tenant_id`,`is_deleted`,`deleted_at`]);function Cf(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 wf(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e,n=(Array.isArray(t.fieldGroups)?t.fieldGroups:[]).map(Cf).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):Sf.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 Tf=12;function Ef(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&&(Sf.has(e)||n++);return n}function Df(e,t={}){if(t.viewport===`mobile`)return`page`;let n=t.pageThreshold??Tf;return Ef(e)>=n?`page`:`drawer`}function Of(e,t,n={}){let r=Df(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 kf=`id`,Af=`owner_id`,jf=`owning_business_unit_id`,Mf=`organization_id`;function Nf(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([kf]),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&&!rs(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`),p=f||u&&d===`business_unit`;if(c&&a.add(Mf),l)for(let e of xf)a.add(e);return f&&a.add(Af),p&&a.add(jf),{tenant:c,audit:l,owner:f,owningBusinessUnit:p,names:a}}var Pf={created_at:{type:`datetime`,label:`Created At`,required:!1,readonly:!0,system:!0,description:`Timestamp when the record was created (auto-populated by the driver).`},created_by:{type:`lookup`,reference:`sys_user`,label:`Created By`,required:!1,readonly:!0,system:!0,description:`User who created the record (populated when an authenticated session is present).`},updated_at:{type:`datetime`,label:`Last Modified At`,required:!1,readonly:!0,system:!0,description:`Timestamp of the most recent modification (auto-populated by the driver).`},updated_by:{type:`lookup`,reference:`sys_user`,label:`Last Modified By`,required:!1,readonly:!0,system:!0,description:`User who last modified the record (populated when an authenticated session is present).`}},Ff={type:`lookup`,reference:`sys_organization`,label:`Organization`,required:!1,hidden:!0,readonly:!0,system:!0,description:`Tenant scope (auto-populated by org-scoping on insert; NULL on single-tenant stacks).`},If={type:`lookup`,reference:`sys_user`,label:`Owner`,required:!1,readonly:!1,system:!0,description:`Record owner (auto-stamped to the creating user on insert; reassignable). Drives owner-scoped views, reports and notifications.`},Lf={type:`lookup`,reference:`sys_business_unit`,label:`Owning Business Unit`,required:!1,hidden:!0,readonly:!0,system:!0,description:`Record-level business-unit ownership (ADR-0117 D1). Server-stamped scope anchor; NULL until the stamping middleware lands.`};function Rf(e){let t=Nf(e),n={};if(t.tenant&&(n[Nt.ORGANIZATION_ID]=Ff),t.audit)for(let e of xf)n[e]=Pf[e];return t.owner&&(n[Nt.OWNER_ID]=If),t.owningBusinessUnit&&(n[Nt.OWNING_BUSINESS_UNIT_ID]=Lf),n}function zf(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let n=e,r=Object.keys(n);if(r.length!==Object.keys(t).length)return!1;for(let e of r)if(n[e]!==t[e])return!1;return!0}function Bf(e){return!e||typeof e!=`object`||Array.isArray(e)?!0:e.external==null}function Vf(e,t){let n=Rf(e)[t],r=Uf(e,t);return n===void 0?r.present?`author`:`absent`:!r.present||r.def!==void 0&&zf(r.def,n)?Bf(e)?`injected-provisioned`:`injected-unprovisioned`:`author`}function Hf(e){return Bf(e)?[]:Object.keys(Rf(e)).filter(t=>Vf(e,t)===`injected-unprovisioned`)}function Uf(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return{present:!1};let n=e.fields;if(Array.isArray(n)){let e=n.find(e=>!!e&&typeof e==`object`&&e.name===t);if(e===void 0)return{present:!1};let r={...e};return delete r.name,{present:!0,def:r}}if(!n||typeof n!=`object`)return{present:!1};let r=n[t];return r===void 0?{present:!1}:!r||typeof r!=`object`||Array.isArray(r)?{present:!0}:{present:!0,def:r}}var Wf=t.z.enum([`comment`,`field_change`,`task`,`event`,`email`,`call`,`note`,`file`,`record_create`,`record_delete`,`approval`,`sharing`,`system`]),Gf=t.z.enum([`all`,`comments_only`,`changes_only`,`tasks_only`]);e.ACCEPTED_FILTER_COMPARAND_TYPES=n,e.ACCEPTED_FILTER_COMPARAND_TYPES_SENTENCE=r,e.AGGREGATION_CASES=Ir,e.AGGREGATION_ROWS=Fr,e.ALL_OPERATORS=Ke,e.API_METHOD_DERIVATION=zs,e.API_METHOD_ORDER=Ps,e.API_OPERATION_ORDER=qo,e.API_PRIMITIVES=Ns,e.AUDIT_FIELD_DEFS=Pf,e.AUDIT_PROVENANCE_FIELDS=xf,e.AddressSchema=N,e.AddressValueSchema=nn,e.AggregationFunction=Jn,e.AggregationMetricType=Id,e.AggregationNodeSchema=Qn,e.AggregationPipelineSchema=Al,e.AggregationStageSchema=kl,e.AnalyticsQuerySchema=Ud,e.ApiMethod=Go,e.ApiOperationSchema=Jo,e.AutoPersistenceConfigSchema=_u,e.BOOLEAN_VALUE_TYPES=It,e.BUILTIN_DRIVER_IDS=Uu,e.BULK_PER_ROW_HOOK_LIMIT_ERROR_CODE=cc,e.BULK_WRITE_HOOK_DISPATCH_CONTRACT=oc,e.BaseEngineOptionsSchema=W,e.CALENDAR_DATE_TYPES=Lt,e.CLOCK_TIME_TYPES=zt,e.COMPUTED_VALUE_TYPES=Yt,e.CONTEXT_TOKENS=Zr,e.CONTEXT_TOKEN_DESCRIPTIONS=ri,e.CONTEXT_TOKEN_SUGGESTIONS=ii,e.CONTEXT_TOKEN_WRAPPED_RE=$r,e.CalendarDateValueSchema=Qt,e.ClockTimeValueSchema=en,e.ComparandTypeProbe=Cr,e.ComparisonOperatorSchema=se,e.ConditionalValidationSchema=mi,e.ConsistencyLevelSchema=xl,e.ContextTokenPlaceholderSchema=ni,e.ContextTokenSchema=ti,e.CrossFieldValidationSchema=di,e.CubeJoinSchema=Vd,e.CubeSchema=Hd,e.CurrencyConfigSchema=wn,e.CurrencyValueSchema=Tn,e.CustomPersistenceConfigSchema=gu,e.DATABASE_DRIVER_SELECTION_ALIASES=Gu,e.DATABASE_DRIVER_SELECTION_IDS=Yu,e.DATA_ACTION_TO_API_OPERATION=Bs,e.DATE_MACRO_ALIAS_TOKENS=Rr,e.DATE_MACRO_DESCRIPTIONS=qr,e.DATE_MACRO_INSTANT_TOKENS=Lr,e.DATE_MACRO_PARAM_RE=Br,e.DATE_MACRO_PERIOD_TOKENS=L,e.DATE_MACRO_TOKENS=zr,e.DATE_MACRO_UNITS=Vr,e.DATE_MACRO_WRAPPED_RE=Gr,e.DEFAULT_AUTONUMBER_FORMAT=St,e.DEFAULT_VALUE_TOKENS=Et,e.DEFAULT_VALUE_TOKEN_CURRENT_USER=M,e.DEFAULT_VALUE_TOKEN_DESCRIPTIONS=Dt,e.DEFAULT_VALUE_TOKEN_NOW=j,e.DEFAULT_VALUE_TOKEN_SUGGESTIONS=hn,e.DRIVER_CONFIG_SCHEMAS=Qu,e.DRIVER_ID_ALIASES=Wu,e.DataEngineAggregateOptionsSchema=Bc,e.DataEngineAggregateRequestSchema=il,e.DataEngineContractSchema=Uc,e.DataEngineCountOptionsSchema=Hc,e.DataEngineCountRequestSchema=rl,e.DataEngineDeleteOptionsSchema=Rc,e.DataEngineDeleteRequestSchema=nl,e.DataEngineExecuteRequestSchema=al,e.DataEngineFilterSchema=Oc,e.DataEngineFindOneRequestSchema=$c,e.DataEngineFindRequestSchema=Qc,e.DataEngineInsertOptionsSchema=Mc,e.DataEngineInsertRequestSchema=el,e.DataEngineQueryOptionsSchema=jc,e.DataEngineRequestSchema=ol,e.DataEngineSortSchema=kc,e.DataEngineUpdateOptionsSchema=Ic,e.DataEngineUpdateRequestSchema=tl,e.DataEngineVectorFindRequestSchema=G,e.DataTypeMappingSchema=ml,e.DatasourceSchema=pd,e.DateGranularity=Yn,e.DateMacroPlaceholderSchema=Kr,e.DateMacroTokenSchema=Wr,e.DimensionSchema=Bd,e.DimensionType=Ld,e.DocumentSchema=Zl,e.DocumentSchemaValidationSchema=Tl,e.DocumentTemplateSchema=Yl,e.DocumentVersionSchema=Jl,e.DriverCapabilitiesSchema=ll,e.DriverConfigSchema=fl,e.DriverDefinitionSchema=ld,e.DriverInterfaceSchema=ul,e.DriverOptionsSchema=K,e.DriverSslToggleSchema=eu,e.DriverType=cd,e.DroppedFieldsEventSchema=Fc,e.ENGINE_UPDATE_UPSERT_REMOVED=Nc,e.ESignatureConfigSchema=Xl,e.EngineAggregateOptionsSchema=zc,e.EngineCountOptionsSchema=Vc,e.EngineDeleteOptionsSchema=Lc,e.EngineQueryOptionsSchema=Ac,e.EngineUpdateOptionsSchema=Pc,e.EqualityOperatorSchema=oe,e.ExpressionBodySchema=Si,e.ExternalCatalogSchema=Fd,e.ExternalColumnSchema=Nd,e.ExternalDatasourceSettingsSchema=dd,e.ExternalTableSchema=Pd,e.FIELD_GROUP_SYSTEM_FIELDS=Sf,e.FIELD_KEY_GUIDANCE=ct,e.FILE_REFERENCE_TYPES=Gt,e.FILTER_ARRAY_LOGIC_KEYWORDS=ze,e.FILTER_COMPARAND_BIGINT_EXACT_LIMIT=i,e.FILTER_COMPARAND_TYPE_CASES=wr,e.FILTER_COMPARAND_TYPE_ROWS=Sr,e.FILTER_LOGIC_CASES=lr,e.FILTER_LOGIC_ROWS=cr,e.FILTER_OPERATORS=We,e.FILTER_SUBTREE_PROVENANCE=hr,e.FILTER_TEXT_CASES=xr,e.FILTER_TEXT_ROWS=br,e.FILTER_TOKEN_WRAPPED_RE=ei,e.FeedFilterMode=Gf,e.FeedItemType=Wf,e.Field=Nn,e.FieldNodeSchema=er,e.FieldOperatorsSchema=Ce,e.FieldReferenceSchema=_,e.FieldSchema=Mn,e.FieldType=yn,e.FileLikeValueSchema=an,e.FilePersistenceConfigSchema=mu,e.FileReferenceIdValueSchema=P,e.FileValueSchema=rn,e.FilterArraySchema=Ue,e.FilterConditionSchema=w,e.FormatValidationSchema=ui,e.FullTextSearchSchema=ar,e.GroupByNodeSchema=Xn,e.HookBodyCapability=z,e.HookBodySchema=wi,e.HookContextSchema=ic,e.HookEvent=nc,e.HookSchema=rc,e.IMPORT_BOOLEAN_FALSE_TOKENS=$s,e.IMPORT_BOOLEAN_TRUE_TOKENS=Qs,e.IMPORT_REFERENCE_TYPES=ec,e.INLINE_CREDENTIAL_REFUSED=X,e.INSTANT_TYPES=Rt,e.ImportFieldMappingSchema=gc,e.IndexSchema=$o,e.InstantValueSchema=$t,e.JSONValidationSchema=fi,e.LEGACY_API_METHODS=U,e.LEGACY_API_METHOD_GUIDANCE=Ko,e.LIFECYCLE_DURATION_REGEX=cs,e.LOGICAL_OPERATORS=Ge,e.LifecycleClassSchema=ss,e.LifecycleSchema=us,e.LocalStoragePersistenceConfigSchema=hu,e.LocationCoordinatesSchema=Cn,e.LocationValueSchema=tn,e.MANAGED_WRITE_VERB_AFFORDANCE=Js,e.MAX_BULK_PER_ROW_HOOK_ROWS=sc,e.MEASURE_FIELD_TYPES=Gd,e.MULTI_CAPABLE_TYPES=Xt,e.MULTI_OPTION_TYPES=Vt,e.MappingSchema=_c,e.MemoryConfigSchema=yu,e.MemoryDriverSpec=xu,e.MemoryPersistenceConfigSchema=vu,e.MetricSchema=zd,e.MongoConfigSchema=Su,e.MongoDriverSpec=Cu,e.MysqlConfigSchema=wu,e.NOW_DEFAULT_LEGAL_TYPES=pn,e.NUMERIC_VALUE_TYPES=Ft,e.NoSQLDataTypeMappingSchema=El,e.NoSQLDatabaseTypeSchema=yl,e.NoSQLDriverConfigSchema=Dl,e.NoSQLIndexSchema=jl,e.NoSQLIndexTypeSchema=Sl,e.NoSQLOperationTypeSchema=bl,e.NoSQLQueryOptionsSchema=Ol,e.NoSQLTransactionOptionsSchema=Ml,e.NormalizedFilterSchema=Oe,e.OBJECT_KEY_GUIDANCE=lt,e.OWNER_FIELD_DEF=If,e.OWNING_BUSINESS_UNIT_FIELD_DEF=Lf,e.ObjectAccessConfigSchema=is,e.ObjectCapabilities=Qo,e.ObjectDependencyGraphSchema=Vl,e.ObjectDependencyNodeSchema=Bl,e.ObjectExtensionSchema=js,e.ObjectExternalBindingSchema=fs,e.ObjectFieldGroupSchema=ds,e.ObjectOwnershipEnum=As,e.ObjectRequiredPermissionsSchema=os,e.ObjectSchema=Es,e.PAGINATION_ALL_IDS=Nr,e.PAGINATION_CASES=jr,e.PAGINATION_ROWS=Ar,e.PAGINATION_UNORDERED_CASES=Mr,e.PAGINATION_ZERO_LIMIT_CASES=Pr,e.PerOperationRequiredPermissionsSchema=as,e.PersistenceAdapterSchema=fu,e.PersistenceTypeSchema=pu,e.PoolConfigSchema=dl,e.PostgresConfigSchema=Du,e.QUERY_CURSOR_REMOVED=nr,e.QUERY_DISTINCT_REMOVED=rr,e.QueryFilterSchema=we,e.QuerySchema=sr,e.RAW_FILE_VALUES_CONTEXT_KEY=qt,e.READ_ONLY_BELONGS_ON_DATASOURCE=$l,e.RECORD_SURFACE_PAGE_THRESHOLD=Tf,e.REFERENCE_VALUE_TYPES=Ht,e.RETIRED_FILTER_OPERATORS=qe,e.RPC_QUERY_ALIAS_SLOTS=Wc,e.RUNTIME_OWNED_FIELD_TYPES=bn,e.RangeOperatorSchema=he,e.ReferenceIdValueSchema=sn,e.ReferenceResolutionErrorSchema=Hl,e.ReferenceResolutionSchema=zl,e.ReplicationConfigSchema=wl,e.RowCrudActionOverrideSchema=ps,e.SCHEMA_MODE_BELONGS_ON_DATASOURCE=Ql,e.SEARCHABLE_ENUM_TYPES=pf,e.SEARCHABLE_TEXTUAL_TYPES=ff,e.SEARCH_AUTO_EXCLUDED_FIELDS=mf,e.SEARCH_AUTO_EXCLUDED_TYPES=hf,e.SEARCH_VIRTUAL_TYPES=gf,e.SECRET_MASK=Zs,e.SINGLE_OPTION_TYPES=Bt,e.SQLDialectSchema=pl,e.SQLDriverConfigSchema=gl,e.SQLiteAlterTableLimitations=vl,e.SQLiteDataTypeMappingDefaults=_l,e.SSLConfigSchema=hl,e.SSL_DETAIL_BELONGS_ON_DATASOURCE=Y,e.STACK_KEY_GUIDANCE=ut,e.STACK_RUNTIME_MEMBERS=dt,e.STRING_VALUE_TYPES=Pt,e.STRUCTURED_JSON_TYPES=Jt,e.SchemaModeSchema=ud,e.ScriptBodySchema=Ci,e.ScriptValidationSchema=ci,e.SeedIdentitySchema=Ul,e.SeedLoadResultSchema=Gl,e.SeedLoaderConfigSchema=Wl,e.SeedLoaderRequestSchema=ql,e.SeedLoaderResultSchema=Kl,e.SeedMode=Nl,e.SeedSchema=Pl,e.SelectOptionSchema=Sn,e.SetOperatorSchema=fe,e.ShardingConfigSchema=Cl,e.SortNodeSchema=Un,e.SpecialOperatorSchema=Se,e.SqlAutoMigrateSchema=J,e.SqliteConfigSchema=Mu,e.SqliteWasmConfigSchema=Fu,e.SqliteWasmPersistModeSchema=Pu,e.StateMachineValidationSchema=li,e.StringOperatorSchema=y,e.TEMPORAL_CASES=Dr,e.TEMPORAL_NOW=Tr,e.TEMPORAL_ROWS=Er,e.TEMPORAL_TIME_CASES=kr,e.TEMPORAL_TIME_ROWS=Or,e.TENANT_SCOPE_FIELD_DEF=Ff,e.TITLE_ELIGIBLE=Qd,e.TITLE_ELIGIBLE_TYPES=Zd,e.TITLE_INELIGIBLE_TYPES=Xd,e.TenancyConfigSchema=ns,e.TimeUpdateInterval=Rd,e.TransformType=hc,e.TursoConfigSchema=Ru,e.TursoDriverSpec=Bu,e.TursoTransportModeSchema=Lu,e.UNRESOLVED_PLACEHOLDER_REFUSED=iu,e.URL_EMBEDDED_CREDENTIAL_REFUSED=tu,e.UniqueScopeSchema=Dn,e.VALID_AST_OPERATORS=je,e.ValidationRuleSchema=pi,e.apiExposureDenialReason=Ks,e.asciiCaseInsensitiveContains=_e,e.asciiCaseInsensitiveRegexSource=ve,e.canServeApiOperation=qs,e.canonicalAstOperator=Ne,e.canonicalizeSqlType=Ad,e.checkLiteralDefaultValue=fn,e.checkManagedApiMethodAffordances=Ys,e.classifyFilterToken=oi,e.containsUnresolvedPlaceholder=au,e.countAuthorableFields=Ef,e.credentialFreeUrl=ru,e.defaultAggregateFor=Kd,e.defaultValueTokenIssue=mn,e.defineCube=Wd,e.defineDatasource=_d,e.defineHook=ac,e.defineMapping=vc,e.defineObjectExtension=Ms,e.defineSeed=Fl,e.deriveFieldGroupLayout=wf,e.deriveRecordFlowSurface=Of,e.deriveRecordSurface=Df,e.describeManagedApiMethodConflicts=Xs,e.discriminateDefaultValueShape=dn,e.driverConfigJsonSchema=uu,e.driverHasLocalDefault=Zu,e.effectiveOperationsArray=Gs,e.emptyGroupValueFor=Jd,e.fieldForm=Ll,e.filterSubtreeProvenanceOf=_r,e.foldAsciiCase=ge,e.foldQueryAliasSlots=Gc,e.formatUnknownAuthoringKey=mt,e.getDriverConfigJsonSchemaById=td,e.getDriverConfigSchema=$u,e.getMemoryConfigJsonSchema=bu,e.getMongoConfigJsonSchema=Q,e.getMysqlConfigJsonSchema=Tu,e.getPostgresConfigJsonSchema=Ou,e.getSqliteConfigJsonSchema=Nu,e.getSqliteWasmConfigJsonSchema=Iu,e.getTursoConfigJsonSchema=zu,e.hasDanglingLikeEscape=C,e.hasDynamicTokens=_t,e.hookForm=Rl,e.injectedSystemColumnDefs=Rf,e.isAcceptedFilterComparand=a,e.isApiOperationAllowed=Ws,e.isApiPrimitive=Ls,e.isAppResolvedDefaultToken=jt,e.isCompatible=Md,e.isContextToken=Qr,e.isCurrentUserDefaultToken=kt,e.isDateMacroToken=Hr,e.isExpressionEnvelopeDefault=un,e.isFileIdToken=Kt,e.isFilterAST=Pe,e.isGlobalUnique=On,e.isIncoherentAggregate=qd,e.isInjectedColumnDefinition=zf,e.isKnownFilterToken=ai,e.isLegacyApiMethod=Rs,e.isMultiValueField=Zt,e.isNowDefaultToken=Ot,e.isOrganizationUnique=An,e.isPlainRecord=ft,e.isRuntimeDefaultToken=At,e.isTenancyDisabled=rs,e.isTitleEligible=$d,e.isUniqueDeclared=kn,e.isVirtualSearchField=_f,e.likePatternToGlobPattern=xe,e.likePatternToRegexSource=ye,e.lintAuthoredRecordKeys=pt,e.markFilterSubtreeProvenance=gr,e.matchesLikePattern=be,e.missingFieldValues=yt,e.nextUtcCalendarDay=Jr,e.normalizeFilterComparandTypes=h,e.objectForm=Il,e.objectTitleCompleteness=df,e.parseAutonumberFormat=gt,e.parseDateMacroParam=Ur,e.parseFilterAST=Le,e.percentScaleOf=Yd,e.placeholderFree=Z,e.placeholderFreeDeep=ou,e.platformProvisionsStorage=Bf,e.provisionPrimary=uf,e.readAutonumberCounter=Tt,e.redactDatasourceConfig=Ed,e.redactUrlPassword=Td,e.redactableConfigKeys=Cd,e.reduceFilterKeyVerdict=fr,e.reduceFilterVerdict=dr,e.referenceTargetOf=Wt,e.referencedFields=A,e.refusedCredentialKeys=Sd,e.refusedInlineCredentialKey=cu,e.renderAutonumber=wt,e.resolveAutonumberFormat=Ct,e.resolveBulkPerRowHookBudget=lc,e.resolveCrudAffordances=Os,e.resolveDatabaseDriverId=Ju,e.resolveDisplayField=sf,e.resolveDriverId=Ku,e.resolveEffectiveApiMethods=Us,e.resolveFilterSubtreeProvenance=vr,e.resolveInjectedColumnProvenance=Vf,e.resolveInjectedSystemColumns=Nf,e.resolveRecordDisplayName=lf,e.resolveSearchFieldResolution=yf,e.resolveSearchFields=bf,e.sequenceWidth=vt,e.stripLegacyApiMethods=Zo,e.suggestDefaultValueToken=gn,e.suggestFieldTypeForSqlType=jd,e.unprovisionedInjectedColumns=Hf,e.urlUserinfoPassword=nu,e.utcInstantMs=Yr,e.validateDriverConfig=nd,e.valueSchemaFor=ln})),l=e((e=>{var t=s();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()}));var i=`Comparand is a number, a Date, a string, or a { $field } reference. STRING is the form the platform itself produces: the date-macro resolver returns only strings ("{current_year_start}" -> "2026-01-01"), and the guaranteed spellings are an ISO calendar day (YYYY-MM-DD), a UTC ISO-8601 instant, or a wall-clock time of day (HH:MM[:SS[.fff]]) for a Field.time column. Those are ASCII and fixed-width, so lexicographic order IS chronological order and every backend agrees; the driver reconciles the comparand with the column (a bare calendar day used as an upper bound becomes the half-open next-day boundary). Ordering NON-temporal text is permitted but NOT promised: the order is the backend collation's (byte-wise on SQLite, the database locale on Postgres, UTF-16 code units in the JS matchers), and those coincide only for ASCII.`;n(()=>t.z.object({$gt:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional().describe(`Greater than. ${i}`),$gte:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional().describe(`Greater than or equal to. ${i}`),$lt:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional().describe(`Less than. ${i}`),$lte:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional().describe(`Less than or equal to. ${i}`)}));function a(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&`$field`in e}function o(e){return`A { "$field": \u2026 } reference is not a valid ${e}. No evaluation path resolves a field reference inside a list: the in-memory evaluator (matchesFilter) leaves the list unresolved and compares the raw reference OBJECT, so it silently matches nothing, and both SQL drivers refuse the position with INVALID_FILTER / 400. Write a literal value here, or move the reference to a scalar comparison operator ($eq/$ne/$gt/$gte/$lt/$lte), whose WHOLE comparand a { $field } reference may be. Ruled 2026-08-11 on #7596: declared = enforced (ADR-0049).`}var c=e=>t.z.array(t.z.any()).superRefine((t,n)=>{t.forEach((t,r)=>{a(t)&&n.addIssue({code:`custom`,path:[r],message:o(`${e} member at index ${r}`)})})}),l=`Membership list. Members are literal values of any type the column stores. A { $field } reference is NOT a member shape: no backend resolves one inside a list (#7596) — put it in a scalar comparison ($eq/$ne/$gt/$gte/$lt/$lte) instead.`;n(()=>t.z.object({$in:c(`$in`).optional().describe(l),$nin:c(`$nin`).optional().describe(l)}));var u=`Closed interval [min, max]. Each endpoint is a number, a Date, or a string. A { $field } reference is NOT an endpoint shape: no backend resolves one inside a list (#7596) — put it in a scalar comparison ($gt/$gte/$lt/$lte), which does compile to a column-to-column bound. STRING is the form the platform itself produces: the date-macro resolver walks INTO arrays, so { $between: ["{current_year_start}", "{current_year_end}"] } resolves to two strings. The guaranteed spellings are an ISO calendar day (YYYY-MM-DD), a UTC ISO-8601 instant, or a wall-clock time of day (HH:MM[:SS[.fff]]) for a Field.time column; those are ASCII and fixed-width, so lexicographic order IS chronological order and every backend agrees. The driver reconciles each endpoint with the column independently (a bare calendar day used as the MAX becomes the half-open next-day boundary). Ranging over NON-temporal text is permitted but NOT promised: the order is the backend collation's, and those coincide only for ASCII.`,d=e=>t.z.union([t.z.number(),t.z.date(),t.z.string()],{error:t=>a(t.input)?o(`$between endpoint at index ${e}`):void 0});n(()=>t.z.object({$between:t.z.tuple([d(0),d(1)]).optional().describe(`Between (inclusive). ${u}`)})),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 it; #5702 lowered it on the SQL family (driver-sql, driver-sqlite-wasm, driver-turso on both transports); #6520 lowered it on every JS evaluation face, so it is portable across every backend the platform ships.]`),$like:t.z.string().optional().describe('Whole-string pattern match with CALLER-bound wildcards: "%" matches any sequence (including empty), "_" matches exactly one character, and a backslash escapes the character after it ("\\%", "\\_", "\\\\") so it matches literally. The pattern must cover the WHOLE value — a pattern with no wildcards is an exact comparison, NOT a substring search; write $contains for containment. A pattern ending in a lone unpaired backslash is refused (INVALID_FILTER). Comparison is case-SENSITIVE, same contract as $contains (#4706 Q2 = A); $ilike is the case-insensitive twin. [#7536. Answered by the SQL family (driver-sql, driver-sqlite-wasm, driver-turso on both transports), by driver-memory and by @objectstack/formula. driver-mongodb, objectql `having` and service-analytics REFUSE it in the INVALID_FILTER envelope rather than approximating it — see FILTER_OPERATORS for why it is staged out of that allowlist.]'),$ilike:t.z.string().optional().describe(`Whole-string pattern match like $like — "%" / "_" wildcards bound by the caller, backslash escapes — but ignoring ASCII case (A-Z against a-z) and ONLY ASCII case: "café" does NOT match "CAFÉ", the same #4706 Q1 = A boundary $icontains declares, because SQLite's fold is ASCII-only and three of the five backends are SQLite underneath. [#7536; staged with $like — see FILTER_OPERATORS.]`)})),n(()=>t.z.object({$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()}));var f=n(()=>t.z.object({$eq:t.z.any().optional(),$ne:t.z.any().optional(),$gt:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional(),$gte:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional(),$lt:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional(),$lte:t.z.union([t.z.number(),t.z.date(),t.z.string(),r]).optional(),$in:c(`$in`).optional().describe(l),$nin:c(`$nin`).optional().describe(l),$between:t.z.tuple([d(0),d(1)]).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(),$like:t.z.string().optional(),$ilike:t.z.string().optional(),$null:t.z.boolean().optional(),$exists:t.z.boolean().optional()})),p=t.z.lazy(()=>t.z.record(t.z.string(),t.z.unknown()).and(t.z.object({$and:t.z.array(p).optional(),$or:t.z.array(p).optional(),$not:p.optional()})));n(()=>t.z.object({where:p.optional()}));var ee=[`$and`,`$or`,`$not`];function m(e,t){return`Not a valid ${e} \u2014 ${t&&typeof t==`object`&&!Array.isArray(t)?`got an object with key(s) ${Object.keys(t).map(e=>JSON.stringify(e)).join(`, `)}`:`got ${Array.isArray(t)?`an array`:t===null?`null`:typeof t}`}. A ${e} is either a FIELD CONDITION ({ "field": { "$op": value } }, whose keys are field names and whose operator map must satisfy FieldOperatorsSchema \u2014 comparand shapes included), or a nested LOGICAL GROUP carrying only ${ee.join(` / `)} and nothing else. Ruled on #7711: declared = enforced (ADR-0049).`}var te=()=>t.z.record(t.z.string(),f).refine(e=>!Object.keys(e).some(e=>e.startsWith(`$`)),{message:`A field condition's keys are field names, never $-prefixed operators (#7711).`,abort:!0}),ne=e=>t.z.union([te(),re],{error:t=>m(e,t.input)}),re=t.z.lazy(()=>t.z.object({$and:t.z.array(ne(`$and member`)).optional(),$or:t.z.array(ne(`$or member`)).optional(),$not:ne(`$not operand`).optional()}).strict()),h=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:`$like`,ilike:`$ilike`,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`})),ie=[`and`,`or`],ae=t.z.string().min(1).refine(e=>!ie.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]].`}),g=t.z.string().refine(e=>h.has(e.toLowerCase()),{error:e=>`Unknown filter operator '${String(e.input)}'. Recognised operators: ${[...h].sort().join(`, `)}.`}),_=t.z.string().refine(e=>ie.includes(e.toLowerCase()),{message:`A logical group opens with 'and' or 'or'.`}),oe=t.z.lazy(()=>t.z.union([t.z.tuple([ae,g,t.z.unknown()]),t.z.tuple([ae,g]),t.z.tuple([_,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).`));function v(e){return t.z.never({error:()=>e}).optional().describe(`[REMOVED] ${e}`)}function se(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}}var ce={surface:`this view/page schema`,history:`Before ADR-0089 D3a these were dropped silently, shipping inert metadata; a mis-layered or stale key is now a loud parse error.`,guidanceSets:[{name:`VISIBILITY_KEY_PATTERN`,keys:/vis|conceal|hidden|show.?when/i,examples:[`visibleWhenn`,`visibleIf`,`hiddenWhen`,`conceal`,`showWhen`],prescription:"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."}]},le=[`disabled`,`disabledWhen`,`readonly`,`readOnly`,`readonlyWhen`,`editable`],ue={name:`EDITABILITY_BOUNDARY_KEYS`,keys:le,prescription:"Editability is a FIELD-level concern. This shape gates VISIBILITY only — a deliberate boundary, not a missing key (#7887): a section / page component has no read-only semantics of its own to enforce. Write `readonly: true` (or the conditional `readonlyWhen` predicate) on the form field(s) inside it instead; to hide the whole section or component, use `visibleWhen`."},de={name:`SELECT_OPTION_EDITABILITY_BOUNDARY_KEYS`,keys:le,prescription:"Editability is not a per-OPTION concern — a deliberate boundary, not a missing key (#8201): an option declares WHICH value may be picked and WHEN it is offered, and nothing in the field pipeline reads a per-option enabled/disabled flag today (the select and radio widgets treat the FIELD-level state as the single authority), so a key here would be metadata the renderer never honours (ADR-0049). To withdraw ONE option, give it the per-option `visibleWhen` predicate — the one `*When` surface that also binds `current_user` (ADR-0068), so an option can be withheld per record or per role, and the rule validator refuses a write of a value whose predicate is false. To freeze the WHOLE picker, write `readonly: true` (or the conditional `readonlyWhen` predicate) on the field that owns these options. If a shown-but-unselectable option ever earns a reader, that is a spec decision to ask for — not a key to write here."},fe={...ce,guidanceSets:[...ce.guidanceSets??[],ue]},pe=t.z.enum([`none`,`no-overlay`,`no-delete`,`full`]),me=t.z.enum([`artifact`,`package`,`env-forced`]),he=t.z.enum([`package`,`org`,`env-forced`]),y={_lock:pe.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:me.optional().describe(`Layer that set _lock (artifact | package | env-forced).`),_provenance:he.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.`)},b=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)`)),x=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)`)),S=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)`)),ge=t.z.enum([`cel`,`cron`,`template`]),_e=t.z.object({rationale:t.z.string().optional(),generatedBy:t.z.string().optional()}),ve=t.z.object({dialect:ge,source:t.z.string().min(1).optional(),ast:t.z.unknown().optional(),meta:_e.optional()}).refine(e=>e.source!==void 0||e.ast!==void 0,{message:"Expression requires at least one of `source` or `ast`"}),C=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cel`,source:e})),ve]),ye=t.z.union([t.z.string().min(1).transform(e=>({dialect:`cron`,source:e})),ve]),be=t.z.union([t.z.string().min(1).transform(e=>({dialect:`template`,source:e})),ve]),xe=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.`}}),Se=`{0000}`,Ce=`NOW()`,w=`current_user`;function we(e){return typeof e==`string`&&/^now\(\)$/i.test(e.trim())}function Te(e){return e===w}function Ee(e){return we(e)||Te(e)}var T={USER:`sys_user`},De=new Set([`text`,`textarea`,`email`,`url`,`phone`,`password`,`secret`,`markdown`,`html`,`richtext`,`code`,`color`,`signature`,`qrcode`]),Oe=new Set([`number`,`currency`,`percent`,`rating`,`slider`,`progress`,`summary`]),ke=new Set([`boolean`,`toggle`]),Ae=new Set([`date`]),je=new Set([`datetime`]),Me=new Set([`time`]),Ne=new Set([`select`,`radio`]),Pe=new Set([`multiselect`,`checkboxes`,`tags`]),Fe=new Set([`lookup`,`master_detail`,`user`,`tree`]),Ie=new Set([`image`,`file`,`avatar`,`video`,`audio`]),Le=new Set([`select`,`radio`,`lookup`,`user`,`file`,`image`]);function Re(e){return Pe.has(e.type)?!0:Le.has(e.type)&&e.multiple===!0}var ze=n(()=>t.z.string().regex(/^\d{4}-\d{2}-\d{2}$/,`expected YYYY-MM-DD (calendar day, not an instant)`)),Be=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)`)),Ve=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)`)),He=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`)})),Ue=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`)})),We=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()})),Ge=n(()=>t.z.string().regex(/^[A-Za-z0-9_-]{1,64}$/,`Expected an opaque sys_file id`));n(()=>t.z.union([t.z.string().min(1),We]));var Ke=/^\s*[[{]/,qe=n(()=>t.z.string().min(1).refine(e=>!Ke.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 E(e){return Array.isArray(e.options)?e.options.map(e=>String(typeof e==`object`&&e?e.value:e)):[]}function Je(e,n=`stored`){let r=e.type,i=(()=>{if(De.has(r))return t.z.string();if(Oe.has(r))return t.z.number().finite();if(ke.has(r))return t.z.boolean();if(Ae.has(r))return ze;if(je.has(r))return Be;if(Me.has(r))return Ve;if(Ne.has(r)||Pe.has(r)){let n=E(e);return n.length>0?t.z.enum(n):t.z.string()}return Fe.has(r)?n===`expanded`?t.z.union([qe,t.z.record(t.z.string(),t.z.unknown())]):qe:Ie.has(r)?n===`expanded`?t.z.union([Ge,We]):Ge:r===`location`?He:r===`address`?Ue: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 Re(e)?t.z.array(i):i}function Ye(e){return typeof e==`object`&&!!e&&!!e.dialect&&typeof e.source==`string`}function Xe(e){return Ye(e)?`expression`:Ee(e)?`token`:`literal`}function Ze(e,t){let n=Je(e,`stored`).safeParse(t);return n.success?{ok:!0}:{ok:!1,detail:n.error.issues[0]?.message??`invalid value`}}var Qe=new Set([`datetime`,`date`,`time`]);function $e(e,t){if(!Ee(t))return null;let n=we(t)?Ce:w,r=e.name??`<unnamed>`;if(Re(e))return`Field "${r}" (${e.type}, multi-value): the default ${JSON.stringify(t)} is the runtime token \`${n}\`, which resolves to a single scalar \u2014 the engine's insert-time resolution assigns one value (applyFieldDefaults) and a physical column DEFAULT is one value; neither produces the array a multi-value field stores. Make the field single-valued, or write a literal array default.`;if(n===Ce)return Qe.has(e.type)?null:`Field "${r}" (${e.type}): the default ${JSON.stringify(t)} is the runtime token \`NOW()\` \u2014 the insert-time clock, resolved by the engine and by the SQL column DEFAULT into a temporal stored form \u2014 and a \`${e.type}\` field has no such form. It is legal only on \`datetime\`, \`date\`, or \`time\`. Use one of those temporal types, or write a literal value this field can store. (Before this gate the engine silently intercepted the token even here and stored an ISO instant \u2014 an interception nobody chose; it is refused instead.)`;if(e.type===`user`||e.type===`lookup`&&e.reference===T.USER)return null;let i=e.type===`lookup`?` (this lookup targets ${e.reference?`\`${e.reference}\``:`no declared object`}, not \`sys_user\`)`:``;return`Field "${r}" (${e.type}): the default ${JSON.stringify(t)} is the runtime token \`current_user\` \u2014 resolved by the engine to the acting user's \`sys_user.id\` at insert time \u2014 and a \`${e.type}\` field cannot hold one${i}. It is legal only on a \`user\` field or a \`lookup\` with \`reference: 'sys_user'\` (#4560 records what happens when that id lands anywhere else). Use one of those, or write a literal record id.`}var et={currentuser:w,"current-user":w,"current user":w,"{current_user}":w,current_user_id:w,"{current_user_id}":w,now:Ce,"{now}":Ce,current_datetime:Ce,current_time:Ce};function tt(e){if(typeof e!=`string`)return;let t=e.trim().toLowerCase();if(!Ee(e))return et[t]}var nt={AED:2,AFN:0,ALL:0,AMD:2,ANG:2,AOA:2,ARS:2,AUD:2,AWG:2,AZN:2,BAM:2,BBD:2,BDT:2,BGN:2,BHD:3,BIF:0,BMD:2,BND:2,BOB:2,BRL:2,BSD:2,BTN:2,BWP:2,BYN:2,BZD:2,CAD:2,CDF:2,CHF:2,CLP:0,CNY:2,COP:0,CRC:2,CUC:2,CUP:2,CVE:2,CZK:2,DJF:0,DKK:2,DOP:2,DZD:2,EGP:2,ERN:2,ETB:2,EUR:2,FJD:2,FKP:2,GBP:2,GEL:2,GHS:2,GIP:2,GMD:2,GNF:0,GTQ:2,GYD:2,HKD:2,HNL:2,HRK:2,HTG:2,HUF:0,IDR:0,ILS:2,INR:2,IQD:0,IRR:0,ISK:0,JMD:2,JOD:3,JPY:0,KES:2,KGS:2,KHR:2,KMF:0,KPW:0,KRW:0,KWD:3,KYD:2,KZT:2,LAK:0,LBP:0,LKR:2,LRD:2,LSL:2,LYD:3,MAD:2,MDL:2,MGA:0,MKD:2,MMK:0,MNT:2,MOP:2,MRU:2,MUR:2,MVR:2,MWK:2,MXN:2,MYR:2,MZN:2,NAD:2,NGN:2,NIO:2,NOK:2,NPR:2,NZD:2,OMR:3,PAB:2,PEN:2,PGK:2,PHP:2,PKR:0,PLN:2,PYG:0,QAR:2,RON:2,RSD:2,RUB:2,RWF:0,SAR:2,SBD:2,SCR:2,SDG:2,SEK:2,SGD:2,SHP:2,SLE:2,SLL:0,SOS:0,SRD:2,SSP:2,STN:2,SVC:2,SYP:0,SZL:2,THB:2,TJS:2,TMT:2,TND:3,TOP:2,TRY:2,TTD:2,TWD:2,TZS:2,UAH:2,UGX:0,USD:2,UYU:2,UZS:2,VES:2,VND:0,VUV:0,WST:2,XAF:0,XCD:2,XCG:2,XDR:2,XOF:0,XPF:0,XSU:2,YER:0,ZAR:2,ZMW:2,ZWG:2,ZWL:2};function D(e){return nt[e.toUpperCase()]}function rt(e,t){let n=D(e);if(n!==void 0&&n!==t)return`currency ${e.toUpperCase()} has ${n} fraction digits; \`precision: ${t}\` contradicts it \u2014 the amount would render minor-unit digits the currency does not have, or drop digits it does (ISO 4217 / CLDR currencyData). Declare \`precision: ${n}\`, or omit \`precision\` and let renderers derive the width from the currency. Codes outside CLDR (crypto/custom) are not checked, and a field in \`dynamic\` currencyMode has no single currency to check against.`}var O=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(`.`)),it=`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.`,at=n(()=>A({surface:`this select option`,history:it,aliases:{text:`label`,name:`label`,title:`label`,key:`value`,id:`value`,isDefault:`default`,selected:`default`,colour:`color`,visible:`visibleWhen`,showWhen:`visibleWhen`},guidanceSets:[de]},{label:t.z.string().describe(`Display label (human-readable, any case allowed)`),value:b.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:C.optional().describe("Per-option visibility predicate (CEL) — option is offered only when TRUE (else omitted). Env: the live `record` plus the host predicate scope, which binds `current_user` — wider than field-level visibleWhen, which has no `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 ot=n(()=>A({surface:`this currency configuration`,history:it,aliases:{decimals:`precision`,scale:`precision`,mode:`currencyMode`,currency:`defaultCurrency`,code:`defaultCurrency`,isoCode:`defaultCurrency`}},{precision:t.z.number().int().min(0).max(10).optional().meta({description:`Decimal precision (default: 2)`,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)`)}).superRefine((e,t)=>{if(e.precision===void 0||e.currencyMode!==`fixed`)return;let n=rt(e.defaultCurrency,e.precision);n!==void 0&&t.addIssue({code:`custom`,path:[`precision`],message:n})}).overwrite(e=>({precision:e.precision??2,currencyMode:e.currencyMode,defaultCurrency:e.defaultCurrency})));n(()=>t.z.object({value:t.z.number().describe(`Monetary amount`),currency:t.z.string().length(3).describe(`Currency code (ISO 4217)`)}));var k=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).`:``}`},st=n(()=>t.z.union([t.z.boolean(),t.z.literal(`global`),t.z.literal(`organization`)],{error:k}));function ct(){let e={},t={};for(let[n,r]of Object.entries(xe))r.to?e[n]=r.to:r.why&&(t[n]=r.why);return{aliases:e,guidance:t}}var lt=n(()=>A({surface:`this field`,history:it,aliases:{...ct().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`,showWhen:`visibleWhen`,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:{...ct().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).",visible:"`visible` is not a field key, and which key you want depends on the form: a static boolean is `hidden` — INVERTED, so `visible: false` is `hidden: true` — while a per-record CEL predicate is `visibleWhen` (shown only when TRUE). Its siblings are `readonlyWhen` and `requiredWhen`."}},{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:O.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:st.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 applied on INSERT when the field is omitted or null (`''` is a real value, not absence). Three legal shapes (#7127), discriminated in the engine's own order: a CEL Expression envelope `{ dialect: 'cel', source: 'today()' }` (accepted structurally; result type is a runtime concern); a runtime TOKEN — `NOW()` on `datetime`/`date`/`time` only, `current_user` on `user` or `lookup` with `reference: 'sys_user'` only, neither on a multi-value field; or a LITERAL, which must satisfy this field's own stored value contract (ADR-0104 D1 `valueSchemaFor`). Anything else is refused at parse time with a prescriptive message."),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`),useGrouping:t.z.boolean().optional().describe("Digit-grouping presentation hint for `number` fields (#7768) — maps to `Intl.NumberFormat`'s `useGrouping`. Absent = renderer decides (interim heuristic today, locale default eventually); `false` = author opts out of grouping (e.g. a year or other ordinal/identifier integer); `true` = author pins grouping on."),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(at).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(),A({surface:`this lookup column`,history:it,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(A({surface:`this lookup filter`,history:it,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(),A({surface:`this dependsOn entry`,history:it,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:C.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:A({surface:`this roll-up summary`,history:it,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:p.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:ot.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:C.optional().describe("Predicate (CEL) — field is shown only when TRUE (else hidden). e.g. P`record.type == 'invoice'`"),readonlyWhen:C.optional().describe("Predicate (CEL) — field is read-only when TRUE. e.g. P`record.status == 'paid'`"),requiredWhen:C.optional().describe("Predicate (CEL) — field is required when TRUE. The only slot; the `conditionalRequired` alias was removed in protocol 17 (#3855)."),conditionalRequired:v("`conditionalRequired` was removed in @objectstack/spec 17 (#3855) — use `requiredWhen`. Rename the key; the value (a CEL predicate) is unchanged. Run `os migrate meta --from 16` to rewrite existing sources 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`),internal:t.z.boolean().optional().describe("[#7728] Never return this field's value on the generic data path — the engine OMITS the key from `find`/`findOne` results, the 201 create body and the by-id update body, on the default projection AND when a client names the field in `?select=`. Storage, filtering and indexing are untouched, so a server-side verifier can still match on the column and a purpose-built mint route can still return the value once at creation. The read protection for ADR-0100's third credential channel (auth-subsystem one-way hashes on `text` columns). Omission, not masking: a mask signals 'a value is set', which carries no information on a `required` column."),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 on BOTH paths: `isSystem` writes (seed replay, migration). Exempt on the UPDATE path ONLY: an opt-in "historical" import (`preserveAudit`, #3493) — which admits a whitelist (the audit/timestamp family plus author-declared business `readonly` fields). On INSERT the exemption does NOT apply (#6640): a non-system create that requests `preserveAudit` still has its readonly fields stripped, and is warned loudly that the exemption is UPDATE-only — replaying archival readonly facts on create requires a system context. 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().meta({description:"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). Omitted on an `autonumber` field ⇒ the contract default `{0000}` (#6555).",default:Se}),externalId:t.z.boolean().default(!1).describe(`Is external ID for upsert operations`),...y}).superRefine((e,t)=>{if(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)."}),e.type===`currency`&&e.precision!==void 0&&e.currencyConfig?.currencyMode===`fixed`){let n=rt(e.currencyConfig.defaultCurrency,e.precision);n!==void 0&&t.addIssue({code:`custom`,path:[`precision`],message:n})}let n=e.defaultValue;if(n==null)return;let r=JSON.stringify(n)??String(n),i=Xe(n);if(i===`expression`)return;if(i===`token`){let r=$e({type:e.type,multiple:e.multiple,options:e.options,name:e.name,reference:e.reference},n);r!==null&&t.addIssue({code:`custom`,path:[`defaultValue`],message:r});return}let a=Ze({type:e.type,multiple:e.multiple,options:e.options},n);if(!a.ok){let i=tt(n),o=i===void 0?``:` Did you mean the runtime token \`${i}\`? Near-miss spellings are never accepted as tokens (a genuinely-intended literal must stay storable) \u2014 write the exact token, or a valid literal.`;t.addIssue({code:`custom`,path:[`defaultValue`],message:`Field "${e.name??`<unnamed>`}" (${e.type}): the default ${r} cannot satisfy this field's own stored value contract \u2014 ${a.detail??`invalid value`}. The engine stores a literal default VERBATIM at insert (applyFieldDefaults), so this would seed data the field type cannot hold, surfacing far from the cause. Write the default in the field's stored value shape, or use one of the other legal shapes: a runtime token (\`NOW()\` on \`datetime\`/\`date\`/\`time\`; \`current_user\` on \`user\` or \`lookup\` with \`reference: 'sys_user'\`) or a CEL Expression envelope ({ dialect: 'cel', source: '\u2026' }).${o}`})}})),ut=e=>e.toLowerCase().replace(/[_\-\s]/g,``);function dt(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 ft=e=>e.toLowerCase().replace(/[-\s]/g,`_`);function pt(e,t,n=3,r=3){let i=ft(e);return t.map(t=>({value:t,distance:dt(i,ft(t)),cased:dt(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 mt(e,t){return e.keys instanceof RegExp?t.search(e.keys)!==-1:e.keys.includes(t)}function ht(e){let{surface:t,knownKeys:n,guidance:r={},guidanceSets:i=[],history:a}=e,o={};for(let[t,n]of Object.entries(e.aliases??{}))o[ut(t)]=n;return e=>{if(e.code!==`unrecognized_keys`)return;let s=e.keys??[],c=[],l=[],u=new Set;for(let e of s){let t=r[e];if(t){l.push(t);continue}let a=i.find(t=>mt(t,e));if(a){u.has(a)||(u.add(a),l.push(a.prescription));continue}let s=Math.max(2,Math.floor(e.length/3)),d=o[ut(e)]??pt(e,n,s,1)[0];d&&d!==e&&c.push(`\`${e}\` \u2192 \`${d}\``)}let d=`Unrecognized key(s) on ${t}: ${s.map(e=>`\`${e}\``).join(`, `)}.`;return c.length&&(d+=` Did you mean ${c.join(`, `)}?`),l.length&&(d+=`
13
- ${l.map(e=>` \u2022 ${e}`).join(`
14
- `)}`),`${d} ${a}`}}function gt(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 gt(n.innerType,t+1);default:return!1}}function _t(){let e=_t;return e.list??=[]}function vt(e,t){let{surface:n,history:r,aliases:i,guidance:a,guidanceSets:o,extraKeys:s=[],retiredForms:c}=e,l;return _t().push({options:e,shape:t}),e=>{if(c&&e.code===`invalid_type`){let t=typeof e.input==`string`?c[e.input]:void 0;if(t)return t}return(l??=ht({surface:n,knownKeys:[...Object.keys(t).filter(e=>!gt(t[e])),...s],history:r,aliases:i,guidance:a,guidanceSets:o}))(e)}}function A(e,n){return t.z.object(n,{error:vt(e,n)}).strict()}var yt=n(()=>A({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`)})),bt=" was removed from `AggregationFunction` in @objectstack/spec 17 (#6188, ADR-0049 enforce-or-remove) — no SQL backend ever compiled it. `SqlDriver.mapAggregateFunc` and `RemoteTransport.aggregate` each lower the same set of functions and refuse the rest, and the v1 dataset runtime had to subtract this one by name to stop it reaching a `COUNT(*)` fallback that returns a row count in place of the value asked for. On the backend family this platform targets it was a declaration that could only fail. ",xt="There is no replacement in the query vocabulary: read the rows with an ordinary `fields` query and shape them in the caller, or model the roll-up as a stored field. It returns only WITH a portable lowering — ADR-0049's enforce leg, implementation first. Run `os migrate meta --from 16` to rewrite existing sources automatically.",St="`array_agg`"+bt+`Delete the aggregation, or the dataset measure that declared it. `+xt,Ct="`string_agg`"+bt+"Its dialect divergence is the widest of the family — the delimiter is a second argument in PostgreSQL, a `SEPARATOR` clause in MySQL and a differently-named function in SQL Server — so there was never one shape to lower it to. Delete the aggregation, or the dataset measure that declared it. "+xt,wt=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`],{error:e=>{if(e.input===`array_agg`)return St;if(e.input===`string_agg`)return Ct}}),Tt=t.z.enum([`day`,`week`,`month`,`quarter`,`year`]),j=n(()=>t.z.union([t.z.string(),t.z.object({field:t.z.string().describe(`Field to group by`),dateGranularity:Tt.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`)})])),M="`query.aggregations[].distinct` was removed in @objectstack/spec 17 (#6815, ADR-0049) — exactly ONE of the six faces that read an aggregation honoured it. The objectql in-memory fallback deduplicated the values before applying the function, while `driver-sql`, `driver-turso`, `driver-mongodb`, `driver-memory` and the service-analytics SQL builder all ignored it — so `{ function: 'sum', field: 'amount', distinct: true }` answered a DEDUPLICATED sum when the engine fell back in memory and an ordinary sum on every SQL datasource: one query, two numbers, chosen by which backend happened to serve it. Both answers are plausible, so nothing surfaced the divergence. Delete the key. For a deduplicated COUNT the live spelling is the `count_distinct` aggregation function, which every SQL face compiles to `COUNT(DISTINCT field)` (#6409) and the in-memory fallback computes identically. `SUM(DISTINCT …)` / `AVG(DISTINCT …)` get no replacement: no backend ever computed them here, and a per-row measure that needs deduplicating is a modelling problem to fix in the data, not a flag on the read.",Et=n(()=>t.z.object({function:wt.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (optional for COUNT(*))`),alias:t.z.string().describe(`Result column alias`),distinct:v(M),filter:p.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.")})),Dt="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 data with `expand` — `expand: { owner_id: { object: 'user', fields: ['name'] } }` — whose nested query names the related columns you want. A dotted `fields` path is NOT the replacement: no driver ever resolved one and the ingress refuses it (`400 INVALID_FIELD`, #7532). Keep the foreign-key column in your own projection (`fields: ['title', 'owner_id']`) — the relation is carried by that key, so projecting it away leaves expansion nothing to resolve. `alias` has no replacement here; an aliased projection is an `aggregations` or `windowFunctions` entry, which carry their own `alias`.",Ot=t.z.string({error:e=>e.code===`invalid_type`&&typeof e.input==`object`&&e.input!==null&&!Array.isArray(e.input)?Dt:void 0}),kt="`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_id: { object: 'user', fields: ['name'] } }` — which the engine resolves via batch $in queries, and whose nested query selects the related record's own columns. Keep the foreign key in your own projection (`fields: ['title', 'owner_id']`): the relation is carried by that column, so projecting it away leaves expansion nothing to resolve. A dotted `fields` path is NOT a replacement — no driver ever resolved one and the ingress refuses it (`400 INVALID_FIELD`, #7532).",At='`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.',jt="`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.",Mt="`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`.",Nt=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).`)})),Pt=t.z.object({object:t.z.string().describe(`Object name (e.g. account)`),fields:t.z.array(Ot).optional().describe("Fields to retrieve — names of the queried object's OWN columns. A dotted path (`owner.name`) is not a projection: no driver resolves one, and the ingress refuses it with `400 INVALID_FIELD` (#7532). Related data is read with `expand`, whose nested QueryAST both filters (`where`) and selects (`fields`) the related record's columns. The projection must RETAIN the foreign-key column: `fields: ['title']` with `expand: 'project_id'` resolves nothing, because the relation is carried by that key — add `'project_id'` and it works. Where the value is wanted on the queried object itself, denormalise it onto that object (a stored field, written when the source changes), the same remedy the sort axis prescribes (#6924)."),where:p.optional().describe(`Filtering criteria (WHERE)`),search:t.z.union([t.z.string(),Nt]).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(yt).optional().describe(`Sorting instructions (ORDER BY)`),limit:t.z.number().optional().describe(`Max records to return (LIMIT)`),offset:t.z.number().optional().describe(`Records to skip (OFFSET)`),top:t.z.number().optional().describe(`Alias for limit (OData compatibility)`),cursor:v(At),joins:v(kt),aggregations:t.z.array(Et).optional().describe(`Aggregation functions`),groupBy:t.z.array(j).optional().describe("GROUP BY targets (strings or `{field, dateGranularity?}` objects for date bucketing)"),having:p.optional().describe(`HAVING — filter over the AGGREGATED rows (aggregation aliases + groupBy projections); applied engine-side after aggregation`),windowFunctions:v(Mt),distinct:v(jt)}),Ft=n(()=>Pt.extend({expand:t.z.lazy(()=>t.z.record(t.z.string(),Ft)).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.")})),It=t.z.enum([`validation`,`authentication`,`authorization`,`not_found`,`conflict`,`rate_limit`,`server`,`external`,`maintenance`]),Lt=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(`.`)),Rt={validation:400,authentication:401,authorization:403,not_found:404,conflict:409,rate_limit:429,server:500,external:502,maintenance:503},zt={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 Bt(e){return zt[e]??(e>=500?`INTERNAL_ERROR`:`VALIDATION_ERROR`)}var Vt=t.z.enum([`no_retry`,`retry_immediate`,`retry_backoff`,`retry_after`]),Ht=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.max_scale.min_items.max_items.invalid_option.invalid_value.reference_not_found.reference_ambiguous.rule_violation.json_schema_violation.invalid_initial_state.invalid_transition`.split(`.`)),Ut=n(()=>t.z.object({field:t.z.string().describe(`Field path (supports dot notation)`),code:Ht.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 })`)})),Wt=n(()=>t.z.object({code:Lt.describe(`Machine-readable error code`),message:t.z.string().describe(`Human-readable error message`),category:It.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:Vt.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(Ut).optional().describe(`One entry per offending value`),fieldErrors:v("`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`)})),Gt=n(()=>t.z.object({success:t.z.literal(!1).describe(`Always false for error responses`),error:Wt.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`)})),Kt={"@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.CONFLICT.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`,`PACKAGE_DELETE_PARTIAL`,`PROJECT_MEMBERSHIP_REQUIRED`,`RECORD_GONE`,`ROUTE_NOT_FOUND`,`SIGN_IN_REQUIRED`,`UNSUPPORTED`,`VALIDATION_FAILED`,`WRITABLE_PACKAGE_REQUIRED`,`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_FIELD_BULK_WRITE_REFUSED`,`FILE_NOT_FOUND`,`INTERNAL`,`INVALID_REQUEST`,`INVALID_RESUME_TOKEN`,`UPLOAD_SESSION_EXPIRED`,`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`,`ELIGIBILITY_UNEVALUABLE`,`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`,`RECORD_NOT_ELIGIBLE`,`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`,`OBJECT_OVERLAY_PACKAGE_MISMATCH`,`OBJECT_PACKAGE_DISABLED`,`ROLLED_BACK`,`TENANT_SCOPE_REQUIRED`,`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`,`INVALID_METADATA`,`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_NEVER_SENT`,`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_CRYPTO_UNAVAILABLE`,`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":[`INVALID_METADATA`,`SUGGESTION_NOT_FOUND`,`SUGGESTION_STATE`],"@objectstack/spec":[`CONNECTOR_UPSTREAM_UNAVAILABLE`,`EXTERNAL_SCHEMA_MISMATCH`,`EXTERNAL_SCHEMA_MODE_VIOLATION`,`EXTERNAL_WRITE_FORBIDDEN`]},qt=Object.freeze([...new Set(Object.values(Kt).flat())].sort()),Jt=t.z.enum([...Lt.options,...qt]),Yt={BAD_REQUEST:400,UNAUTHORIZED:401,PAYMENT_REQUIRED:402,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,NOT_ACCEPTABLE:406,PROXY_AUTHENTICATION_REQUIRED:407,REQUEST_TIMEOUT:408,CONFLICT:409,GONE:410,LENGTH_REQUIRED:411,PRECONDITION_FAILED:412,PAYLOAD_TOO_LARGE:413,CONTENT_TOO_LARGE:413,URI_TOO_LONG:414,UNSUPPORTED_MEDIA_TYPE:415,RANGE_NOT_SATISFIABLE:416,EXPECTATION_FAILED:417,MISDIRECTED_REQUEST:421,UNPROCESSABLE_ENTITY:422,UNPROCESSABLE_CONTENT:422,LOCKED:423,FAILED_DEPENDENCY:424,TOO_EARLY:425,UPGRADE_REQUIRED:426,PRECONDITION_REQUIRED:428,TOO_MANY_REQUESTS:429,REQUEST_HEADER_FIELDS_TOO_LARGE:431,UNAVAILABLE_FOR_LEGAL_REASONS:451,INTERNAL_SERVER_ERROR:500,NOT_IMPLEMENTED:501,BAD_GATEWAY:502,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504,HTTP_VERSION_NOT_SUPPORTED:505,VARIANT_ALSO_NEGOTIATES:506,INSUFFICIENT_STORAGE:507,LOOP_DETECTED:508,NOT_EXTENDED:510,NETWORK_AUTHENTICATION_REQUIRED:511};function Xt(e){let t=Yt[e];if(t!==void 0){let n=zt[t];if(n!==void 0&&n!==e)return n}let n=e.split(`_`);for(let t of Lt.options){if(t===e)continue;let r=new Set(t.split(`_`));if(n.every(e=>r.has(e)))return t}}var Zt=t.z.object({code:t.z.string().regex(/^[A-Z][A-Z0-9_]*$/).describe(`The registered extension code the waiver keeps admissible`),shadows:Lt.describe(`The standard-catalog member whose condition the code re-spells`),reason:t.z.string().min(1).describe(`Why the synonym stays registered — recorded so admission is a decision, not drift`)}),Qt=[{code:`CONFLICT`,shadows:`RESOURCE_CONFLICT`,reason:`Pre-gate synonym on the wire (respondSharingError 409 arm; registered by #8111). Wire value kept; consolidation deferred per #8211.`},{code:`FORBIDDEN`,shadows:`PERMISSION_DENIED`,reason:`Pre-gate synonym on the wire from @objectstack/rest, plugin-sharing and plugin-approvals. Wire value kept; consolidation deferred per #8211.`},{code:`INTERNAL`,shadows:`INTERNAL_ERROR`,reason:`Pre-gate synonym on the wire from five packages. Wire value kept; consolidation deferred per #8211.`},{code:`NOT_FOUND`,shadows:`RESOURCE_NOT_FOUND`,reason:`Pre-gate synonym on the wire from @objectstack/rest and plugin-sharing. Wire value kept; consolidation deferred per #8211.`},{code:`UNAUTHORIZED`,shadows:`UNAUTHENTICATED`,reason:`Pre-gate synonym (401 reason phrase) on the wire from @objectstack/rest — surfaced by the detector when the #8211 gate landed, beyond the four the card named; same class, same grandfather rationale. Wire value kept; consolidation deferred per #8211.`}];function $t(e=Kt,t=Qt){let n=new Map(t.map(e=>[e.code,e.shadows])),r=[];for(let[t,i]of Object.entries(e))for(let e of i){let i=Xt(e);i!==void 0&&n.get(e)!==i&&r.push({package:t,code:e,shadows:i})}return r}var en=n(()=>t.z.object({code:Jt.describe(`Error code (e.g. VALIDATION_ERROR; StandardErrorCode ∪ the ledger the serving side registers — ERROR_CODE_LEDGER for framework packages)`),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`)}));function tn(e){let n=[...Lt.options,...e];return en.extend({code:t.z.enum(n).describe(`Error code (StandardErrorCode ∪ the ledger this consumer registered)`)})}var N=n(()=>t.z.object({success:t.z.boolean().describe(`Operation success status`),error:en.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`)})),nn=new Set([`success`,`data`,`error`,`meta`]);function rn(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))nn.has(e)||n.push(`stray top-level key \`${e}\` \u2014 the payload belongs under \`data\``);return n}var P=n(()=>t.z.record(t.z.string(),t.z.unknown()).describe(`Key-value map of record data`)),an=n(()=>t.z.object({data:P.describe(`Record data to insert`)})),on=n(()=>t.z.object({data:P.describe(`Partial record data to update`)})),sn=n(()=>t.z.object({records:t.z.array(P).describe(`Array of records to process`),allOrNone:t.z.boolean().default(!0).describe(`If true, rollback entire transaction on any failure`)})),cn=n(()=>t.z.intersection(Ft,t.z.object({format:t.z.enum([`csv`,`json`,`xlsx`]).default(`csv`)}))),ln=n(()=>N.extend({data:P.describe(`The requested or modified record`)})),un=n(()=>N.extend({data:t.z.array(P).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`)})),dn=n(()=>t.z.object({id:t.z.string().describe(`Record ID`)})),fn=n(()=>t.z.object({id:t.z.string().optional().describe(`Record ID if processed`),success:t.z.boolean(),errors:t.z.array(en).optional(),index:t.z.number().optional().describe(`Index in original request`),data:t.z.unknown().optional().describe(`Result data (e.g. created record)`)})),pn=n(()=>N.extend({data:t.z.array(fn).describe(`Results for each item in the batch`)})),mn=n(()=>N.extend({id:t.z.string().describe(`ID of the deleted record`)})),hn={create:{input:an,output:ln},delete:{input:dn,output:mn},get:{input:dn,output:ln},update:{input:on,output:ln},list:{input:Ft,output:un},bulkCreate:{input:sn,output:pn},bulkUpdate:{input:sn,output:pn},bulkUpsert:{input:sn,output:pn},bulkDelete:{input:t.z.object({ids:t.z.array(t.z.string())}),output:pn}},gn=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`)})),_n=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`)})),vn=n(()=>t.z.object({preventNPlusOne:t.z.boolean().describe(`Enable N+1 query detection and prevention`),dataLoader:gn.optional().describe(`DataLoader batch loading configuration`),batchStrategy:_n.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`)})),F=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."),yn=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`.")),bn=n(()=>t.z.object({url:t.z.string().describe(`API endpoint URL`),method:yn.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`)})),xn=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(F).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`)})),Sn=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`)})),Cn=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`)})),wn=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 — NOT EXECUTED in 17.x, and publish REJECTS the key: there is no transformation-function registry anywhere in the platform, so it stays in the frozen vocabulary and is refused rather than parsed and ignored (#5040 E7). A mapping entry moves and renames fields by dot path and nothing more — shape the value where it is produced instead (a flow endpoint whose flow computes it, or a formula field on the object)`)})),Tn="This is the metadata layer's own storage bookkeeping, not endpoint vocabulary. It is written onto the stored ROW by `register` / `publishPackage` and peeled off before this schema sees a body (#5309), so writing it on a declaration configures nothing. Remove it — publication state is managed by `objectstack publish`, not authored.",En=A({surface:`this API endpoint`,history:"Until #5384 closed this shape these were dropped silently — the endpoint still published and served, minus whatever the key was meant to configure (a `cacheTTL` / `objectParam` typo cost the whole policy or projection, with `os validate` green).",aliases:{auth:`authRequired`,authentication:`authRequired`,requiresAuth:`authRequired`,cacheTTL:`cacheTtl`,ttl:`cacheTtl`,cache:`cacheTtl`,rateLimiting:`rateLimit`,throttle:`rateLimit`,id:`name`,url:`path`,route:`path`,endpoint:`path`,uri:`path`,verb:`method`,httpMethod:`method`,handler:`target`,objectParam:`objectParams`,inputMappings:`inputMapping`,outputMappings:`outputMapping`,requestMapping:`inputMapping`,responseMapping:`outputMapping`,title:`summary`},guidance:{namespace:"`namespace` is not an endpoint key. Under ADR-0121 D2 the namespace segment of `path` comes from the stack's `manifest.namespace` and has no per-endpoint override — declare it there. Only the subpath of `/api/v1/apps/<manifest.namespace>/<subpath>` is yours to name here.",package:Tn,packageId:Tn,state:Tn,version:Tn,publishedAt:Tn,publishedBy:Tn,publishedDefinition:Tn}},{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:F.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 — only 'object_operation' and 'flow' EXECUTE in 17.x. 'script' and 'proxy' stay in the frozen vocabulary (#5040) and are rejected at publish, not parsed and ignored: express script logic as a flow whose script node runs your registered function, and an outbound call as a flow using a declared connector`),target:t.z.string().describe("Target Flow ID or Script Name or Proxy URL, per `type` — but only the Flow ID is reachable in 17.x, since publish rejects `type: 'script'` and `type: 'proxy'` (an `object_operation` endpoint is addressed by `objectParams.object` / `.operation`; neither the publish gate nor the executor reads `target` for that type)"),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(wn).optional().describe(`Map Request Body to Internal Params`),outputMapping:t.z.array(wn).optional().describe(`Map Internal Result to Response Body`),authRequired:t.z.boolean().default(!0).describe(`Require authentication`),rateLimit:Sn.optional().describe(`Rate limiting policy`),cacheTtl:t.z.number().optional().describe(`Response cache TTL in seconds`),...y});function Dn(e){let t=String(e??``);return t.length>1&&t.endsWith(`/`)?t.slice(0,-1):t}var On=Object.assign(En,{create:e=>e}),kn=`apps`,An=`/api/v1`;function jn(e){return`${An}/${kn}/${e}/`}var Mn=new Set([`__proto__`,`prototype`,`constructor`]),Nn=new Set([`find`,`get`,`delete`]),Pn=[`inputMapping`,`outputMapping`],Fn=/^[a-z][a-z0-9_]{1,19}$/;function In(e){if(typeof e!=`string`||e===``)return;let t=e.split(`.`);for(let e of t)if(e===``||Mn.has(e))return;return t}function Ln(e,t){return e.length>t.length?!1:e.every((e,n)=>t[n]===e)}var Rn="`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 zn(e,t){if(!e||e.length===0)return[];let n=[],r=typeof t.namespace==`string`?t.namespace:void 0,i=r!==void 0&&Fn.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 \`${An}/${kn}/<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?jn(r):void 0,o=new Map;for(let t=0;t<e.length;t++){let r=e[t],i=Hn(r,`Endpoint '${r.name}' (apis[${t}])`,(...e)=>[`apis`,t,...e],a,o);if(i){n.push(i);continue}o.set(Vn(r),{index:t,name:r.name})}return n}function Bn(e){return Hn(e,`Endpoint '${e.name}'`,(...e)=>e,void 0,new Map)}function Vn(e){return`${e.method.toUpperCase()} ${Dn(e.path)}`}function Hn(e,t,n,r,i){return I(e,t,n,r)??Un(e,t,n)??Wn(e,t,n)??qn(e,t,n)??Jn(e,t,n,i)}function I(e,t,n,r){if(r===void 0)return;let i=e.path,a=Dn(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 Un(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 Wn(e,t,n){for(let r of Pn){let i=Gn(e,r,t,n);if(i)return i}return Kn(e,t,n)}function Gn(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(!In(o.source))return{path:r(t,e,`source`),message:`${n} declares ${s}.source '${String(o.source)}', which is not a usable field path. ${Rn}`};let c=In(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. ${Rn}`};let l=a.find(e=>Ln(e.segments,c)||Ln(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 Kn(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||!Nn.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 qn(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 Jn(e,t,n,r){let i=Vn(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 Yn=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`),Xn=n(()=>t.z.object({enabled:t.z.boolean(),status:Yn,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`)})),Zn=`__serviceInfo`,Qn=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 $n(e){if(!e||typeof e!=`object`)return;let t=e[Zn];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 er=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`),datasources:t.z.string().optional().describe(`e.g. /api/v1/datasources — base for the datasources/:name/external/* federation-admin family; absent when no host mounts it`),email:t.z.string().optional().describe(`e.g. /api/v1/email — base for the email/send endpoint; absent when no host mounts it`),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`)})),tr=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).')),nr={production:`production`,sandbox:`sandbox`,development:`development`,test:`development`,staging:`sandbox`,preview:`sandbox`,trial:`sandbox`,prod:`production`,dev:`development`};function rr(e){let t=typeof e==`string`?e.trim().toLowerCase():``;return t===``?`production`:nr[t]??`development`}var ir=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`)),ar=Object.freeze(Object.keys(ir.shape)),or=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 sr(){return Object.fromEntries(Object.entries(ir.shape).map(([e,t])=>{let n=t.description;return[e,n?or.describe(n):or]}))}var cr=n(()=>t.z.object({name:t.z.string(),version:t.z.string(),environment:tr,routes:er,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(),Xn).describe(`Per-service availability map keyed by CoreServiceName`),capabilities:t.z.object(sr()).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`)})),lr=n(()=>t.z.object({route:t.z.string().describe(`Route path pattern`),method:F.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`)})),ur=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(lr).describe(`Per-route health entries`)})),dr=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(`,`)),fr=t.z.enum([`data.record.created`,`data.record.updated`,`data.record.deleted`]),pr=t.z.enum([`data.records.updated`,`data.records.deleted`]),mr=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:dr.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`)})),hr=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:fr.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`)})),gr=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique event identifier`),type:pr.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`)})),_r=t.z.enum([`online`,`away`,`busy`,`offline`]),vr=t.z.enum([`created`,`updated`,`deleted`]),yr=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),status:_r.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)`)})),br=t.z.enum([`websocket`,`sse`,`polling`]),xr=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)`),Sr=n(()=>t.z.object({type:xr.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`)})),Cr=n(()=>t.z.object({id:t.z.string().uuid().describe(`Unique subscription identifier`),events:t.z.array(Sr).describe(`Array of events to subscribe to`),transport:br.describe(`Transport protocol to use`),channel:t.z.string().optional().describe(`Optional channel name for grouping subscriptions`)})),wr=n(()=>yr),Tr=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:vr.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`)})),Er=n(()=>t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable realtime synchronization`),transport:br.default(`websocket`).describe(`Transport protocol`),subscriptions:t.z.array(Cr).optional().describe(`Default subscriptions`)}).passthrough()),Dr=t.z.enum([`subscribe`,`unsubscribe`,`event`,`ping`,`pong`,`ack`,`error`,`presence`,`cursor`,`edit`]),Or=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")`)),kr=n(()=>t.z.object({subscriptionId:t.z.string().uuid().describe(`Unique subscription identifier`),events:t.z.array(Or).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`)})),Ar=n(()=>t.z.object({subscriptionId:t.z.string().uuid().describe(`Subscription ID to unsubscribe from`)})),jr=_r,Mr=n(()=>t.z.object({userId:t.z.string().describe(`User identifier`),sessionId:t.z.string().uuid().describe(`Unique session identifier`),status:jr.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`)})),Nr=n(()=>t.z.object({status:jr.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`)})),Pr=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`)})),Fr=t.z.enum([`insert`,`delete`,`replace`]),Ir=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:Fr.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)`)})),Lr=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`)})),L=t.z.object({messageId:t.z.string().uuid().describe(`Unique message identifier`),type:Dr.describe(`Message type`),timestamp:t.z.string().datetime().describe(`ISO 8601 datetime when message was sent`)}),Rr=n(()=>L.extend({type:t.z.literal(`subscribe`),subscription:kr.describe(`Subscription configuration`)})),zr=n(()=>L.extend({type:t.z.literal(`unsubscribe`),request:Ar.describe(`Unsubscribe request`)})),Br=n(()=>L.extend({type:t.z.literal(`event`),subscriptionId:t.z.string().uuid().describe(`Subscription ID this event belongs to`),eventName:S.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`)})),Vr=n(()=>L.extend({type:t.z.literal(`presence`),presence:Mr.describe(`Presence state`)})),Hr=n(()=>L.extend({type:t.z.literal(`cursor`),cursor:Pr.describe(`Cursor position`)})),Ur=n(()=>L.extend({type:t.z.literal(`edit`),operation:Ir.describe(`Edit operation`)})),Wr=n(()=>L.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`)})),Gr=n(()=>L.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`)})),Kr=n(()=>L.extend({type:t.z.literal(`ping`)})),qr=n(()=>L.extend({type:t.z.literal(`pong`),pingMessageId:t.z.string().uuid().optional().describe(`ID of ping message being responded to`)})),Jr=n(()=>t.z.discriminatedUnion(`type`,[Rr,zr,Br,Vr,Hr,Ur,Wr,Gr,Kr,qr])),Yr=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`)})),Xr=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`)})),Zr=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)`)})),Qr=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)`)})),$r=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`)})),ei=t.z.enum([`system`,`api`,`auth`,`static`,`webhook`,`plugin`]),ti=t.z.enum([`error`,`priority`,`first-wins`,`last-wins`]),ni=n(()=>t.z.object({method:F,path:t.z.string().describe(`URL Path pattern`),category:ei.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`)})),ri=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:xn.optional(),staticMounts:t.z.array(Cn).optional()})),ii=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`)})),ai=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(`.`))),oi=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`)})),si=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`)})})),ci=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`)})),li={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 `)}},ui=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:ci.optional().describe(`OData metadata configuration`)}).passthrough()),di=t.z.enum([`read`,`create`,`update`,`delete`,`transfer`,`restore`,`purge`,`export`]),fi=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.`),pi=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.`)})),mi=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(pi).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.`)})),hi=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:mi.optional().describe(`Row-level determination for the specific record under explanation; set only for record-grained requests.`)})),gi=200;n(()=>t.z.object({object:t.z.string(),operation:di,recordId:t.z.string().optional().describe(`Optional id of one concrete record to explain at row granularity; omitted = object-level (pre-C2) request. Mutually exclusive with recordIds.`),recordIds:t.z.array(t.z.string()).min(1).max(gi).optional().describe(`Batch of record ids (1–200) to answer at row granularity in one round trip; records[i] answers recordIds[i]. Mutually exclusive with recordId.`),userId:t.z.string().optional()}).superRefine((e,t)=>{e.recordId!==void 0&&e.recordIds!==void 0&&t.addIssue({code:`custom`,path:[`recordIds`],message:`recordId and recordIds are mutually exclusive — send one record as recordId, or the batch as recordIds, never both.`})}));var _i=n(()=>t.z.object({recordId:t.z.string().describe(`The concrete record id this verdict is about (echoes the request recordId or recordIds[i]).`),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); omitted for a missing record.`)}));n(()=>t.z.object({allowed:t.z.boolean(),object:t.z.string(),operation:di,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:fi.optional()}),layers:t.z.array(hi),readFilter:t.z.unknown().optional(),record:_i.optional().describe(`Row-level verdict for the specific record; set only for singular record-grained requests.`),records:t.z.array(_i).optional().describe(`Per-record verdicts for a batch request — records[i] answers recordIds[i]; set only when the request carried recordIds.`)}));var R=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(R).default([])}));var vi=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:fi.optional(),authGate:t.z.object({code:t.z.string(),message:t.z.string()}).optional().describe("ADR-0069 authentication-policy gate: present only while the principal is blocked from protected resources until they remediate (expired password, enforced MFA), absent for every healthy session. `code` is the stable machine code the client branches on (PASSWORD_EXPIRED / MFA_REQUIRED) and `message` is what the blocked user reads; both are required because the transport seam renders them as the 403 body. AUTHENTICATION, not authorization — it suspends access entirely rather than narrowing it, and nothing in the permission/RLS path reads it, while the allow-listed remediation endpoints stay reachable. Server-constructed only, never client-supplied; a guest/anonymous principal never carries one."),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().describe('Historical import: preserve the ORIGINAL audit timeline for this write instead of stamping it "now" (#3493). Opt-in and server-constructed only, never client-supplied. On the UPDATE path it admits a whitelist — the audit/timestamp family (created_at / created_by / updated_at / updated_by) plus author-declared business `readonly` fields — while platform-managed `system` columns (tenancy, generated) stay stripped. On INSERT the exemption does NOT apply (#6640): a create is stripped earlier, at the DataProtocol ingress, whose only exemption is `context.isSystem`, so a non-system create carrying `preserveAudit` still has those fields stripped and is warned (WARN) that the exemption is UPDATE-only — replaying archival readonly facts on create requires a system context. Permissions / RLS / field-level security are unaffected.'),oauthScopes:t.z.array(t.z.string()).optional(),accessToken:t.z.string().optional(),transaction:t.z.unknown().optional(),traceId:t.z.string().optional()})),yi=n(()=>t.z.union([t.z.record(t.z.string(),t.z.unknown()),p]).describe(`Data Engine query filter conditions`)),bi=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(yt)]).describe(`Sort order definition`)),z=n(()=>t.z.object({context:vi.partial().optional()})),xi=n(()=>z.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),p]).optional(),fields:t.z.array(Ot).optional(),orderBy:t.z.array(yt).optional(),limit:t.z.number().optional(),offset:t.z.number().optional(),top:t.z.number().optional(),cursor:v(At),search:t.z.union([t.z.string(),Nt]).optional(),searchFields:t.z.array(t.z.string()).optional(),expand:t.z.lazy(()=>t.z.record(t.z.string(),Ft)).optional(),distinct:v(jt)}).describe(`QueryAST-aligned query options for IDataEngine.find() operations`));n(()=>z.extend({filter:yi.optional(),select:t.z.array(t.z.string()).optional(),sort:bi.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 Si=n(()=>z.extend({returning:t.z.boolean().default(!0).optional()}).describe(`Options for DataEngine.insert operations`)),Ci="`update.options.upsert` was removed in @objectstack/spec 17 (#8057, ADR-0049) — it was declared and allowlisted but never implemented: no engine or driver path ever read it, so `{ upsert: true }` was accepted and silently dropped and the update stayed a plain update. Delete the key. Express create-if-absent explicitly: a by-id update whose id names no row throws RECORD_NOT_FOUND (#7867's not-found gate) rather than inserting, so read the row first (`findOne`) and call `insert` or `update` on what you find. A first-class upsert, if ever built, must reconcile with that gate by design rather than through this silent flag.",wi=n(()=>z.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),p]).optional(),upsert:v(Ci),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.update operations`)),Ti=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`,`primary_key`]).describe(`Why the fields were dropped: static readonly (#2948), a TRUE readonlyWhen predicate (#3042), or the primary-key strip of a payload id the engine ruled is not an identifier (#6437)`)}).describe(`A write-path strip event: caller-supplied fields legally dropped from the payload (#3407)`));n(()=>z.extend({filter:yi.optional(),upsert:v(Ci),multi:t.z.boolean().default(!1).optional(),returning:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.update operations`));var Ei=n(()=>z.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),p]).optional(),multi:t.z.boolean().default(!1).optional()}).describe(`QueryAST-aligned options for DataEngine.delete operations`));n(()=>z.extend({filter:yi.optional(),multi:t.z.boolean().default(!1).optional()}).describe(`Options for DataEngine.delete operations`));var Di=n(()=>z.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),p]).optional(),groupBy:t.z.array(j).optional().describe("GROUP BY targets (strings or `{field, dateGranularity?}` objects for date bucketing)"),aggregations:t.z.array(Et).optional(),having:p.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(()=>z.extend({filter:yi.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 Oi=n(()=>z.extend({where:t.z.union([t.z.record(t.z.string(),t.z.unknown()),p]).optional()}).describe(`QueryAST-aligned options for DataEngine.count operations`));n(()=>z.extend({filter:yi.optional()}).describe(`Options for DataEngine.count operations`)),n(()=>t.z.object({find:t.z.function().input(t.z.tuple([t.z.string(),xi.optional()])).output(t.z.promise(t.z.array(t.z.unknown()))),findOne:t.z.function().input(t.z.tuple([t.z.string(),xi.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()))]),Si.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()),wi.optional()])).output(t.z.promise(t.z.unknown())),delete:t.z.function().input(t.z.tuple([t.z.string(),Ei.optional()])).output(t.z.promise(t.z.unknown())),count:t.z.function().input(t.z.tuple([t.z.string(),Oi.optional()])).output(t.z.promise(t.z.number())),aggregate:t.z.function().input(t.z.tuple([t.z.string(),Di])).output(t.z.promise(t.z.array(t.z.unknown())))}).describe(`Standard Data Engine Contract`));var ki=[{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 Ai(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 ji=ki.filter(e=>e.canonical===`where`);function Mi(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 Ni={filter:yi.optional()};function Pi(e,t){let n={...e};return Ai(n,ji,e=>t.addIssue(Mi(e))),n}function Fi(e,t){let n={...e};return Ai(n,ki,e=>t.addIssue(Mi(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 Ii=xi.extend({...Ni,select:t.z.array(t.z.string()).optional(),sort:bi.optional(),skip:t.z.number().int().min(0).optional(),populate:t.z.array(t.z.string()).optional()}).transform((e,t)=>Fi(e,t)),Li=n(()=>t.z.object({method:t.z.literal(`find`),object:t.z.string(),query:Ii.optional()})),Ri=n(()=>t.z.object({method:t.z.literal(`findOne`),object:t.z.string(),query:Ii.optional()})),zi=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:Si.optional()})),Bi=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:wi.extend(Ni).transform((e,t)=>Pi(e,t)).optional()})),Vi=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:Ei.extend(Ni).transform((e,t)=>Pi(e,t)).optional()})),Hi=n(()=>t.z.object({method:t.z.literal(`count`),object:t.z.string(),query:Oi.extend(Ni).transform((e,t)=>Pi(e,t)).optional()})),Ui=n(()=>t.z.object({method:t.z.literal(`aggregate`),object:t.z.string(),query:Di.extend(Ni).transform((e,t)=>Pi(e,t))})),Wi=n(()=>t.z.object({method:t.z.literal(`execute`),command:t.z.unknown(),options:t.z.record(t.z.string(),t.z.unknown()).optional()})),Gi=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()),p]).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`,[Li,Ri,zi,Bi,Vi,Hi,Ui,Wi,Gi]).describe(`Virtual ObjectQL Request Protocol`));var Ki=t.z.enum([`create`,`update`,`upsert`,`delete`]),qi=n(()=>t.z.object({id:t.z.string().optional().describe(`Record ID (required for update/delete)`),data:P.optional().describe(`Record data (required for create/update/upsert)`),externalId:t.z.string().optional().describe(`External ID for upsert matching`)})),Ji=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. Default false: the first failure ENDS the run — records before it stay written (nothing is rolled back on this arm), and every record after it is reported `errors[0].code` NOT_ATTEMPTED rather than omitted, so `results` always covers all `total` records and `succeeded + failed === total` (#7539)."),validateOnly:v('`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.')})),Yi=n(()=>t.z.object({operation:Ki.describe(`Type of batch operation`),records:t.z.array(qi).describe(`Array of records to process (server caps the count — see batch.maxBatchSize)`),options:Ji.optional().describe(`Batch operation options`)})),Xi=n(()=>t.z.object({id:t.z.string().describe(`Record ID`),data:P.describe(`Fields to update`)})),Zi=n(()=>t.z.object({records:t.z.array(Xi).describe(`Array of records to update (server caps the count — see batch.maxBatchSize)`),options:Ji.optional().describe(`Update options`)})),Qi=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(en).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). A NON-atomic batch that stopped (the `continueOnError: false` default) marks its un-attempted tail with the same NOT_ATTEMPTED code — rows before the failure stay written and keep reporting success, since nothing was rolled back (#7539)."),data:P.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(Ti).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.")})),$i=n(()=>N.extend({operation:Ki.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(Qi).describe(`Detailed results for each record`)})),ea=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:Ji.optional().describe(`Delete options`)})),ta={batchOperation:{input:Yi,output:$i},updateMany:{input:Zi,output:$i},deleteMany:{input:ea,output:$i}},na=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:Ji.optional().describe(`Default batch options`)}).passthrough()),ra=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:P.optional().describe(`Record payload for create/update; a value may be { $ref: <opIndex> } to reference an earlier op's created id`)})),ia=n(()=>t.z.object({operations:t.z.array(ra).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`)})),aa=n(()=>Ti.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`)),oa=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(aa).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.")})),B=t.z.enum([`public`,`private`,`no-cache`,`no-store`,`must-revalidate`,`max-age`]),sa=n(()=>t.z.object({directives:t.z.array(B).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)`)})),ca=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`)})),la=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:sa.optional().describe(`Client cache control preferences`)})),ua=n(()=>t.z.object({data:t.z.unknown().optional().describe(`Metadata payload (omitted for 304 Not Modified)`),etag:ca.optional().describe(`ETag for this resource version`),lastModified:t.z.string().datetime().optional().describe(`Last modification timestamp`),cacheControl:sa.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`)})),da=t.z.enum([`all`,`object`,`field`,`permission`,`layout`,`custom`]),fa=n(()=>t.z.object({target:da.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)`)})),pa=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`)})),ma={getCached:{input:la,output:ua},invalidate:{input:fa,output:pa}};function ha(e,t,n,r=!1){let i=e?.origin;switch(e?.code){case`too_small`:return i===`number`||i===`bigint`||i===`date`?`min_value`:i===`array`||i===`set`?`min_items`:`min_length`;case`too_big`:return i===`number`||i===`bigint`||i===`date`?`max_value`:i===`array`||i===`set`?`max_items`:`max_length`;case`invalid_format`:return e?.format===`email`?`invalid_email`:e?.format===`url`?`invalid_url`:`invalid_format`;case`invalid_type`:return r&&ga(n,t)===void 0?`required`:`invalid_type`;case`invalid_value`:return`invalid_option`;case`unrecognized_keys`:return`unknown_field`;case`invalid_union`:case`invalid_element`:case`invalid_key`:return`invalid_shape`;default:return`invalid_value`}}function ga(e,t){if(!Array.isArray(t))return;let n=e;for(let e of t){if(n==null)return;n=n[e]}return n}var _a=3,va=3,ya=new Set([`invalid_key`,`invalid_element`]);function ba(e){return Array.isArray(e?.path)?e.path:[]}function xa(e){return e.every(e=>ba(e).length===0&&(e?.code===`invalid_type`||e?.code===`invalid_value`))}function Sa(e){return e.some(e=>e?.code===`unrecognized_keys`)}function Ca(e){let t=e.map((e,t)=>({issues:e,index:t})).filter(e=>!xa(e.issues));if(t.length===0)return[];let n=e=>[e.issues.length,+!Sa(e.issues)],r=[...t].sort((e,t)=>{let[r,i]=n(e),[a,o]=n(t);return r-a||i-o||e.index-t.index}),[i,a]=n(r[0]);return r.filter(e=>{let[t,r]=n(e);return t===i&&r===a}).slice(0,va).map(e=>e.issues)}function wa(e,t,n,r,i,a,o){let s=Array.isArray(e?.path),c=s?[...t,...e.path]:t,l=s?c.join(`.`):[...t,String(e?.path??``)].join(`.`),u=e?.code===`invalid_union`&&Array.isArray(e?.errors)?e.errors.filter(e=>Array.isArray(e)):[],d=ya.has(e?.code)&&Array.isArray(e?.issues)?e.issues:[],f=(u.length>0||d.length>0)&&n<_a,p={field:l,code:ha(e,s?c:e?.path,i,a),message:String(e?.message??`Invalid value`)};if(!f){let e=JSON.stringify([p.field,p.code,p.message]);if(r.has(e))return;r.add(e)}if(o.push(p),f){if(u.length>0){for(let e of Ca(u))for(let t of e)wa(t,c,n+1,r,i,a,o);return}for(let e of d)wa(e,c,n+1,r,i,a,o)}}function Ta(e,...t){if(!Array.isArray(e))return[];let n=t.length>0,r=[];for(let i of e)wa(i,[],0,new Set,t[0],n,r);return r}var Ea=t.z.object({lock:pe.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(),Da=/^(default|[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*)$/,Oa=n(()=>t.z.record(t.z.string().regex(Da,"an inline label map is keyed by BCP-47 locale tags (`en`, `zh-CN`, …) or `default` — not by `key`/`defaultValue`, which was the retired key-reference form (#5055) and resolves to nothing"),t.z.string()).describe(`Inline locale map: BCP-47 tag → translated string`)),V=n(()=>t.z.union([t.z.string(),Oa]).describe(`Display label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time`)),ka=`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.`,Aa=n(()=>A({surface:`these ARIA attributes`,history:ka,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:V.optional().describe(`Accessible label for screen readers (WAI-ARIA aria-label). Plain string, or an inline locale map — no translation-bundle slot addresses this key, so a plain string is announced in the source language.`),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`)),ja=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`])),Ma=n(()=>A({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:V.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)})),Na=n(()=>A({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:V.optional().describe(`Series display label`),type:ja.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`)})),Pa=n(()=>A({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:V.optional(),style:t.z.enum([`solid`,`dashed`,`dotted`]).default(`dashed`)})),Fa=n(()=>A({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(()=>A({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(()=>A({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:ja,title:V.optional().describe(`Chart title`),subtitle:V.optional().describe(`Chart subtitle`),description:V.optional().describe(`Accessibility description — announced to screen readers as the chart’s label`),xAxis:Ma.optional().describe(`X-Axis configuration`),yAxis:t.z.array(Ma).optional().describe(`Y-Axis configuration (support dual axis)`),series:t.z.array(Na).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(Pa).optional().describe(`Reference lines/bands drawn over the plot: { type: "line" | "region", axis: "x" | "y", value, endValue?, color?, label?, style? }`),interaction:Fa.optional().describe(`Interaction toggles: { tooltips?, brush? }`),aria:Aa.optional().describe(`ARIA accessibility attributes`)}));var Ia=n(()=>t.z.enum([`count`,`sum`,`avg`,`min`,`max`])),La=n(()=>t.z.union([t.z.string().describe(`Field to group by`),A({surface:`this chart groupBy`,history:"Until #5583 an undeclared key inside the structured groupBy was dropped at parse — `dateGranularty` for `dateGranularity` cost the date bucketing silently, and the chart drew one point per raw timestamp.",aliases:{granularity:`dateGranularity`,bucket:`dateGranularity`,name:`field`,as:`alias`,label:`alias`},guidance:{function:"`function` belongs on the aggregate, not inside `groupBy` — write `aggregate: { function, field, groupBy: { field, dateGranularity } }`.",groupBy:"You are already inside `groupBy` — the structured form is `{ field, dateGranularity?, alias? }`, not a nested `groupBy`."}},{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(()=>A({surface:`this chart aggregate`,history:"Until #5583 an undeclared aggregate key was dropped at parse — `groupby` for `groupBy` degraded the chart to a single ungrouped point, and `fn` for `function` fell back to the default, both with `build`/`validate` fully green.",aliases:{fn:`function`,agg:`function`,aggregation:`function`,measure:`field`,dimension:`groupBy`,category:`groupBy`},guidance:{dateGranularity:'`dateGranularity` goes INSIDE `groupBy`, not beside it — write `groupBy: { field: "<date field>", dateGranularity: "month" }`.',alias:"`alias` renames the GROUP column and lives inside the structured `groupBy` node. The measure column is named after `field` (or the literal `count` for a fieldless count) and is not renameable here — see `chartAggregateResultKeys` in `./chart-aggregate.ts`.",filter:"`filter` is a prop on the chart itself (`<ObjectChart filter={…}>`), not part of the aggregate.",objectName:"`objectName` is the chart's own prop — the aggregate runs against it and does not name it again.",measures:"An inline aggregate is SINGLE-MEASURE by design (one `function` over one `field`); two measures would collide on the result column name. Multi-measure is the dataset path's job — bind `dataset` + `values` instead (ADR-0021 Level B, see `./chart-aggregate.ts`)."}},{field:t.z.string().optional().describe(`Field to aggregate — required for sum/avg/min/max, optional for count`),function:Ia.describe(`Aggregation function`),groupBy:La.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 Ra=`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.`,za=n(()=>A({surface:`this sharing config`,history:Ra,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`)})),Ba=t.z.enum([`update`,`delete`,`custom`]),Va=t.z.enum([`perRecord`,`aggregate`]),Ha=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:O.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:x.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()),Ua=n(()=>A({surface:`this bulk action definition`,aliases:{action:`name`,actionname:`name`,title:`label`,op:`operation`,mode:`execution`,confirm:`confirmText`,confirmmessage:`confirmText`,limit:`maxRecords`,max:`maxRecords`,batch:`batchSize`,permissions:`requiredPermissions`,capabilities:`requiredPermissions`,requiresPermissions:`requiredPermissions`,requiredCapabilities:`requiredPermissions`,acl:`requiredPermissions`},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)."},{name:x.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:Ba.describe("What the executor does: 'update'/'delete' are data-plane mass mutations; 'custom' dispatches an object action (see `execution`)."),execution:Va.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(Ha).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:C.optional().describe("Eligibility predicate (CEL) — a string or a `{dialect, source}` envelope, i.e. `action.visible` without its boolean-literal arm (#5970): a per-record predicate has nothing to say as a constant. 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."),requiredPermissions:t.z.array(t.z.string()).optional().describe("[ADR-0066 D4] Capability gate on the button, `action.requiredPermissions` semantics verbatim: absent or empty always passes, several are AND-ed, and a client that cannot resolve the caller's capabilities fails OPEN (the server stays the authority). This key exists for INLINE defs — notably the `update`/`delete` data-plane forms, which dispatch no action and so have nothing to inherit a gate from; a def promoted from `bulkActions: ['<name>']` (or an aggregate def naming a declared action) inherits the action's own declaration instead. On a data-plane def the gate governs visibility only — the write itself is still authorized by the data API's object permissions and server hooks."),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.`)}).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`."})})),H=`Until #4001 closed these shapes an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`,Wa=n(()=>t.z.discriminatedUnion(`provider`,[A({surface:"this `object` data source",history:H,aliases:{objectName:`object`}},{provider:t.z.literal(`object`),object:t.z.string().describe(`Target object name`)}),A({surface:"this `api` data source",history:H,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:bn.optional().describe(`Configuration for fetching data`),write:bn.optional().describe(`Configuration for submitting data (for forms/editable tables)`)}),A({surface:"this `value` data source",history:H,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`)}),A({surface:"this `schema` data source",history:H,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.`)})])),Ga=[`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`],Ka=[`in`,`not_in`],qa=[`between`],Ja={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 Ya(e){return typeof e!=`string`||Ga.includes(e)?e:Ja[e]??Ja[e.toLowerCase()]??e}var Xa=[`id`],Za=[`filter`,`sort`],Qa=12,$a="`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 eo(e,t,n){if(n>Qa||!e||typeof e!=`object`)return e;if(Array.isArray(e)){let r=!1,i=e.map(e=>{let i=eo(e,t,n+1);return i!==e&&(r=!0),i});return r?i:e}let r=e,i;if(t)for(let e of Xa)e in r&&(i??={...r},delete i[e]);for(let[e,t]of Object.entries(i??r)){let a=eo(t,Za.includes(e),n+1);a!==t&&(i??={...r},i[e]=a)}return i??e}function to(e){return eo(e,!1,0)}function no(e){return e===null?`null`:e===void 0?`no value`:Array.isArray(e)?`an array of ${e.length}`:`a ${typeof e}`}function ro(e){if(e===void 0)return`(omitted)`;let t;try{t=JSON.stringify(e)??String(e)}catch{t=String(e)}return t.length>40?`${t.slice(0,39)}\u2026`:t}function io(e,t){let n=e.operator,r=e.value,i=typeof e.field==`string`?e.field:`<field>`,a=Ka.includes(n),o=qa.includes(n);if(a){if(Array.isArray(r))return;t.addIssue({code:`custom`,path:[`value`],message:`Operator "${n}" on field "${i}" requires an ARRAY of values. Received ${no(r)} (${ro(r)}). "${n}" tests membership of a list \u2014 write ${r===void 0?`["…"]`:ro([r])} for a single value, or use ${n===`in`?`"equals"`:`"not_equals"`} to compare against it. An empty list [] is allowed and is a real predicate. This is refused at authoring time because the query path refuses it too (400 INVALID_FILTER, #5869).`});return}o&&(Array.isArray(r)&&r.length===2||t.addIssue({code:`custom`,path:[`value`],message:`Operator "${n}" on field "${i}" requires a [min, max] value array. Received ${no(r)} (${ro(r)}). A range needs exactly two bounds, in order. This is refused at authoring time because the query path refuses it too (400 INVALID_FILTER, #5869).`}))}var ao=n(()=>A({surface:`this filter rule`,history:H,guidance:{id:$a}},{field:t.z.string().describe(`Field name to filter on`),operator:t.z.preprocess(Ya,t.z.enum(Ga)).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. The accepted SHAPE depends on the operator: `in` / `not_in` take an array (any length, including []), `between` takes exactly [min, max], every other operator takes a scalar. The unary operators (is_empty / is_not_empty / is_null / is_not_null) take their direction from the operator name and ignore this key.")}).superRefine(io).describe(`View filter rule`)),oo=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`)),so=n(()=>A({surface:`this column summary configuration`,history:H},{type:oo.describe(`Aggregation function`),field:t.z.string().optional().describe(`Field to aggregate (defaults to the column field)`)}).describe(`Column footer summary configuration`)),co=n(()=>A({surface:`this column prefix`,history:H},{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`)),lo=n(()=>A({surface:`this list column`,history:H},{field:t.z.string().describe(`Field name (snake_case)`),label:V.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([oo,so]).optional().describe(`Footer aggregation for this column — the function alone, or { type, field } to aggregate another field`),prefix:co.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`)})),uo=n(()=>A({surface:`this selection configuration`,history:H},{type:t.z.enum([`none`,`single`,`multiple`]).default(`none`).describe(`Selection mode`)})),fo=n(()=>A({surface:`this pagination configuration`,history:H},{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`)})),po=n(()=>t.z.enum([`compact`,`short`,`medium`,`tall`,`extra_tall`]).describe(`Row height / density setting for list view`)),mo=n(()=>A({surface:`this grouping field`,history:H},{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`)})),ho=n(()=>A({surface:`this grouping configuration`,history:H},{fields:t.z.array(mo).min(1).describe(`Fields to group by, in nesting order — the first entry is the outermost group and each later entry nests one level deeper (at least one field)`)}).describe(`Record grouping configuration`)),go=n(()=>A({surface:`this gallery configuration`,history:H},{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`)),_o=n(()=>A({surface:`this timeline configuration`,history:H},{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`)),vo=n(()=>A({surface:`this view sharing`,history:H},{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`)),yo=n(()=>A({surface:`this row color configuration`,history:H},{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`)),bo=n(()=>t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).describe(`Visualization type that users can switch to`)),xo=n(()=>A({surface:`this user actions configuration`,history:H},{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`)),So=n(()=>A({surface:`this appearance configuration`,history:H},{showDescription:t.z.boolean().default(!0).describe(`Show the view description text`),allowedVisualizations:t.z.array(bo).optional().describe(`Whitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])`)}).describe(`Appearance and visualization configuration`)),Co=n(()=>A({surface:`this view tab`,history:H},{name:x.describe(`Tab identifier (snake_case)`),label:V.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(ao).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`)),wo=n(()=>A({surface:`this user filter field`,history:H},{field:t.z.string().describe(`Field name on the source object (must exist — checked by reference diagnostics)`),label:V.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(A({surface:`this user filter option`,history:H,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:V.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`)),To=n(()=>A({surface:`these user filters`,history:H},{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(wo).optional().describe(`Fields exposed as quick filters (dropdown/toggle elements)`),tabs:t.z.array(Co).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("Let end users add their own tab after the presets (tabs element): the affordance asks for a name and snapshots the filters currently applied as a new tab. SESSION-SCOPED — an added tab lives only for the current mount, is never written back as metadata (ADR-0047), and carries a remove control the authored presets do not. Page lists only — object views use `listViews` for named presets")}).describe(`End-user quick-filter configuration (Airtable "User filters" parity)`)),Eo=n(()=>A({surface:`this add record configuration`,history:H},{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`)),Do=n(()=>A({surface:`this kanban configuration`,history:H},{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`)})),Oo=n(()=>A({surface:`this list chart configuration`,history:H},{chartType:ja.extract([`bar`,`line`,`pie`,`area`,`scatter`]).default(`bar`).describe(`Chart visualisation type`),dataset:x.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`)),ko=n(()=>A({surface:`this calendar configuration`,history:H},{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`)})),Ao=n(()=>A({surface:`this gantt quick filter`,history:H},{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(),A({surface:`this gantt quick-filter option`,history:H,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`)})),jo=n(()=>A({surface:`this gantt configuration`,history:H},{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(),A({surface:`this gantt tooltip field`,history:H,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(Ao).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()),Mo=n(()=>A({surface:`this tree configuration`,history:H},{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()),No=n(()=>t.z.enum([`page`,`drawer`,`modal`,`split`,`popover`,`new_window`,`none`])),Po=n(()=>A({surface:`this navigation configuration`,history:H},{mode:No.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.')})),Fo="'pdf' was removed from `view.exportOptions` formats in @objectstack/spec 17.0.0 (#8010; PDF export itself was declined as #1301 NOT_PLANNED) — no renderer has ever produced a PDF export: ObjectGrid dropped the declared format from the export menu with only a runtime console.warn, so authoring it was a parse-clean no-op. Delete the value; the surviving formats are 'csv', 'xlsx' and 'json'. Run `os migrate meta --from 16` to rewrite existing sources automatically.",Io=t.z.enum([`csv`,`xlsx`,`json`],{error:e=>e.input===`pdf`?Fo:void 0}),Lo=A({surface:`this export options block`,history:H},{formats:t.z.array(Io).optional().describe(`Formats offered in the export menu (default: ['csv', 'json']). XLSX is delivered by the server stream only.`),maxRecords:t.z.number().int().nonnegative().optional().describe(`Maximum number of records to export; 0 or absent = unlimited`),includeHeaders:t.z.boolean().optional().describe(`Include column headers in the exported file (default true)`),fileNamePrefix:t.z.string().optional().describe(`Download file name prefix — replaces the object label and suppresses the view label in the generated file name`),streaming:t.z.boolean().optional().describe(`Set false to force the client-side export path (csv/json only) instead of the server stream`)}),Ro=e=>{let t=e.input;return(Array.isArray(t)?t.includes(`pdf`):t&&typeof t==`object`&&Array.isArray(t.formats)&&t.formats.includes(`pdf`))?Fo:void 0},zo=n(()=>A({surface:`this list view`,history:H},{name:x.optional().describe(`Internal view name (lowercase snake_case)`),label:V.optional(),type:t.z.enum([`grid`,`kanban`,`gallery`,`calendar`,`timeline`,`gantt`,`map`,`chart`,`tree`]).default(`grid`),data:Wa.optional().describe(`Data source configuration (defaults to "object" provider)`),columns:t.z.union([t.z.array(t.z.string()),t.z.array(lo)]).describe(`Fields to display as columns`),filter:t.z.array(ao).optional().describe(`Filter criteria (JSON Rules)`),sort:t.z.union([t.z.string(),t.z.array(A({surface:`this sort entry`,history:H,aliases:{direction:`order`},guidance:{id:$a}},{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:To.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`),compactToolbar:t.z.boolean().optional().describe(`Collapse Group/Color/Density/Hide-fields into a single View settings popover`),selection:uo.optional().describe(`Row selection configuration`),navigation:Po.optional().describe(`Configuration for item click navigation (page, drawer, modal, etc.)`),pagination:fo.optional().describe(`Pagination configuration`),kanban:Do.optional().describe(`Kanban-board configuration — applies when the view renders as a kanban layout`),calendar:ko.optional().describe(`Calendar configuration — applies when the view renders as a calendar layout`),gantt:jo.optional().describe(`Gantt-timeline configuration — applies when the view renders as a gantt layout`),gallery:go.optional(),timeline:_o.optional(),chart:Oo.optional(),tree:Mo.optional().describe(`Tree/hierarchy configuration — applies when the view renders as a tree layout`),description:V.optional().describe(`View description for documentation/tooltips`),sharing:vo.optional().describe(`View sharing and access configuration`),rowHeight:po.optional().describe(`Row height / density setting`),grouping:ho.optional().describe(`Group records by one or more fields`),rowColor:yo.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(Ua).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}`."),conditionalFormatting:t.z.array(A({surface:`this conditional formatting rule`,history:H,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:C.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.union([t.z.array(Io).transform(e=>({formats:e})),Lo],{error:Ro}).optional().describe("Export configuration for the list toolbar export menu: `{ formats?, maxRecords?, includeHeaders?, fileNamePrefix?, streaming? }`. A bare format array is the legacy spelling and lifts to `{ formats: [...] }` at parse."),userActions:xo.optional().describe(`User action toggles for the view toolbar`),appearance:So.optional().describe(`Appearance and visualization configuration`),tabs:t.z.array(Co).optional().describe(`Tab definitions for multi-tab view interface`),addRecord:Eo.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:A({surface:`this empty state`,history:H,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:V.optional(),message:V.optional(),icon:t.z.string().optional()}).optional().describe(`Empty state configuration when no records found`),aria:Aa.optional().describe(`ARIA accessibility attributes for the list view`),responsive:v("`view.responsive` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer ever read it; the grid is responsive by its own layout rules. Delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically."),performance:v("`view.performance` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer or runtime read it; list-view performance tuning was never implemented. Delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically."),striped:v("`view.striped` was removed in @objectstack/spec 17.0.0 (#7176, ADR-0049 enforce-or-remove) — every measured reader only copied it forward and no renderer ever applied it, so authoring it was a parse-clean no-op. There is no authorable striped-rows switch; delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically."),bordered:v("`view.bordered` was removed in @objectstack/spec 17.0.0 (#7176, ADR-0049 enforce-or-remove) — every measured reader only copied it forward and no renderer ever applied it (the grid frame is the renderer's own constant, not authorable). Delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically."),virtualScroll:v("`view.virtualScroll` was removed in @objectstack/spec 17.0.0 (#7176, ADR-0049 enforce-or-remove) — every measured reader only copied it forward and no grid ever virtualized off it; authoring it was a parse-clean no-op. Delete the key; large datasets page via `pagination`. Run `os migrate meta --from 16` to rewrite existing sources automatically.")})),Bo=n(()=>A({surface:`this public picker configuration`,history:H},{displayFields:t.z.array(t.z.string()).min(1).max(5).optional().describe("Fields projected into each picker result (with `id`); the visitor's search matches `contains` on the first entry. At most 5 (the route projects no more); omitted → ['name']."),maxResults:t.z.number().int().min(1).max(50).optional().describe(`Maximum rows a lookup returns (default 20, hard ceiling 50 — the route clamps; anonymous visitors cannot paginate past it).`),filter:t.z.array(ao).optional().describe("Static pre-filter rows ANDed ahead of the visitor's search (e.g. only active records are searchable). Same `{ field, operator, value }` dialect as list-view filters."),object:t.z.string().optional().describe("Referenced-object override for the picker search; omitted → resolved from the field definition (`referenceTo`).")}).describe(`Public-lookup opt-in: enables GET /forms/:slug/lookup/:field for this field on an anonymous public form (without it the route answers 403 LOOKUP_NOT_PUBLIC).`)),Vo=n(()=>{let e={field:t.z.string().describe(`Field name (snake_case)`),type:O.optional().describe(`Field type (auto-infers widget if omitted)`),options:t.z.array(at).optional().describe(`Options for select/multiselect/radio/checkboxes fields`),reference:t.z.string().optional().describe(`Target object name for lookup/master_detail fields`),publicPicker:Bo.optional().describe(`Opt this field into the anonymous public-form lookup picker (GET /forms/:slug/lookup/:field). Without it the route answers 403 LOOKUP_NOT_PUBLIC and the field is stripped from the rendered public form.`),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:V.optional().describe(`Display label override`),placeholder:V.optional().describe(`Placeholder text`),helpText:V.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:A({surface:`this record key field`,history:H,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:V.optional().describe(`Display label for the key column`),placeholder:V.optional().describe(`Placeholder when entering a new key`),helpText:V.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:C.optional().describe("Visibility predicate (CEL) — field shown only when TRUE. Root: `record` (+ `previous`, `parent`) in runtime forms, or `data` in metadata forms. No `current_user` at field level — it is unbound here and the predicate would fault open (per-option `visibleWhen` is the surface that binds it). Inside a repeater `data` is the ROW, but it is still spelled `data` — a bare identifier is unbound and faults open too. e.g. P`record.priority == 'urgent'`"),visibleOn:C.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).`)};return t.z.object(e,{error:vt({...ce,surface:`this form field`,extraKeys:[`fields`],aliases:{disabled:`readonly`}},e)})}),Ho=n(()=>Vo.extend({fields:t.z.array(t.z.lazy(()=>Ho)).optional().describe(`Sub-fields for composite/repeater/record types`)}).strict().transform(se)),Uo=n(()=>A({...fe,surface:`this form section`},{name:t.z.string().optional().describe(`Stable section identifier for i18n lookup (snake_case)`),label:V.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:C.optional().describe("Visibility predicate (CEL) — section shown only when TRUE. Root: `record` (+ `previous`, `parent`) in runtime forms, or `data` in metadata forms. No `current_user` at section level — it is unbound here and the predicate would fault open."),visibleOn:C.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(),Ho]))}).transform(se)),Wo=n(()=>A({surface:`this form button configuration`,history:H},{show:t.z.boolean().optional().describe(`Whether the button is rendered (renderer default applies when omitted)`),label:V.optional().describe(`Button label (i18n-capable; renderer default when omitted)`)}).strict());function Go(e){if(e.groups===void 0)return e;let{groups:t,...n}=e;return n.sections===void 0?{...n,sections:t}:n}var U=`ruled 2026-08-11 on #7496`,Ko=/\{\{record\.[a-z_][a-z0-9_]*\}\}/g,qo=/^[a-z][a-z0-9+.-]*:/i,Jo=/[\s\u0000-\u001f\u007f]/;function Yo(e){if(e===``)return`A \`redirect\` submit behavior needs a \`url\` \u2014 an empty string is not a destination. Write the in-app path the submitter should land on, e.g. \`/thanks\` (${U}).`;if(qo.test(e))return`\`submitBehavior.url\` accepts a RELATIVE path only, and this is an absolute URL (${U}). A post-submit redirect that can leave the app is an open redirect, so the scheme form is refused at the authoring door rather than sanitized at the renderer. Write the in-app path instead \u2014 \`/thanks\`, not \`https://example.com/thanks\`. To send the browser OUT of the app deliberately, that is an app navigation item (\`{ type: 'url', url }\`), which is declared for external addresses.`;if(e.startsWith(`//`))return`\`submitBehavior.url\` accepts a RELATIVE path only, and a leading \`//\` is protocol-relative \u2014 the browser reads \`//example.com/thanks\` as ANOTHER ORIGIN despite the leading slash (${U}). Use a single leading slash for an in-app path; for a deliberate external link use an app navigation item (\`{ type: 'url', url }\`).`;if(e.includes(`\\`))return`\`submitBehavior.url\` must not contain a backslash \u2014 browsers normalise \`\\\` to \`/\` while resolving, so \`/\\example.com\` navigates off-origin exactly like \`//example.com\` and would walk straight past the relative-only rule (${U}). Write the path with forward slashes; percent-encode a backslash that is genuinely part of a path segment (\`%5C\`).`;if(Jo.test(e))return`\`submitBehavior.url\` must not contain whitespace or control characters \u2014 browsers strip them before resolving, so a leading one hides what the address really starts with and defeats the relative-only rule (${U}). Percent-encode a space that belongs in the path (\`%20\`).`;let t=e.replace(Ko,``);if(t.includes(`{`)||t.includes(`}`))return`\`submitBehavior.url\` interpolates ONLY declared record fields, spelled \`{{record.field_name}}\` \u2014 \`${t.match(/\{\{?[^{}]*\}?\}?/)?.[0]??`{`}\` is not that shape (${U}). The record just submitted is the whole scope a post-submit redirect has, and the field segment takes the same lowercase snake_case grammar fields are declared under. Every interpolated value is URL-escaped when the redirect is built, so a token is a value in the path or query \u2014 never a way to add path structure.`;if(!e.startsWith(`/`))return`\`submitBehavior.url\` must start with \`/\` \u2014 a document-relative path like \`thanks\` resolves against whichever console route the form happened to be opened from, so one form lands in different places depending on how it was reached (${U}). Write the rooted in-app path: \`/thanks\`.`}var Xo=n(()=>A({surface:`this form view`,history:H},{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:Wa.optional().describe(`Data source configuration (defaults to "object" provider)`),sections:t.z.array(Uo).optional(),groups:t.z.array(Uo).optional().describe("[LEGACY ALIAS → `sections`] Accepted for back-compat and folded onto `sections` at parse; `sections` wins when both are present. Prefer `sections`."),subforms:t.z.array(A({surface:`this subform`,history:H,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:v("`form.defaultSort` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — nothing read it: a related list inside a form sorts by its own list view's `sort`. Delete the key and set the sort on the related list view instead. Run `os migrate meta --from 16` to rewrite existing sources automatically."),sharing:za.optional().describe(`Public sharing configuration for this form`),submitBehavior:t.z.discriminatedUnion(`kind`,[A({surface:"this `thank-you` submit behavior",history:H,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()}),A({surface:"this `redirect` submit behavior",history:H,aliases:{delay:`delayMs`,delayMS:`delayMs`,timeout:`delayMs`,to:`url`,href:`url`,target:`url`}},{kind:t.z.literal(`redirect`),url:t.z.string().superRefine((e,t)=>{let n=Yo(e);n&&t.addIssue({code:`custom`,message:n})}).describe("Where the browser goes after a successful submit. Ruled 2026-08-11 (#7496): (1) RELATIVE paths only — it must start with `/`, and absolute or protocol-relative URLs are refused, which is what closes the open-redirect face; (2) interpolation ONLY from declared record fields, spelled `{{record.field_name}}`, and every interpolated value is URL-escaped when the redirect is built; (3) a verbatim redirect on the resolved relative path is the intended consumption. To send the browser OUT of the app, use an app navigation item (`{ type: 'url', url }`) instead."),delayMs:t.z.number().int().min(0).optional()}),A({surface:"this `continue` submit behavior",history:H,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`)}),A({surface:"this `next-record` submit behavior",history:H,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. On the `redirect` arm, `url` is relative-only and interpolates only declared record fields as `{{record.field_name}}`, URL-escaped (ruled 2026-08-11, #7496)."),buttons:t.z.object({submit:Wo.optional().describe(`Submit button`),cancel:Wo.optional().describe(`Cancel button`),reset:Wo.optional().describe(`Reset button`)}).strict().optional().describe(`Form action-button visibility & labels; folded onto the flat renderer props by ObjectUI ObjectForm (framework#1894 / #2998).`),defaults:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Initial field values for create-mode forms (folded into ObjectUI ObjectForm initial values; framework#1894 / #2998).`),aria:v("`form.aria` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no form renderer ever applied it, so declared ARIA attributes silently did not reach the DOM. Delete the key. The form renderer emits its own semantic markup; report gaps as renderer issues rather than per-view attribute overrides. Run `os migrate meta --from 16` to rewrite existing sources automatically.")}).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.`})})}).overwrite(Go)),Zo=n(()=>A({surface:`these object user filters`,history:H,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."}},{...To.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.')})),Qo=n(()=>zo.omit({userFilters:!0}).extend({userFilters:Zo.optional()})),$o="Wrap it: `defineView({ list: { type, data, columns, … } })`, or name it — `defineView({ listViews: { my_view: { … } } })`.",es=n(()=>A({surface:`this view container`,history:H,guidance:Object.fromEntries([`type`,`columns`,`data`,`viewKind`,`filters`,`sort`].map(e=>[e,`\`${e}\` belongs to a single VIEW, not to the container. ${$o} 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:V.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:Qo.optional(),form:Xo.optional(),listViews:t.z.record(t.z.string(),Qo).optional().describe(`Additional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)`),formViews:t.z.record(t.z.string(),Xo).optional().describe(`Additional named form views`),protection:Ea.optional().describe(`Package author protection block — lock policy for this view.`),...y})),ts=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>`."),ns=t.z.enum([`package`,`shared`,`personal`]).describe(`View identity layer: package | shared | personal.`),rs=t.z.enum([`list`,`form`]).describe("Whether `config` is a ListView (list family) or a FormView.");function is(){return{name:ts,object:t.z.string().describe(`Bound object name — the foreign key used to aggregate views.`),label:V.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:ns.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:Ea.optional().describe(`Package author protection block — lock policy for this view.`),...y}}function as(e,n){return{viewKind:t.z.literal(e),config:n,...is()}}var os={surface:`this view item`,history:H,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`,[A(os,as(`list`,zo.describe(`List-family view configuration.`))),A(os,as(`form`,Xo.describe(`Form view configuration.`)))]));function ss(){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 cs=n(()=>t.z.discriminatedUnion(`viewKind`,[t.z.object({...as(`list`,zo.describe(`List-family view configuration.`)),...ss()}).strip(),t.z.object({...as(`form`,Xo.describe(`Form view configuration.`)),...ss()}).strip()])),ls='This inline view config names no `object`, so the saved row could never be served: `GET /meta/view?object=…` and the view switcher match stored views on `object` + `viewKind`, and a row missing them is registered yet renders nowhere. Bind it — add `object: "<object_name>"` and `viewKind: "list" | "form"` — or save a ViewItem record (`{ name, object, viewKind, config: { … } }`), or make it a container. '+$o,us='This inline view config names no `viewKind`, so the saved row could never be served: `GET /meta/view?object=…` and the view switcher match stored views on `object` + `viewKind`, and a row missing them is registered yet renders nowhere. Bind it — add `viewKind: "list" | "form"` alongside `object` — or save a ViewItem record (`{ name, object, viewKind, config: { … } }`), or make it a container. '+$o;function ds(){return{name:t.z.string().optional().describe(`Save name / qualified view id (stamped by the write path).`),object:t.z.string({error:e=>e.input===void 0?ls:void 0}).describe("Bound object name — REQUIRED on an inline view config (#7741): the object-bound read paths (`GET /meta/view?object=`, the view switcher) match on `object` + `viewKind`, so an unbound row can never be served. Inherited from the shadowed entry on personalization PUTs (#2555)."),viewKind:t.z.enum(rs.options,{error:e=>e.input===void 0?us:void 0}).describe("View family — REQUIRED on an inline view config (#7741): half of the `object` + `viewKind` pair the object-bound read paths match on. Inherited from the shadowed entry on personalization PUTs (#2555)."),label:V.optional().describe(`Display label (inherited from the shadowed entry — #2555).`),isDefault:t.z.boolean().optional(),order:t.z.number().int().optional(),scope:ns.optional(),owner:t.z.string().optional(),hidden:t.z.boolean().optional(),protection:Ea.optional(),...y,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 fs(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)}var ps=new Set([`name`,`viewKind`,`object`,`label`]);function ms(e,t,n=0){let r=e?._zod?.def;if(!(!r||n>6)){if(r.type===`object`){for(let e of Object.keys(r.shape??{}))t.add(e);return}if(r.type===`union`){for(let e of r.options??[])ms(e,t,n+1);return}for(let e of[`innerType`,`in`,`out`,`schema`])r[e]&&ms(r[e],t,n+1)}}function hs(e){if(typeof e!=`object`||!e||Array.isArray(e))return!0;let t=Cs();return Object.keys(e).some(e=>t.has(e))}function gs(e,t){if(typeof e!=`object`||!e||Array.isArray(e)||hs(e))return!0;let n=Object.keys(e),r=n.filter(e=>ps.has(e)),i=n.filter(e=>!ps.has(e)),a=(e,t=5)=>`${e.slice(0,t).map(e=>`\`${e}\``).join(`, `)}${e.length>t?`, …`:``}`;return t.addIssue({code:`custom`,path:[],message:"Not a `view` body: no recognized `view` key. Expected at least one of a container slot (`list` / `form` / `listViews` / `formViews`), a ViewItem record (`viewKind` + `config`), or an inline view config (`type`, `columns`, `sections`, `filter`, …). "+(n.length===0?"Received `{}`.":`Received `)+(i.length>0?`unrecognized ${i.length===1?`key`:`keys`} ${a(i)}`:``)+(i.length>0&&r.length>0?`, and `:``)+(r.length>0?`only identity fields (${a(r)}) \u2014 these say which view this attaches to, not what the view is, and the write path stamps them itself`:``)+(n.length===0?``:`.`)}),!1}var _s=n(()=>es.refine(fs,{message:"A view container must define at least one of `list`, `form`, `listViews`, or `formViews`."})),vs=n(()=>zo.extend(ds()).strip()),ys=n(()=>Xo.extend(ds()).strip()),bs=[`viewItem`,`container`,`listOverlay`,`formOverlay`],xs={viewItem:cs,container:_s,listOverlay:vs,formOverlay:ys},Ss;function Cs(){if(!Ss){let e=new Set;for(let t of bs)ms(xs[t],e);for(let t of ps)e.delete(t);Ss=e}return Ss}function ws(e){let t=(e._zod?.def?.shape)?.type?._zod?.values;return new Set([...t??[]].filter(e=>typeof e==`string`))}function Ts(e){if(typeof e!=`object`||!e||Array.isArray(e))return null;let t=e;if(t.config!==void 0)return`viewItem`;if(t.list!==void 0||t.form!==void 0||t.listViews!==void 0||t.formViews!==void 0)return`container`;if(t.viewKind===`form`)return`formOverlay`;if(t.viewKind===`list`)return`listOverlay`;if(typeof t.type==`string`){if(ws(Xo).has(t.type))return`formOverlay`;if(ws(zo).has(t.type))return`listOverlay`}return null}function Es(e,t,n){return{code:`invalid_type`,expected:`object`,input:n,path:[],message:`Not the \`${e}\` branch \u2014 this body reads as \`${t}\`, so that branch carries the diagnosis.`}}function Ds(){let e=new t.z.core.$ZodCheck({check:`custom`,when:()=>!0});return e._zod.check=e=>{if(e.issues.length===0)return;let t=Ts(e.value);if(t!==null)for(let n=0;n<e.issues.length;n+=1){let r=e.issues[n];r?.code!==`invalid_union`||!Array.isArray(r.errors)||r.errors.length===bs.length&&(e.issues[n]={...e.issues[n],errors:r.errors.map((n,r)=>{let i=bs[r];return i===t?n:[Es(i,t,e.value)]})})}},e}n(()=>{let e=bs.map(e=>xs[e]);return t.z.preprocess((e,n)=>gs(e,n)?to(e):t.z.NEVER,t.z.union(e).check(Ds()))});var Os=t.z.enum([`select`,`insert`,`update`,`delete`,`all`]),ks=n(()=>A({surface:`this RLS policy`,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.`},{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:Os.describe(`Database operation this policy applies to`),using:t.z.string().optional().describe("Filter condition for SELECT/UPDATE/DELETE, authored in canonical CEL (ADR-0058 D1). It enforces when the predicate lowers to an ObjectQL filter: a field compared against a literal or a `current_user.*` context value using `==`, `!=`, `<`, `<=`, `>` or `>=`; `in` against a `current_user.*` array or an inline literal list (e.g. status in ['draft', 'pending']); these combined with `&&` / `||`; or the bare allow-all `true`. Anything that does not lower fails closed — the policy matches zero rows. The legacy SQL-ish spellings are still accepted through a transitional bridge that rewrites `=` to `==` and `IN` to `in` (deprecated under ADR-0058 D1); SQL `AND` / `OR` / `NOT IN` / `IS NULL` / `LIKE` are NOT bridged and fail closed. 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:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),tags:t.z.array(t.z.string()).optional().describe(`Policy categorization tags`)}).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 As={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`),...y},js=n(()=>A({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`}},{...As,type:t.z.literal(`script`),condition:C.describe("Predicate (CEL). If TRUE, validation fails. e.g. P`record.amount < 0`")})),Ms=n(()=>A({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`}},{...As,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.")})),Ns=n(()=>A({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`}},{...As,type:t.z.literal(`format`),field:t.z.string(),regex:t.z.string().optional(),format:t.z.enum([`email`,`url`,`phone`,`json`]).optional()})),Ps=n(()=>A({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`}},{...As,type:t.z.literal(`cross_field`),condition:C.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.`)})),Fs=n(()=>A({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`}},{...As,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`)})),Is=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[js,Ms,Ns,Ps,Fs,Ls])),Ls=n(()=>A({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`}},{...As,type:t.z.literal(`conditional`),when:C.describe("Predicate (CEL). e.g. P`record.type == 'enterprise'`"),then:Is.describe(`Validation rule to apply when condition is true`),otherwise:Is.optional().describe(`Validation rule to apply when condition is false`)}));function Rs(e){return e!=null&&(typeof e!=`string`||e.trim()!==``)}n(()=>t.z.object({userId:t.z.string().optional().describe(`Invoking user id (absent when the call carries no user)`),organizationId:t.z.string().optional().describe(`Active organization id (blessed developer-facing name; absent when the call is org-less)`),positions:t.z.array(t.z.string()).optional().describe('Position names held by the caller (ADR-0090 D3 vocabulary; the value of `ExecutionContext.positions`, whose schema comment reads "Formerly `roles`") — the CANONICAL spelling at this boundary and the key an action body should read. Within the #5613 deprecation window `buildActionSession()` emits the same array under both this key and the deprecated `roles`, so migrating is a change of key and nothing else; `roles` is then removed on the v11 session-alias removal path (#3280 deprecate → #3290 remove: one window, then gone). Never gate PRIVILEGE on this array — ask the security service, which evaluates capability grants, placements and the derived posture (ADR-0095), never a position-name string comparison.'),roles:t.z.array(t.z.string()).optional().describe('DEPRECATED alias of `positions` — the same caller position names under the one spelling ADR-0090 D3 forbids (the value is `ExecutionContext.positions`, "Formerly `roles`"). Read `positions` instead: within the #5613 deprecation window `buildActionSession()` emits both keys with identical values, so migrating is a change of key and nothing else. The migration prescription and its acceptance criteria are the ADR-0087 semantic migration `action-session-roles-to-positions`; removal follows the v11 session-alias removal path (#3280 deprecated → #3290 removed). Never gate PRIVILEGE on this array — ask the security service, which evaluates capability grants, placements and the derived posture (ADR-0095), never a role-name string comparison.')}).describe("Action-body `ctx.session` — the caller identity an action body reads (runtime shape, never authored)"));var zs='`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 existing sources automatically.',Bs=t.z.enum([`api.read`,`api.write`,`api.transaction`,`crypto.uuid`,`log`],{error:e=>e.input===`crypto.hash`?zs:void 0}),Vs='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.',Hs=A({surface:`this expression (L1) hook body`,aliases:{expression:`source`,formula:`source`,code:`source`,script:`source`},guidance:{capabilities:`\`capabilities\` ${Vs}`,timeoutMs:`\`timeoutMs\` ${Vs}`,memoryMb:`\`memoryMb\` ${Vs}`},history:`Until #4001 these were dropped silently.`},{language:t.z.literal(`expression`),source:t.z.string().min(1).describe(`Formula expression source`)}).describe(`L1 expression body — pure formula, no IO`),Us=A({surface:`this sandboxed JS (L2) hook body`,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.`},{language:t.z.literal(`js`),source:t.z.string().min(1).describe(`Function body source`),capabilities:t.z.array(Bs).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)`)}).describe(`L2 sandboxed JS body — runs inside an isolated VM with declared capabilities`),Ws=t.z.discriminatedUnion(`language`,[Hs,Us]).describe(`Hook/Action body — expression (L1) or sandboxed JS (L2)`),Gs={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.`},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).`}}},Ks=Object.keys(Gs);function qs(e){return`features.${e} ${Gs[e].semantics===`opt-in`?`== true`:`!= false`}`}function Js(e,t){let{requiresFeature:n,...r}=e;if(n===void 0)return r;let i=qs(n),a=r.visible;return a===void 0||a===!0?{...r,visible:{dialect:`cel`,source:i}}:a===!1?(t.addIssue({code:`custom`,path:[`requiresFeature`],message:"`requiresFeature` cannot compose with `visible: false` — the literal already hides this unconditionally, so the feature gate can never take effect. Drop `requiresFeature` to keep it hidden, or drop `visible: false` to let the flag decide."}),r):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 Ys={referenceto:`reference`,referenceobject:`reference`,referencedobject:`reference`,targetobject:`reference`,visiblewhen:`visible`,visibleon:`visible`,visibility:`visible`,description:`helpText`,help:`helpText`,default:`defaultValue`},Xs="`color` is a per-option key of a FIELD's option list (`SelectOptionSchema` in `data/field.zod.ts`), read where a STORED value is displayed — the grid cell and the detail badge. An action param's options are never rendered that way: the dialog builds an INPUT from them, submits the picked value and discards the list, so no renderer would read `color` here even if this shape declared it (#5016 measured this). Drop the key — to colour the value once it is stored, declare the option list on the FIELD.",Zs=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 and no widget reads. An action param's options are \`{ label, value, visibleWhen }\`; drop the key.`,Qs=n(()=>A({surface:`this action param`,aliases:Ys,history:`Until #3405 these were dropped silently — the param still parsed, so a mis-spelled config shipped as a control that quietly ignored it.`},{name:t.z.string().optional(),field:x.optional(),objectOverride:x.optional(),label:V.optional(),type:O.optional(),required:t.z.boolean().optional().default(!1),options:t.z.array(A({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`,visible:`visibleWhen`,showWhen:`visibleWhen`},guidance:{color:Xs,icon:Zs(`icon`),disabled:Zs(`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:V,value:t.z.string(),visibleWhen:C.optional().describe("Per-option visibility predicate (CEL) — option is offered only when TRUE (else omitted). Same env as the field-level per-option visibleWhen (record + current_user). e.g. P`record.tier == 'gold'`")})).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:x.optional().describe(`Reference target object for inline lookup/master_detail params; mirrors FieldSchema.reference.`),defaultFromRow:t.z.boolean().optional(),visible:C.optional().describe(`Param visibility predicate (CEL); omits the param when false.`),requiresFeature:t.z.enum(Ks).optional().describe("Public auth feature flag gating this param; lowered into `visible` at parse time.")}).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.`}).superRefine((e,t)=>{if(!Rs(e.defaultValue)||!e.type)return;let n={type:e.type,multiple:e.multiple,options:e.options},r=Ze(n,e.defaultValue);if(r.ok||e.field&&e.multiple===void 0&&Le.has(e.type)&&Ze({...n,multiple:!Re(n)},e.defaultValue).ok)return;let i=r.detail??`invalid value`,a=e.name??e.field??`<unnamed>`;t.addIssue({code:`custom`,path:[`defaultValue`],message:`Action param "${a}" (${e.type}): the default ${JSON.stringify(e.defaultValue)} cannot satisfy this param's own value contract \u2014 ${i}. The dialog would PREFILL this value and the submit would then be refused with that same message (ADR-0104 D2), for a field the user never touched \u2014 so the 400 names the param but not this default, which is the real cause. Write the default in the param's declared value shape, or drop \`defaultValue\`.`})}).transform((e,t)=>Js(e,t))),$s=t.z.enum([`script`,`url`,`modal`,`flow`,`api`,`form`]),ec=new Set($s.options.filter(e=>e!==`script`)),tc="`global_nav` was removed from `ACTION_LOCATIONS` in @objectstack/spec 17 (#6888, ADR-0049 enforce-or-remove) — no running-app surface ever rendered it. The console command palette (`⌘K`) builds its groups from nav items, objects, dashboards, pages, reports, recent items and record search; it reads no action metadata at all, so an action declaring this location never reached a user. The only thing that DID draw it was the Studio designer, which previewed a command-palette frame for a surface the product does not have — an authoring tool teaching authors to write dead metadata (ADR-0078). Place the action on a location a renderer serves (`list_toolbar`, `list_item`, `record_header`, `record_more`, `record_related`, `record_section`), or — for an action that deliberately has no UI home, such as an object-less one invoked over REST/MCP/AI — declare it headless with `locations: []`, which keeps its capability gate, param contract and audit trail. Run `os migrate meta --from 16` to rewrite existing sources automatically.",nc=t.z.enum([`list_toolbar`,`list_item`,`record_header`,`record_more`,`record_related`,`record_section`],{error:e=>e.input===`global_nav`?tc:void 0}),rc=t.z.enum([`data`,`action`,`flow`,`integration`,`vector_search`,`analytics`,`utility`]),ic=`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.`,ac=A({surface:`this action's AI exposure block`,history:ic,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:rc.optional().describe(`Tool category override (defaults to "action").`),paramHints:t.z.record(t.z.string(),A({surface:`this AI parameter hint`,history:ic,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.`)}),oc=t.z.union([t.z.boolean(),C]),sc=()=>A({surface:`this action`,history:ic,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:x.describe(`Machine name (lowercase snake_case)`),label:V.describe(`Display label`),description:V.optional().describe("Explanatory line shown under the title in the action's param dialog. Carries the confirm question for an action that collects params (one dialog, not two — #7278). Not the LLM-facing `ai.description`."),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(nc).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:$s.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:Ws.optional().describe("Action body — expression (L1) or sandboxed JS (L2). Only used when type is `script`."),execute:v("`execute` was removed in @objectstack/spec 17 (#3855) — use `target`. Rename the key; the value (a handler / flow / URL ref) is unchanged. Run `os migrate meta --from 16` to rewrite existing sources automatically."),params:t.z.array(Qs,{error:e=>e.code===`invalid_type`&&e.input!==null&&typeof e.input==`object`&&!Array.isArray(e.input)?"`params` is the parameter DEFINITION array (fields collected from the user before the action runs), not a values map. For a `type:'api'` action's static request body — including `{{page.<var>}}` tokens — use `bodyExtra: { … }` instead (#5777). For a `type:'url'` action there is nowhere to move it to, by decision: put static values straight into the `target` string (`${param.X}` interpolates a value collected by the params dialog, `${ctx.X}` one from the action context), and open a new tab with `openIn: 'new-tab'`. The url-side readings of an object `params` — a static `${param.X}` scope, and `params.newTab` — are RETIRED, not renamed (#6828). Expected an array of ActionParam, received an object.":void 0}).optional().describe("Input parameters required from user — an ActionParam[] DEFINITION array, never a payload map (a static request body goes in `bodyExtra`)."),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:V.optional().describe("Confirmation message before execution. On a registered action, pairing this with a non-empty `params` is refused (#7428) — that opens a second dialog for one decision; put the question on `description` instead. Correct on a param-LESS action, where the confirm is the only dialog there is."),successMessage:V.optional().describe(`Success message to show after execution`),errorMessage:V.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:A({surface:`this result dialog`,history:ic,aliases:{label:`title`,heading:`title`,message:`description`,body:`description`,ok:`acknowledge`,confirm:`acknowledge`,button:`acknowledge`,display:`format`,render:`format`,show:`fields`,reveal:`fields`}},{title:V.optional(),description:V.optional(),acknowledge:V.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(A({surface:`this result dialog field`,history:ic,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:V.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:oc.optional().describe("Visibility predicate — `true`/`false` literal, CEL string, or `{dialect, source}` envelope. The action is offered when it evaluates TRUE. Omit = always visible."),requiresFeature:t.z.enum(Ks).optional().describe("Public auth feature flag gating this action; lowered into `visible` at parse time."),disabled:oc.optional().describe("Disabled predicate — `true`/`false` literal, CEL string, or `{dialect, source}` envelope. The action is shown but refused when it evaluates TRUE. Omit = never disabled."),requiredPermissions:t.z.array(t.z.string()).optional().describe("[ADR-0066 D4] Capabilities required to invoke this action. Enforced with 403 on the platform action route (script/flow/modal + MCP) and mirrored as a UI hide; a `type: api` action pointed at a custom endpoint must re-check it there."),shortcut:v("`action.shortcut` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — it never triggered anything: no keydown listener feeds ActionEngine.getShortcuts(), and objectui's keyboard stack (useKeyboardShortcuts) is hand-registered and never consults action metadata. Delete the key. For a real shortcut, register the key in the Console keyboard stack and have its handler invoke the action by name. Run `os migrate meta --from 16` to rewrite existing sources automatically."),bulkEnabled:v("`action.bulkEnabled` was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — the multi-select toolbar is driven by the LIST VIEW's `bulkActions` / `bulkActionDefs`, never by this flag, so setting it changed nothing. Delete the key and declare the action in the view's `bulkActions` instead. Run `os migrate meta --from 16` to rewrite existing sources automatically."),ai:ac.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`),A({surface:`this body shape`,history:ic,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('Static request-body fields for a type:"api" action, merged last (overrides user params). `{{page.<var>}}` tokens are resolved by the runtime. This — not `params` — is where a payload goes.'),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:Aa.optional().describe(`ARIA accessibility attributes`),...y}),cc=n(()=>sc().refine(e=>!(ec.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`]}).refine(e=>!(e.confirmText!=null&&Array.isArray(e.params)&&e.params.length>0),{message:"An action that declares `confirmText` beside a non-empty `params` shows the user TWO dialogs for one decision — the confirm, then the param prompt, with nothing sent until the second. Carry the confirm question in the action's top-level `description` instead (it renders under the param dialog's title) and drop `confirmText`: one condition, one wording, one dialog (#7278). Not `ai.description` — that is the LLM-facing tool contract. `confirmText` stays correct for a param-LESS action, where the confirm IS the only dialog, and for a view's `bulkActionDefs`, where the pair renders one dialog by that schema's own contract.",path:[`confirmText`]}).transform((e,t)=>Js(e,t)));function lc(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(lc,sc().pick({type:!0,name:!0,label:!0,target:!0,openIn:!0,method:!0,params:!0,bodyExtra:!0,confirmText:!0,successMessage:!0,errorMessage:!0,refreshAfter:!0,opensInNewTab:!0}).partial({name:!0,label:!0}).refine(e=>!(ec.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 uc=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`bulk`]),dc=[`upsert`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`],fc={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"},pc=t.z.enum([`get`,`list`,`create`,`update`,`delete`,`upsert`,`bulk`,`aggregate`,`history`,`search`,`restore`,`purge`,`import`,`export`]),mc=new Set(dc),hc=new Set;function gc(e,t){if(!Array.isArray(e))return e;let n=[...new Set(e.filter(e=>typeof e==`string`&&mc.has(e)))];if(n.length===0)return e;let r=e.filter(e=>!(typeof e==`string`&&mc.has(e))),i=`${[...n].sort().join(`,`)}${r.length===0?`|deny-all`:``}`;return hc.has(i)||(hc.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:
15
- `+n.map(e=>` \u2022 \`${e}\`: ${fc[e]}`).join(`
16
- `)+(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.":``)+`
17
- Codemod: node scripts/codemod/apimethods-legacy-to-primitives.mjs`)),r}var _c=A({surface:"`enable`",history:"Until this shape was closed an unknown flag was dropped without a word — the object shipped as if the author had never written it (#1535); `enable` is a closed vocabulary in which every flag carries an enforcement contract (#2707).",guidance:{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 existing sources 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 existing sources automatically."}},{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=>gc(e),t.z.array(uc)).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`)}),vc=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:st.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:v("`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 existing sources automatically."),partial:v("`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 existing sources automatically.")})),yc={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."},bc="The two supported tenancy modes are: database-per-tenant = environment-level deployment (no object config); row-level isolation = `tenancy.enabled` + `tenancy.tenantField`.",xc=n(()=>A({surface:"`tenancy`",history:bc,guidance:yc},{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).")})),Sc=n(()=>A({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).`)})),Cc=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(),wc=t.z.union([t.z.array(t.z.string()),Cc]),Tc=t.z.enum([`record`,`audit`,`telemetry`,`transient`,`event`]),Ec=/^\d+(h|d|w|y)$/,Dc=e=>t.z.string().regex(Ec,`${e} must be a duration literal like '6h', '14d', '12w' or '7y'`),Oc=n(()=>A({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:Tc.describe(`Persistence contract: record (business truth, permanent) | audit (compliance ledger) | telemetry (high-freq log) | transient (ephemeral state) | event (bus messages).`),retention:A({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:Dc(`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:A({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:Dc(`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:A({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 takes its window from `shards` × `unit`, not from an age you name — reclaimed by DROPping the oldest shard whole on SQLite, by an equivalent age-based reap elsewhere. Set the window with `shards`/`unit`, or use `retention` instead of rotation."}},{strategy:t.z.literal(`rotation`).describe("Time-shard the table. The retained window (`shards` × `unit`) is the same on every dialect; the reclamation is not — SQLite DROPs the oldest shard whole (O(1) reclaim), other dialects reap that same window by age from `created_at`."),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:A({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:Dc(`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:Dc(`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`})})),kc=n(()=>A({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.")})),W=A({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)`),Ac=A({surface:`this row CRUD override`,history:`This shape has been closed since objectui#2614, so the key was never silently dropped — until #7832 the rejection just could not tell you which key to write instead.`,aliases:{showWhen:`visibleWhen`},guidance:{visible:"`visible` is the CUSTOM row-action spelling (`actions[].visible`), where one key takes either form. This override splits them: write `enabled: false` for the object-level on/off, or `visibleWhen: <CEL over record.*>` for a per-record predicate (FALSE hides that row's button).",disabled:"`disabled` is the CUSTOM row-action spelling (`actions[].disabled`). The per-record form here is `disabledWhen: <CEL over record.*>` (TRUE renders that row's button disabled); there is no boolean `disabled` — switch the affordance off with `enabled: false`."}},{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:C.optional().describe(`CEL predicate over the record in scope (row record for edit/delete, host record for a related-list create/import toolbar); false → hide the button. Fail-closed.`),disabledWhen:C.optional().describe(`CEL predicate over the record in scope (row record for edit/delete, host record for a related-list create/import toolbar); true → render the button disabled. Fail-soft.`)}).describe(`Boolean-or-predicates override for a built-in CRUD affordance.`),jc="`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 WRITABLE affordances — create, edit, delete and exportCsv (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. CSV `import` is deliberately NOT in that default (#4671): it stays opt-in per object via `userActions: { import: true }`, which is what a v16 `system` object already resolved to. Run `os migrate meta --from 16` to rewrite existing sources automatically.",Mc={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."},Nc=A({surface:`this object`,aliases:{capabilities:`enable`,features:`enable`},guidance:Mc,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."},{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`?jc: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`,`business_unit`,`org`,`none`],{error:"`ownership` is the record-ownership model — one of 'user' (default) | 'business_unit' | '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 plus owning_business_unit_id) | business_unit (unit-owned: owning_business_unit_id only, no owner_id) | org | none (no per-record owner, neither anchor). Distinct from the package own/extend contribution kind.`),userActions:A({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.union([t.z.boolean(),Ac]).optional().describe(`Show generic "New" button. Boolean, or an object adding visibleWhen/disabledWhen CEL predicates evaluated once per toolbar against the record in scope (the host record on a related list).`),import:t.z.union([t.z.boolean(),Ac]).optional().describe(`Show CSV import wizard entry. Boolean, or an object adding visibleWhen/disabledWhen CEL predicates evaluated once per toolbar against the record in scope (the host record on a related list).`),edit:t.z.union([t.z.boolean(),Ac]).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(),Ac]).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),A({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: `'user'` (or omitted) injects it, while `'org'` and `'none'` BOTH skip it and no `owner_id` is injected at all — `'org'` for an org-wide catalog (Dataverse-style), `'none'` for a junction/link table. `'business_unit'` skips it too, for a different reason: that tier is owned by an org UNIT rather than a person, so it carries `owning_business_unit_id` and deliberately no `owner_id` (ADR-0117 D1). `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 the ownership anchors (`owner_id` and `owning_business_unit_id`) are 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:W.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")`}),lt).describe(`Field definitions map. Keys must be snake_case identifiers.`),indexes:t.z.array(vc).optional().describe(`Database performance indexes`),fieldGroups:t.z.array(kc).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:xc.optional().describe(`Multi-tenancy configuration for SaaS applications`),access:Sc.optional().describe(`[ADR-0066 D2] Object exposure posture (public-by-default vs private secure-by-default).`),requiredPermissions:wc.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:Oc.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(Is).optional().describe(`Object-level validation rules`),activityMilestones:t.z.array(A({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:be.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(),Qo).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. Entries must name a STORED column: a virtual `formula` field is computed on read and materializes no column, so searching it can never match and it is refused (#6674) — mirror the value onto a stored text field and declare that."),enable:_c.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:A({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(cc).optional().describe(`Actions associated with this object (auto-populated from top-level actions via objectName)`),protection:Ea.optional().describe(`Package author protection block — lock policy for this object.`),...y});function Pc(e){return e.split(`_`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function Fc(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 Ic(e,t){let n,r=1/0;for(let i of t){let t=Fc(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 Lc(e,t,n){let r=typeof e==`string`&&e.length>0?e:`<unnamed>`,i=t.map(e=>{let t=Mc[e];if(t)return` \u2022 ${t}`;let r=Ic(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(`, `)}.
18
- These keys would previously have been stripped silently at build, shipping dead metadata with no diagnostic (ADR-0032 "no silent failure", issue #1535).
19
-
20
- ${i.join(`
21
- `)}
22
-
23
- Remove the unknown key(s), fix the typo, or move the logic to a supported mechanism.`)}var Rc=new Set;function zc(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>`;Rc.has(i)||(Rc.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 Bc(e,t,n){if(t!==`system-data`)return;let r=Gc({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 already grants create, edit, delete and exportCsv, so \`userActions\` is for NARROWING those (#3355). The one verb it does not grant is CSV \`import\`, which is opt-in per object (#4671).`)}function Vc(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 Hc(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 Uc=n(()=>{let e=Nc.parse.bind(Nc),t=Nc.safeParse.bind(Nc);return Object.assign(Nc,{parse(t,n){return e(Hc(Vc(t)),n)},safeParse(e,n){return t(Hc(Vc(e)),n)},create:e=>{let t=e,n=Object.keys(Nc.shape),r=Object.keys(t).filter(e=>!n.includes(e));if(r.length>0)throw Lc(t.name,r,n);zc(t.name,t.fields,t.managedBy),Bc(t.name,t.managedBy,t.userActions);let i={...t,label:t.label??Pc(t.name)};return Nc.parse(i)}})}),Wc={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:!1,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 Gc(e){let t=Wc[e?.managedBy??`platform`]??Wc.platform,n=e?.userActions??{},r=Kc(n.create,t.create),i=Kc(n.import,t.import),a=Kc(n.edit,t.edit),o=Kc(n.delete,t.delete),s={create:r.enabled,import:i.enabled,edit:a.enabled,delete:o.enabled,exportCsv:n.exportCsv??t.exportCsv};return r.predicates&&(s.createPredicates=r.predicates),i.predicates&&(s.importPredicates=i.predicates),a.predicates&&(s.editPredicates=a.predicates),o.predicates&&(s.deletePredicates=o.predicates),s}function Kc(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`,`overlay`]),n(()=>A({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(),lt).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(Is).optional().describe(`Additional validation rules to merge into the target object`),indexes:t.z.array(vc).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 qc=t.z.enum([`own`,`own_and_reports`,`unit`,`unit_and_below`,`org`]),Jc={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`},Yc=n(()=>A({surface:`this object permission`,aliases:Jc,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.`},{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) — bypasses sharing rules and ownership on the objects record sharing enforces on; on an object with NO owner field sharing abstains, so the platform created_by write floor still applies (#6698).`),readScope:qc.optional().describe(`[ADR-0057 D1] Read depth: own|unit|unit_and_below|org`),writeScope:qc.optional().describe(`[ADR-0057 D1] Write depth: own|unit|unit_and_below|org`)})),Xc=n(()=>Yc.extend({apiOperations:t.z.array(pc).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()),Zc=n(()=>A({surface:`this admin scope`,history:`Until #4001 these were dropped silently — the scope still parsed, so a delegation boundary the author intended was never enforced.`},{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`)})),Qc=n(()=>A({surface:`this field permission`,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.`},{readable:t.z.boolean().default(!0).describe(`Field read access`),editable:t.z.boolean().default(!1).describe(`Field edit access`)})),$c={objectpermissions:`objects`,entities:`objects`,entitypermissions:`objects`,fieldpermissions:`fields`,fls:`fields`,fieldlevelsecurity:`fields`,tabs:`tabPermissions`,tabvisibility:`tabPermissions`,rls:`rowLevelSecurity`,rowlevelsecurityrules:`rowLevelSecurity`,policies:`rowLevelSecurity`};n(()=>A({surface:`this permission set`,aliases:$c,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.`},{name:x.describe(`Permission set name, unique per organization (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(),Yc).describe(`Entity permissions`),fields:t.z.record(t.z.string(),Qc).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(ks).optional().describe(`Row-level security policies (see rls.zod.ts for full spec)`),adminScope:Zc.optional().describe(`[ADR-0090 D12] Scoped delegated-administration grant (BU subtree + assignable-set allowlist)`),protection:Ea.optional().describe(`Package author protection block — lock policy for this permission set.`),...y}));var el=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:el.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 tl=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:tl.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 nl=n(()=>t.z.enum([`logic`,`data`,`io`,`human`,`control`,`custom`]).describe(`Action palette category`)),rl=n(()=>t.z.enum([`flow`,`approval`]).describe(`Authoring paradigm that may offer this action`)),il=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:nl.default(`custom`).describe(`Palette category`),paradigms:t.z.array(rl).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:v("`ActionDescriptor.isAsync` was removed in @objectstack/spec 17 (#6748, ADR-0049) — no execution path ever read it, so declaring it never made a node suspend and omitting it never stopped one. Delete the key. The live mechanism is two-part: an executor suspends by RETURNING `suspend: true` from `execute()`, and its descriptor must declare `supportsPause: true` (plus the `resumeAuthority` its pauses need) or the engine refuses that suspension (#6667). Declaring `isAsync: true` alongside `supportsPause: true` was always redundant; declaring it alone was always inert."),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). Carries no schema default so an omission stays observable — and an omission is fail-CLOSED at run time, equivalent to 'service': a pausing node whose pause is open to the generic route must declare 'any' explicitly (#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)`)),al=n(()=>t.z.string().describe(`BCP-47 Language Tag (e.g. en-US, zh-CN)`)),G=`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.`,ol=n(()=>A({surface:`this field translation`,history:G,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`)),sl=n(()=>A({surface:`this action result dialog translation`,history:G,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`)),cl=e=>A({surface:e,history:G,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`),description:t.z.string().optional().describe(`Translated action description — the explanatory line under the title in the action's param dialog`),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(),A({surface:`this action parameter translation`,history:G,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:sl.optional().describe(`Translations for the action result dialog`)}),K=n(()=>A({surface:`this object translation`,history:G,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(),ol).optional().describe(`Field-level translations`),_views:t.z.record(t.z.string(),A({surface:`this view translation`,history:G,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:A({surface:`this view empty-state translation`,history:G,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(),cl(`this object action translation`)).optional().describe(`Action translations keyed by action name`),_sections:t.z.record(t.z.string(),A({surface:`this section translation`,history:G,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`),_tabs:t.z.record(t.z.string(),A({surface:`this view tab translation`,history:G,aliases:{name:`label`,title:`label`,heading:`label`,text:`label`}},{label:t.z.string().optional().describe(`Translated tab label`)})).optional().describe(`Filter-preset tab translations keyed by tab name`)}).describe(`Translation data for a single object`)),q={screens:"`screens` is not a top-level translation group — screen copy is addressed under the flow that owns it: 'flows.<flow_name>.screens.<node_id>.title' and 'flows.<flow_name>.screens.<node_id>.fields.<field_name>.label'.",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)"},ll="a screen field declares no help/hint copy — `ScreenFieldConfig` is `name`/`label`/`type`/`required`/`options`/`defaultValue`/`placeholder`/`visibleWhen`, so there is nothing here to translate. Use `placeholder` for the in-input hint the field does declare.",ul="select-option labels are not translatable on a screen field: `ScreenFieldConfig.options[].value` is unconstrained (numbers and booleans are legal), so an option map keyed by value — the shape `objects.<object>.fields.<field>.options` uses — cannot address them unambiguously. Author the option labels on the node's `config`.",dl=()=>({objects:t.z.record(t.z.string(),K).optional().describe(`Object translations keyed by object name`),apps:t.z.record(t.z.string(),A({surface:`this app translation`,history:G,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(),A({surface:`this navigation group translation`,history:G,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(),cl(`this global action translation`)).optional().describe(`Global action translations keyed by action name`),dashboards:t.z.record(t.z.string(),A({surface:`this dashboard translation`,history:G,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(),A({surface:`this dashboard header action translation`,history:G,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(),A({surface:`this widget translation`,history:G,aliases:{label:`title`,name:`title`,heading:`title`,subtitle:`subCaption`}},{title:t.z.string().optional().describe(`Translated widget title`),description:t.z.string().optional().describe(`Translated widget description`),subCaption:t.z.string().optional().describe("Translated metric sub-caption (overlays the widget's `options.description`, a different authored field from `description`)")})).optional().describe(`Widget translations keyed by widget id`)})).optional().describe(`Dashboard translations keyed by dashboard name`),pages:t.z.record(t.z.string(),A({surface:`this page translation`,history:G,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"),components:t.z.record(t.z.string(),A({surface:`this page component translation`,history:G,aliases:{name:`title`,heading:`title`,text:`label`,caption:`description`,help:`description`,helpText:`description`,empty:`emptyText`,emptyState:`emptyText`,submit:`submitLabel`}},{title:t.z.string().optional().describe("Translated component title (`page:card`, `record:related_list`, …)"),description:t.z.string().optional().describe(`Translated component description / supporting copy`),label:t.z.string().optional().describe("Translated component label — overlays the component's own `label` when it declares one, else `properties.label`"),placeholder:t.z.string().optional().describe("Translated input placeholder (`element:record_picker`, `element:text_input`)"),emptyText:t.z.string().optional().describe("Translated empty-state text (`element:record_picker`)"),submitLabel:t.z.string().optional().describe("Translated submit button label (`element:form`)")})).optional().describe("Per-component copy keyed by component id (`PageComponentSchema.id`)")})).optional().describe(`Page translations keyed by page name`),flows:t.z.record(t.z.string(),A({surface:`this flow translation`,history:G,aliases:{name:`label`,title:`label`,nodes:`screens`,steps:`screens`,screen:`screens`,pages:`screens`},guidance:{successMessage:"`flow.successMessage` / `flow.errorMessage` are not part of the flows translation surface — it carries the flow label, per-screen headings and per-screen field copy (#7646). The terminal toast renders the string authored on the flow.",errorMessage:"`flow.errorMessage` / `flow.successMessage` are not part of the flows translation surface — it carries the flow label, per-screen headings and per-screen field copy (#7646). The terminal toast renders the string authored on the flow."}},{label:t.z.string().optional().describe(`Translated flow label`),screens:t.z.record(t.z.string(),A({surface:`this flow screen translation`,history:G,aliases:{label:`title`,name:`title`,heading:`title`,header:`title`,inputs:`fields`,items:`fields`},guidance:{description:"`description` — a screen's body text (`config.description`) — is not part of the flows translation surface, which carries the heading (`title`) and per-field copy (#7646)."}},{title:t.z.string().optional().describe("Translated screen heading (overlays `config.title`, or the node label when the screen declares none)"),fields:t.z.record(t.z.string(),A({surface:`this flow screen field translation`,history:G,aliases:{name:`label`,title:`label`,text:`label`},guidance:{help:ll,helpText:ll,hint:ll,tooltip:ll,description:ll,options:ul,choices:ul,values:ul}},{label:t.z.string().optional().describe(`Translated screen field label`),placeholder:t.z.string().optional().describe(`Translated screen field placeholder`)})).optional().describe("Screen field translations keyed by field name (`ScreenFieldConfig.name`)")})).optional().describe("Screen translations keyed by screen node id (`FlowNode.id`, the client's `ScreenSpec.nodeId`)")})).optional().describe(`Screen-flow translations keyed by flow name`),settings:t.z.record(t.z.string(),A({surface:`this settings manifest translation`,history:G,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(),A({surface:`this settings group translation`,history:G,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(),A({surface:`this setting translation`,history:G,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(),A({surface:`this settings action translation`,history:G,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(),A({surface:`this metadata-form translation`,history:G,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(),A({surface:`this metadata-form section translation`,history:G,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(),A({surface:`this metadata-form field translation`,history:G,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:A({surface:`the shared Settings UI translations`,history:G},{sourceLabels:A({surface:`the settings source-badge labels`,history:G,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`)}),fl=n(()=>A({surface:`this locale of the translation bundle`,history:G,guidance:q,aliases:{object:`objects`,fields:`objects`,app:`apps`,page:`pages`,dashboard:`dashboards`,flow:`flows`,setting:`settings`,message:`messages`,strings:`messages`,labels:`messages`,actions:`globalActions`},extraKeys:[`locale`]},dl()).describe(`Translation data for objects, apps, and UI messages`));n(()=>t.z.record(al,fl).describe(`Map of locale codes to translation data`)),n(()=>A({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:al.describe(`Default locale (e.g., "en")`),supportedLocales:t.z.array(al).describe(`Supported BCP-47 locale codes`),fallbackLocale:al.optional().describe(`Fallback locale code`)}).describe(`Internationalization configuration`)),n(()=>A({surface:`this translation`,history:G,guidance:q,aliases:{object:`objects`,app:`apps`,page:`pages`,flow:`flows`,setting:`settings`,message:`messages`,strings:`messages`,labels:`messages`,actions:`globalActions`,lang:`locale`,language:`locale`}},{...dl(),locale:al.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`),...y}).describe("One locale of translations — the `translation` metadata type"));var pl=n(()=>t.z.enum([`missing`,`redundant`,`stale`]).describe(`Translation diff status: missing from bundle, redundant (no matching metadata), or stale (metadata changed)`)),ml=n(()=>t.z.object({key:t.z.string().describe(`Dot-path translation key`),status:pl.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`)),hl=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(ml).describe(`Detailed diff items`),breakdown:t.z.array(hl).optional().describe(`Per-group coverage breakdown`)}).describe(`Aggregated translation coverage result`));var gl=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:x.describe(`Machine name (snake_case)`),format:gl.optional().describe(`Source file format`)}).describe(`Base metadata record fields shared across kernel and system`));var _l=n(()=>t.z.enum([`filesystem`,`memory`,`none`])),vl=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:_l.default(`none`).describe(`Fallback strategy when datasource is unavailable`),rootDir:t.z.string().optional().describe(`Root directory path`),formats:t.z.array(gl).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 yl=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`)})),bl=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(yl).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()})),xl=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`)})),Sl=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(xl).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 Cl=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`)})),wl=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.capability.agent.tool.skill`.split(`.`))),Tl=t.z.object({type:wl.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(cc).optional().describe(`Declarative type-level actions (e.g. datasource "Test connection"), reusing ActionSchema; merged with plugin-registered actions when emitted`)});n(()=>Tl.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 El=n(()=>t.z.object({types:t.z.array(wl).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`)})),Dl=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`)})),Ol=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`)})),kl=n(()=>t.z.object({storage:vl.describe(`Storage backend configuration`),customizationPolicies:t.z.array(Cl).optional().describe(`Default customization policies per type`),mergeStrategy:Sl.optional().describe(`Merge strategy for package upgrades`),additionalTypes:t.z.array(Tl.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:kl.optional().describe(`Plugin configuration`)}));var Al=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`)})),jl=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`)})),Ml=n(()=>t.z.enum([`full`,`partial`,`experimental`,`deprecated`]).describe(`Level of protocol conformance`)),Nl=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`)),Pl=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:Nl,specification:t.z.string().optional().describe(`URL or path to protocol specification`),description:t.z.string().optional()})),Fl=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`)})),Il=n(()=>t.z.object({protocol:Pl,conformance:Ml.default(`full`),implementedFeatures:t.z.array(t.z.string()).optional().describe(`List of implemented feature names`),features:t.z.array(Fl).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()})),Ll=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:Nl,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`)})),Rl=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`)})),zl=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`)})),Bl=n(()=>t.z.object({implements:t.z.array(Il).optional().describe(`List of protocols this plugin conforms to`),provides:t.z.array(Ll).optional().describe(`Services/APIs this plugin offers to others`),requires:t.z.array(Rl).optional().describe(`Required plugins and their capabilities`),extensionPoints:t.z.array(zl).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`)}));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 Vl=[`ui`,`driver`,`server`,`app`,`theme`,`agent`,`objectql`],Hl=[`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`,...Vl]).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 Ul=t.z.enum([`insert`,`update`,`upsert`,`replace`,`ignore`]),Wl=n(()=>A({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:Ul.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`),...y})),Gl={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`},Kl={defaultopen:`expanded`,open:`expanded`,collapsed:`expanded`,isopen:`expanded`},ql={defaultopen:`type: 'group' (with expanded)`,open:`type: 'group' (with expanded)`,collapsed:`type: 'group' (with expanded)`,isopen:`type: 'group' (with expanded)`},Jl=new Set([`object`,`group`]),Yl={name:`id`,sort:`order`,sortorder:`order`,position:`order`},Xl=Object.fromEntries([`label`,`title`,`icon`,`badge`,`badgeVariant`,`visible`,`requiredPermissions`,`requiresObject`,`requiresService`].map(e=>[e,`\`${e}\` is not a separator key \u2014 a separator is a divider and declares only \`id\` and \`order\`. Put labels, icons, badges and visibility gating on the items it separates, or use \`{ type: 'group', label: '\u2026' }\` for a titled section.`])),Zl=e=>({surface:`this \`${e}\` navigation item`,aliases:{...e===`separator`?Yl:Gl,...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`?Kl:ql},...Jl.has(e)?{extraKeys:[`children`]}:{},guidance:{...Jl.has(e)?{}:{children:"`children` is only meaningful on a `group` item (or an `object` item nesting its views). Nest entries under `{ type: 'group', children: [...] }`."},...e===`separator`?Xl:{}},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)."}),J=t.z.object({id:x.describe(`Unique identifier for this navigation item (lowercase snake_case)`),label:V.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:C.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`)}),Ql=n(()=>A(Zl(`object`),{...J.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.`),runAction:t.z.string().optional().describe(`Auto-run this declared action once on arrival at the object's list surface (deep-link "navigate = run action", #4848). Must name an action defined in the stack; validated by defineStack and lint. Not combinable with recordId.`)})),$l=(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."}),e.runAction&&e.recordId&&n.addIssue({code:t.z.ZodIssueCode.custom,path:[`runAction`],message:"`runAction` cannot be combined with `recordId` — the auto-run fires on the object's LIST surface, and a recordId entry lands on a record detail instead, so the declared action would never run. Remove `recordId` to keep the list deep-link, or remove `runAction` to keep the record deep-link."})},eu=n(()=>A(Zl(`dashboard`),{...J.shape,type:t.z.literal(`dashboard`),dashboardName:t.z.string().describe(`Target dashboard name`)})),Y=n(()=>A(Zl(`page`),{...J.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`)})),X=n(()=>A(Zl(`url`),{...J.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`)})),tu=n(()=>A(Zl(`report`),{...J.shape,type:t.z.literal(`report`),reportName:t.z.string().describe(`Target report name`)})),nu=n(()=>A(Zl(`action`),{...J.shape,type:t.z.literal(`action`),actionDef:A({surface:`this nav item's action definition`,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.`},{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`)}).describe(`Action definition to execute when clicked`)})),ru=n(()=>A(Zl(`component`),{...J.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`)})),iu=n(()=>A(Zl(`group`),{...J.shape,type:t.z.literal(`group`),expanded:t.z.boolean().default(!1).describe(`Default expansion state in sidebar`)})),au=n(()=>A(Zl(`separator`),{type:t.z.literal(`separator`),id:x.optional().describe(`Optional id for the separator`),order:t.z.number().optional().describe(`Sort order within the same level (lower = first)`)})),Z=t.z.lazy(()=>t.z.discriminatedUnion(`type`,[Ql.extend({children:t.z.array(Z).optional().describe(`Child navigation items (e.g. specific views)`)}).strict().superRefine($l),eu,Y,X,tu,nu,ru,au,iu.extend({children:t.z.array(Z).describe(`Child navigation items`)}).strict()])),ou=n(()=>A({surface:`this navigation contribution`,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.`},{app:x.describe(`Target app name to contribute navigation into (e.g. "setup")`),group:x.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(Z).describe(`Navigation items contributed into the target app/group`)}).describe(`A navigation contribution: a package injecting nav items into an app it does not own (ADR-0029 D7)`)),su=n(()=>A({surface:`this app's branding block`,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.`},{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`)})),cu="`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.",lu="`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.",uu='`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.',du=n(()=>A({surface:`this navigation area`,aliases:{title:`label`,name:`id`,items:`navigation`,children:`navigation`},guidance:{order:cu,sort:cu,visible:lu,visibleWhen:lu,visibleOn:lu,requiredPermissions:uu,permissions:uu},history:`Until #4001 these were dropped silently — the area still parsed, so its gating or ordering was quietly ignored.`},{id:x.describe(`Unique area identifier (lowercase snake_case)`),label:V.describe(`Area display label`),icon:t.z.string().optional().describe(`Area icon name`),description:V.optional().describe(`Area description`),navigation:t.z.array(Z).describe(`Navigation items within this area`)})),fu={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."},pu=n(()=>A({surface:`this app context selector`,aliases:{name:`id`,title:`label`,source:`optionsSource`,options:`optionsSource`},guidance:fu,history:`Until #4001 these were dropped silently — the selector still parsed, so its scope variable behaved differently than declared.`},{id:x.describe(`Selector id; selected value is exposed as the nav template var {<id>}`),label:V.describe(`Dropdown label`),icon:t.z.string().optional().describe(`Icon name`),optionsSource:A({surface:`this context selector's options source`,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.`},{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(A({surface:`this context-selector option filter`,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.`},{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)`)})).optional().describe(`Predicates (AND) each option row must satisfy`)}).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`)})),mu="`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.",hu='Publish state is not authorable on an app. The ADR-0045 publish gate is the machine-managed `_unpublished` key: the AI materialization path sets it, and `POST /packages/:id/publish-drafts` (the "Publish" button) clears it. Delete this key. If you wanted to keep the app out of the App Switcher — the personal-settings case, e.g. Account — that is `hidden: true`, which is navigation presentation ONLY and never affects access (#4829).',gu=n(()=>A({surface:`this app`,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:mu,homepage:mu,landingpage:mu,unpublished:hu,published:hu,draft:hu},history:`Until #4001 these were dropped silently — the app still parsed, so navigation or gating the author declared never reached the shell.`},{name:x.describe(`App unique machine name (lowercase snake_case)`),label:V.describe(`App display label`),version:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),description:V.optional().describe(`App description`),icon:t.z.string().optional().describe(`App icon used in the App Launcher`),branding:su.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 only — never an access gate)`),_unpublished:t.z.boolean().optional().describe(`Machine-managed publish gate (ADR-0045 §3) — true = unpublished, externally unobservable. Written by AI materialization, cleared by publish-drafts. Never authored.`),navigation:t.z.array(Z).optional().describe(`Full navigation tree for the app sidebar`),areas:t.z.array(du).optional().describe(`Navigation areas for partitioning navigation by business domain`),contextSelectors:t.z.array(pu).optional().describe(`App-level scope dropdowns whose value is injected into nav items as {<id>} template vars`),homePageId:v(mu),requiredPermissions:t.z.array(t.z.string()).optional().describe(`Permissions required to access this app`),objects:v('`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. Run `os migrate meta --from 16` to rewrite existing sources automatically.'),apis:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),sharing:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),embed:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),mobileNavigation:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),defaultAgent:x.optional().describe(`Platform agent bound to this app's ambient chat ('ask' is the implicit default; 'build' for authoring surfaces) — ADR-0063 §1`),aria:v("`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 page component that renders the DOM node instead (`page.components[].aria`; `page.aria` and the list view `aria` are live too). Delete the key. Run `os migrate meta --from 16` to rewrite existing sources automatically."),protection:Ea.optional().describe(`Package author protection block — lock policy for this app.`),...y})),_u=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)`),vu=t.z.union([t.z.array(t.z.string()),_u]),yu=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)`),bu=t.z.enum([`node`,`sandbox`,`worker`]).describe(`Plugin trust tier (ADR-0025 §3.6)`),xu=t.z.enum([`bundled`,`manifest-deps`]).describe(`Dependency packaging strategy (ADR-0025 §3.3)`),Su=t.z.record(t.z.string(),t.z.string()).describe(`Per-file content digests of the plugin artifact (ADR-0025 §3.2)`),Q=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`,...Vl,`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:vu.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", "mongodb")`),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(Wl).optional().describe(`Initial seed data (prefer top-level data field)`),capabilities:Bl.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(ou).optional().describe(`Navigation items this package contributes into apps owned by other packages`),loading:v("`manifest.loading` was removed in @objectstack/spec 17.0.0 (#4914, ADR-0049 enforce-or-remove) — the entire block (`strategy`, `preload`, `codeSplitting`, `dynamicImport`, `initialization`, `dependencyResolution`, `hotReload`, `caching`, `sandboxing`, `monitoring`) had no runtime reader in any repo, so authoring it configured nothing. Delete the key. Plugins are composed at boot — `defineStack` registers them and the kernel runs `init` then `start` in an order topologically resolved from each composed plugin's own `dependencies` / `optionalDependencies` (`resolvePluginOrder`); the set is fixed until the process restarts. ⚠️ `loading.sandboxing` in particular never isolated anything: it did not run plugins in a process, vm, iframe or web-worker, and `allowedServices` gated no call. If you were relying on it for isolation, you had none — use the plugin trust tier (`manifest.runtime`) and the permission declarations, which are enforced."),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:yu.optional().describe("Plugin compatibility ranges (ADR-0025 §3.2; supersedes `engine`)"),runtime:bu.optional().describe(`Plugin trust tier (ADR-0025 §3.6)`),packaging:xu.optional().describe(`Dependency packaging strategy (ADR-0025 §3.3)`),integrity:Su.optional().describe(`Per-file content digests of the plugin artifact (ADR-0025 §3.2)`)}),Cu=t.z.enum([`satisfied`,`needs_install`,`needs_upgrade`,`conflict`]).describe(`Resolution status for a dependency`),wu=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:Cu.describe(`Resolution status`),conflictReason:t.z.string().optional().describe(`Explanation of the conflict`)}).describe(`Resolution result for a single dependency`)),Tu=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`)),Eu=n(()=>t.z.object({dependencies:t.z.array(wu).describe(`Resolution result for each dependency`),canProceed:t.z.boolean().describe(`Whether installation can proceed`),requiredActions:t.z.array(Tu).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`)),Du=t.z.enum([`installed`,`disabled`,`installing`,`upgrading`,`uninstalling`,`error`]).describe(`Package installation status`),Ou=n(()=>t.z.object({manifest:Q.describe(`Full package manifest`),status:Du.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 ku=n(()=>t.z.object({status:Du.optional().describe(`Filter by package status`),type:Q.shape.type.optional().describe(`Filter by package type`),enabled:t.z.boolean().optional().describe(`Filter by enabled state`)}).describe(`List packages request`)),Au=n(()=>t.z.object({packages:t.z.array(Ou).describe(`List of installed packages`),total:t.z.number().describe(`Total package count`)}).describe(`List packages response`)),ju=n(()=>t.z.object({id:t.z.string().describe(`Package identifier`)}).describe(`Get package request`)),Mu=n(()=>t.z.object({package:Ou.describe(`Package details`)}).describe(`Get package response`)),Nu=n(()=>t.z.object({manifest:Q.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`)),Pu=n(()=>t.z.object({package:Ou.describe(`Installed package details`),message:t.z.string().optional().describe(`Installation status message`),dependencyResolution:Eu.optional().describe(`Dependency resolution result from install analysis`)}).describe(`Install package response`)),Fu=n(()=>t.z.object({id:t.z.string().describe(`Package ID to uninstall`)}).describe(`Uninstall package request`)),Iu=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`)),Lu=n(()=>t.z.object({id:t.z.string().describe(`Package ID to enable`)}).describe(`Enable package request`)),Ru=n(()=>t.z.object({package:Ou.describe(`Enabled package details`),message:t.z.string().optional().describe(`Enable status message`)}).describe(`Enable package response`)),zu=n(()=>t.z.object({id:t.z.string().describe(`Package ID to disable`)}).describe(`Disable package request`)),Bu=n(()=>t.z.object({package:Ou.describe(`Disabled package details`),message:t.z.string().optional().describe(`Disable status message`)}).describe(`Disable package response`)),Vu=n(()=>t.z.object({trigger:t.z.string(),payload:t.z.record(t.z.string(),t.z.unknown())})),Hu=n(()=>t.z.object({success:t.z.boolean(),jobId:t.z.string().optional(),result:t.z.unknown().optional()})),Uu=n(()=>t.z.object({actions:t.z.array(il).describe(`Registered action descriptors (built-in + plugin)`),total:t.z.number().int().nonnegative().describe(`Number of descriptors returned (after any filters)`)})),Wu=n(()=>t.z.object({})),Gu=n(()=>cr.partial().required({version:!0}).extend({apiName:t.z.string().optional().describe("API name (deprecated — use `name`; removed in protocol 18)")})),Ku=n(()=>t.z.object({})),qu=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)`)})),Ju=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`)})),Yu=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),items:t.z.array(t.z.unknown()).describe(`Array of metadata items`)})),Xu=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`)})),Zu={lock:pe.optional().describe("Resolved lock verdict for this item (ADR-0010 §3.3). `none` means unlocked; `no-overlay` / `no-delete` / `full` refuse the corresponding write with 403 `ITEM_LOCKED`. Resolved from the document's `_lock`, with the packaged artifact winning over any org overlay."),lockReason:t.z.string().optional().describe("Human-readable explanation shown next to a refused write. Present only when the resolved item declares `_lockReason`."),lockSource:me.optional().describe("Which layer asserted the lock. Present only when the resolved item declares `_lockSource`."),lockDocsUrl:t.z.string().optional().describe("Documentation link surfaced beside `lockReason`. Present only when the resolved item declares `_lockDocsUrl`."),provenance:he.optional().describe("Where the item came from (package | org | env-forced). Present only when the resolved item declares `_provenance`."),packageId:t.z.string().optional().describe("Owning package machine id. Present only when the resolved item declares `_packageId`."),packageVersion:t.z.string().optional().describe("Owning package version. Present only when the resolved item declares `_packageVersion`."),editable:t.z.boolean().optional().describe("Whether an overlay write is permitted — false iff `lock` is `no-overlay` or `full`. A derived verdict: do not recompute it from `lock` client-side."),deletable:t.z.boolean().optional().describe("Whether deleting the overlay is permitted — false iff `lock` is `no-delete` or `full`."),resettable:t.z.boolean().optional().describe(`Whether the item can be reset to its packaged default — true iff it is artifact-backed, i.e. there is a baseline to reset TO.`)},Qu=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`),...Zu})),$u=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name (canonical singular)`),name:t.z.string().describe(`Item name`),code:t.z.unknown().describe("LAYER 1 — the packaged artifact baseline exactly as shipped, before any tenant customization. `null` when no artifact ships this item (it exists only as an overlay)."),overlay:t.z.unknown().describe("LAYER 2 — the stored customization row ALONE, not merged with `code`. `null` when this tenant has not customized the item."),overlayScope:t.z.enum([`org`,`env`]).nullable().describe("Which scope the `overlay` row was read from — `org` for a tenant overlay, `env` for an environment-level one. `null` exactly when `overlay` is null."),effective:t.z.unknown().describe("LAYER 3 — the merged result, i.e. the value an ordinary `GET /meta/:type/:name` would return under `item`. `null` when the item resolves to nothing at all."),_diagnostics:Ol.optional().describe('Load-time spec-validation verdict for `effective`, so the Studio edit page can raise invalid-metadata banners and inline field errors without a second round trip. ABSENT for metadata types that register no Zod schema (function / service / router) — absence means "no opinion", never "valid".'),...Zu,lock:pe.describe(`Resolved lock verdict (ADR-0010 §3.3), artifact winning over overlay. Always present on this path.`),editable:t.z.boolean().describe(`Whether an overlay write is permitted. Always present on this path.`),deletable:t.z.boolean().describe(`Whether deleting the overlay is permitted. Always present on this path.`),resettable:t.z.boolean().describe(`Whether the item can be reset to its packaged default. Always present on this path.`)})),ed=n(()=>t.z.object({rule:t.z.string().describe("Stable diagnostic rule id (`flow-multi-write-unfiltered`, `approval-expression-invalid`, …). Machine-readable and stable across releases — the key a renderer groups or suppresses by."),path:t.z.string().describe("Config path inside the SUBMITTED body (`flows[0].nodes[1].config.multi`), so an editor can jump to the offending key. May be empty when the finding is about the item as a whole."),where:t.z.string().describe('Human-readable location — `flow "leave_approval" · node "approve"`. Prose for a person; use `path` for anything mechanical.'),message:t.z.string().describe(`What is wrong, in the rule author's own words.`),hint:t.z.string().describe(`How to fix it.`),severity:t.z.enum([`error`,`warning`,`info`]).describe("How the gate treated this finding. `error` means the write was REFUSED (these appear on the 422, never on a 2xx); `warning` / `info` are advisory — the write succeeded and the finding is FYI.")})),td=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`)})),nd=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.'),advisories:t.z.array(ed).optional().describe('Non-gating findings from the #4463 runtime authoring gate — the same shared author-time rules `os validate` / `os build` / `os lint` run, applied to this body on its way to `active`. The write SUCCEEDED; these are what the gate has to say about it anyway (#4717, closing #4463 D3). Present ONLY when at least one advisory was raised — an empty array is never emitted, so a clean save\'s response bytes are unchanged and absence means "nothing to report", never "the gate did not run". Advisory by construction: every entry has `severity` `warning` or `info`, because an `error` finding refuses the write and arrives as the 422 `invalid_metadata` envelope instead of here. A caller that ignores this key behaves exactly as before. Runtime-only: the CLI surfaces the same findings on its own stdout, and a Studio / MCP / AI author has no CLI at all, which is the gap #4463 exists to close. NOTE the door asymmetry — `POST /meta/:type/:name/publish` does not carry this field yet (its declaration landed separately as #7294); the gate runs on both doors, only the save door reports.'),message:t.z.string().optional()})),rd=n(()=>t.z.object({success:t.z.boolean().describe("Always true on a 2xx — the draft was promoted. It does NOT cover the best-effort side effects below, each of which reports its own `success`."),version:t.z.string().describe("Content hash of the just-promoted 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 `op='publish'` metadata event this promotion appended to the item history (sys_metadata_history.event_seq). Orders writes; unlike `version` it is not an OCC token."),seedApplied:t.z.object({success:t.z.boolean().describe(`False when the seed rows did not fully land. The publish itself still succeeded — check this rather than assuming data went live.`),inserted:t.z.number().int().describe(`Rows created by the externalId-keyed upsert.`),updated:t.z.number().int().describe(`Rows updated by the externalId-keyed upsert.`),error:t.z.string().optional().describe(`Single failure message, present when the seed apply threw before the loader ran (including "no readable seed bodies").`),errors:t.z.array(t.z.unknown()).optional().describe(`Per-record failures reported by the seed loader. Present only when the loader ran and returned a non-empty error list.`)}).optional().describe("Outcome of materializing a published `seed` body into data rows. Present ONLY when the published type is `seed` — publishing a seed is what makes its rows live, so the load rides along with the metadata promotion. Best-effort: a seed-load problem is surfaced here, never thrown, so a caller must check `seedApplied.success` instead of assuming the 200 covered the data. Absent on the batch path, which suppresses the per-item apply and loads every seed body in one later pass."),materializeApplied:t.z.object({success:t.z.boolean().describe(`False when the materializer threw or reported failure; the publish still succeeded.`),inserted:t.z.number().int().describe(`Data-plane rows created by the materializer.`),updated:t.z.number().int().describe(`Data-plane rows updated by the materializer.`),error:t.z.string().optional().describe("Materializer failure message, present only when `success` is false.")}).optional().describe('Outcome of the ADR-0086 P2 publish-time materializer — the step that projects the published body into its data-plane row (e.g. `permission` → `sys_permission_set`, under the owning package). Present ONLY when a materializer is registered for this metadata type, which is why it is optional: its absence means "no materializer ran", never "it failed". Best-effort, same contract as `seedApplied`.'),projectionApplied:t.z.object({success:t.z.boolean().describe(`False when the projector threw; the metadata promotion 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. The same receipt {@link SaveMetaItemResponseSchema} carries, because the projector runs on BOTH write doors: a direct active save and this draft→active promotion. Present ONLY when a projector is registered for this metadata type. Best-effort — a projector failure is reported here and logged, never thrown.`),message:t.z.string().optional().describe("Human-readable receipt, e.g. `Published draft — type=view, name=cases [seq=3]`. The producer sets it on every publish today; it stays optional to match the producer's own signature and its `SaveMetaItemResponse` twin, and because an absent human-readable string strips no data — the failure mode #5745 exists to prevent.")})),id=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),name:t.z.string().describe(`Item name`)})),ad=n(()=>t.z.object({success:t.z.boolean(),reset:t.z.boolean().optional(),message:t.z.string().optional()})),od=n(()=>t.z.object({type:t.z.string().describe(`Metadata type name`),name:t.z.string().describe(`Item name`),cacheRequest:la.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).`)})),sd=n(()=>ua),cd=n(()=>t.z.object({object:t.z.string().describe(`Object name (snake_case)`),type:t.z.enum([`list`,`form`]).describe(`View type`)})),ld=n(()=>es),ud=n(()=>t.z.object({object:t.z.string().describe(`The unique machine name of the object to query (e.g. "account").`),query:Ft.optional().describe(`Structured query definition (filter, sort, select, pagination).`)})),dd=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).`)})),fd=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:v(jt),count:t.z.coerce.boolean().optional().describe(`Include total count in response.`)})),pd=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.`)})),md=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.`)})),hd=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.`)})),gd=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(Ti).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.")})),_d=n(()=>t.z.object({field:t.z.string().describe("The field the finding is about (`_record` for an object-level rule)."),code:t.z.string().describe("Machine-readable finding code, e.g. `required`, `invalid_type`, `rule_violation`."),message:t.z.string().describe(`Human-readable message — a validation rule's author-written text where one exists.`)})),vd=n(()=>t.z.object({object:t.z.string().describe(`The object name.`),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()))]).describe(`A candidate record, or an array of them. Nothing is persisted.`),mode:t.z.enum([`insert`,`update`]).optional().describe("Which write the verdict should predict. `insert` (default) walks every declared field, so a missing required field is a finding; `update` judges only the supplied keys, matching a PATCH.")})),yd=n(()=>t.z.object({object:t.z.string().describe(`The object name.`),mode:t.z.enum([`insert`,`update`]).describe(`The write mode the verdict was reached for.`),valid:t.z.boolean().describe(`True when EVERY row is valid — the whole-set answer.`),results:t.z.array(t.z.object({valid:t.z.boolean().describe(`True when this row would be accepted by the write path.`),errors:t.z.array(_d).describe(`Findings that would REJECT this row. Empty when valid.`),warnings:t.z.array(_d).describe(`Findings the target deployment ADMITS rather than rejects — today, ADR-0104 value shapes under a warn-first posture. The row is valid; the write would store it and log the same complaint.`)})).describe(`Per-row verdicts, in submission order.`),posture:t.z.object({valueShapeStrict:t.z.boolean().describe(`True when this deployment rejects non-conforming value shapes (ADR-0104 self-certified).`),mediaValueShapeStrict:t.z.boolean().describe(`The same, for media field value shapes.`)}).describe(`The ADR-0104 posture the verdict was reached under — reported because it is the difference between "this row is fine" and "this row is fine HERE". The same row can be an error on a self-certified deployment and an admitted warning on an un-migrated one, and a caller explaining a verdict needs to know which it got. An unconditionally-strict preview was considered and rejected (#4633 option B): it would fail rows on every un-migrated deployment that the write would have accepted.`)})),bd=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.")})),xd=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(Ti).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`.")})),Sd=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.")})),Cd=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`)})),wd=n(()=>t.z.object({object:t.z.string().describe(`Object name`),request:Yi.describe(`Batch operation request`)})),Td=n(()=>$i),Ed=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`)})),Dd=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(Ti).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.)")})),Od=n(()=>Zi.extend({object:t.z.string().describe(`Object name`)})),kd=n(()=>$i),Ad=n(()=>ea.extend({object:t.z.string().describe(`Object name`)})),jd=n(()=>$i),Md=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)`)})),Nd=n(()=>t.z.object({allowed:t.z.boolean().describe(`Whether the action is permitted`),reason:t.z.string().optional().describe(`Reason if denied`)})),Pd=n(()=>t.z.object({object:t.z.string().describe(`Object name to get permissions for`)})),Fd=n(()=>t.z.object({object:t.z.string().describe(`Object name`),permissions:Yc.describe(`Object-level permissions`),fieldPermissions:t.z.record(t.z.string(),Qc).optional().describe(`Field-level permissions keyed by field name`)})),Id=n(()=>t.z.object({})),Ld=n(()=>t.z.object({objects:t.z.record(t.z.string(),Xc).describe(`Effective object permissions keyed by object name`),systemPermissions:t.z.array(t.z.string()).describe(`Effective system-level permissions`)})),Rd=n(()=>t.z.object({transport:br.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`)})),zd=n(()=>t.z.object({connectionId:t.z.string().describe(`Unique connection identifier`),transport:br.describe(`Negotiated transport protocol`),url:t.z.string().optional().describe(`WebSocket/SSE endpoint URL`)})),Bd=n(()=>t.z.object({connectionId:t.z.string().optional().describe(`Connection ID to disconnect`)})),Vd=n(()=>t.z.object({success:t.z.boolean().describe(`Whether disconnection succeeded`)})),Hd=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`)})),Ud=n(()=>t.z.object({subscriptionId:t.z.string().describe(`Unique subscription identifier`),channel:t.z.string().describe(`Subscribed channel name`)})),Wd=n(()=>t.z.object({subscriptionId:t.z.string().describe(`Subscription ID to cancel`)})),Gd=n(()=>t.z.object({success:t.z.boolean().describe(`Whether unsubscription succeeded`)})),Kd=n(()=>t.z.object({channel:t.z.string().describe(`Channel to set presence in`),state:wr.describe(`Presence state to set`)})),qd=n(()=>t.z.object({success:t.z.boolean().describe(`Whether presence was set`)})),Jd=n(()=>t.z.object({channel:t.z.string().describe(`Channel to get presence for`)})),Yd=n(()=>t.z.object({channel:t.z.string().describe(`Channel name`),members:t.z.array(wr).describe(`Active members and their presence state`)})),Xd=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`)})),Zd=n(()=>t.z.object({deviceId:t.z.string().describe(`Registered device ID`),success:t.z.boolean().describe(`Whether registration succeeded`)})),Qd=n(()=>t.z.object({deviceId:t.z.string().describe(`Device ID to unregister`)})),$d=n(()=>t.z.object({success:t.z.boolean().describe(`Whether unregistration succeeded`)})),ef=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`)})),tf=n(()=>t.z.object({})),nf=n(()=>t.z.object({preferences:ef.describe(`Current notification preferences`)})),rf=n(()=>t.z.object({preferences:ef.partial().describe(`Preferences to update`)})),af=n(()=>t.z.object({preferences:ef.describe(`Updated notification preferences`)})),of=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`)})),sf="`cursor` was removed from GET /api/v1/notifications in @objectstack/spec 17 (#6361, ADR-0049) — it was declared on the request AND the response and honoured on neither: the server reads only `read`/`type`/`limit`, and no emit site ever wrote the response key, so a caller paginating by it re-read the first window forever with no error and no 400. Delete the key; the `cursor` argument of `client.notifications.list()` was removed with it. This route is NOT paginated — it answers the newest `limit` notifications and stops, so ask for a bigger window (`limit`, clamped by the server into 1..200) instead of a next page. A first-class inbox cursor, if ever built, will be a response-minted opaque token, not this key.",cf=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().optional().describe(`Maximum number of notifications to return — the newest N. Omitted leaves the window to the server, which is not a fixed part of this contract: the platform inbox answers 50 and clamps any requested value into 1..200 rather than refusing it. This endpoint is not paginated — there is no continuation token, so a larger window is the only way to see more.`),cursor:v(sf)})),lf=n(()=>t.z.object({notifications:t.z.array(of).describe(`List of notifications — the newest window, not a page`),unreadCount:t.z.number().describe(`Total number of unread notifications`),cursor:v(sf)})),uf=n(()=>t.z.object({ids:t.z.array(t.z.string()).describe(`Notification IDs to mark as read`)})),df=n(()=>t.z.object({success:t.z.boolean().describe(`Whether the operation succeeded`),readCount:t.z.number().describe(`Number of notifications marked as read`)})),ff=n(()=>t.z.object({})),pf=n(()=>t.z.object({success:t.z.boolean().describe(`Whether the operation succeeded`),readCount:t.z.number().describe(`Number of notifications marked as read`)})),mf=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()),hf=n(()=>t.z.object({messages:t.z.array(mf).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`)})),gf=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`)})),_f=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, …)`)})),vf=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`)})),yf=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(mf).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`)})),bf=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`)})),xf=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`)})),Sf=n(()=>t.z.object({conversations:t.z.array(yf).describe(`Matching conversations`)})),Cf=n(()=>t.z.object({type:t.z.string().describe(`Frame type (text-delta, tool-input-available, finish, error, …)`)}).passthrough()),wf=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`})),Tf=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)`)})),Ef=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:Tf.describe(`Capability set implied by the agent surface`)})),Df=n(()=>t.z.object({agents:t.z.array(Ef).describe(`Agents this caller may chat with`)})),Of=n(()=>t.z.object({messages:t.z.array(mf).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, …)`)})),kf=n(()=>t.z.enum([`pending`,`approved`,`executed`,`failed`,`rejected`])),Af=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:kf.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)`)})),jf=n(()=>t.z.object({status:kf.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)`)})),Mf=n(()=>t.z.object({items:t.z.array(Af).describe(`Queued actions, newest first`),total:t.z.number().describe(`Number of rows returned (not a total across pages)`)})),Nf=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`)})),Pf=n(()=>t.z.object({status:t.z.literal(`rejected`).describe(`Always "rejected"`),id:t.z.string().describe(`The rejected action id`)})),Ff=n(()=>t.z.object({})),If=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("Locale label. Equals `code` on every serving surface today — the client names locales for its UI (#7634)"),isDefault:t.z.boolean().default(!1).describe(`Whether this is the default locale`)})).describe(`Available locales`)})),Lf=n(()=>t.z.object({locale:t.z.string().describe(`BCP-47 locale code`)})),Rf=n(()=>t.z.object({locale:t.z.string().describe(`Locale code`),translations:fl.describe(`Translation data`)})),zf=n(()=>t.z.object({object:t.z.string().describe(`Object name`),locale:t.z.string().describe(`BCP-47 locale code`)})),Bf=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`)})),Vf=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:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),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`)})),Hf=t.z.enum([`create`,`read`,`update`,`delete`,`list`]),Uf=n(()=>t.z.object({method:F.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`)})),Wf=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(Hf,Uf.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)`)})),Gf=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`),maskObjectFields:t.z.boolean().default(!0).describe(`[ADR-0106 D8] Mask served object schemas to the caller's readable fields`),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`)})),Kf=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`)})),qf=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(Hf,t.z.boolean()).optional().describe(`Enable/disable specific operations`)})).optional().describe(`Per-object route customization`)})),Jf=n(()=>t.z.object({api:Vf.optional().describe(`REST API configuration`),crud:Wf.optional().describe(`CRUD endpoints configuration`),metadata:Gf.optional().describe(`Metadata endpoints configuration`),batch:Kf.optional().describe(`Batch endpoints configuration`),routes:qf.optional().describe(`Route generation configuration`),openApi31:v("`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`.")})),Yf=n(()=>t.z.object({id:t.z.string().describe(`Unique endpoint identifier`),method:F.describe(`HTTP method`),path:t.z.string().describe(`Full URL path`),object:t.z.string().describe(`Object name (snake_case)`),operation:t.z.union([Hf,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()})),Xf=n(()=>t.z.object({endpoints:t.z.array(Yf).describe(`All generated endpoints`),total:t.z.number().int().describe(`Total number of endpoints`),byObject:t.z.record(t.z.string(),t.z.array(Yf)).optional().describe(`Endpoints grouped by object`),byOperation:t.z.record(t.z.string(),t.z.array(Yf)).optional().describe(`Endpoints grouped by operation`)})),Zf=Object.assign(Vf,{create:e=>e}),Qf=Object.assign(Jf,{create:e=>e}),$f=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`)})),ep=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`)})),tp=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($f).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(),ep).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`)})),np=t.z.enum([`swagger-ui`,`redoc`,`rapidoc`,`stoplight`,`scalar`,`graphiql`,`postman`,`custom`]),rp=n(()=>t.z.object({type:np.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`)})),ip=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`)})),ap=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(ip).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(ip)})).optional().describe(`Request folders for organization`)})),op=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`)})),sp=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`)})),cp=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($f).optional().default([]).describe(`API server URLs`),ui:rp.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(ap).optional().default([]).describe(`Predefined test collections`),changelog:t.z.array(op).optional().default([]).describe(`API version changelog`),codeTemplates:t.z.array(sp).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(),ep).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`)})),lp=n(()=>t.z.object({openApiSpec:tp.optional().describe(`Generated OpenAPI specification`),testCollections:t.z.array(ap).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`)})),up=Object.assign(cp,{create:e=>e}),dp=Object.assign(ap,{create:e=>e}),fp=Object.assign(tp,{create:e=>e}),pp=t.z.enum([`count`,`sum`,`avg`,`min`,`max`,`count_distinct`,`number`,`string`,`boolean`]),mp=t.z.enum([`string`,`number`,`boolean`,`time`,`geo`]),hp=t.z.enum([`second`,`minute`,`hour`,`day`,`week`,`month`,`quarter`,`year`]),gp=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:pp,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()})),_p=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:mp,sql:t.z.string().describe(`SQL expression or column reference`),granularities:t.z.array(hp).optional()})),vp=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)`)}));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(),gp).describe(`Quantitative metrics`),dimensions:t.z.record(t.z.string(),_p).describe(`Qualitative attributes`),joins:t.z.record(t.z.string(),vp).optional(),refreshKey:t.z.object({every:t.z.string().optional(),sql:t.z.string().optional()}).optional(),public:t.z.boolean().default(!1)}));var yp=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:p.optional().describe(`Filtering criteria (canonical Query DSL FilterCondition)`),timeDimensions:t.z.array(t.z.object({dimension:t.z.string(),granularity:hp.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()})),bp=t.z.enum([`/api/v1/analytics/query`,`/api/v1/analytics/meta`,`/api/v1/analytics/sql`]),xp=n(()=>yp.extend({cube:t.z.string().describe(`Target cube name`),query:v("`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:v("`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()),Sp=n(()=>N.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)`)})})),Cp=n(()=>t.z.object({cube:t.z.string().optional().describe(`Optional cube name to filter`)})),wp=()=>t.z.object({name:t.z.string().describe('Cube-qualified member name, `"<cube>.<key>"` — the spelling `/analytics/query` accepts'),type:t.z.string().describe("Aggregation type for a measure (`AggregationMetricType`) or data type for a dimension (`DimensionType`). Declared as a string rather than either enum because the projection copies the value through verbatim and this one shape serves both member kinds."),title:t.z.string().optional().describe("Display label, projected from the definition's `label`")}),Tp=n(()=>N.extend({data:t.z.array(t.z.object({name:t.z.string().describe(`Cube name`),title:t.z.string().optional().describe(`Human-readable cube title`),measures:t.z.array(wp()).describe("Measures this cube accepts in `/analytics/query`"),dimensions:t.z.array(wp()).describe("Dimensions this cube accepts in `/analytics/query`")})).describe("Available cubes, each as the `CubeMeta` discovery projection — the cube name, its title, and the measures/dimensions a client may name in a query. A bare array: there is no `cubes` wrapper object, and no cube `sql` is published.")})),Ep=n(()=>N.extend({data:t.z.object({sql:t.z.string(),params:t.z.array(t.z.unknown())})})),Dp=t.z.enum([`urlPath`,`header`,`queryParam`,`dateBased`]),Op=t.z.enum([`preview`,`current`,`supported`,`deprecated`,`retired`]),kp=n(()=>t.z.object({version:t.z.string().describe(`Version identifier (e.g., "v1", "v2beta1", "2025-01-01")`),status:Op.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)`)})),Ap=n(()=>t.z.object({strategy:Dp.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(kp).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`)})),jp=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(kp).optional().describe(`Full version definitions with lifecycle metadata`)})),Mp={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},Np=t.z.enum([`local`,`google`,`github`,`microsoft`,`ldap`,`saml`]),Pp=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()})),Fp=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()})),Ip=t.z.enum([`email`,`username`,`phone`,`magic-link`,`social`]),Lp=n(()=>t.z.object({type:Ip.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`)})),Rp=n(()=>t.z.object({email:t.z.string().email(),password:t.z.string(),name:t.z.string(),image:t.z.string().optional()})),zp=n(()=>t.z.object({refreshToken:t.z.string().describe(`Refresh token`)})),Bp=n(()=>N.extend({data:t.z.object({session:Fp.describe(`Active Session Info`),user:Pp.describe(`Current User Details`),token:t.z.string().optional().describe(`Bearer token if not using cookies`)})})),Vp=n(()=>N.extend({data:Pp})),$={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`},Hp=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`)})})),Up={login:$.signInEmail,register:$.signUpEmail,logout:$.signOut,me:$.getSession};function Wp(e,t){return`${e.replace(/\/$/,``)}${$[t]}`}var Gp={"/login":$.signInEmail,"/register":$.signUpEmail,"/logout":$.signOut,"/me":$.getSession,"/refresh":$.getSession},Kp=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`)})),qp=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`)})),Jp="`features.passkeys` was removed from GET /api/v1/auth/config in @objectstack/spec 17 (#7481, ADR-0049) — it was served from introduction and consumed by nothing: no login UI in any client reads it, and no better-auth passkey plugin is wired behind it, so a deployer who set `plugins.passkeys: true` flipped a switch that changed no behaviour anywhere. Delete the key. There is no replacement flag to read: passkey sign-in is not a capability this platform offers yet. It returns to this payload in the change that ships the login UI (objectui#4179), classified in PUBLIC_AUTH_FEATURES again at that point — do not re-add it ahead of a consumer.",Yp="`features.magicLink` was removed from GET /api/v1/auth/config in @objectstack/spec 17 (#7481, ADR-0049) — the ADVERTISEMENT was inert, not the capability: no client renders a magic-link sign-in affordance off this flag, so it only told a deployer that a UI existed when none did. Delete the key. The server side is unchanged and still yours to call: `AuthPluginConfig.plugins.magicLink` wires better-auth's magic-link plugin, and `/api/v1/auth/magic-link/send` + `/magic-link/verify` answer exactly as before — drive them from your own UI, or wait for objectui#4179, which restores this flag along with the login UI that reads it.",Xp=n(()=>t.z.object({twoFactor:t.z.boolean().default(!1).describe(`Two-factor authentication enabled`),passkeys:v(Jp),magicLink:v(Yp),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)`)})),Zp=n(()=>t.z.object({emailPassword:qp.describe(`Email/password authentication config`),socialProviders:t.z.array(Kp).describe(`Available social/OAuth providers`),features:Xp.describe(`Enabled authentication features`)})),Qp=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`)})),$p=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`)})])),em=n(()=>t.z.enum([`global`,`tenant`,`user`,`session`,`temp`,`cache`,`data`,`logs`,`config`,`public`]).describe(`Storage scope classification`)),tm=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)`)})),nm=n(()=>t.z.enum([`s3`,`azure_blob`,`gcs`,`minio`,`r2`,`spaces`,`wasabi`,`backblaze`,`local`]).describe(`Storage provider type`)),rm=n(()=>t.z.enum([`private`,`public_read`,`public_read_write`,`authenticated_read`,`bucket_owner_read`,`bucket_owner_full_control`]).describe(`Storage access control level`)),im=n(()=>t.z.enum([`standard`,`intelligent`,`infrequent_access`,`glacier`,`deep_archive`]).describe(`Storage class/tier for cost optimization`)),am=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:im.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 om=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`)})),sm=n(()=>t.z.object({acl:rm.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`)})),cm=n(()=>t.z.object({id:b.describe(`Rule identifier`),enabled:t.z.boolean().default(!0).describe(`Enable this rule`),action:am.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:im.optional().describe(`Target storage class for transition action`)}).refine(e=>!(e.action===`transition`&&!e.targetStorageClass),{message:`targetStorageClass is required when action is "transition"`})),lm=n(()=>t.z.object({enabled:t.z.boolean().default(!1).describe(`Enable lifecycle policies`),rules:t.z.array(cm).default([]).describe(`Lifecycle rules`)})),um=n(()=>t.z.object({name:b.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:nm.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:sm.optional().describe(`Access control configuration`),lifecyclePolicy:lm.optional().describe(`Lifecycle policy configuration`),multipartConfig:om.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`)})),dm=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`)})),fm=n(()=>t.z.object({name:b.describe(`Storage configuration identifier`),label:t.z.string().describe(`Display label`),provider:nm.describe(`Primary storage provider`),scope:em.optional().default(`global`).describe(`Storage scope`),connection:dm.describe(`Connection credentials`),buckets:t.z.array(um).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`)}));fm.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}),fm.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}),fm.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}),fm.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 pm=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)`)})),mm=n(()=>t.z.object({fileId:t.z.string().describe(`File ID returned from presigned request`),eTag:t.z.string().optional().describe(`S3 ETag verification`)})),hm=n(()=>N.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`)})})),gm=n(()=>N.extend({data:tm.describe(`Uploaded file metadata`)})),_m=n(()=>N.extend({data:t.z.object({url:t.z.string().describe(`Short-lived signed download URL; may be server-relative`)})})),vm=n(()=>N.extend({data:t.z.object({key:t.z.string().describe(`Storage key the bytes were written to`)})})),ym=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)`)})),bm=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`)})),xm=n(()=>N.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`)})})),Sm=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`)})),Cm=n(()=>N.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`)})})),wm=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`)})),Tm=n(()=>N.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`)})})),Em=n(()=>N.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`)})})),Dm={getPresignedUrl:{method:`POST`,path:`/api/v1/storage/upload/presigned`,input:pm,output:hm},completeUpload:{method:`POST`,path:`/api/v1/storage/upload/complete`,input:mm,output:gm},initiateChunkedUpload:{method:`POST`,path:`/api/v1/storage/upload/chunked`,input:bm,output:xm},uploadChunk:{method:`PUT`,path:`/api/v1/storage/upload/chunked/:uploadId/chunk/:chunkIndex`,input:Sm,output:Cm},completeChunkedUpload:{method:`POST`,path:`/api/v1/storage/upload/chunked/:uploadId/complete`,input:wm,output:Tm},getUploadProgress:{method:`GET`,path:`/api/v1/storage/upload/chunked/:uploadId/progress`,output:Em},getDownloadUrl:{method:`GET`,path:`/api/v1/storage/files/:fileId/url`,output:_m}},Om=n(()=>N.extend({data:Uc.describe(`Full Object Schema`)})),km=n(()=>N.extend({data:gu.describe(`Full App Configuration`)})),Am=n(()=>N.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)`)})),jm=n(()=>t.z.object({type:wl.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`)})),Mm=n(()=>N.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`)})),Nm=n(()=>N.extend({data:t.z.array(t.z.record(t.z.string(),t.z.unknown())).describe(`Array of metadata definitions`)})),Pm=n(()=>N.extend({data:t.z.array(t.z.string()).describe(`Array of metadata item names`)})),Fm=n(()=>N.extend({data:t.z.object({exists:t.z.boolean().describe(`Whether the item exists`)})})),Im=n(()=>N.extend({data:t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Deleted item name`)})})),Lm=n(()=>El.describe(`Metadata query with filtering, sorting, and pagination`)),Rm=n(()=>N.extend({data:Dl.describe(`Paginated query result`)})),zm=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`)})),Bm=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`)})),Vm=n(()=>N.extend({data:Al.describe(`Bulk operation result`)})),Hm=n(()=>N.extend({data:bl.optional().describe(`Overlay definition, undefined if none`)})),Um=n(()=>bl.describe(`Overlay to save`)),Wm=n(()=>N.extend({data:t.z.record(t.z.string(),t.z.unknown()).optional().describe(`Effective metadata with all overlays applied`)})),Gm=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`)})),Km=n(()=>N.extend({data:t.z.unknown().describe(`Exported metadata bundle`)})),qm=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)`)})),Jm=n(()=>N.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`)})),Ym=n(()=>t.z.object({type:t.z.string().describe(`Metadata type to validate against`),data:t.z.unknown().describe(`Metadata payload to validate`)})),Xm=n(()=>N.extend({data:Ol.describe(`Validation result`)})),Zm=n(()=>N.extend({data:t.z.array(t.z.string()).describe(`Registered metadata type identifiers`)})),Qm=n(()=>N.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(cc).optional().describe(`Declarative type-level actions (buttons) the metadata-admin UI renders for this type`)}).optional().describe(`Type info`)})),$m=n(()=>N.extend({data:t.z.array(jl).describe(`Items this item depends on`)})),eh=n(()=>N.extend({data:t.z.array(jl).describe(`Items that depend on this item`)})),th=t.z.enum([`metadata`,`data`,`auth`,`file-storage`,`search`,`cache`,`queue`,`automation`,`analytics`,`realtime`,`job`,`notification`,`ai`,`i18n`,`ui`]),nh=n(()=>t.z.enum([`required`,`core`,`optional`]));n(()=>t.z.object({name:th,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(th,t.z.unknown().describe(`Service Instance implementing the protocol interface`))),n(()=>t.z.object({id:t.z.string(),name:th,options:t.z.record(t.z.string(),t.z.unknown()).optional()}));var rh=t.z.object({prefix:t.z.string().regex(/^\//).describe(`URL path prefix for routing (e.g. /api/v1/data)`),service:th.describe(`Target core service name`),authRequired:t.z.boolean().default(!0).describe(`Whether authentication is required`),criticality:nh.default(`optional`).describe(`Service criticality level for unavailability handling`),permissions:t.z.array(t.z.string()).optional().describe(`Required permissions for this route namespace`)}),ih=t.z.object({routes:t.z.array(rh).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"`)}),ah=t.z.enum([`ROUTE_NOT_FOUND`,`METHOD_NOT_ALLOWED`,`NOT_IMPLEMENTED`,`SERVICE_UNAVAILABLE`]).describe("Route-resolution failure mode emitted in `error.code`"),oh=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:F.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 sh=t.z.enum([`authentication`,`authorization`,`logging`,`validation`,`transformation`,`error`,`custom`]),ch=n(()=>t.z.object({name:t.z.string().regex(/^[a-z_][a-z0-9_]*$/).describe(`Middleware name (snake_case)`),type:sh.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`)}));Object.assign(ch,{create:e=>e});var lh=t.z.enum([`discovery`,`metadata`,`data`,`batch`,`permission`,`analytics`,`automation`,`ui`,`realtime`,`notification`,`ai`,`i18n`]),uh=n(()=>t.z.enum([`implemented`,`stub`,`planned`])),dh=n(()=>t.z.object({method:F.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:lh.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:uh.optional().describe(`Handler implementation status: implemented (default if omitted), stub, or planned`)})),fh=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:lh.describe(`Primary category for this route group`),methods:t.z.array(t.z.string()).optional().describe(`Protocol method names implemented`),endpoints:t.z.array(dh).optional().describe(`Endpoint definitions`),middleware:t.z.array(ch).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`)}),ph=t.z.enum([`strict`,`permissive`,`strip`]),mh=t.z.object({enabled:t.z.boolean().default(!0).describe(`Enable automatic request validation`),mode:ph.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`)}),hh=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`)}),gh=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`)}),_h=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`)}),vh=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(fh).describe(`Route registrations`),validation:mh.optional().describe(`Request validation configuration`),responseEnvelope:hh.optional().describe(`Response envelope configuration`),errorHandling:gh.optional().describe(`Error handling configuration`),openApi:_h.optional().describe(`OpenAPI documentation configuration`),globalMiddleware:t.z.array(ch).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(F).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`)}),yh={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}]},bh={prefix:`/api/v1/meta`,service:`metadata`,category:`metadata`,methods:[`getMetaTypes`,`getMetaItems`,`getMetaItem`,`getMetaItemLayered`,`saveMetaItem`,`publishMetaItem`],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:`GET`,path:`/:type/:name/layers`,handler:`getMetaItemLayered`,category:`metadata`,public:!1,summary:`Get a metadata item as its three layers (code / overlay / effective)`,description:'Diagnostic projection powering Studio\'s "code default vs override vs effective" comparison: the packaged baseline, the tenant customization row, and the merged result side by side. A DIFFERENT representation from `GET /:type/:name`, which answers only the merged value under `item` — hence its own path and its own response schema (#5882). Reached until now only as `GET /:type/:name?layers=true`, which still works during its deprecation window but is answered with `Deprecation` / `Link` headers pointing here.',tags:[`Metadata`],responseSchema:`GetMetaItemLayeredResponseSchema`,cacheable:!1},{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},{method:`POST`,path:`/:type/:name/publish`,handler:`publishMetaItem`,category:`metadata`,public:!1,summary:`Publish the pending draft overlay (promotes draft → active)`,description:"Promotes the item's pending DRAFT overlay to the live `active` row and records an `op='publish'` history event. The sibling write door of `PUT /:type/:name` — the ADR-0033 two-step spelling, where `?mode=draft` stages a body and this makes it live. 404 `[no_draft]` when there is nothing to publish; 409 `metadata_conflict` when the published row advanced while the draft was held. Served since before #7294 with no declaration behind it — this entry is what makes its response contract nameable.",tags:[`Metadata`],responseSchema:`PublishMetaItemResponseSchema`,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}]},xh={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}]},Sh={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}]},Ch={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 the newest window of notifications for the current user (not paginated)`,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}]},wh={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}]},Th={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}]},Eh={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}]},Dh=Object.assign(vh,{create:e=>e}),Oh=Object.assign(fh,{create:e=>e});function kh(){return[yh,bh,xh,Sh,Ch,wh,Th,Eh]}var Ah=t.z.object({path:t.z.string().describe(`Full URL path (e.g. /api/v1/analytics/query)`),method:F.describe(`HTTP method (GET, POST, etc.)`),category:lh.describe(`Route category`),handlerStatus:uh.describe(`Handler status`),service:t.z.string().describe(`Target service name`),healthCheckPassed:t.z.boolean().optional().describe(`Whether the health check probe succeeded`)}),jh=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(Ah).describe(`Per-endpoint coverage entries`)}),Mh=n(()=>t.z.enum([`rest`,`odata`])),Nh=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`)})),Ph=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`)})),Fh=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`)})),Ih=n(()=>t.z.object({operatorMappings:t.z.array(Nh).optional().describe(`Custom operator mappings`),rest:Ph.optional().describe(`REST query adapter configuration`),odata:Fh.optional().describe(`OData query adapter configuration`)})),Lh=t.z.enum([`csv`,`json`,`jsonl`,`xlsx`,`parquet`]),Rh=t.z.enum([`pending`,`processing`,`completed`,`failed`,`cancelled`,`expired`]),zh=n(()=>t.z.object({object:t.z.string().describe(`Object name to export`),format:Lh.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`)})),Bh=n(()=>N.extend({data:t.z.object({jobId:t.z.string().describe(`Export job ID`),status:Rh.describe(`Initial job status`),estimatedRecords:t.z.number().int().optional().describe(`Estimated total records`),createdAt:t.z.string().datetime().describe(`Job creation timestamp`)})})),Vh=n(()=>N.extend({data:t.z.object({jobId:t.z.string().describe(`Export job ID`),status:Rh.describe(`Current job status`),format:Lh.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`)})})),Hh=t.z.enum([`strict`,`lenient`,`dry_run`]),Uh=t.z.enum([`skip`,`update`,`create_new`,`fail`]),Wh=n(()=>t.z.object({mode:Hh.default(`strict`).describe(`Validation mode for the import`),deduplication:t.z.object({strategy:Uh.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"])`)})),Gh=n(()=>N.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)`)})})),Kh=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)`)})),qh=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:Lh.optional().describe(`Default file format for this template`),mappings:t.z.array(Kh).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`)})),Jh=t.z.enum([`insert`,`update`,`upsert`]),Yh=n(()=>t.z.union([t.z.record(t.z.string(),t.z.string()),t.z.array(Kh)])),Xh=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:Yh.optional().describe(`Source column → target field mapping`),dryRun:t.z.boolean().default(!1).describe("Validate + coerce every row without persisting. The verdict is the engine's own write-path validation, with one boundary an author should know: a preview runs NO automations. Hooks never fire in a dry run (#6037) — a preview that executed user-authored side effects (mail, outbound calls, writes to other objects) would be the retired `validateOnly` defect in a new spelling. So a dry run with `runAutomations: true` can report `required` for a field a `beforeInsert` hook would populate during the real import; for hook-derived fields the real write is authoritative."),writeMode:Jh.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(!0).describe("Fire triggers/hooks for each imported row. ON by default, and opting out must be explicit: automations always ran on import historically (the engine ignored this flag until #2922), so a caller that wants a silent bulk load sends `runAutomations: false` — omitting the key runs them. This matches platform convention (Salesforce fires triggers on import by default). One boundary: a `dryRun` preview runs NO automations whatever this flag says (#6037)."),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)`)})),Zh=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)`)})),Qh=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:Jh.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(Zh).describe(`Per-row outcomes`)})),$h=5e4,eg=t.z.enum([`pending`,`running`,`succeeded`,`failed`,`cancelled`]),tg=Xh,ng=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:eg.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)`)})),rg=n(()=>t.z.object({jobId:t.z.string().describe(`Import job id`),object:t.z.string().describe(`Target object name`),status:eg.describe(`Current job status`),dryRun:t.z.boolean().describe(`Whether this is a validate-only pass`),writeMode:Jh.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)`)})),ig=n(()=>rg.extend({results:t.z.array(Zh).describe(`Capped sample of per-row outcomes (failures first)`),resultsTruncated:t.z.boolean().describe("Whether `results` is a capped sample of a larger set")})),ag=n(()=>t.z.object({object:t.z.string().optional().describe(`Filter to one target object`),status:eg.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`)})),og=n(()=>t.z.object({jobId:t.z.string().describe(`Import job id`),object:t.z.string().describe(`Target object name`),status:eg.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)`)})),sg=n(()=>t.z.object({jobs:t.z.array(og).describe(`Import jobs, newest first`)})),cg=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`)})),lg=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:Lh.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:ye.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`)})),ug=n(()=>t.z.object({jobId:t.z.string().describe(`Export job ID`)})),dg=n(()=>N.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:Lh.describe(`Export file format`),expiresAt:t.z.string().datetime().describe(`Download URL expiration timestamp`),checksum:t.z.string().optional().describe(`File checksum (SHA-256)`)})})),fg=n(()=>t.z.object({object:t.z.string().optional().describe(`Filter by object name`),status:Rh.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`)})),pg=n(()=>t.z.object({jobId:t.z.string().describe(`Export job ID`),object:t.z.string().describe(`Object name that was exported`),status:Rh.describe(`Current job status`),format:Lh.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`)})),mg=n(()=>N.extend({data:t.z.object({jobs:t.z.array(pg).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`)})})),hg=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:Lh.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:ye.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`)})),gg=n(()=>N.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`)})})),_g={createExportJob:{method:`POST`,path:`/api/v1/data/:object/export`,input:zh,output:Bh},getExportJobProgress:{method:`GET`,path:`/api/v1/data/export/:jobId`,input:t.z.object({jobId:t.z.string()}),output:Vh},getExportJobDownload:{method:`GET`,path:`/api/v1/data/export/:jobId/download`,input:ug,output:dg},listExportJobs:{method:`GET`,path:`/api/v1/data/export`,input:fg,output:mg},scheduleExport:{method:`POST`,path:`/api/v1/data/export/schedules`,input:hg,output:gg},cancelExportJob:{method:`POST`,path:`/api/v1/data/export/:jobId/cancel`,input:t.z.object({jobId:t.z.string()}),output:N}},vg={createImportJob:{method:`POST`,path:`/api/v1/data/:object/import/jobs`,input:tg,output:ng},getImportJobProgress:{method:`GET`,path:`/api/v1/data/import/jobs/:jobId`,input:t.z.object({jobId:t.z.string()}),output:rg},getImportJobResults:{method:`GET`,path:`/api/v1/data/import/jobs/:jobId/results`,input:t.z.object({jobId:t.z.string()}),output:ig},listImportJobs:{method:`GET`,path:`/api/v1/data/import/jobs`,input:ag,output:sg},cancelImportJob:{method:`POST`,path:`/api/v1/data/import/jobs/:jobId/cancel`,input:t.z.object({jobId:t.z.string()}),output:N},undoImportJob:{method:`POST`,path:`/api/v1/data/import/jobs/:jobId/undo`,input:t.z.object({jobId:t.z.string()}),output:cg}};function yg(){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:v("`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` and `flow.errorHandling`. Rename the key to `backoffMs`; the value (milliseconds before the first retry) is unchanged. Run `os migrate meta --from 16` to rewrite existing sources automatically.")}}var bg=n(()=>t.z.object(yg())),xg=[{nodeType:`loop`,key:`body`,arity:`one`},{nodeType:`parallel`,key:`branches`,arity:`many`},{nodeType:`try_catch`,key:`try`,arity:`one`},{nodeType:`try_catch`,key:`catch`,arity:`one`}],Sg=new Map([...new Set(xg.map(e=>e.nodeType))].map(e=>[e,xg.filter(t=>t.nodeType===e)]));new Set(xg.map(e=>e.key));var Cg=`Until #4001 an undeclared key here was dropped silently — the container still parsed, registered and ran, with the author's configuration simply absent.`,wg={join:"A `parallel` block joins IMPLICITLY: it continues once, when every branch has completed (ADR-0031 §Decision 2). There is no join to configure and no arrival count to get wrong — that is the point of the construct, so the key has no replacement.",joinGateway:"`join_gateway` is a BPMN **interop** node type, not a `parallel` config key. ADR-0031 §Decision 5 keeps the BPMN gateways for import/export and §Decision 2 folds an imported `parallel_gateway`/`join_gateway` pair INTO this block — so by the time you are writing `parallel`, the join has already been absorbed."},Tg=1e5,Eg=n(()=>A({surface:`this control-flow region`,history:Cg,guidance:{name:"A region is not named. Only a `parallel` branch carries a `name` (`config.branches[].name`) — a `loop` body, a `try` region and a `catch` region are identified by the container that holds them.",label:"A region is not labelled. `label` is required on every NODE inside `nodes[]`, which is where you are seeing it; the region itself is identified by its container slot."}},{nodes:t.z.array(t.z.lazy(()=>Fg)).min(1).describe(`Region body nodes (single-entry/single-exit sub-graph)`),edges:t.z.array(t.z.lazy(()=>Lg)).default([]).describe(`Region body edges`)}));n(()=>A({surface:`this loop container config`,history:Cg,aliases:{itemVariable:`iteratorVariable`},guidance:{flowName:"`flowName` belongs to the `map` node, which runs a separate subflow per item (ADR-0037). A `loop` runs an INLINE `body` region in the enclosing variable scope — put the per-item steps in `config.body`, or change the node `type` to `map` if you meant the subflow form."}},{collection:t.z.union([t.z.string().min(1),t.z.array(t.z.unknown())]).meta({description:`Template/variable resolving to the array to iterate (an inline array is accepted)`,xExpression:`template`}),iteratorVariable:t.z.string().min(1).default(`item`).describe(`Loop variable holding the current item`),indexVariable:t.z.string().optional().describe(`Optional loop variable holding the current index`),maxIterations:t.z.number().int().min(1).max(Tg).optional().describe(`Hard cap on iterations (clamped to the engine ceiling)`),body:Eg.optional().describe(`Loop body region (omit for legacy flat-graph loops)`)}));var Dg=n(()=>A({surface:`this parallel branch`,history:Cg,aliases:{label:`name`}},{name:t.z.string().optional().describe(`Branch label`),nodes:t.z.array(t.z.lazy(()=>Fg)).min(1).describe(`Branch body nodes`),edges:t.z.array(t.z.lazy(()=>Lg)).default([]).describe(`Branch body edges`)}));n(()=>A({surface:`this parallel block config`,history:Cg,guidance:wg},{branches:t.z.array(Dg).min(2).describe(`Branch regions executed concurrently; implicit join at block end`)})),n(()=>A({surface:`this try/catch config`,history:Cg,guidance:{finally:"There is no `finally` region. The `try_catch` node's ORDINARY out-edges are the continuation and run whichever way the protected region went (ADR-0031 §Decision 3 surfaces the engine's existing `fault` edge, not BPMN boundary events) — put the always-run steps in the nodes AFTER this container."}},{try:Eg.describe(`Protected region`),catch:Eg.optional().describe(`Handler region run when the try region fails`),errorVariable:t.z.string().default(`$error`).describe(`Variable holding the caught error in the catch region`),retry:bg.optional().describe(`Optional retry policy for the try region`)}));function Og(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function kg(e){let t=e.config;if(!t)return[];let n=Sg.get(e.type);if(!n)return[];let r=[];for(let{key:i,arity:a}of n){let n=t[i];if(a===`many`){if(!Array.isArray(n))continue;n.forEach((t,n)=>r.push({raw:t,key:i,index:n,label:`${e.type} '${e.id}' ${Ag(i)} ${n}`,schema:Dg}));continue}n!=null&&r.push({raw:n,key:i,label:`${e.type} '${e.id}' ${i}`,schema:Eg})}return r}function Ag(e){return e.endsWith(`es`)?e.slice(0,-2):e.replace(/s$/,``)}var jg=32,Mg=0;function Ng(e){let t=e.config;if(!t||Mg>=jg)return e;Mg++;try{let n=t;for(let t of kg(e)){if(!Og(t.raw))continue;let e=t.schema.safeParse(t.raw);if(e.success){if(t.index===void 0)n={...n,[t.key]:e.data};else{let r=[...n[t.key]];r[t.index]=e.data,n={...n,[t.key]:r}}}}return n===t?e:{...e,config:n}}finally{Mg--}}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 Pg=n(()=>A({surface:`this flow variable`,aliases:{input:`isInput`,output:`isOutput`,default:`defaultValue`,initialValue:`defaultValue`},history:`Until #4001 these were dropped silently — the variable still parsed, so a mis-declared input/output contract shipped without a diagnostic.`},{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`),defaultValue:t.z.unknown().optional().describe("Value bound at run start when no parameter supplies one — this is what makes a declared variable always bound. An explicitly supplied param wins, including `false` and `null`; the boundary is `params[name] !== undefined`.")})),Fg=n(()=>Ig().transform(Ng));function Ig(){return A({surface:`this flow node`,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.`},{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:A({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:A({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(),A({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:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),waitEventConfig:A({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`, and QUOTE the number: the key is a string, and a bare numeric string is read as milliseconds, so `timerDuration: '60000'` is a 60s wait (`timerDuration: 'PT1M'` says the same in ISO 8601)."},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:v("`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` — but QUOTE the number: the key is a string, and a bare numeric string is read as milliseconds, making `timeoutMs: 60000` and `timerDuration: '60000'` the same wait (`timerDuration: 'PT1M'` is the ISO 8601 spelling of that same 60s). Stored flows are converted automatically — the conversion does the quoting for you. Run `os migrate meta --from 16` to rewrite existing sources automatically."),onTimeout:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically.")}).optional().describe(`Configuration for wait node event resumption`),boundaryConfig:A({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`)})}var Lg=n(()=>A({surface:`this flow edge`,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.`},{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:C.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.")})),Rg=n(()=>A({surface:`this flow`,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.`},{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:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),type:t.z.enum([`autolaunched`,`record_change`,`schedule`,`screen`,`api`]).describe(`Flow type`),variables:t.z.array(Pg).optional().describe(`Flow variables`),nodes:t.z.array(Fg).describe(`Flow nodes`),edges:t.z.array(Lg).describe(`Flow connections`),active:v("`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. Run `os migrate meta --from 16` to rewrite existing sources automatically."),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:A({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`),...yg(),maxRetries:yg().maxRetries.describe(`Retry attempts after the initial one. Read only under strategy: 'retry', which requires >= 1; 0 (the default) means no retry.`),fallbackNodeId:v("`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 type: '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. Run `os migrate meta --from 16` to rewrite existing sources automatically.")}).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:Ea.optional().describe(`Package author protection block — lock policy for this flow.`),...y}));n(()=>t.z.object({flowName:t.z.string().describe(`Flow machine name`),version:t.z.number().int().min(1).describe(`Version number`),definition:Rg.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 zg=t.z.enum([`pending`,`running`,`paused`,`completed`,`failed`,`cancelled`,`timed_out`,`retrying`]),Bg=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.")})),Vg=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`)})),Hg=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:Bg.optional().describe(`Records this step selected / acted on, as reported by the node executor`),skippedBy:Vg.optional().describe("The gate that closed, when `status` is `skipped`")})),Ug=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)`)})),Wg=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)`)})),Gg=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(Ug).describe(`Per-node breakdown, in first-execution order`),gates:t.z.array(Wg).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".')})),Kg=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:zg.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(Hg).describe(`Ordered list of executed steps`),summary:Gg.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`)})),qg=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:qg.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:ye.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:zg.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 Jg=n(()=>t.z.object({name:t.z.string().describe(`Flow machine name (snake_case)`)})),Yg=n(()=>Jg.extend({runId:t.z.string().describe(`Execution run ID`)})),Xg=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`)})),Zg=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`)})),Qg=n(()=>N.extend({data:t.z.object({flows:t.z.array(Zg).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`)})})),$g=n(()=>Jg),e_=n(()=>N.extend({data:Rg.describe(`Full flow definition`)})),t_=n(()=>Rg),n_=n(()=>N.extend({data:Rg.describe(`The created flow definition`)})),r_=n(()=>Jg.extend({definition:Rg.partial().describe(`Partial flow definition to update`)})),i_=n(()=>N.extend({data:Rg.describe(`The updated flow definition`)})),a_=n(()=>Jg),o_=n(()=>N.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`)})})),s_=n(()=>Jg.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`)})),c_=n(()=>N.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`)})})),l_=n(()=>Jg.extend({enabled:t.z.boolean().describe(`Whether to enable (true) or disable (false) the flow`)})),u_=n(()=>N.extend({data:t.z.object({name:t.z.string().describe(`Flow name`),enabled:t.z.boolean().describe(`New enabled state`)})})),d_=n(()=>Jg.extend({status:zg.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`)})),f_=n(()=>N.extend({data:t.z.object({runs:t.z.array(Kg).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`)})})),p_=n(()=>Yg),m_=n(()=>N.extend({data:Kg.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`]),g_={listFlows:{method:`GET`,path:`/api/automation`,input:Xg,output:Qg},getFlow:{method:`GET`,path:`/api/automation/:name`,input:$g,output:e_},createFlow:{method:`POST`,path:`/api/automation`,input:t_,output:n_},updateFlow:{method:`PUT`,path:`/api/automation/:name`,input:r_,output:i_},deleteFlow:{method:`DELETE`,path:`/api/automation/:name`,input:a_,output:o_},triggerFlow:{method:`POST`,path:`/api/automation/:name/trigger`,input:s_,output:c_},toggleFlow:{method:`POST`,path:`/api/automation/:name/toggle`,input:l_,output:u_},listRuns:{method:`GET`,path:`/api/automation/:name/runs`,input:d_,output:f_},getRun:{method:`GET`,path:`/api/automation/:name/runs/:runId`,input:p_,output:m_}},__=n(()=>t.z.enum([`added`,`modified`,`removed`,`renamed`]).describe(`Type of metadata change between package versions`)),v_=n(()=>t.z.object({type:t.z.string().describe(`Metadata type`),name:t.z.string().describe(`Metadata name`),changeType:__.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`)),y_=n(()=>t.z.enum([`none`,`low`,`medium`,`high`,`critical`]).describe(`Severity of upgrade impact`)),b_=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:y_.describe(`Severity assessment from none (seamless) to critical (breaking changes)`),changes:t.z.array(v_).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:Q.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:Q.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 x_=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:x_.describe(`Current upgrade phase`),plan:b_.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 S_=t.z.enum([`objects`,`views`,`pages`,`flows`,`dashboards`,`permissions`,`agents`,`reports`,`actions`,`translations`,`themes`,`datasets`,`apis`,`triggers`,`workflows`]).describe(`Metadata category within the artifact`),C_=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:S_.optional().describe(`Metadata category this file belongs to`)}).describe(`A single file entry within the artifact`)),w_=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`)),T_=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`)),E_=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(C_).optional().describe(`List of files contained in the artifact`),metadataCategories:t.z.array(S_).optional().describe(`Metadata categories included in this artifact`),checksums:w_.optional().describe(`SHA256 checksums for artifact integrity verification`),signature:T_.optional().describe(`Digital signature for artifact authenticity verification`)}).describe(`Package artifact structure and metadata`)),D_=n(()=>t.z.enum([`private`,`org`,`marketplace`]).describe(`Package visibility: private = owner org only; org = all envs in owner org; marketplace = public registry`)),O_=n(()=>t.z.string().min(1).describe(`Package category for marketplace discovery (e.g. "crm", "hr", "finance", "devtools")`)),k_=n(()=>t.z.enum([`objectstack`,`partner`,`community`,`private`]).describe(`Package publisher provenance tier`)),A_=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`)),j_=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`)),M_=n(()=>t.z.record(A_,j_).describe(`Locale-keyed overrides; missing keys fall back to base columns`)),N_=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)`),namespace:t.z.string().regex(/^[a-z][a-z0-9_]{1,19}$/,`Namespace must be 2-20 chars, lowercase alphanumeric + underscore`).optional().describe(`Metadata namespace claimed by the package (mirrors manifest.namespace; e.g. "crm" → object names "crm_account")`),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:D_.default(`private`),category:O_.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:k_.default(`private`),isStarter:t.z.boolean().default(!1).describe(`If true, surfaces in the Create Project blueprint picker as a starter template`),translations:M_.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:N_.shape.manifestId,namespace:N_.shape.namespace,ownerOrgId:t.z.string().describe(`Owner organization ID`),displayName:N_.shape.displayName,description:N_.shape.description,visibility:D_.optional(),category:O_.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:k_.optional(),isStarter:t.z.boolean().optional(),translations:M_.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:N_.shape.displayName.optional(),description:N_.shape.description,readme:N_.shape.readme,visibility:D_.optional(),category:O_.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:k_.optional(),isStarter:t.z.boolean().optional(),translations:M_.optional()}).describe(`Update mutable package metadata`));var P_=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:P_.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 F_=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 I_=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`)),L_=n(()=>t.z.enum([`draft`,`submitted`,`in-review`,`approved`,`published`,`rejected`,`suspended`,`deprecated`,`unlisted`]).describe(`Marketplace listing status`)),R_=n(()=>t.z.enum([`free`,`freemium`,`paid`,`subscription`,`usage-based`,`contact-sales`]).describe(`Package pricing model`)),z_=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(Hl).default(`app`).describe("Consumer-installable package type (ADR-0019: only `app` is listable)"),publisherId:t.z.string().describe(`Publisher ID`),status:L_.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:I_.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:R_.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:F_.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:M_.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:I_.optional().describe(`Filter by category`),tags:t.z.array(t.z.string()).optional().describe(`Filter by tags`),pricing:R_.optional().describe(`Filter by pricing model`),publisherVerification:P_.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(z_).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:I_,count:t.z.number().int().min(0)})).optional(),pricing:t.z.array(t.z.object({model:R_,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:F_.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 B_=n(()=>t.z.object({packageId:t.z.string().describe(`Package identifier`)})),V_=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`)),H_=n(()=>N.extend({data:t.z.object({packages:t.z.array(Ou).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`)),U_=n(()=>B_),W_=n(()=>N.extend({data:Ou.describe(`Installed package details`)}).describe(`Get installed package response`)),G_=n(()=>t.z.object({manifest:Q.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:F_.optional().describe(`Artifact reference for marketplace installation`)}).describe(`Install package request`)),K_=n(()=>N.extend({data:t.z.object({package:Ou.describe(`Installed package details`),dependencyResolution:Eu.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`)),q_=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:Q.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`)),J_=n(()=>N.extend({data:t.z.object({success:t.z.boolean().describe(`Whether the upgrade succeeded`),phase:t.z.string().describe(`Current upgrade phase`),plan:b_.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`)),Y_=n(()=>t.z.object({manifest:Q.describe(`Package manifest to resolve dependencies for`),platformVersion:t.z.string().optional().describe(`Current platform version for compatibility filtering`)}).describe(`Resolve dependencies request`)),X_=n(()=>N.extend({data:Eu.describe(`Dependency resolution result with topological sort`)}).describe(`Resolve dependencies response`)),Z_=n(()=>t.z.object({artifact:E_.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`)),Q_=n(()=>N.extend({data:t.z.object({success:t.z.boolean().describe(`Whether the upload succeeded`),artifactRef:F_.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`)),$_=n(()=>B_.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`)),ev=n(()=>N.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`)),tv=n(()=>B_),nv=n(()=>N.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`)),rv=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`]),iv={listPackages:{method:`GET`,path:`/api/v1/packages`,input:V_,output:H_},getPackage:{method:`GET`,path:`/api/v1/packages/:packageId`,input:U_,output:W_},installPackage:{method:`POST`,path:`/api/v1/packages/install`,input:G_,output:K_},upgradePackage:{method:`POST`,path:`/api/v1/packages/upgrade`,input:q_,output:J_},resolveDependencies:{method:`POST`,path:`/api/v1/packages/resolve-dependencies`,input:Y_,output:X_},uploadArtifact:{method:`POST`,path:`/api/v1/packages/upload`,input:Z_,output:Q_},rollbackPackage:{method:`POST`,path:`/api/v1/packages/:packageId/rollback`,input:$_,output:ev},uninstallPackage:{method:`DELETE`,path:`/api/v1/packages/:packageId`,input:tv,output:nv}};e.AckMessageSchema=Wr,e.AiAgentCapabilitiesSchema=Tf,e.AiAgentChatRequestSchema=Of,e.AiAgentSummarySchema=Ef,e.AiAgentsResponseSchema=Df,e.AiChatRequestSchema=hf,e.AiChatResponseSchema=gf,e.AiCompleteRequestSchema=_f,e.AiConversationSchema=yf,e.AiMessageSchema=mf,e.AiModelsResponseSchema=vf,e.AiPendingActionSchema=Af,e.AiPendingActionStatusSchema=kf,e.AiStreamChunkSchema=Cf,e.AnalyticsEndpoint=bp,e.AnalyticsMetadataResponseSchema=Tp,e.AnalyticsQueryRequestSchema=xp,e.AnalyticsResultResponseSchema=Sp,e.AnalyticsSqlResponseSchema=Ep,e.ApiChangelogEntrySchema=op,e.ApiDocumentationConfig=up,e.ApiDocumentationConfigSchema=cp,e.ApiEndpoint=On,e.ApiEndpointSchema=En,e.ApiErrorSchema=en,e.ApiMappingSchema=wn,e.ApiRoutesSchema=er,e.ApiTestCollection=dp,e.ApiTestCollectionSchema=ap,e.ApiTestRequestSchema=ip,e.ApiTestingUiConfigSchema=rp,e.ApiTestingUiType=np,e.AppDefinitionResponseSchema=km,e.ApproveAiPendingActionResponseSchema=Nf,e.AuthEndpointAliases=Up,e.AuthEndpointPaths=$,e.AuthEndpointSchema=Hp,e.AuthFeaturesConfigSchema=Xp,e.AuthProvider=Np,e.AuthProviderInfoSchema=Kp,e.AutomationActionsResponseSchema=Uu,e.AutomationApiContracts=g_,e.AutomationApiErrorCode=h_,e.AutomationFlowPathParamsSchema=Jg,e.AutomationRunPathParamsSchema=Yg,e.AutomationTriggerRequestSchema=Vu,e.AutomationTriggerResponseSchema=Hu,e.BasePresenceSchema=yr,e.BaseResponseSchema=N,e.BatchApiContracts=ta,e.BatchConfigSchema=na,e.BatchDataRequestSchema=wd,e.BatchDataResponseSchema=Td,e.BatchEndpointsConfigSchema=Kf,e.BatchLoadingStrategySchema=_n,e.BatchOperationResultSchema=Qi,e.BatchOperationType=Ki,e.BatchOptionsSchema=Ji,e.BatchRecordSchema=qi,e.BatchUpdateRequestSchema=Yi,e.BatchUpdateResponseSchema=$i,e.BulkDataEventSchema=gr,e.BulkDataEventType=pr,e.BulkRequestSchema=sn,e.BulkResponseSchema=pn,e.CacheControlSchema=sa,e.CacheDirective=B,e.CacheInvalidationRequestSchema=fa,e.CacheInvalidationResponseSchema=pa,e.CacheInvalidationTarget=da,e.CapabilityDescriptorSchema=or,e.CheckPermissionRequestSchema=Md,e.CheckPermissionResponseSchema=Nd,e.CodeGenerationTemplateSchema=sp,e.CompleteChunkedUploadRequestSchema=wm,e.CompleteChunkedUploadResponseSchema=Tm,e.CompleteUploadRequestSchema=mm,e.ConceptListResponseSchema=Am,e.ConflictResolutionStrategy=ti,e.CreateAiConversationRequestSchema=bf,e.CreateDataRequestSchema=hd,e.CreateDataResponseSchema=gd,e.CreateExportJobRequestSchema=zh,e.CreateExportJobResponseSchema=Bh,e.CreateFlowRequestSchema=t_,e.CreateFlowResponseSchema=n_,e.CreateImportJobRequestSchema=tg,e.CreateImportJobResponseSchema=ng,e.CreateManyDataRequestSchema=Ed,e.CreateManyDataResponseSchema=Dd,e.CreateRequestSchema=an,e.CrossObjectBatchDroppedFieldsSchema=aa,e.CrossObjectBatchOperationSchema=ra,e.CrossObjectBatchRequestSchema=ia,e.CrossObjectBatchResponseSchema=oa,e.CrudEndpointPatternSchema=Uf,e.CrudEndpointsConfigSchema=Wf,e.CrudOperation=Hf,e.CursorMessageSchema=Hr,e.CursorPositionSchema=Pr,e.DEFAULT_ANALYTICS_ROUTES=Th,e.DEFAULT_AUTOMATION_ROUTES=Eh,e.DEFAULT_BATCH_ROUTES=Sh,e.DEFAULT_DATA_CRUD_ROUTES=xh,e.DEFAULT_DISCOVERY_ROUTES=yh,e.DEFAULT_I18N_ROUTES=wh,e.DEFAULT_METADATA_ROUTES=bh,e.DEFAULT_NOTIFICATION_ROUTES=Ch,e.DEFAULT_VERSIONING_CONFIG=Mp,e.DataEventSchema=hr,e.DataEventType=fr,e.DataLoaderConfigSchema=gn,e.DeduplicationStrategy=Uh,e.DeleteDataRequestSchema=Sd,e.DeleteDataResponseSchema=Cd,e.DeleteFlowRequestSchema=a_,e.DeleteFlowResponseSchema=o_,e.DeleteManyDataRequestSchema=Ad,e.DeleteManyDataResponseSchema=jd,e.DeleteManyRequestSchema=ea,e.DeleteMetaItemRequestSchema=id,e.DeleteMetaItemResponseSchema=ad,e.DeleteResponseSchema=mn,e.DeviceRequestResponseSchema=Qp,e.DeviceTokenResponseSchema=$p,e.DisablePackageRequestSchema=zu,e.DisablePackageResponseSchema=Bu,e.DiscoveryEnvironmentSchema=tr,e.DiscoverySchema=cr,e.DispatcherConfigSchema=ih,e.DispatcherErrorCode=ah,e.DispatcherErrorResponseSchema=oh,e.DispatcherRouteSchema=rh,e.DocumentStateSchema=Lr,e.ERROR_CODE_LEDGER=Kt,e.ETagSchema=ca,e.EditMessageSchema=Ur,e.EditOperationSchema=Ir,e.EditOperationType=Fr,e.EmailPasswordConfigPublicSchema=qp,e.EnablePackageRequestSchema=Lu,e.EnablePackageResponseSchema=Ru,e.EndpointMapping=Gp,e.EndpointRegistrySchema=Xf,e.EnhancedApiErrorSchema=Wt,e.ErrorCategory=It,e.ErrorCode=Jt,e.ErrorHandlingConfigSchema=gh,e.ErrorHttpStatusMap=Rt,e.ErrorMessageSchema=Gr,e.ErrorResponseSchema=Gt,e.EventMessageSchema=Br,e.EventPatternSchema=Or,e.EventSubscriptionSchema=kr,e.ExportApiContracts=_g,e.ExportFormat=Lh,e.ExportImportTemplateSchema=qh,e.ExportJobProgressSchema=Vh,e.ExportJobStatus=Rh,e.ExportJobSummarySchema=pg,e.ExportRequestSchema=cn,e.FieldErrorCode=Ht,e.FieldErrorSchema=Ut,e.FieldMappingEntrySchema=Kh,e.FileDownloadUrlResponseSchema=_m,e.FileTypeValidationSchema=ym,e.FileUploadResponseSchema=gm,e.FindDataRequestSchema=ud,e.FindDataResponseSchema=dd,e.FlowSummarySchema=Zg,e.GeneratedApiDocumentationSchema=lp,e.GeneratedEndpointSchema=Yf,e.GetAnalyticsMetaRequestSchema=Cp,e.GetAuthConfigResponseSchema=Zp,e.GetDataRequestSchema=pd,e.GetDataResponseSchema=md,e.GetDiscoveryRequestSchema=Wu,e.GetDiscoveryResponseSchema=Gu,e.GetEffectivePermissionsRequestSchema=Id,e.GetEffectivePermissionsResponseSchema=Ld,e.GetExportJobDownloadRequestSchema=ug,e.GetExportJobDownloadResponseSchema=dg,e.GetFieldLabelsRequestSchema=zf,e.GetFieldLabelsResponseSchema=Bf,e.GetFlowRequestSchema=$g,e.GetFlowResponseSchema=e_,e.GetInstalledPackageRequestSchema=U_,e.GetInstalledPackageResponseSchema=W_,e.GetLocalesRequestSchema=Ff,e.GetLocalesResponseSchema=If,e.GetMetaItemCachedRequestSchema=od,e.GetMetaItemCachedResponseSchema=sd,e.GetMetaItemLayeredResponseSchema=$u,e.GetMetaItemRequestSchema=Xu,e.GetMetaItemResponseSchema=Qu,e.GetMetaItemsRequestSchema=Ju,e.GetMetaItemsResponseSchema=Yu,e.GetMetaTypesRequestSchema=Ku,e.GetMetaTypesResponseSchema=qu,e.GetNotificationPreferencesRequestSchema=tf,e.GetNotificationPreferencesResponseSchema=nf,e.GetObjectPermissionsRequestSchema=Pd,e.GetObjectPermissionsResponseSchema=Fd,e.GetPackageRequestSchema=ju,e.GetPackageResponseSchema=Mu,e.GetPresenceRequestSchema=Jd,e.GetPresenceResponseSchema=Yd,e.GetPresignedUrlRequestSchema=pm,e.GetRunRequestSchema=p_,e.GetRunResponseSchema=m_,e.GetTranslationsRequestSchema=Lf,e.GetTranslationsResponseSchema=Rf,e.GetUiViewRequestSchema=cd,e.GetUiViewResponseSchema=ld,e.HandlerStatusSchema=uh,e.HttpFindQueryParamsSchema=fd,e.HttpMethod=F,e.HttpStatusErrorCodeMap=zt,e.IMPORT_JOB_MAX_ROWS=$h,e.IdRequestSchema=dn,e.ImportJobApiContracts=vg,e.ImportJobProgressSchema=rg,e.ImportJobResultsSchema=ig,e.ImportJobStatus=eg,e.ImportJobSummarySchema=og,e.ImportMappingSchema=Yh,e.ImportRequestSchema=Xh,e.ImportResponseSchema=Qh,e.ImportRowResultSchema=Zh,e.ImportValidationConfigSchema=Wh,e.ImportValidationMode=Hh,e.ImportValidationResultSchema=Gh,e.ImportWriteMode=Jh,e.InitiateChunkedUploadRequestSchema=bm,e.InitiateChunkedUploadResponseSchema=xm,e.InstallPackageRequestSchema=Nu,e.InstallPackageResponseSchema=Pu,e.ListAiConversationsRequestSchema=xf,e.ListAiConversationsResponseSchema=Sf,e.ListAiPendingActionsRequestSchema=jf,e.ListAiPendingActionsResponseSchema=Mf,e.ListExportJobsRequestSchema=fg,e.ListExportJobsResponseSchema=mg,e.ListFlowsRequestSchema=Xg,e.ListFlowsResponseSchema=Qg,e.ListImportJobsRequestSchema=ag,e.ListImportJobsResponseSchema=sg,e.ListInstalledPackagesRequestSchema=V_,e.ListInstalledPackagesResponseSchema=H_,e.ListNotificationsRequestSchema=cf,e.ListNotificationsResponseSchema=lf,e.ListPackagesRequestSchema=ku,e.ListPackagesResponseSchema=Au,e.ListRecordResponseSchema=un,e.ListRunsRequestSchema=d_,e.ListRunsResponseSchema=f_,e.LoginRequestSchema=Lp,e.LoginType=Ip,e.MarkAllNotificationsReadRequestSchema=ff,e.MarkAllNotificationsReadResponseSchema=pf,e.MarkNotificationsReadRequestSchema=uf,e.MarkNotificationsReadResponseSchema=df,e.MetadataBulkRegisterRequestSchema=zm,e.MetadataBulkResponseSchema=Vm,e.MetadataBulkUnregisterRequestSchema=Bm,e.MetadataCacheApi=ma,e.MetadataCacheRequestSchema=la,e.MetadataCacheResponseSchema=ua,e.MetadataDeleteResponseSchema=Im,e.MetadataDependenciesResponseSchema=$m,e.MetadataDependentsResponseSchema=eh,e.MetadataEffectiveResponseSchema=Wm,e.MetadataEndpointsConfigSchema=Gf,e.MetadataEventSchema=mr,e.MetadataEventType=dr,e.MetadataExistsResponseSchema=Fm,e.MetadataExportRequestSchema=Gm,e.MetadataExportResponseSchema=Km,e.MetadataImportRequestSchema=qm,e.MetadataImportResponseSchema=Jm,e.MetadataItemResponseSchema=Mm,e.MetadataListResponseSchema=Nm,e.MetadataNamesResponseSchema=Pm,e.MetadataOverlayResponseSchema=Hm,e.MetadataOverlaySaveRequestSchema=Um,e.MetadataQueryRequestSchema=Lm,e.MetadataQueryResponseSchema=Rm,e.MetadataRegisterRequestSchema=jm,e.MetadataTypeInfoResponseSchema=Qm,e.MetadataTypesResponseSchema=Zm,e.MetadataValidateRequestSchema=Ym,e.MetadataValidateResponseSchema=Xm,e.ModificationResultSchema=fn,e.NotificationPreferencesSchema=ef,e.NotificationSchema=of,e.OData=li,e.ODataConfigSchema=ui,e.ODataErrorSchema=si,e.ODataFilterFunctionSchema=ai,e.ODataMetadataSchema=ci,e.ODataQueryAdapterSchema=Fh,e.ODataQuerySchema=ii,e.ODataResponseSchema=oi,e.ObjectDefinitionResponseSchema=Om,e.OpenApiGenerationConfigSchema=_h,e.OpenApiSecuritySchemeSchema=ep,e.OpenApiServerSchema=$f,e.OpenApiSpec=fp,e.OpenApiSpecSchema=tp,e.OperatorMappingSchema=Nh,e.PackageApiContracts=iv,e.PackageApiErrorCode=rv,e.PackageInstallRequestSchema=G_,e.PackageInstallResponseSchema=K_,e.PackagePathParamsSchema=B_,e.PackageRollbackRequestSchema=$_,e.PackageRollbackResponseSchema=ev,e.PackageUpgradeRequestSchema=q_,e.PackageUpgradeResponseSchema=J_,e.PingMessageSchema=Kr,e.PongMessageSchema=qr,e.PresenceMessageSchema=Vr,e.PresenceStateSchema=Mr,e.PresenceStatus=_r,e.PresenceUpdateSchema=Nr,e.PresignedUrlResponseSchema=hm,e.PublishMetaItemResponseSchema=rd,e.QueryAdapterConfigSchema=Ih,e.QueryAdapterTargetSchema=Mh,e.QueryOptimizationConfigSchema=vn,e.REGISTERED_ERROR_CODES=qt,e.RawUploadResponseSchema=vm,e.RealtimeConfigSchema=Er,e.RealtimeConnectRequestSchema=Rd,e.RealtimeConnectResponseSchema=zd,e.RealtimeDisconnectRequestSchema=Bd,e.RealtimeDisconnectResponseSchema=Vd,e.RealtimeEventSchema=Tr,e.RealtimeEventType=xr,e.RealtimePresenceSchema=wr,e.RealtimeRecordAction=vr,e.RealtimeSubscribeRequestSchema=Hd,e.RealtimeSubscribeResponseSchema=Ud,e.RealtimeUnsubscribeRequestSchema=Wd,e.RealtimeUnsubscribeResponseSchema=Gd,e.RecordDataSchema=P,e.RefreshTokenRequestSchema=zp,e.RegisterDeviceRequestSchema=Xd,e.RegisterDeviceResponseSchema=Zd,e.RegisterRequestSchema=Rp,e.RejectAiPendingActionResponseSchema=Pf,e.RequestValidationConfigSchema=mh,e.ResolveDependenciesRequestSchema=Y_,e.ResolveDependenciesResponseSchema=X_,e.ResponseEnvelopeConfigSchema=hh,e.RestApiConfig=Zf,e.RestApiConfigSchema=Vf,e.RestApiEndpointSchema=dh,e.RestApiPluginConfig=Dh,e.RestApiPluginConfigSchema=vh,e.RestApiRouteCategory=lh,e.RestApiRouteRegistration=Oh,e.RestApiRouteRegistrationSchema=fh,e.RestQueryAdapterSchema=Ph,e.RestServerConfig=Qf,e.RestServerConfigSchema=Jf,e.RetryStrategy=Vt,e.RouteCategory=ei,e.RouteCoverageEntrySchema=Ah,e.RouteCoverageReportSchema=jh,e.RouteDefinitionSchema=ni,e.RouteGenerationConfigSchema=qf,e.RouteHealthEntrySchema=lr,e.RouteHealthReportSchema=ur,e.RouterConfigSchema=ri,e.RuntimeAuthoringIssueSchema=ed,e.SERVICE_SELF_INFO_KEY=Zn,e.STANDARD_SYNONYM_WAIVERS=Qt,e.SaveMetaItemRequestSchema=td,e.SaveMetaItemResponseSchema=nd,e.ScheduleExportRequestSchema=hg,e.ScheduleExportResponseSchema=gg,e.ScheduledExportSchema=lg,e.ServiceInfoSchema=Xn,e.ServiceSelfInfoSchema=Qn,e.ServiceStatus=Yn,e.SessionResponseSchema=Bp,e.SessionSchema=Fp,e.SessionUserSchema=Pp,e.SetPresenceRequestSchema=Kd,e.SetPresenceResponseSchema=qd,e.SimpleCursorPositionSchema=Qr,e.SimplePresenceStateSchema=Zr,e.SingleRecordResponseSchema=ln,e.StandardApiContracts=hn,e.StandardErrorCode=Lt,e.StandardSynonymWaiverSchema=Zt,e.StorageApiContracts=Dm,e.SubscribeMessageSchema=Rr,e.SubscriptionEventSchema=Sr,e.SubscriptionSchema=Cr,e.ToggleFlowRequestSchema=l_,e.ToggleFlowResponseSchema=u_,e.TransportProtocol=br,e.TriggerFlowRequestSchema=s_,e.TriggerFlowResponseSchema=c_,e.UndoImportJobResponseSchema=cg,e.UninstallPackageApiRequestSchema=tv,e.UninstallPackageApiResponseSchema=nv,e.UninstallPackageRequestSchema=Fu,e.UninstallPackageResponseSchema=Iu,e.UnregisterDeviceRequestSchema=Qd,e.UnregisterDeviceResponseSchema=$d,e.UnsubscribeMessageSchema=zr,e.UnsubscribeRequestSchema=Ar,e.UpdateAiConversationRequestSchema=wf,e.UpdateDataRequestSchema=bd,e.UpdateDataResponseSchema=xd,e.UpdateFlowRequestSchema=r_,e.UpdateFlowResponseSchema=i_,e.UpdateManyDataRequestSchema=Od,e.UpdateManyDataResponseSchema=kd,e.UpdateManyRecordSchema=Xi,e.UpdateManyRequestSchema=Zi,e.UpdateNotificationPreferencesRequestSchema=rf,e.UpdateNotificationPreferencesResponseSchema=af,e.UpdateRequestSchema=on,e.UploadArtifactRequestSchema=Z_,e.UploadArtifactResponseSchema=Q_,e.UploadChunkRequestSchema=Sm,e.UploadChunkResponseSchema=Cm,e.UploadProgressSchema=Em,e.UserProfileResponseSchema=Vp,e.ValidateDataIssueSchema=_d,e.ValidateDataRequestSchema=vd,e.ValidateDataResponseSchema=yd,e.ValidationMode=ph,e.VersionDefinitionSchema=kp,e.VersionNegotiationResponseSchema=jp,e.VersionStatus=Op,e.VersioningConfigSchema=Ap,e.VersioningStrategy=Dp,e.WELL_KNOWN_CAPABILITY_KEYS=ar,e.WebSocketConfigSchema=Yr,e.WebSocketEventSchema=Xr,e.WebSocketMessageSchema=Jr,e.WebSocketMessageType=Dr,e.WebSocketPresenceStatus=jr,e.WebSocketServerConfigSchema=$r,e.WellKnownCapabilitiesSchema=ir,e.envelopeViolations=rn,e.getAuthEndpointUrl=Wp,e.getDefaultRouteRegistrations=kh,e.identityFreeEndpointGateFailure=Bn,e.makeApiErrorSchema=tn,e.normalizeEndpointPath=Dn,e.readServiceSelfInfo=$n,e.resolveDiscoveryEnvironment=rr,e.standardErrorCodeForHttpStatus=Bt,e.standardSynonymOf=Xt,e.standardSynonymViolations=$t,e.validateApiEndpointDeclarations=zn,e.zodIssuesToFields=Ta})),u=e(((e,t)=>{var n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,s=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},u=(e,t,i,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of a(t))!o.call(e,c)&&c!==i&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},d=e=>u(n({},`__esModule`,{value:!0}),e),f={};s(f,{FilterBuilder:()=>re,ObjectStackClient:()=>le,QueryBuilder:()=>h,RealtimeAPI:()=>ne,ScopedProjectClient:()=>ue,createFilter:()=>ae,createQuery:()=>ie}),t.exports=d(f);var p=c(),ee=l(),m=i(),te=l(),ne=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()}`,i=[`metadata.${e}.created`,`metadata.${e}.updated`,`metadata.${e}.deleted`];return this.subscriptions.set(r,{filter:{type:e,packageId:n?.packageId,eventTypes:i},handler:n=>{if(!n.type.startsWith(`metadata.`))return;let r=te.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=te.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=te.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=[]}},re=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,`contains`,t]),this}ilike(e,t){return this.conditions.push([e,`ilike`,t]),this}startsWith(e,t){return this.conditions.push([e,`starts_with`,t]),this}endsWith(e,t){return this.conditions.push([e,`ends_with`,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}},h=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 re;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 ie(e){return new h(e)}function ae(){return new re}var g={where:!0,fields:!0,orderBy:!0,limit:!0,offset:!0,expand:!0};function _(e){return Object.keys(g).some(t=>t in e)}function oe(e){if(e==null)return;let t;if(Array.isArray(e))t=e.map(e=>String(e).trim()).filter(Boolean);else if(typeof e==`object`){for(let[t,n]of Object.entries(e)){let e=typeof n==`object`&&n&&!Array.isArray(n)?Object.keys(n):[];if(e.length>0)throw Error(`data.find(): expand['${t}'] carries a nested query (${e.slice().sort().join(`, `)}), but the list route accepts only \`expand=<comma-separated relation names>\` \u2014 a nested per-relation query has no transport spelling on a GET, so it would be dropped rather than applied. Pass relation names only, or use data.query() with a QueryAST \`expand\` for nested detail.`)}t=Object.keys(e).map(e=>e.trim()).filter(Boolean)}else return;return t.length>0?t.join(`,`):void 0}async function*v(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(`
24
- `))!==-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 se(e){return typeof e==`string`&&e?e:typeof e?.message==`string`&&e.message?e.message:`Action failed`}function ce(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:se(e.error)}:{success:!0,data:e.data}:{success:!0,data:e}}var le=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=this.getRoute(`email`),n=await this.fetch(`${this.baseUrl}${t}/send`,{method:`POST`,body:JSON.stringify(e)});return this.unwrapResponse(n)}},this.datasources={external:{listTables:async(e,t)=>{let n=t?.schema?`?schema=${encodeURIComponent(t.schema)}`:``,r=this.getRoute(`datasources`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/external/tables${n}`);return this.unwrapResponse(i)},draft:async(e,t,n)=>{let r=this.getRoute(`datasources`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/external/tables/${encodeURIComponent(t)}/draft`,{method:`POST`,body:JSON.stringify(n??{})});return this.unwrapResponse(i)},import:async(e,t,n)=>{let r=this.getRoute(`datasources`),i=await this.fetch(`${this.baseUrl}${r}/${encodeURIComponent(e)}/external/tables/${encodeURIComponent(t)}/import`,{method:`POST`,body:JSON.stringify(n??{})});return this.unwrapResponse(i)},refreshCatalog:async e=>{let t=this.getRoute(`datasources`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}/external/refresh-catalog`,{method:`POST`,body:JSON.stringify({})});return this.unwrapResponse(n)},validate:async e=>{let t=this.getRoute(`datasources`),n=await this.fetch(`${this.baseUrl}${t}/${encodeURIComponent(e)}/external/validate`,{method:`POST`,body:JSON.stringify({})});return this.unwrapResponse(n)}}},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,status:s,expiresAt:c}=(await(await this.fetch(`${this.baseUrl}${i}/upload/chunked/${e}/progress`)).json()).data;if(s===`expired`){let t=Error(`Upload session ${e} expired${c?` at ${c}`:``}; start a new chunked upload`);throw t.code=`UPLOAD_SESSION_EXPIRED`,t.httpStatus=410,t.details={uploadId:e,expiresAt:c},t}let l=[],u=t instanceof ArrayBuffer?t:await t.arrayBuffer();for(let t=o;t<a;t++){let i=t*n,a=Math.min(i+n,u.byteLength),o=new Blob([u.slice(i,a)]),s=await this.storage.uploadPart(e,t,r,o);l.push({chunkIndex:t,eTag:s.data.eTag})}return this.storage.completeChunkedUpload({uploadId:e,parts:l})}},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),t?.status&&r.set(`status`,t.status);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 ce(await this.unwrapResponse(r))}catch(e){return{success:!1,error:se(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));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 v(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 v(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={},o;if(_(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),o=oe(i.expand),i.aggregations&&(a.aggregations=i.aggregations),i.groupBy&&(a.groupBy=i.groupBy)):Object.assign(a,t),a.top!=null&&r.set(`top`,a.top.toString()),a.skip!=null&&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 s=a.filter??a.filters;s&&(this.isFilterAST(s)||Array.isArray(s)?r.set(`filter`,JSON.stringify(s)):typeof s==`object`&&s&&Object.entries(s).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(`,`)),o&&r.set(`expand`,o);let c=await this.fetch(`${this.baseUrl}${n}/${e}?${r.toString()}`);return this.unwrapResponse(c)},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,m.createLogger)({level:e.debug?`debug`:`info`,format:`pretty`}),this.realtimeAPI=new ne(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 ee.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 ue(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)}_apiBase(){let e=this.discoveryInfo?.routes?.data;if(typeof e==`string`&&e.endsWith(`/data`)){let t=e.slice(0,-5),n=this.discoveryInfo?.scoping;if(n?.scoped){let e=typeof n.environmentId==`string`&&n.environmentId?`/environments/${n.environmentId}`:void 0;if(e&&t.endsWith(e))t=t.slice(0,-e.length);else{let e=t.replace(/\/environments\/[^/]+$/,``);if(e===t)return`/api/v1`;t=e}}if(t)return t}return`/api/v1`}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,p.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`,datasources:`/api/v1/datasources`,email:`/api/v1/email`}[e]||`/api/v1/${e}`}},ue=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={},a;if(_(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),a=oe(r.expand),r.aggregations&&(i.aggregations=r.aggregations),r.groupBy&&(i.groupBy=r.groupBy)):Object.assign(i,t),i.top!=null&&n.set(`top`,i.top.toString()),i.skip!=null&&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 o=i.filter??i.filters;o&&(this.parent._isFilterAST(o)||Array.isArray(o)?n.set(`filter`,JSON.stringify(o)):typeof o==`object`&&o&&Object.entries(o).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(`,`)),a&&n.set(`expand`,a);let s=n.toString(),c=await this.parent._fetch(this.url(`/data/${e}${s?`?${s}`:``}`));return this.parent._unwrap(c)},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),t?.status&&n.set(`status`,t.status);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`${this.parent._apiBase()}/environments/${encodeURIComponent(this.environmentId)}`}url(e){return`${this.parent._baseUrl()}${this.scope()}${e}`}};0&&(t.exports={FilterBuilder:re,ObjectStackClient:le,QueryBuilder:h,RealtimeAPI:ne,ScopedProjectClient:ue,createFilter:ae,createQuery:ie})}))();function d(e){if(!e||typeof e!=`object`)return[];let t=e.advisories;return Array.isArray(t)?t.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.rule==`string`&&typeof t.path==`string`&&typeof t.where==`string`&&typeof t.message==`string`&&typeof t.hint==`string`&&typeof t.severity==`string`}):[]}var f=`/meta`,p=`/api/v1`;function ee(e){let t=e.baseUrl.replace(/\/+$/,``),n=e.environmentId?`${p}/environments/${encodeURIComponent(e.environmentId)}${f}`:`${p}${f}`;return/\/api\/v\d+$/i.test(t)?`${t.replace(/\/api\/v\d+$/i,``)}${e.environmentId?`${p}/environments/${encodeURIComponent(e.environmentId)}${f}`:`${p}${f}`}`:`${t}${n}`}async function m(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}function te(e){if(!e||typeof e!=`object`||Array.isArray(e))return!1;let t=e;return typeof t.type==`string`&&typeof t.name==`string`&&`item`in t}var ne=class e{base;fetchImpl;headers;previewDrafts;onSaveAdvisory;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,this.onSaveAdvisory=e.onSaveAdvisory}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,...this.onSaveAdvisory?{onSaveAdvisory:this.onSaveAdvisory}:{}})}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,...this.onSaveAdvisory?{onSaveAdvisory:this.onSaveAdvisory}:{}})}async listTypes(){let e=await this.fetchImpl(this.base,{method:`GET`,headers:this.headers,cache:`no-store`});if(!e.ok)throw await m(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 m(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 m(i);let a=await i.json();return Array.isArray(a)?a:a?.drafts??a?.data?.drafts??[]}async readItemResponse(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 m(o);return await o.json()}async get(e,t,n={}){let r=await this.readItemResponse(e,t,n);return te(r)?r.item??null:r}async getDraft(e,t,n={}){return this.readItemResponse(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 m(c);let l=await c.json();if(this.onSaveAdvisory)try{let n=d(l);n.length>0&&this.onSaveAdvisory({type:e,name:t,mode:r.mode===`draft`?`draft`:`publish`,advisories:n})}catch{}return l}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 m(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 m(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 m(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 m(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 m(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 m(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 m(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 m(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 m(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 m(o);return await o.json()}},re=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}},h=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}}},ie=class extends h{constructor(e,t){super(`Metadata not found for object: ${e}`,`METADATA_NOT_FOUND`,404,{objectName:e,...t}),this.name=`MetadataNotFoundError`}},ae=class extends h{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}}},g=class extends h{url;constructor(e,t,n,r){super(`Connection error: ${e}`,`CONNECTION_ERROR`,r||503,{url:t,...n}),this.url=t,this.name=`ConnectionError`}},_=class extends h{constructor(e=`Authentication failed`,t,n){super(e,`AUTHENTICATION_ERROR`,n||401,t),this.name=`AuthenticationError`}},oe=class extends h{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 v(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 _(r,i,401);case 403:return new _(r,i,403);case 404:return t?.includes(`metadata`)||t?.includes(`schema`)||t?.includes(`getObjectSchema`)?new ie(se(t),i):new h(r,`NOT_FOUND`,404,i);case 400:return new oe(r,void 0,e?.data?.errors,i);case 503:return new g(r,e?.config?.url,i,503);case 504:return new g(r,e?.config?.url,i,504);default:return new h(r,`UNKNOWN_ERROR`,n,i)}}function se(e){if(!e)return`unknown`;let t=e.match(/\(([^)]+)\)/);return t?t[1]:`unknown`}var ce=`sys_user_preference`;function le(e){let{dataSource:t,userId:n,key:r,resource:i=ce,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 ue={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 de(e){return typeof e==`string`?ue[e.toLowerCase()]??ue[e]??e:null}var fe=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 pe(e){if(!e||typeof e!=`object`)return null;let t=e.field,n=de(e.operator??e.op??`=`);return!t||!n?null:[String(t),n,e.value]}function me(e){let t=e[0];return e.length>0&&typeof t==`object`&&!!t&&!Array.isArray(t)&&t.field!==void 0}function he(e){let t=e.map((e,t)=>{if(Array.isArray(e))return x(e);let n=pe(e);if(!n)throw new fe(e,t);return n});return t.length===1?t[0]:[`and`,...t]}var y=new Set([`and`,`or`]);function b(e){if(me(e))return he(e);let t=e[0];return typeof t==`string`&&y.has(t.toLowerCase())?[t,...e.slice(1).map(x)]:e.every(e=>Array.isArray(e))?e.map(x):e}function x(e){if(Array.isArray(e))return e.length>0?b(e):e;if(e&&typeof e==`object`&&e.field!==void 0){let t=pe(e);if(t)return t}return e}function S(e){if(e!=null){if(Array.isArray(e))return e.length===0?void 0:b(e);if(typeof e==`object`)return Object.keys(e).length===0?void 0:a(e)}}function ge(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 _e=new Map;async function ve(e,t){let n=e||`<default>`,r=_e.get(n);if(r)return r;let i=t().catch(e=>{throw _e.delete(n),e});return _e.set(n,i),i}function C(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 ye(e){if(!e||typeof e!=`object`)return!1;let n=e;if(n.httpStatus===404||n.status===404||n.statusCode===404)return!0;let r=typeof n.code==`string`?n.code:``;return t({code:r},[`OBJECT_NOT_FOUND`,`RECORD_NOT_FOUND`])}var be=[`OBJECT_API_DISABLED`,`OBJECT_API_METHOD_NOT_ALLOWED`];function xe(e){return t(e,be)}var Se=`PERMISSION_DENIED`;function Ce(e){return o(e,Se)}var w=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}},we=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 Te(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 Ee=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 T(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 oe(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 Ee({currentVersion:typeof n.currentVersion==`string`?n.currentVersion:null,currentRecord:n.currentRecord??null,message:typeof t.message==`string`?t.message:void 0})}function De(e,t){if(!t||typeof t!=`object`)return null;let n=typeof t.method==`string`&&t.method?t.method:void 0,r=typeof t.url==`string`&&t.url?t.url:void 0,i=typeof t.status==`number`?t.status:typeof t.statusCode==`number`?t.statusCode:void 0;if(!n&&!r&&i===void 0)return null;let a=t.error&&typeof t.error==`object`?t.error:void 0,o=typeof t.code==`string`&&t.code||(a&&typeof a.code==`string`?a.code:void 0),s=[n??`GET`,r??`<unknown url>`];return s.push(`-> ${i??`no status`}`),o&&s.push(`[${o}]`),`${e}: ${s.join(` `)}`}function Oe(){let e=e=>{if(!e||typeof e!=`object`)return!1;if(e.status===404||e.statusCode===404)return!0;let n=e.error;if(n&&typeof n==`object`){let e=n.code;if(t({code:e},[`OBJECT_NOT_FOUND`,`RECORD_NOT_FOUND`]))return!0}return!1},n={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] ${De(t,r)??t} (suppressed expected 404)`,r);return}console.error(De(t,r)??t,n??``,r??``)},fatal:(e,t,n)=>console.error(De(e,n)??e,t??``,n??``),log:(e,...t)=>console.log(e,...t),child:()=>n,withTrace:()=>n};return n}function ke(e){if(typeof e!=`object`||!e)return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(ke).join(`,`)}]`;let t=e;return`{${Object.keys(t).sort().map(e=>`${JSON.stringify(e)}:${ke(t[e])}`).join(`,`)}}`}function Ae(e,t){if(e===t)return!0;let n=e==null,r=t==null;return n||r?n&&r:ke(e)===ke(t)}function je(e,t,n){if(!t||!n||typeof t!=`object`||typeof n!=`object`)return e;let r=[];for(let i of e){let e=i.fields.filter(e=>!Object.prototype.hasOwnProperty.call(t,e)||!Object.prototype.hasOwnProperty.call(n,e)||!Ae(t[e],n[e]));e.length>0&&r.push({...i,fields:e})}return r}function Me(e){let t=e?.list??e;return t?.data?.object??t?.object??t?.objectName}function Ne(e){if(!e||typeof e!=`object`)return null;let t=e,n=`item`in t?t.item:t;if(!n||typeof n!=`object`)return null;let r=n.list??n;return!r||typeof r!=`object`?null:Object.keys(r).length>0?r:null}function Pe(e){let t=e??void 0;return{removed:!!(t?.deleted??t?.reset??!0),...typeof t?.reset==`boolean`?{reset:t.reset}:{},...typeof t?.message==`string`?{message:t.message}:{}}}function Fe(e,t,n,r){return{...e,...t,name:n,object:e?.object||e?.data?.object||r}}var Ie=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;saveAdvisoryListeners=new Set;constructor(e){this.client=new u.ObjectStackClient({...e,logger:Oe()}),this.installSaveAdvisoryInterceptor(),this.metadataCache=new re(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 ve(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=C(n),this.connected=!0,this.reconnectAttempts=0,this.setConnectionState(`connected`)}catch(e){let t=new g(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}::${ke(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(!xe(t)&&ye(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(ye(e))return null}try{return(await this.client.data.get(e,String(t))).record}catch(e){if(ye(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,i){let a=n?.droppedFields;if(!Array.isArray(a)||a.length===0)return;let o=a.filter(e=>!!e&&typeof e==`object`&&Array.isArray(e.fields)&&e.fields.length>0),s=n?.record,c=je(o,i,s);c.length!==0&&this.emitWriteWarning({operation:e,resource:t,...r===void 0?{}:{id:r},droppedFields:c})}notifyBatchDroppedFields(e,t){let n=t?.droppedFields;if(!Array.isArray(n)||n.length===0)return;let r=t?.results;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 i=typeof n.index==`number`?e[n.index]:void 0,a=typeof n.index==`number`&&Array.isArray(r)?r[n.index]:void 0,[o]=je([{object:n.object,fields:n.fields,reason:n.reason}],i?.data,a);if(!o)continue;let s=(i?.action??`create`)===`create`?`create`:`update`;this.emitWriteWarning({operation:s,resource:n.object??i?.object??``,...i?.id!==void 0&&i?.id!==null?{id:i.id}:{},droppedFields:[o]})}}onWriteWarning(e){return this.writeWarningListeners.add(e),()=>{this.writeWarningListeners.delete(e)}}onSaveAdvisory(e){return this.saveAdvisoryListeners.add(e),()=>{this.saveAdvisoryListeners.delete(e)}}emitSaveAdvisory(e){for(let t of this.saveAdvisoryListeners)try{t(e)}catch(e){console.warn(`ObjectStackAdapter: save-advisory listener error`,e)}}installSaveAdvisoryInterceptor(){let e=this.client.meta,t=e.saveItem.bind(e);e.saveItem=async(e,n,r)=>{let i=await t(e,n,r);try{let t=d(i);t.length>0&&this.emitSaveAdvisory({type:e,name:n,mode:i?.state===`draft`?`draft`:`publish`,advisories:t})}catch(e){console.warn(`ObjectStackAdapter: save-advisory read error`,e)}return i}}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,t),n.record}catch(e){throw T(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,n),i.record}catch(e){throw T(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.success&&this.emitMutation({type:`delete`,resource:e,id:t}),r.success}catch(e){throw T(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 T(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 T(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 ae(`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 ae(`update`,t.length,s.length,s,{resource:e,totalRecords:n.length});return t}default:throw new h(`Unsupported bulk operation: ${t}`,`UNSUPPORTED_OPERATION`,400)}}catch(r){if(o(),r instanceof ae||r instanceof h)throw r;let i=r instanceof Error?r.message:String(r),a=n.map((e,t)=>({index:t,error:i}));throw new ae(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 h(`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 T(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 h(`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 T(e)}}async getImportJobProgress(e){await this.connect();let t=this.importJobApi();if(!t)throw new h(`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 T(e)}}async getImportJobResults(e){await this.connect();let t=this.importJobApi();if(!t)throw new h(`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 T(e)}}async listImportJobs(e={}){await this.connect();let t=this.importJobApi();if(!t)throw new h(`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 T(e)}}async cancelImportJob(e){await this.connect();let t=this.importJobApi();if(!t)throw new h(`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 T(e)}}async undoImportJob(e){await this.connect();let t=this.importJobApi();if(!t||typeof t.undoImportJob!=`function`)throw new h(`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 T(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=ge(t.$orderby);if(r&&n.set(`sort`,r),t.$filter!==void 0&&t.$filter!==null){let e=S(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.code=e?.code??e?.error?.code,t.httpStatus=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=S(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 t={};e.$select&&(t.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)||(t.filters=Array.isArray(e.$filter)?b(e.$filter):a(e.$filter)));let n=ge(e.$orderby);return n&&(t.sort=n),e.$skip!==void 0&&(t.skip=e.$skip),e.$top!==void 0&&(t.top=e.$top),e.$search!=null&&String(e.$search).trim()!==``&&(t.search=String(e.$search).trim()),e.$searchFields&&e.$searchFields.length>0&&(t.searchFields=e.$searchFields),t}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 ye(n)?new ie(e,{originalError:t}):t instanceof h?t:v(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}}invalidateViewKeys(e,t){this.metadataCache.invalidate?.(`view:${e}:${t}`),this.metadataCache.invalidate?.(`view-overrides:${e}`)}async listViewOverrides(e){await this.connect();let t=`view-overrides:${e}`;return await this.metadataCache.get(t,async()=>{let t=await this.client.meta.getItems(`view`),n=Array.isArray(t?.items)?t.items:Array.isArray(t)?t:[],r={};for(let t of n){if(!t||typeof t!=`object`||Me(t)!==e)continue;let n=t.name;typeof n==`string`&&n&&(r[n]=t)}return r})}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);return this.invalidateViewKeys(e,t),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(Me(t)!==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 ne({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.invalidateViewKeys(e,n),i&&i.item?i.item:r}async updateView(e,t,n){await this.connect();let r=this.metadataClient(),i=Ne(await r.get(`view`,t,{state:`draft`}));if(i){let a=Fe(i,n,t,e);return await r.save(`view`,t,a,{mode:`draft`}),this.invalidateViewKeys(e,t),a}let a;try{let e=await this.client.meta.getItem(`view`,t);a=e&&(e.item||e)||{},a?.list&&(a=a.list)}catch(n){throw ye(n)?Object.assign(Error(`updateView: view "${t}" not found on object "${e}" — no pending draft and no published overlay. Use createView() to create one.`),{cause:n}):n}let o=Fe(a,n,t,e),s=await this.client.meta.saveItem(`view`,t,o);return this.invalidateViewKeys(e,t),s&&s.item?s.item:o}async deleteView(e,t){await this.connect();let n=this.metadataClient();try{let r=Pe(await n.reset(`view`,t,{state:`draft`})),i;try{i=Pe(await n.reset(`view`,t))}catch(n){let i={deleted:!1,draft:r,published:{removed:!1}};throw Object.assign(Error(`deleteView: view "${t}" on object "${e}" is NOT fully removed — the draft home was ${r.removed?`discarded`:`already absent`}, but deleting the published overlay failed. The published row is still serving the view; retry the delete.`),{cause:n,outcome:i})}return{deleted:r.removed||i.removed,draft:r,published:i}}finally{this.invalidateViewKeys(e,t)}}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 probeAppAccess(e){if(!e)return`unknown`;try{return await this.client.meta.getItem(`app`,e),`granted`}catch(e){return Ce(e)?`denied`:`unknown`}}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=Te(n);if(r.kind===`rejected`)throw new we(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 w(`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,drillRanges:Array.isArray(s?.drillRanges)?s.drillRanges: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 h((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 h((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 h(`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 h(`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 h(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{le as n,ne as r,Ie as t};