@objectstack/console 17.5.0 → 17.7.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 (282) hide show
  1. package/CHANGELOG.md +806 -0
  2. package/dist/.objectstack-injection.json +2 -2
  3. package/dist/.objectui-sha +1 -1
  4. package/dist/assets/{ActionResultDialog-CLdIyOW6.js → ActionResultDialog-ChYnuROr.js} +3 -3
  5. package/dist/assets/{AiPendingActionsPage-OKYz66yR.js → AiPendingActionsPage-Dh3-i4BB.js} +1 -1
  6. package/dist/assets/{ApiConsolePage-CcrKovu8.js → ApiConsolePage-CKYEqlMs.js} +1 -1
  7. package/dist/assets/AppDocsIndex-B5Tky2xg.js +1 -0
  8. package/dist/assets/{AppManagementPage-D_xz8cTZ.js → AppManagementPage-ZwyvnHpM.js} +1 -1
  9. package/dist/assets/ApprovalsInboxPage-DD4fe0Em.js +1 -0
  10. package/dist/assets/{AuditLogPage-CoghqsZb.js → AuditLogPage-Sed6iMqP.js} +1 -1
  11. package/dist/assets/BookPage-DYjUsQIc.js +1 -0
  12. package/dist/assets/{ComponentNavView-BxsixSU9.js → ComponentNavView-DrlxM4SY.js} +1 -1
  13. package/dist/assets/CreateViewDialog-Cp72x_O7.js +1 -0
  14. package/dist/assets/DashboardView-juicRxcP.js +1 -0
  15. package/dist/assets/DocPage-CxJaQ-pC.js +1 -0
  16. package/dist/assets/{DocsIndex-B2zw_HAp.js → DocsIndex-LALVtIVR.js} +1 -1
  17. package/dist/assets/{DocsLayout-DezZ8x7_.js → DocsLayout-BAwlJQQf.js} +1 -1
  18. package/dist/assets/DocsSlug-CkF1E-Zs.js +1 -0
  19. package/dist/assets/ExpressionProvider-Dr0e99r1.js +1 -0
  20. package/dist/assets/FlowRunsPage-R3W3t2s4.js +1 -0
  21. package/dist/assets/{IntegrationsPage-2leVkVDH.js → IntegrationsPage-DIuFLEbF.js} +2 -2
  22. package/dist/assets/InterfaceListPage-BfoCldGu.js +1 -0
  23. package/dist/assets/{MarketplaceInstalledPage-EPPHSitW.js → MarketplaceInstalledPage-DyjhcUNB.js} +1 -1
  24. package/dist/assets/MarketplacePackagePage-BbO27Pgs.js +4 -0
  25. package/dist/assets/{MarketplacePage-BnQKykgv.js → MarketplacePage-DO2_b64U.js} +1 -1
  26. package/dist/assets/{MetadataInspector-BWxLkr0O.js → MetadataInspector-BQyu9pOE.js} +1 -1
  27. package/dist/assets/ObjectDataPage-DIY-yefK.js +1 -0
  28. package/dist/assets/PageView-C-qWu3Jw.js +1 -0
  29. package/dist/assets/ProfilePage-Qp8DL8CF.js +1 -0
  30. package/dist/assets/{PublicFormsPage-DlE6tck_.js → PublicFormsPage-D3AT2EH9.js} +1 -1
  31. package/dist/assets/RecordDetailView-B3XBEgk2.js +3 -0
  32. package/dist/assets/RecordFormPage-CcoZfUJ3.js +1 -0
  33. package/dist/assets/ReportDefaultInspector-DVcWM6sh.js +1 -0
  34. package/dist/assets/ReportView-pJCFptzp.js +2 -0
  35. package/dist/assets/RuntimeDraftBar-DObTyFu2.js +1 -0
  36. package/dist/assets/SchemaForm-BWSWYMLE.js +3 -0
  37. package/dist/assets/SearchResultsPage-ChVIzFob.js +1 -0
  38. package/dist/assets/{SettingsHub-BGKIj-Zq.js → SettingsHub-CPP9FDe8.js} +1 -1
  39. package/dist/assets/SettingsView-CrHAROu9.js +1 -0
  40. package/dist/assets/{SkeletonDetail-C8fMI-Mu.js → SkeletonDetail-CP-35B8x.js} +1 -1
  41. package/dist/assets/{af-BfSmLD34.js → af-Bhbso4Pg.js} +1 -1
  42. package/dist/assets/ai-BAPiCsNk.js +3 -0
  43. package/dist/assets/app-shell-eager-leaves-D9tgfJOe.js +1 -0
  44. package/dist/assets/{ar-B9ttrM75.js → ar-DG8TAFtm.js} +1 -1
  45. package/dist/assets/{ar-DZ-C1rn-cyl.js → ar-DZ-BtSien-d.js} +1 -1
  46. package/dist/assets/{ar-EG-BaDxKP_o.js → ar-EG-DpXC0zoY.js} +1 -1
  47. package/dist/assets/{ar-MA-DbxNEcmd.js → ar-MA-D1qVJLyE.js} +1 -1
  48. package/dist/assets/{ar-SA-DeC5LXcX.js → ar-SA-BIYKNgv8.js} +1 -1
  49. package/dist/assets/{ar-TN-C9KpTFJz.js → ar-TN-mUR5Mq3s.js} +1 -1
  50. package/dist/assets/{az-cMerDwRO.js → az-B7IqwHGK.js} +1 -1
  51. package/dist/assets/{be-ZTSbszQh.js → be-CnZyPaSX.js} +1 -1
  52. package/dist/assets/{be-tarask-BXZEUrgX.js → be-tarask--uMMCC7l.js} +1 -1
  53. package/dist/assets/{bg-BDogpmn5.js → bg-CZwuirtY.js} +1 -1
  54. package/dist/assets/{bn-Cz04uxmh.js → bn-BbOX0r-z.js} +1 -1
  55. package/dist/assets/{bs-CpFnCl-j.js → bs-B5W75cYR.js} +1 -1
  56. package/dist/assets/{ca-CHC4M52Z.js → ca-Be69LdIM.js} +1 -1
  57. package/dist/assets/{ckb-Dxw-RNm8.js → ckb-B-nKM1Vn.js} +1 -1
  58. package/dist/assets/contracts-DieHW666.js +1 -0
  59. package/dist/assets/{createDerive-DvA_JGNq.js → createDerive-CynsXU-B.js} +1 -1
  60. package/dist/assets/{cs-DsFaJ5Z7.js → cs-qHngxH7l.js} +1 -1
  61. package/dist/assets/{cy-FH4JFDTs.js → cy-DscO2Pgf.js} +1 -1
  62. package/dist/assets/{da-D1pVjaAq.js → da-vibkaLMF.js} +1 -1
  63. package/dist/assets/data-adapter-BDsrq0TX.js +2 -0
  64. package/dist/assets/{de-AT-DUMQCisj.js → de-AT--JneEuBw.js} +1 -1
  65. package/dist/assets/{de-DKrxSvnP.js → de-BCT78XYW.js} +1 -1
  66. package/dist/assets/default-inspector-registry-Dktr6x_q.js +1 -0
  67. package/dist/assets/dist-yh3dYtHt.js +14 -0
  68. package/dist/assets/drillUrlFilters-N0RngQg6.js +1 -0
  69. package/dist/assets/{el-l3-bHySV.js → el-Cl0y9T2b.js} +1 -1
  70. package/dist/assets/en-AU-By42tTB7.js +1 -0
  71. package/dist/assets/{en-CA-DGH5NF0a.js → en-CA-BqEEoj-Y.js} +1 -1
  72. package/dist/assets/en-GB-Cx8B9nkB.js +1 -0
  73. package/dist/assets/en-IE-CX9nv6uO.js +1 -0
  74. package/dist/assets/en-IN-ByGSBHa4.js +1 -0
  75. package/dist/assets/en-NZ-BPMwa2ZN.js +1 -0
  76. package/dist/assets/en-ZA-lj_N4R6c.js +1 -0
  77. package/dist/assets/{eo-CL6CXHZx.js → eo-oOXROuhF.js} +1 -1
  78. package/dist/assets/{es-BIJ0rksI.js → es-EudscwjH.js} +1 -1
  79. package/dist/assets/{et-BGgMzjm1.js → et-CB-5LLh6.js} +1 -1
  80. package/dist/assets/{eu-CqvAoRrX.js → eu-B4-hcseX.js} +1 -1
  81. package/dist/assets/{fa-IR-DNz3oA1-.js → fa-IR-CogavcMJ.js} +1 -1
  82. package/dist/assets/{fi-DNSfKWuW.js → fi-CIBE0mYa.js} +1 -1
  83. package/dist/assets/{formatLong-CHb9WA3O.js → formatLong-qqgm7lV1.js} +1 -1
  84. package/dist/assets/{fr-CA-CotiswPx.js → fr-CA-BugXMutW.js} +1 -1
  85. package/dist/assets/{fr-DYRJCirJ.js → fr-CDReXYWW.js} +1 -1
  86. package/dist/assets/{fr-CH-CpiEYWpc.js → fr-CH-fiTiB6X1.js} +1 -1
  87. package/dist/assets/framework-CAuH4h0L.js +35 -0
  88. package/dist/assets/{fy-B69yM3FE.js → fy-t_GzIAg_.js} +1 -1
  89. package/dist/assets/{gd-BAy8AsX6.js → gd-CSncIxtN.js} +1 -1
  90. package/dist/assets/{getIcon-BEVyC4y3.js → getIcon-BDkBRQFw.js} +1 -1
  91. package/dist/assets/{gl-soLn_weL.js → gl-_138Mj2S.js} +1 -1
  92. package/dist/assets/{gu-B19Yo9yC.js → gu-COfH-YUT.js} +1 -1
  93. package/dist/assets/{he-DYTPo33p.js → he-BXL4lOKY.js} +1 -1
  94. package/dist/assets/{hi-D2dIK7Oy.js → hi-kXuYI0TJ.js} +1 -1
  95. package/dist/assets/{highlighted-body-OFNGDK62-CExufvVt.js → highlighted-body-OFNGDK62-CK7x7Gzm.js} +1 -1
  96. package/dist/assets/{hr-BV-VOPMu.js → hr-DAOsQWzI.js} +1 -1
  97. package/dist/assets/{ht-C7MM4qkS.js → ht-Ch8SKz8p.js} +1 -1
  98. package/dist/assets/{hu-Rha1m2Ym.js → hu-q6W_rWPT.js} +1 -1
  99. package/dist/assets/{hy-CiTNgbdV.js → hy-0M8OmwnM.js} +1 -1
  100. package/dist/assets/i18n-DTfZonAM.js +17 -0
  101. package/dist/assets/i18n-locale-ar-O6rs-Cir.js +4 -0
  102. package/dist/assets/i18n-locale-de-CMc1jk4a.js +4 -0
  103. package/dist/assets/i18n-locale-en-CbRQO81h.js +4 -0
  104. package/dist/assets/i18n-locale-es-t47nyoCX.js +4 -0
  105. package/dist/assets/i18n-locale-fr-E425EqJM.js +4 -0
  106. package/dist/assets/i18n-locale-ja-y_fk77fz.js +4 -0
  107. package/dist/assets/i18n-locale-ko-CdnY2uCg.js +4 -0
  108. package/dist/assets/i18n-locale-pt-BaUOXS6y.js +4 -0
  109. package/dist/assets/i18n-locale-ru-pFlhX9wg.js +4 -0
  110. package/dist/assets/i18n-locale-zh-Dkj4ROTN.js +4 -0
  111. package/dist/assets/i18n-runtime-CdWyaiOD.js +1 -0
  112. package/dist/assets/{id-Cijsfjt-.js → id-BM_H1_jv.js} +1 -1
  113. package/dist/assets/index-ocmkyCt6.js +19 -0
  114. package/dist/assets/index-v2Ijn9Gr.css +2 -0
  115. package/dist/assets/{infrastructure-BHSync5f.js → infrastructure-CSnL6ntj.js} +2 -2
  116. package/dist/assets/integration-7NqwVHuJ.js +1 -0
  117. package/dist/assets/{is-xS1WTyeC.js → is-B_7jXZfS.js} +1 -1
  118. package/dist/assets/isSameWeek-D90tBsli.js +1 -0
  119. package/dist/assets/{it-C2i_c9sd.js → it-CBM0J9cD.js} +1 -1
  120. package/dist/assets/{it-CH-l516ZNXj.js → it-CH-BQltCNsR.js} +1 -1
  121. package/dist/assets/{ja-D9_ewLny.js → ja-DBjnsx21.js} +1 -1
  122. package/dist/assets/{ja-Hira-D_6ExgHw.js → ja-Hira-BZfSmj1i.js} +1 -1
  123. package/dist/assets/{ka-BYHGyees.js → ka-HwpuKgUY.js} +1 -1
  124. package/dist/assets/{kk-CbTFtuqb.js → kk-DLKA9paj.js} +1 -1
  125. package/dist/assets/{km-Dr2gwhIn.js → km-BU5kermq.js} +1 -1
  126. package/dist/assets/{kn-CprH8JD7.js → kn-BNFqbCoi.js} +1 -1
  127. package/dist/assets/{ko-CsFS2u5i.js → ko-D8n4uMqQ.js} +1 -1
  128. package/dist/assets/{lb-CbFKN7Ob.js → lb-B1empQ7m.js} +1 -1
  129. package/dist/assets/{lt-Bq0xkLp0.js → lt-gMukpK3G.js} +1 -1
  130. package/dist/assets/{lv-Cj6vg6Qo.js → lv-D2O5AnsZ.js} +1 -1
  131. package/dist/assets/{match-CiPp9BME.js → match-BTF6WqJh.js} +1 -1
  132. package/dist/assets/{match-C_jFGO9e.js → match-Cyum2eeW.js} +1 -1
  133. package/dist/assets/{match-Co4ivumx.js → match-ScHH8kYk.js} +1 -1
  134. package/dist/assets/mermaid-GHXKKRXX-D4H6EVJQ.js +1 -0
  135. package/dist/assets/metadata-admin-CEhVmXFv.js +9 -0
  136. package/dist/assets/{mk-MXFM99YL.js → mk-D-Zl0xVN.js} +1 -1
  137. package/dist/assets/{mn-D5Q9B6Jt.js → mn-jJbTslgD.js} +1 -1
  138. package/dist/assets/{ms-CCzPRldx.js → ms-CUuJHLA4.js} +1 -1
  139. package/dist/assets/{mt-mjJpN6xW.js → mt-yIcbfxKY.js} +1 -1
  140. package/dist/assets/{nb-BIlNqdEb.js → nb-D9WNypoj.js} +1 -1
  141. package/dist/assets/{nl-BE-FwXjQsmV.js → nl-BE-B1vKiw2h.js} +1 -1
  142. package/dist/assets/{nl-D2uBtIxG.js → nl-DC7b5e90.js} +1 -1
  143. package/dist/assets/{nn-B0loJ7SV.js → nn-uP4yJ9s0.js} +1 -1
  144. package/dist/assets/{oc-U7-yH1sO.js → oc-DHTqadJI.js} +1 -1
  145. package/dist/assets/{pl-mTy0JYgi.js → pl-Bxnnizf5.js} +1 -1
  146. package/dist/assets/plugin-calendar-b7C35ANT.js +1 -0
  147. package/dist/assets/plugin-charts-b-yVtmdI.js +7 -0
  148. package/dist/assets/plugin-chatbot-D1KW_oIO.js +122 -0
  149. package/dist/assets/plugin-dashboard-DTkPoPEb.js +6 -0
  150. package/dist/assets/plugin-form-UIRm-FpQ.js +1 -0
  151. package/dist/assets/plugin-gantt-9dtc8zzX.js +63 -0
  152. package/dist/assets/plugin-grid-Cp4RKtMJ.js +10 -0
  153. package/dist/assets/plugin-kanban-B2JOPZIJ.js +1 -0
  154. package/dist/assets/plugin-map-CBJcVJYk.js +1 -0
  155. package/dist/assets/{plugin-markdown-D1nTQc1T.js → plugin-markdown-CNlDzqP-.js} +1 -1
  156. package/dist/assets/plugin-report-IZzgQb-Q.js +59 -0
  157. package/dist/assets/plugin-timeline-DsmtjcJ3.js +1 -0
  158. package/dist/assets/plugin-tree-DTRPBdhe.js +1 -0
  159. package/dist/assets/plugin-view-D9ixsNDG.js +1 -0
  160. package/dist/assets/plugins-views-CnvkdSJK.js +3 -0
  161. package/dist/assets/{pt-BR-2KtO5Js1.js → pt-BR-D416seHT.js} +1 -1
  162. package/dist/assets/{pt-Bet5OOQf.js → pt-DwHBy9_c.js} +1 -1
  163. package/dist/assets/{ro-37U6sgzi.js → ro-DDf1X3Np.js} +1 -1
  164. package/dist/assets/{ru-CyuAY-5E.js → ru-8eM3mcgK.js} +1 -1
  165. package/dist/assets/{runtime-metadata-persistence-afAW-MeD.js → runtime-metadata-persistence-DX29lQ62.js} +1 -1
  166. package/dist/assets/{se-DeJabuC6.js → se-D4JvQeRX.js} +1 -1
  167. package/dist/assets/{sk-DWEpjfkR.js → sk-DvpgttGI.js} +1 -1
  168. package/dist/assets/{sl-4oSvNhIR.js → sl-B3gCZ-_a.js} +1 -1
  169. package/dist/assets/{sq-BjkBCaXW.js → sq-CVaTmL0V.js} +1 -1
  170. package/dist/assets/{sr-Dxm1DsRS.js → sr-CnH5Ffyz.js} +1 -1
  171. package/dist/assets/{sr-Latn-Dawg6oP2.js → sr-Latn-Dw9w61q6.js} +1 -1
  172. package/dist/assets/src-BUry7633.js +2 -0
  173. package/dist/assets/{src-C8NYjdVm.js → src-DMDT5a27.js} +1 -1
  174. package/dist/assets/src-ZxH3AOCu.js +16 -0
  175. package/dist/assets/{studioEntry-nXQP3iL0.js → studioEntry-DAqcBFtr.js} +1 -1
  176. package/dist/assets/{submitRedirect-jK-cEIbP.js → submitRedirect-iy0oOi7I.js} +1 -1
  177. package/dist/assets/{sv-CROOGJGz.js → sv-CU7wdxyK.js} +1 -1
  178. package/dist/assets/{ta-BZnTmFI_.js → ta-DPH6q0HR.js} +1 -1
  179. package/dist/assets/{te-BN0v0x5t.js → te-BSaThkGV.js} +1 -1
  180. package/dist/assets/{th-CBjKhp_U.js → th-NXP8_Qb8.js} +1 -1
  181. package/dist/assets/{tr-x0Ne4N4H.js → tr-DDXoH663.js} +1 -1
  182. package/dist/assets/types-zod-ChJ30y25.js +1 -0
  183. package/dist/assets/{ug-sgzNhsKo.js → ug-Guus6pPe.js} +1 -1
  184. package/dist/assets/ui-components-D8wcRNrt.js +37 -0
  185. package/dist/assets/ui-layout-BYO3rRIl.js +1 -0
  186. package/dist/assets/{uk-o_DQ5VHJ.js → uk-uiy4vsp8.js} +1 -1
  187. package/dist/assets/use-book-data-DFTswcKm.js +1 -0
  188. package/dist/assets/{useActionModal-CSvbHkQ7.js → useActionModal-h52Z5Pkl.js} +1 -1
  189. package/dist/assets/useCanAuthorMetadata-TDrVrYGB.js +1 -0
  190. package/dist/assets/useDatasetCatalog-BOd0Ybr1.js +1 -0
  191. package/dist/assets/useNavSelDeepLink-67Y4qCNO.js +1 -0
  192. package/dist/assets/useNavTargetLabel-D8lRdb6O.js +1 -0
  193. package/dist/assets/useOpenRecordList-C7oqUD3F.js +1 -0
  194. package/dist/assets/{usePackageL10n-CMx66am-.js → usePackageL10n-Jl2XiF2F.js} +1 -1
  195. package/dist/assets/{useSettingsLabel-Kkr2q0Oo.js → useSettingsLabel-CSpBDTdy.js} +1 -1
  196. package/dist/assets/{uz-Cyrl-DbtkQtz_.js → uz-Cyrl-Cmb5bvbf.js} +1 -1
  197. package/dist/assets/{uz-Be41d4jl.js → uz-DJWxoTz4.js} +1 -1
  198. package/dist/assets/vendor-objectstack-C4eD5dbT.js +139 -0
  199. package/dist/assets/{vi-84mZmklk.js → vi-Bb3QoIJC.js} +1 -1
  200. package/dist/assets/{zh-CN-DD1reegJ.js → zh-CN-C-Hts1ZR.js} +1 -1
  201. package/dist/assets/{zh-HK-B05u30WI.js → zh-HK-CtBAZ_ZS.js} +1 -1
  202. package/dist/assets/{zh-TW-Bb-WimPD.js → zh-TW-B7DDahD-.js} +1 -1
  203. package/dist/chunk-membership.json +116 -104
  204. package/dist/eager-closure.json +126 -120
  205. package/dist/index.html +4 -4
  206. package/dist/sdui.manifest.json +998 -115
  207. package/package.json +1 -1
  208. package/dist/assets/AppDocsIndex-F4zDq2zz.js +0 -1
  209. package/dist/assets/ApprovalsInboxPage-DrEUmaDb.js +0 -1
  210. package/dist/assets/CreateViewDialog-xyKlpLEW.js +0 -1
  211. package/dist/assets/DashboardView-CGC-_Om8.js +0 -1
  212. package/dist/assets/DocPage-CIZE5kdj.js +0 -1
  213. package/dist/assets/DocsSlug-DXdFdwlS.js +0 -1
  214. package/dist/assets/ExpressionProvider-DZfMwyMs.js +0 -1
  215. package/dist/assets/FlowRunsPage-CvY3nJMF.js +0 -1
  216. package/dist/assets/InterfaceListPage-BdECC_i3.js +0 -1
  217. package/dist/assets/MarketplacePackagePage-C7NOu2Ir.js +0 -4
  218. package/dist/assets/ObjectDataPage-BIzp65Mo.js +0 -1
  219. package/dist/assets/PageView-CVLgCRSF.js +0 -1
  220. package/dist/assets/ProfilePage-D2qGgxPK.js +0 -1
  221. package/dist/assets/RecordDetailView-DQKydU7X.js +0 -3
  222. package/dist/assets/RecordFormPage-BTjwxJIA.js +0 -1
  223. package/dist/assets/ReportDefaultInspector-DdsQAkd7.js +0 -1
  224. package/dist/assets/ReportView-GIdKJdOt.js +0 -2
  225. package/dist/assets/RuntimeDraftBar-BbMdi3Kp.js +0 -1
  226. package/dist/assets/SchemaForm-C8X1ve4p.js +0 -3
  227. package/dist/assets/SearchResultsPage-Jwhqsdyo.js +0 -1
  228. package/dist/assets/SettingsView-D8SMKdrc.js +0 -1
  229. package/dist/assets/app-shell-eager-leaves-CDVclng4.js +0 -1
  230. package/dist/assets/appRoute-DbnWDEa1.js +0 -1
  231. package/dist/assets/data-adapter-DMbe6Njk.js +0 -1
  232. package/dist/assets/default-inspector-registry-CpL3fFhl.js +0 -1
  233. package/dist/assets/dist-BXrEV1ag.js +0 -13
  234. package/dist/assets/drillUrlFilters-hi-2d3DW.js +0 -1
  235. package/dist/assets/en-AU-C6x7mDhH.js +0 -1
  236. package/dist/assets/en-GB-0-nho2eK.js +0 -1
  237. package/dist/assets/en-IE-2fC3BkfV.js +0 -1
  238. package/dist/assets/en-IN-C1QcFhxn.js +0 -1
  239. package/dist/assets/en-NZ-C80ptZT7.js +0 -1
  240. package/dist/assets/en-ZA-ByZDrjeb.js +0 -1
  241. package/dist/assets/framework-DcWkeiND.js +0 -35
  242. package/dist/assets/i18n-CEKxYdmD.js +0 -9
  243. package/dist/assets/i18n-locale-ar-DN7sl3GF.js +0 -4
  244. package/dist/assets/i18n-locale-de-C40JErvb.js +0 -4
  245. package/dist/assets/i18n-locale-en-CITPDIHy.js +0 -4
  246. package/dist/assets/i18n-locale-es-C8DdWN6c.js +0 -4
  247. package/dist/assets/i18n-locale-fr-COIdEZZl.js +0 -4
  248. package/dist/assets/i18n-locale-ja-DYF_rU_s.js +0 -4
  249. package/dist/assets/i18n-locale-ko-B-ODYAtX.js +0 -4
  250. package/dist/assets/i18n-locale-pt-CK1SyBIm.js +0 -4
  251. package/dist/assets/i18n-locale-ru-jLzvShMO.js +0 -4
  252. package/dist/assets/i18n-locale-zh-Bf9Gbbvl.js +0 -4
  253. package/dist/assets/i18n-runtime-CTgAQF4N.js +0 -1
  254. package/dist/assets/index-CLyvpiGc.css +0 -2
  255. package/dist/assets/index-CfnfGw5W.js +0 -20
  256. package/dist/assets/isSameWeek-DWYeNyh8.js +0 -1
  257. package/dist/assets/mermaid-GHXKKRXX-DVLc_uym.js +0 -1
  258. package/dist/assets/metadata-admin-CybaOCdO.js +0 -9
  259. package/dist/assets/nav-selection-Dzm_mA3C.js +0 -1
  260. package/dist/assets/plugin-calendar-CKRBcML7.js +0 -1
  261. package/dist/assets/plugin-charts-DGTJxXCB.js +0 -7
  262. package/dist/assets/plugin-chatbot-DwtwNA-y.js +0 -122
  263. package/dist/assets/plugin-dashboard-C1AYKmGX.js +0 -6
  264. package/dist/assets/plugin-form-CV8ZY04-.js +0 -1
  265. package/dist/assets/plugin-gantt-BRIb2_8G.js +0 -63
  266. package/dist/assets/plugin-grid-C9h7mRVv.js +0 -11
  267. package/dist/assets/plugin-kanban-BcJ0Dhys.js +0 -1
  268. package/dist/assets/plugin-map-D24ZUOUj.js +0 -1
  269. package/dist/assets/plugin-report-BfGintAq.js +0 -59
  270. package/dist/assets/plugin-timeline-CbBRq_qt.js +0 -1
  271. package/dist/assets/plugin-tree-BNX2A5J5.js +0 -1
  272. package/dist/assets/plugin-view-DzWQWYyH.js +0 -1
  273. package/dist/assets/plugins-views-DraK4xz0.js +0 -3
  274. package/dist/assets/src-B8lv0plz.js +0 -18
  275. package/dist/assets/src-DoDvT77T.js +0 -1
  276. package/dist/assets/types-zod-Y2RwUUeJ.js +0 -1
  277. package/dist/assets/ui-components-BTB1NkUW.js +0 -37
  278. package/dist/assets/ui-layout-bZfafwJa.js +0 -1
  279. package/dist/assets/use-book-data-C3eyZJSG.js +0 -1
  280. package/dist/assets/useOpenRecordList-B5-qaFUx.js +0 -1
  281. package/dist/assets/vendor-objectstack-XuWC71M9.js +0 -266
  282. package/dist/assets/vendor-zod-CHLW1iCr.js +0 -64
@@ -0,0 +1,14 @@
1
+ import{t as e}from"./rolldown-runtime-C0FnF6B9.js";import{$ as t,$n as n,A as r,B as i,C as a,D as o,Dn as s,Dt as c,E as l,Et as u,G as d,Gn as f,H as p,Hn as m,In as h,It as g,Ji as _,Jn as v,Jt as y,Kn as b,L as ee,Li as x,Ln as te,Lr as ne,Lt as re,Mn as ie,Mt as ae,N as oe,Nn as se,Nt as ce,O as le,Ot as ue,Pt as de,Qi as fe,Qt as pe,R as me,Rn as he,S as ge,Sn as _e,St as ve,U as ye,Un as be,V as xe,W as Se,Wn as Ce,Xi as we,Xn as Te,Xt as Ee,Yi as De,Z as Oe,Zi as ke,Zn as Ae,Zr as je,Zt as Me,_ as Ne,_r as Pe,_t as Fe,a as Ie,ai as Le,an as Re,b as ze,bn as Be,bt as Ve,cn as He,ct as Ue,da as We,dn as Ge,dt as Ke,ei as qe,en as Je,er as Ye,et as Xe,f as Ze,fa as Qe,gn as $e,gt as et,h as tt,hn as nt,hr as rt,ht as it,i as at,ia as ot,ii as st,j as ct,jn as lt,k as ut,kt as dt,l as ft,la as pt,ln as mt,lt as ht,ma as gt,mt as _t,nn as vt,oi as yt,on as bt,p as xt,pa as St,pn as Ct,pr as wt,pt as Tt,qt as Et,r as Dt,ri as Ot,rt as kt,si as At,sn as jt,tt as Mt,ua as Nt,un as Pt,ut as Ft,v as It,vr as Lt,vt as Rt,w as zt,wn as Bt,xn as Vt,y as Ht,yn as Ut,yt as Wt,zn as Gt,zt as Kt}from"./vendor-objectstack-C4eD5dbT.js";import{r as qt}from"./contracts-DieHW666.js";var Jt=e(((e,t)=>{t.exports={}}));Vt();var S=Jt(),Yt=/^on[A-Z]/,Xt=new Set([`dangerouslySetInnerHTML`,`ref`,`key`]),Zt=`type`;function Qt(e,t={}){return new tn(e,t).parseDocument()}var $t=e=>/[A-Za-z]/.test(e),en=e=>/[A-Za-z0-9:_-]/.test(e),tn=class{constructor(e,t){this.src=e,this.opts=t,this.pos=0,this.diagnostics=[]}parseDocument(){if(this.skipTrivia(),this.peek()!==`<`)return this.error(`no-root`,`Expected a single root element`),{tree:null,diagnostics:this.diagnostics};let e=this.parseElement();return this.skipTrivia(),e&&this.pos<this.src.length&&this.error(`multiple-roots`,`A page must have exactly one root element`,this.pos),{tree:e,diagnostics:this.diagnostics}}parseElement(){let e=this.pos;if(!this.eat(`<`))return this.error(`expected-element`,`Expected "<"`,e),null;let t=this.readName();if(!t)return this.error(`bad-tag`,`Expected a tag name after "<"`,e),null;this.opts.allowedTags&&!this.opts.allowedTags.has(t)&&this.error(`forbidden-tag`,`<${t}> is not an allowed component`,e,t);let n={};for(;;){this.skipWs();let r=this.peek();if(r===``||r===`>`||r===`/`)break;let i=this.parseAttr(e,t);if(!i)break;i.drop||(n[i.name]=i.value)}this.skipWs();let r;this.eat(`/`)?this.eat(`>`)||this.error(`bad-self-close`,`Malformed self-closing <${t}>`,this.pos,t):this.eat(`>`)?r=this.parseChildren(t):this.error(`unterminated-open-tag`,`Unterminated <${t}> open tag`,e,t);let i={...n,type:t};return r&&r.length&&(i.children=r),i}parseAttr(e,t){let n=this.readName();if(!n)return this.error(`bad-attr`,`Malformed attribute on <${t}>`,this.pos,t),this.pos++,null;this.skipWs();let r=!0;return this.eat(`=`)&&(this.skipWs(),r=this.parseAttrValue(t)),n===Zt?(this.error(`forbidden-attr`,`Attribute "${Zt}" is not allowed on <${t}> \u2014 on this tier the tag name IS the component, so <${t}> already means type "${t}". Delete the attribute, or write the tag of the component you meant.`,e,t),{name:n,value:void 0,drop:!0}):Yt.test(n)||Xt.has(n)?(this.error(`forbidden-attr`,`Attribute "${n}" is not allowed on <${t}>`,e,t),{name:`__forbidden_${n}`,value:void 0}):{name:n,value:r}}parseAttrValue(e){let t=this.peek();if(t===`"`||t===`'`)return this.readString(t);if(t===`{`)return nn(this.readBraced());this.error(`bad-attr-value`,`Expected an attribute value on <${e}>`,this.pos,e)}parseChildren(e){let t=[];for(;;){if(this.pos>=this.src.length){this.error(`unclosed-element`,`Unclosed <${e}>`,this.pos,e);break}if(this.src.startsWith(`</`,this.pos)){this.pos+=2,this.skipWs();let t=this.readName();this.skipWs(),this.eat(`>`),t!==e&&this.error(`mismatched-tag`,`Expected </${e}> but found </${t}>`,this.pos,e);break}if(this.src.startsWith(`{/*`,this.pos)){let e=this.src.indexOf(`*/}`,this.pos);e===-1?(this.error(`unclosed-comment`,`Unclosed comment`,this.pos),this.pos=this.src.length):this.pos=e+3;continue}if(this.peek()===`<`){let e=this.parseElement();e&&t.push(e);continue}if(this.peek()===`{`){let e=this.pos;this.readBraced(),this.error(`expression-child`,`Inline {expression} children are not supported yet — bind via a component prop`,e);continue}let n=this.readTextRun().replace(/\s+/g,` `),r=n.trim(),i=t.length>0,a=this.peek()===`<`&&!this.src.startsWith(`</`,this.pos);if(r){let e=i&&n.startsWith(` `)?` `:``,o=a&&n.endsWith(` `)?` `:``;t.push(`${e}${r}${o}`)}else n&&i&&a&&t.push(` `)}return t}peek(){return this.pos<this.src.length?this.src[this.pos]:``}eat(e){return this.src[this.pos]===e&&(this.pos++,!0)}readName(){if(!$t(this.peek()))return``;let e=this.pos;for(this.pos++;this.pos<this.src.length&&en(this.src[this.pos]);)this.pos++;return this.src.slice(e,this.pos)}readString(e){this.pos++;let t=this.pos;for(;this.pos<this.src.length&&this.src[this.pos]!==e;)this.pos++;let n=this.src.slice(t,this.pos);return this.eat(e)||this.error(`unterminated-string`,`Unterminated string literal`,t),n}readBraced(){let e=this.pos,t=0,n=null;for(;this.pos<this.src.length;this.pos++){let r=this.src[this.pos];if(n){r===n&&this.src[this.pos-1]!==`\\`&&(n=null);continue}if(r===`"`||r===`'`)n=r;else if(r===`{`)t++;else if(r===`}`&&(t--,t===0)){let t=this.src.slice(e+1,this.pos);return this.pos++,t}}return this.error(`unterminated-brace`,`Unterminated "{"`,e),this.src.slice(e+1)}readTextRun(){let e=this.pos;for(;this.pos<this.src.length&&this.src[this.pos]!==`<`&&this.src[this.pos]!==`{`;)this.pos++;return this.src.slice(e,this.pos)}skipWs(){for(;this.pos<this.src.length&&/\s/.test(this.src[this.pos]);)this.pos++}skipTrivia(){for(;;){if(this.skipWs(),this.src.startsWith(`{/*`,this.pos)){let e=this.src.indexOf(`*/}`,this.pos);this.pos=e===-1?this.src.length:e+3;continue}break}}error(e,t,n,r){this.diagnostics.push({severity:`error`,code:e,message:t,start:n??this.pos,tag:r})}};function nn(e){let t=e.trim();try{return JSON.parse(t)}catch{let e=ln(t);return e===C?{$expr:t}:e}}var C=Symbol(`not-a-literal`),rn=/[ \t\n\r]/,an=/[A-Za-z_$]/,on=/[A-Za-z0-9_$]/,sn=/^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/,cn={'"':`"`,"\\":`\\`,"/":`/`,b:`\b`,f:`\f`,n:`
2
+ `,r:`\r`,t:` `};function ln(e){let t=new un(e),n=t.value();return n===C?C:(t.ws(),t.done()?n:C)}var un=class{constructor(e){this.src=e,this.pos=0}done(){return this.pos>=this.src.length}ws(){for(;this.pos<this.src.length&&rn.test(this.src[this.pos]);)this.pos++}value(){this.ws();let e=this.src[this.pos];return e===void 0?C:e===`"`||e===`'`?this.string(e):e===`[`?this.array():e===`{`?this.object():this.keyword(`true`)?!0:this.keyword(`false`)?!1:this.keyword(`null`)?null:this.number()}keyword(e){if(!this.src.startsWith(e,this.pos))return!1;let t=this.src[this.pos+e.length];return t!==void 0&&on.test(t)?!1:(this.pos+=e.length,!0)}number(){let e=sn.exec(this.src.slice(this.pos));return e?(this.pos+=e[0].length,Number(e[0])):C}string(e){this.pos++;let t=``;for(;;){let n=this.src[this.pos];if(n===void 0)return C;if(n===e)return this.pos++,t;if(n===`\\`){let n=this.src[this.pos+1];if(n===void 0)return C;if(n===`u`){let e=this.src.slice(this.pos+2,this.pos+6);if(!/^[0-9a-fA-F]{4}$/.test(e))return C;t+=String.fromCharCode(parseInt(e,16)),this.pos+=6;continue}if(n===`'`&&e===`'`){t+=`'`,this.pos+=2;continue}let r=cn[n];if(r===void 0)return C;t+=r,this.pos+=2;continue}if(n<` `)return C;t+=n,this.pos++}}array(){this.pos++;let e=[];if(this.ws(),this.src[this.pos]===`]`)return this.pos++,e;for(;;){let t=this.value();if(t===C)return C;e.push(t),this.ws();let n=this.src[this.pos];if(n===`,`){this.pos++;continue}return n===`]`?(this.pos++,e):C}}object(){this.pos++;let e={};if(this.ws(),this.src[this.pos]===`}`)return this.pos++,e;for(;;){this.ws();let t=this.key();if(t===C||(this.ws(),this.src[this.pos]!==`:`))return C;this.pos++;let n=this.value();if(n===C)return C;Object.defineProperty(e,t,{value:n,writable:!0,enumerable:!0,configurable:!0}),this.ws();let r=this.src[this.pos];if(r===`,`){this.pos++;continue}return r===`}`?(this.pos++,e):C}}key(){let e=this.src[this.pos];if(e===`"`||e===`'`)return this.string(e);if(e!==void 0&&an.test(e)){let e=this.pos;for(this.pos++;this.pos<this.src.length&&on.test(this.src[this.pos]);)this.pos++;return this.src.slice(e,this.pos)}return C}};function dn(e){return e===void 0?[]:Array.isArray(e)?e:[e]}var fn=new Set([`dashboard`,`dashboard-grid`]),pn=[`dateGranularity`,`description`,`limit`,`sortBy`,`sortOrder`,`stageOrder`],mn=new Set(pn),hn=e=>typeof e==`object`&&!!e&&!Array.isArray(e),gn=e=>hn(e)&&`$expr`in e;function _n(e){if(!fn.has(e.type))return[];let t=e.widgets;if(!Array.isArray(t))return[];let n=[];return t.forEach((t,r)=>{if(!hn(t)||gn(t)||t.component!==void 0||t.dataset===void 0||t.dataset===null||t.dataset===``)return;let i=t.options;if(!hn(i)||gn(i)||Array.isArray(t.suppressWarnings)&&t.suppressWarnings.includes(`unconsumed-widget-option`))return;let a=typeof t.id==`string`&&t.id!==``?t.id:`#${r}`,o=typeof t.type==`string`&&t.type!==``?t.type:`widget`;for(let t of Object.keys(i))mn.has(t)||n.push({severity:`warning`,code:`unconsumed-widget-option`,message:`<${e.type}> widget "${a}" (${o}): options.${t} reaches no renderer \u2014 dashboard widget renderers read only: ${pn.join(`, `)}`,tag:e.type})}),n}var vn=`children`;function yn(e){return e.inputs.some(e=>e.name===vn)}var bn=Object.freeze([{name:`type`,scope:`every-node`,tsType:null},{name:`id`,scope:`every-node`,tsType:`string`},{name:`className`,scope:`every-node`,tsType:`string`},{name:`style`,scope:`every-node`,tsType:`Record<string, unknown>`},{name:`visible`,scope:`every-node`,tsType:`boolean`},{name:`visibleWhen`,scope:`every-node`,tsType:`string`},{name:`visibleOn`,scope:`every-node`,tsType:`string`},{name:`hidden`,scope:`every-node`,tsType:`boolean`},{name:`hiddenOn`,scope:`every-node`,tsType:`string`},{name:`disabled`,scope:`every-node`,tsType:`boolean`},{name:`disabledOn`,scope:`every-node`,tsType:`string`},{name:`bind`,scope:`every-node`,tsType:`string`},{name:`testId`,scope:`every-node`,tsType:`string`},{name:vn,scope:`every-node`,tsType:`unknown`},{name:`name`,scope:`where-undeclared`,tsType:`string`},{name:`label`,scope:`where-undeclared`,tsType:`string | Record<string, string>`},{name:`description`,scope:`where-undeclared`,tsType:`string | Record<string, string>`},{name:`placeholder`,scope:`where-undeclared`,tsType:`string`},{name:`data`,scope:`where-undeclared`,tsType:`unknown`},{name:`ariaLabel`,scope:`where-undeclared`,tsType:`string | { key: string; defaultValue?: string; params?: Record<string, unknown> }`}]),xn=e=>new Set(bn.filter(t=>t.scope===e).map(e=>e.name)),Sn=xn(`every-node`),Cn=xn(`where-undeclared`),wn=e=>typeof e==`object`&&!!e&&`$expr`in e;function Tn(e,t){let n=[],r=new Set,i=[],a=e=>{if(typeof e==`string`)return;let o=t.components[e.type];if(!o)n.push({severity:`error`,code:`unknown-component`,message:`<${e.type}> is not a known component`,tag:e.type});else{o.namespace&&r.add(o.namespace);let t=new Map(o.inputs.map(e=>[e.name,e]));for(let t of o.inputs)t.required&&!(t.name in e)&&n.push({severity:`error`,code:`missing-required-prop`,message:`<${e.type}> is missing required prop "${t.name}"`,tag:e.type});for(let[r,a]of Object.entries(e)){if(Sn.has(r)||Cn.has(r)&&!t.has(r))continue;let o=t.get(r);if(!o){n.push({severity:`warning`,code:`unknown-prop`,message:`<${e.type}> has no prop "${r}"`,tag:e.type});continue}if(o.binding&&i.push({tag:e.type,input:r,kind:o.binding,value:a}),wn(a))n.push({severity:`warning`,code:`inert-expression`,message:`<${e.type}> prop "${r}" is a braced expression this tier never evaluates \u2014 the value will be silently ignored at render. This tier materializes LITERALS only (strings, numbers, booleans, null, arrays, objects; quotes may be single or double, object keys may be unquoted), e.g. columns={['name','amount']} works \u2014 columns={rows.map((r) => r.name)} cannot`,tag:e.type});else{let t=jn(e.type,o,a);if(t)n.push(t);else{let t=An(e.type,o,a);t&&n.push(t)}}}e.children?.length&&!yn(o)&&n.push({severity:`warning`,code:`not-a-container`,message:`<${e.type}> does not accept children`,tag:e.type}),n.push(..._n(e))}e.children&&e.children.forEach(a)};return e&&a(e),{diagnostics:n,requires:[...r],bindings:i}}var En=e=>(e.enum??[]).map(e=>typeof e==`object`?e.value:e);function Dn(e,t,n){switch(e){case`number`:return typeof n==`number`;case`boolean`:return typeof n==`boolean`;case`string`:case`color`:case`date`:case`code`:case`file`:return typeof n==`string`;case`array`:return Array.isArray(n);case`object`:return typeof n==`object`&&!!n&&!Array.isArray(n);case`enum`:return En(t).includes(n);default:return!0}}function On(e,t){switch(e){case`number`:return`a number`;case`boolean`:return`a boolean`;case`array`:return`an array`;case`object`:return`an object`;case`enum`:return`one of ${JSON.stringify(En(t))}`;default:return`a string`}}function kn(e){return Array.isArray(e)?e.map((e,t)=>[String(t),e]):typeof e==`object`&&e?Object.entries(e):null}function An(e,t,n){let r=dn(t.of);if(r.length===0)return null;let i=kn(n);if(i===null)return null;let a=i.filter(([,e])=>!r.some(n=>Dn(n,t,e)));if(a.length===0)return null;let o=r.map(e=>On(e,t)).join(` or `);return{severity:r.includes(`enum`)?`error`:`warning`,code:`member-type-mismatch`,message:`<${e}> prop "${t.name}" expected every member to be ${o} \u2014 ${a.map(([e])=>`[${e}]`).join(`, `)} ${a.length===1?`is`:`are`} not`,tag:e}}function jn(e,t,n){let r=dn(t.type);return r.length===0||r.some(e=>Dn(e,t,n))?null:r.length===1&&r[0]===`enum`?{severity:`error`,code:`invalid-enum`,message:`<${e}> prop "${t.name}"=${JSON.stringify(n)} is not one of ${JSON.stringify(En(t))}`,tag:e}:{severity:r.includes(`enum`)?`error`:`warning`,code:`type-mismatch`,message:`<${e}> prop "${t.name}" expected ${r.map(e=>On(e,t)).join(` or `)}`,tag:e}}new Set(bn.filter(e=>e.tsType!==null).map(e=>e.name));function Mn(e,t){let n=Qt(e,{allowedTags:new Set(Object.keys(t.components))}),r=Tn(n.tree,t),i=[...n.diagnostics,...r.diagnostics];return{tree:n.tree,diagnostics:i,requires:r.requires,bindings:r.bindings,ok:!i.some(e=>e.severity===`error`)}}var Nn=new Set([...Kt,...Object.values(ye)]);function Pn(e){return Te(e).names}function Fn(e){return new Map(Object.entries(_e(e)))}function In(e){return new Set(Ye(e))}function Ln(e){if(!e||typeof e!=`object`)return[];let t=e.objects;return Array.isArray(t)?t.filter(e=>!!e&&typeof e==`object`):t&&typeof t==`object`?Object.entries(t).filter(([,e])=>!!e&&typeof e==`object`).map(([e,t])=>({name:e,...t})):[]}function Rn(e){let t=new Map;for(let n of Ln(e)){let e=typeof n.name==`string`&&n.name.length>0?n.name:void 0;if(!e)continue;let r=In(n);r.size>0&&t.set(e,r)}return t}function zn(e,t){return`'${t}' is an injected system column with NO storage behind it: '${e}' is an external object (ADR-0015), so the remote database owns its schema and the platform registers this anchor without provisioning a column`}function Bn(e,t){return`If the remote table really carries '${t}', declare it in ${e}'s own fields (mapped through the external binding's columnMap) so the reference resolves to a column you vouch for; otherwise drop the reference, or opt the object out of the injection (\`ownership: 'none'\` for the ownership anchors, \`systemFields: { audit: false }\` for the audit family).`}var Vn=new Set([`lookup`,`master_detail`,`user`,`tree`]);function Hn(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function w(e){return Array.isArray(e)?e.filter(Hn):Hn(e)?Object.entries(e).map(([e,t])=>({name:e,...Hn(t)?t:{}})):[]}function Un(e){let t=e?.packages;if(t===void 0)return[];if(Array.isArray(t))return t.filter(Hn);let n=Error(`A stack's \`packages\` must be an array of package entries (ADR-0130 D4, \`ArtifactPackageSchema\`), but this stack carries \`packages\` of type ${t===null?`null`:typeof t}. Omit the key entirely for a single-package stack \u2014 \`manifest\` is retained, not replaced.`);throw n.code=`INVALID_ARTIFACT_PACKAGES`,n.status=422,n}function Wn(e){return typeof e==`string`&&e.length>0?e:void 0}function Gn(e){return{type:typeof e.type==`string`?e.type:void 0,reference:Ce(e),multiple:e.multiple===!0||void 0}}function Kn(e){let t=e.fields;if(!t||typeof t!=`object`)return null;let n=new Set,r=new Map;for(let e of w(t)){let t=Wn(e.name);t&&(n.add(t),r.set(t,Gn(e)))}if(n.size===0)return null;let i=Fn(e),a=new Map;for(let t of Pn(e))a.set(t,Gn(i.get(t)??{}));return{names:n,fields:r,injected:a}}function qn(e){let t=new Map;if(!e||typeof e!=`object`)return t;for(let n of w(e.objects)){let e=Wn(n.name);e&&t.set(e,Kn(n))}return t}function T(e,t,n){let r=Wn(t),i=Wn(n);if(!r||!i)return;let a=i.split(`.`),o=r;for(let t=0;t<a.length-1;t++){if(!e.has(o))return{kind:`unknowable`,reason:`object-not-in-stack`,object:o};let n=e.get(o);if(!n)return{kind:`unknowable`,reason:`no-field-map`,object:o};let r=a[t],i=n.fields.get(r);if(!i)return n.injected.has(r)?{kind:`unknowable`,reason:`injected-hop`,object:o}:{kind:`hop-unknown`,at:t,segment:r,object:o,candidates:n.names};if(!i.type||!Vn.has(i.type))return{kind:`hop-not-relationship`,at:t,segment:r,object:o,type:i.type};if(!i.reference)return{kind:`hop-untargeted`,at:t,segment:r,object:o};o=i.reference}if(!e.has(o))return{kind:`unknowable`,reason:`object-not-in-stack`,object:o};let s=e.get(o);if(!s)return{kind:`unknowable`,reason:`no-field-map`,object:o};let c=a[a.length-1];if(s.names.has(c))return{kind:`ok`,object:o,field:c,meta:s.fields.get(c)};let l=s.injected.get(c);return l?{kind:`ok`,object:o,field:c,meta:l,injected:!0}:{kind:`field-unknown`,object:o,field:c,candidates:s.names}}function Jn(e){let t=new Set;if(!Array.isArray(e))return t;for(let n of e){if(typeof n!=`string`||!n)continue;let e=n.split(`.`);for(let n=1;n<=e.length;n++)t.add(e.slice(0,n).join(`.`))}return t}function Yn(e,t,n){switch(e.kind){case`ok`:case`unknowable`:case`hop-untargeted`:return;case`hop-unknown`:return{message:`${n} "${t}" traverses "${e.segment}", which is not a field on object "${e.object}".${E(e.segment,e.candidates)}`,detail:`Fields on "${e.object}": ${$n(e.candidates)}.`};case`hop-not-relationship`:return{message:`${n} "${t}" traverses "${e.segment}", which is a${e.type?` \`${e.type}\``:`n ordinary`} field on object "${e.object}" and not a relationship \u2014 there is nothing to join through.`,detail:`Only ${[...Vn].sort().join(` / `)} fields are traversable (ADR-0021 derives every join from the object graph; you never write an ON clause).`};case`field-unknown`:return{message:`${n} "${t}" is not a field on object "${e.object}".${E(e.field,e.candidates)}`,detail:`Fields on "${e.object}": ${$n(e.candidates)}.`}}}function Xn(e){return!e||e.kind===`unknowable`||e.kind===`hop-untargeted`}function Zn(e,t){let n,r=1/0;for(let i of t){let t;if(e.length>=3&&(i.includes(e)||e.includes(i)))t=Math.abs(i.length-e.length);else{let n=Qn(e,i);if(n>Math.max(2,Math.floor(e.length/3)))continue;t=100+n}t<r&&(r=t,n=i)}return n}function E(e,t){let n=Zn(e,t);return n?` Did you mean "${n}"?`:``}function Qn(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function $n(e){let t=[...e].sort();return t.length>0?t.join(`, `):`(none)`}var er=new Set([`filter`,`filters`,`runtimeFilter`,`relatedListFilter`,`filterBy`,`lookupFilters`]);function tr(e,t){return typeof e==`string`&&e.length>0?e:t}function nr(e,t,n,r,i=new Set){if(e&&typeof e==`object`&&!i.has(e)){if(i.add(e),Array.isArray(e)){e.forEach((e,a)=>nr(e,`${t}[${a}]`,n,r,i));return}for(let[a,o]of Object.entries(e)){let e=`${t}.${a}`;if(er.has(a)){r({value:o,path:e,where:n});continue}nr(o,e,n,r,i)}}}function rr(e,t,n){if(e&&typeof e==`object`)for(let{key:r,kind:i}of t)w(e[r]).forEach((e,t)=>{let a=tr(e.name??e.id,`#${t}`);if(i===`dashboard`){(Array.isArray(e.widgets)?e.widgets:[]).forEach((e,i)=>{let o=tr(e.id??e.title,`#${i}`);nr(e,`${r}[${t}].widgets[${i}]`,`dashboard "${a}" \xB7 widget "${o}"`,n,new Set)});let{widgets:i,...o}=e;nr(o,`${r}[${t}]`,`dashboard "${a}"`,n,new Set);return}nr(e,`${r}[${t}]`,`${i} "${a}"`,n,new Set)})}var ir=32;function ar(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&!(e instanceof Date)}function or(e,t,n,r,i){if(!(i>ir))for(let[a,o]of Object.entries(e)){let e=`${t}.${a}`;if(a===`$and`||a===`$or`){Array.isArray(o)&&o.forEach((t,a)=>{ar(t)&&or(t,`${e}[${a}]`,n,r,i+1)});continue}if(a===`$not`){ar(o)&&or(o,e,n,r,i+1);continue}if(a.startsWith(`$`))continue;let s=n?`${n}.${a}`:a;if(ar(o)&&!Object.keys(o).some(e=>e.startsWith(`$`))&&Object.keys(o).length>0){or(o,e,s,r,i+1);continue}r({field:s,path:e})}}function sr(e,t,n,r=0){if(!(r>ir)){if(Array.isArray(e)){if(typeof e[0]==`string`&&typeof e[1]==`string`&&![`and`,`or`].includes(e[0].toLowerCase())&&vt.has(e[1].toLowerCase())){n({field:e[0],path:`${t}[0]`});return}e.forEach((e,i)=>{typeof e!=`string`&&sr(e,`${t}[${i}]`,n,r+1)});return}if(ar(e)){if(typeof e.field==`string`&&typeof e.operator==`string`){n({field:e.field,path:`${t}.field`});return}or(e,t,``,n,r)}}}var cr=`widget-dataset-unknown`,lr=`widget-dimension-unknown`,ur=`widget-measure-unknown`,dr=`chart-field-unknown`,fr=`chart-config-missing`,pr=`chart-measures-missing`,mr=`chart-dimensions-missing`,hr=`widget-measures-missing`,gr=`table-count-only`,_r=`measure-aggregate-incoherent`,vr=`widget-legacy-analytics-shape`,yr=`widget-legacy-analytics-unrenderable`,br=`dashboard-filter-field-unknown`,xr=`dashboard-filter-field-unprovisioned`,Sr=`dashboard-filter-field-not-included`,Cr=`widget-filter-field-unknown`,wr=`widget-filter-field-not-included`,Tr=`widget-sortby-unselected`,Er=[`categoryField`,`valueField`,`xAxisField`,`yAxisFields`,`aggregate`,`aggregation`,`rowField`,`columnField`];function Dr(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}var Or=new Set([`combo`]),kr=new Set([`metric`,`kpi`,`gauge`,`solid-gauge`,`bullet`]),Ar=new Set([`table`,`pivot`]),jr=new Set(Pe.options.filter(e=>!kr.has(e)&&!Ar.has(e)));function Mr(e){return typeof e==`string`&&jr.has(e)}var Nr=new Set(Pe.options.filter(e=>!jr.has(e)));function Pr(e){return typeof e==`string`&&Nr.has(e)}function D(e){let t=[...e];return t.length>0?t.join(`, `):`(none)`}var Fr=`dateRange`,Ir=`created_at`;function Lr(e){let t=new Map,n=e.dateRange;if(n&&typeof n==`object`){let e=n.field,r=typeof e==`string`&&e?e:Ir;t.set(Fr,{name:Fr,field:r})}for(let n of w(e.globalFilters)){if(typeof n.field!=`string`||!n.field)continue;let e=typeof n.name==`string`&&n.name?n.name:n.field,r=Array.isArray(n.targetWidgets)?n.targetWidgets.filter(e=>typeof e==`string`):void 0;t.set(e,{name:e,field:n.field,targetWidgets:r})}return[...t.values()]}function Rr(e,t){let n=e.filterBindings,r=n&&typeof n==`object`?n[t.name]:void 0;if(r!==!1){if(typeof r==`string`&&r)return{field:r,explicit:!0};if(t.targetWidgets&&t.targetWidgets.length>0){let n=typeof e.id==`string`?e.id:void 0;if(!n||!t.targetWidgets.includes(n))return}return{field:t.field,explicit:!1}}}function zr(e){let t=[],n=new Map;for(let t of w(e.datasets))typeof t.name==`string`&&n.set(t.name,t);let r=new Map;for(let t of w(e.objects)){if(typeof t.name!=`string`)continue;let e=new Map;for(let n of w(t.fields))typeof n.name==`string`&&typeof n.type==`string`&&e.set(n.name,n.type);r.set(t.name,e)}let i=Rn(e),a=qn(e),o=w(e.datasets);for(let e=0;e<o.length;e++){let n=o[e],i=typeof n.object==`string`?r.get(n.object):void 0;if(!i)continue;let a=w(n.measures);for(let r=0;r<a.length;r++){let o=a[r],s=typeof o.field==`string`?o.field:void 0,c=typeof o.aggregate==`string`?o.aggregate:void 0;if(!s||!c)continue;let l=i.get(s);l&&lt(c,l)&&t.push({severity:`warning`,rule:_r,where:`dataset "${typeof n.name==`string`?n.name:`(dataset ${e})`}" \u203A measure "${typeof o.name==`string`?o.name:`(measure ${r})`}"`,path:`datasets[${e}].measures[${r}]`,message:`measure "${o.name}" applies ${c} to ${l} field "${s}" \u2014 summed percentages are meaningless (they can exceed 100%).`,hint:`Use aggregate "avg" for percentage/rate fields (or "count" of records). If a running total is genuinely intended, suppress with: suppressWarnings: ['${_r}'] on the measure.`})}}let s=w(e.dashboards);for(let e=0;e<s.length;e++){let r=s[e],o=typeof r.name==`string`?r.name:`(dashboard ${e})`,c=Array.isArray(r.widgets)?r.widgets:[],l=Lr(r);for(let r=0;r<c.length;r++){let s=c[r],u=`dashboard "${o}" \u203A widget "${typeof s.id==`string`?s.id:`(widget ${r})`}"`,d=`dashboards[${e}].widgets[${r}]`,f=e=>Array.isArray(s.suppressWarnings)&&s.suppressWarnings.includes(e),p=e=>{e.severity===`warning`&&f(e.rule)||t.push({...e,where:u,path:e.path??d})},m=Er.filter(e=>s[e]!==void 0);if(m.length>0){let e=typeof s.options==`object`&&s.options!==null&&s.options.data!==void 0,t=s.dataset!==void 0||s.object!==void 0||s.data!==void 0||e,n=m.map(e=>`\`${e}\``).join(`, `),r=m.length>1,i="Bind a semantic dataset and select fields BY NAME: `dataset: '<name>', dimensions: [...], values: [...]`. Dataset-bound widgets render through DatasetWidget (pivot rows/cols come from `dimensions`, cell values from `values`).";p(t?{severity:`warning`,rule:vr,message:`sets legacy analytics key${r?`s`:``} ${n} that the ADR-0021 single-form cutover removed \u2014 the dashboard renderer ignores ${r?`them`:`it`}.`,hint:`${i} These inline keys are a no-op. Suppress with suppressWarnings: ['${vr}'] if intentional.`}:{severity:`error`,rule:yr,message:`sets legacy analytics key${r?`s`:``} ${n} (removed by the ADR-0021 single-form cutover) and binds no data source (no \`dataset\`, \`object\`, or inline \`data\`) \u2014 it renders nothing.`,hint:`${i} The renderer ignores the legacy keys, so without a data source this widget has no data at all.`})}let h=typeof s.dataset==`string`?s.dataset:void 0,g=h?n.get(h):void 0;if(h&&!g&&p({severity:`error`,rule:cr,message:`dataset "${h}" does not resolve to a declared dataset.`,hint:`Declared datasets: ${D(n.keys())}.${E(h,n.keys())} Define the dataset with defineDataset() or fix the reference (ADR-0021).`}),!h){p({severity:`error`,rule:cr,message:"binds no `dataset` — the ADR-0021 widget shape requires one, so this widget resolves no data and renders empty.",hint:`Set \`dataset: '<name>'\` (plus \`values\`, and \`dimensions\` where the chart family needs them). Declared datasets: ${D(n.keys())}.`});continue}if(!g)continue;if(l.length>0){let e=typeof g.object==`string`?g.object:void 0,t=e?a.get(e):void 0;if(e&&t){let n=Jn(g.include);for(let r of l){let o=Rr(s,r);if(!o)continue;let c=o.field,l=T(a,e,c);if(Xn(l)||!l)continue;let u=o.explicit?`binds dashboard filter \`${r.name}\` to field \`${c}\` (via filterBindings), but `:`inherits dashboard filter \`${r.name}(${c})\`, but `;if(l.kind!==`ok`){let n=c.includes(`.`)?Yn(l,c,`the effective field`):void 0;if(n){p({severity:`error`,rule:br,message:`${u}${n.message} The filter is ANDed into EVERY bound widget's analytics query, so the query addresses a column that does not exist.`,hint:`Point filterBindings: { ${r.name}: '<field>' } at a field that resolves on \`${e}\` \u2014 or at a \`relationship[.relationship].field\` path whose prefix is declared in dataset "${h}"'s \`include\` \u2014 or opt out with filterBindings: { ${r.name}: false }. ${n.detail}`});continue}p({severity:`error`,rule:br,message:o.explicit?`binds dashboard filter \`${r.name}\` to field \`${c}\` (via filterBindings), but object \`${e}\` (dataset "${h}") has no field \`${c}\`.`:`inherits dashboard filter \`${r.name}(${c})\`, but object \`${e}\` (dataset "${h}") has no field \`${c}\`.`,hint:o.explicit?`Point filterBindings: { ${r.name}: '<field>' } at a field that exists on \`${e}\`, or opt out with filterBindings: { ${r.name}: false }.${E(c,t.names)} Object fields: ${D(t.names)}.`:`Set filterBindings: { ${r.name}: false } on this widget to opt out, or re-target to an existing field with filterBindings: { ${r.name}: '<field>' }.${E(c,t.names)} Object fields: ${D(t.names)}.`});continue}let d=c.lastIndexOf(`.`);if(d>=0){let t=c.slice(0,d);if(!n.has(t)){p({severity:`error`,rule:Sr,message:`${u}its relationship prefix "${t}" is not declared in dataset "${h}"'s \`include\` \u2014 and ADR-0021 joins ONLY declared paths, so no join is compiled and the column is out of this query's reach. The filter is ANDed into EVERY bound widget's analytics query, so the whole board renders empty, not one tile.`,hint:`Add "${t}" to dataset "${h}"'s include (declaring "a.b" implicitly includes "a"), filter on a field of "${e}" itself, or opt out with filterBindings: { ${r.name}: false }. Declared include paths: ${n.size>0?[...n].sort().join(`, `):`(none)`}.`});continue}}if(!l.injected)continue;let f=l.object,m=l.field;i.get(f)?.has(m)&&p({severity:`warning`,rule:xr,message:`${u}${zn(f,m)}. The filter is ANDed into this widget's analytics query (#2501), so it can never match a real value \u2014 on SQLite it silently degrades to constant-false and the widget renders empty (HTTP 200, zero rows, no error).`,hint:`${Bn(f,m)} A widget can also opt out with filterBindings: { ${r.name}: false }. Suppress with suppressWarnings: ['${xr}'] if the remote schema resolves it some other way.`})}}}if(s.filter!==void 0&&s.filter!==null){let e=typeof g.object==`string`?g.object:void 0,t=e?a.get(e):void 0;if(e&&t){let t=Jn(g.include);sr(s.filter,`${d}.filter`,({field:n,path:r})=>{let i=T(a,e,n);if(Xn(i)||!i)return;let o=Yn(i,n,`filter key`);if(o){p({severity:`error`,rule:Cr,path:r,message:`${o.message} The widget's own \`filter\` is ANDed into the dataset query as \`runtimeFilter\`, so the condition addresses a column that does not exist: the widget renders successfully and empty, and nothing reports the miss.`,hint:`Filter on a field that exists on "${e}" (dataset "${h}"), or on a \`relationship[.relationship].field\` path whose prefix is declared in that dataset's \`include\`. ${o.detail}`});return}let s=n.lastIndexOf(`.`);if(s<0)return;let c=n.slice(0,s);t.has(c)||p({severity:`error`,rule:wr,path:r,message:`filter key "${n}" resolves on the object graph, but its relationship prefix "${c}" is not declared in dataset "${h}"'s \`include\` \u2014 and ADR-0021 joins ONLY declared paths, so no join is compiled and the column is out of this query's reach. The widget renders empty.`,hint:`Add "${c}" to dataset "${h}"'s include (declaring "a.b" implicitly includes "a"), or filter on a field of "${e}" itself. Declared include paths: ${t.size>0?[...t].sort().join(`, `):`(none)`}.`})})}}let _=new Set;for(let e of w(g.dimensions))typeof e.name==`string`&&_.add(e.name);let v=new Map;for(let e of w(g.measures))typeof e.name==`string`&&v.set(e.name,e);let y=Dr(s.dimensions);for(let e=0;e<y.length;e++)_.has(y[e])||p({severity:`error`,rule:lr,message:`dimensions[${e}] "${y[e]}" is not a dimension of dataset "${h}" (declared dimensions: ${D(_)}).`,hint:`Widgets select dataset dimensions BY NAME.${E(y[e],_)} Add the dimension to the dataset or fix the reference.`});let b=Dr(s.values);for(let e=0;e<b.length;e++)v.has(b[e])||p({severity:`error`,rule:ur,message:`values[${e}] "${b[e]}" is not a measure of dataset "${h}" (declared measures: ${D(v.keys())}).`,hint:`Widgets select dataset measures BY NAME, not by base column.${E(b[e],v.keys())} Add the measure to the dataset or fix the reference.`});let ee=s.options&&typeof s.options==`object`&&!Array.isArray(s.options)?s.options:void 0,x=typeof ee?.sortBy==`string`?ee.sortBy:void 0;if(x&&!y.includes(x)&&!b.includes(x)){let e=_.has(x)||v.has(x),t=[...y,...b];p({severity:`error`,rule:Tr,path:`${d}.options.sortBy`,message:e?`options.sortBy "${x}" is declared by dataset "${h}" but is not selected by this widget (selects: ${D(t)}), so the query result will not contain that column and the authored order cannot be applied.`:`options.sortBy "${x}" is neither a \`dimensions\` nor a \`values\` entry of this widget (selects: ${D(t)}) \u2014 \`sortBy\` must name one this widget actually selects, so the authored order cannot be applied.`,hint:e?`Add "${x}" to this widget's ${_.has(x)?`dimensions`:`values`}, or order by something it already selects.${E(x,t)}`:`Point options.sortBy at one of this widget's selected names (${D(t)}).${E(x,t)} Ordering is applied to the query RESULT, so it can only name a column that result carries.`})}let te=s.chartConfig&&typeof s.chartConfig==`object`?s.chartConfig:void 0;if(typeof s.type==`string`&&Or.has(s.type),te){let e=new Set(b.filter(e=>v.has(e))),t=`Suppress with suppressWarnings: ['${dr}'] if the inert key is intentional.`,n=te.xAxis&&typeof te.xAxis==`object`?te.xAxis:void 0;n&&typeof n.field==`string`&&!_.has(n.field)&&!y.includes(n.field)&&p({severity:`warning`,rule:dr,message:`chartConfig.xAxis.field "${n.field}" does not resolve to a dimension of dataset "${h}" (declared dimensions: ${D(_)}) \u2014 and the dashboard renderer ignores an authored axis \`field\` in any case: \`axisPresentation\` strips it, so the x-axis stays bound to this widget's first dimension (${D(y)}). The binding is a silent no-op, not a query that fails.`,hint:`Delete the key: \`chartConfig.xAxis\` is refused on a dataset-bound widget (ADR-0021) and the x-axis binding comes from this widget's \`dimensions\`. Run \`os migrate meta --from 17\` to list the mechanical edits for existing sources; apply them by hand.${E(n.field,_)} ${t}`});let r=(n,r,i)=>{if(b.includes(r))return;let a=v.has(r),o=a?`chartConfig.${n} "${r}" is a measure of dataset "${h}" but is not selected in the widget's values (${D(b)})`:`chartConfig.${n} "${r}" does not resolve to a measure of dataset "${h}" (declared measures: ${D(v.keys())})`,s=i===`series`?`the dashboard renderer derives one series per selected measure and matches an authored entry BY NAME, so this entry pairs with no series and the presentation on it (mark, colour, stack, axis side) lands on nothing`:`the dashboard renderer ignores an authored axis \`field\` \u2014 \`axisPresentation\` strips it \u2014 so the y-axis bindings stay derived from this widget's values (${D(b)}) and the key re-points nothing`,c=a?`Add "${r}" to the widget's values, or bind the chart to a selected measure.`:`Post-cutover data is keyed by the dataset's measure NAME, not the base column.${E(r,e.size>0?e:v.keys())}`,l=i===`series`?"`chartConfig.series` is refused on a dataset-bound widget: series membership follows `values` (and a second `dimensions` entry to split). Delete the key.":"`chartConfig.yAxis` is refused on a dataset-bound widget: the bindings come from `values`, one entry per mark. Delete the key.";p({severity:`warning`,rule:dr,message:`${o} \u2014 ${s}. It is a silent no-op, not a query that fails.`,hint:`${c} ${l} ${t}`})},i=Array.isArray(te.yAxis)?te.yAxis:[];for(let e=0;e<i.length;e++){let t=i[e]?.field;typeof t==`string`&&r(`yAxis[${e}].field`,t,`axis`)}let a=Array.isArray(te.series)?te.series:[];for(let e=0;e<a.length;e++){let t=a[e]?.name;typeof t==`string`&&r(`series[${e}].name`,t,`series`)}}if(b.length===0){if(Mr(s.type))p({severity:`warning`,rule:pr,message:`'${s.type}' widget selects no measures (\`values\` is empty), so the renderer short-circuits to the authoring placeholder "Pick measures (values) for this dataset widget." before any query runs \u2014 no chart is drawn at all.`,hint:`Select at least one measure of dataset "${h}" BY NAME \u2014 values: ['<measure>'] (declared measures: ${D(v.keys())}).`+(y.length===0?` This widget selects no \`dimensions\` either; a chart family needs one to plot against (see ${mr}).`:``)+` If the widget is deliberately still being authored, suppress with: suppressWarnings: ['${pr}']`});else if(Pr(s.type)){let e=kr.has(s.type)?`the single KPI number this tile is for is not drawn at all`:`no table is rendered at all`;p({severity:`warning`,rule:hr,message:`'${s.type}' widget selects no measures (\`values\` is empty), so the renderer short-circuits to the authoring placeholder "Pick measures (values) for this dataset widget." before any query runs \u2014 ${e}.`,hint:`Select at least one measure of dataset "${h}" BY NAME \u2014 values: ['<measure>'] (declared measures: ${D(v.keys())}). A '${s.type}' widget needs no \`dimensions\`, so measures are the whole fix. If the widget is deliberately still being authored, suppress with: suppressWarnings: ['${hr}']`})}}else y.length===0&&Mr(s.type)&&p({severity:`warning`,rule:mr,message:`'${s.type}' widget selects no dimensions, so the renderer's \`isMetric\` test (\`METRIC_TYPES.has(widgetType) || dimensions.length === 0\`) is true and it draws a single KPI number instead of a '${s.type}' chart. The number is real, so nothing looks broken \u2014 the declared chart family is simply gone.`,hint:`Plot the chart against a dataset dimension \u2014 dimensions: ['<name>'] (declared dimensions: ${D(_)}) \u2014 or, if a single value IS what this tile should show, declare it as a 'metric' or 'kpi' widget so the type matches what renders. Suppress with: suppressWarnings: ['${mr}']`});if(s.type!==`table`&&s.type!==`pivot`||y.length>0||b.length===0)continue;let ne=b.map(e=>v.get(e));ne.some(e=>!e)||ne.every(e=>e.aggregate===`count`&&!e.derived)&&p({severity:`warning`,rule:gr,message:`a '${s.type}' widget bound to dataset "${h}" selects only count measure(s) (${b.join(`, `)}) and no dimensions, so it renders a single summary row \u2014 not a per-record list.`,hint:`A flat record listing is not an analytics dataset. Model it as an object-bound ListView (ADR-0017) surfaced through app navigation, and use a 'metric' widget here if you only need the count. If a single-row table is intentional, add an explicit dimension or suppress with: suppressWarnings: ['${gr}']`})}}return t}var Br=`measure-aggregate-field-type-refused`,Vr=`dimension-json-stored-field-refused`,Hr=e=>!!e&&typeof e==`object`&&!Array.isArray(e),Ur=e=>typeof e==`string`&&e.length>0?e:void 0,Wr=new Map(Object.entries(ae).map(([e,t])=>[e,t]));function Gr(e,t){return Bt(e,t.type)?!(e===`count_distinct`&&ie(t)):!1}function Kr(e){let t=[];for(let[n]of Wr)Gr(n,e)&&t.push(n);return t}function qr(e){return e.multiple===!0?`\`${e.type}\` with \`multiple: true\``:`\`${e.type}\``}function Jr(e,t){return{type:t,multiple:e.meta?.multiple===!0}}function Yr(e,t){return e.object===t?`object "${t}"`:`object "${e.object}" (reached through this dataset's join chain)`}function Xr(e){return Je.has(e.type)?`structured-json`:ie(e)?`multi-value`:null}function Zr(e){let t=[];if(!Hr(e))return t;let n=w(e.datasets);if(n.length===0)return t;let r=qn(e);return n.forEach((e,n)=>{let i=Ur(e.object);if(!i||!r.has(i)||!r.get(i))return;let a=Ur(e.name)??`#${n}`;w(e.dimensions).forEach((e,o)=>{let s=Ur(e.field);if(!s)return;let c=T(r,i,s);if(!c||Xn(c)||c.kind!==`ok`)return;let l=c.meta?.type;if(!l)return;let u=Jr(c,l),d=Xr(u);if(d===null)return;let f=Ur(e.name)??`#${o}`,p=`dimension "${f}" groups by field "${s}", which ${Yr(c,i)} declares as ${qr(u)} \u2014 `,m="The analytics door refuses every query that groups by this dimension with `400 INVALID_FIELD` before any SQL is built, so a report or dashboard that selects it gets that refusal instead of an answer.";t.push({severity:`error`,rule:Vr,where:`dataset "${a}" \u203A dimension "${f}"`,path:`datasets[${n}].dimensions[${o}].field`,message:d===`structured-json`?p+`a structured-JSON value, which analytics does not group by. A JSON document is no group key the SQL dialects share: one groups each serialized document apart, another refuses the statement. ${m}`:p+`a multi-value field, which analytics does not group by. A list of values is no group key the SQL dialects share: one groups each serialized list apart, another refuses the statement. ${m}`,hint:d===`structured-json`?`Group by a field that stores one scalar value: store the part of the document you group on in a field of its own and point this dimension at that field, or remove the dimension.`:`Filter by one member instead of grouping: a record query on "${c.object}" with where { "${c.field}": { "$contains": VALUE } } counts or lists the records that hold VALUE, one query per member. Point this dimension at a field that stores one value, or remove it.`})}),w(e.measures).forEach((e,o)=>{let s=Ur(e.aggregate),c=Ur(e.field);if(!s||!c)return;let l=Wr.get(s);if(!l)return;let u=T(r,i,c);if(!u||Xn(u)||u.kind!==`ok`)return;let d=u.meta?.type;if(!d)return;let f=Jr(u,d);if(Gr(s,f))return;let p=Bt(s,d),m=Ur(e.name)??`#${o}`;t.push({severity:`error`,rule:Br,where:`dataset "${a}" \u203A measure "${m}"`,path:`datasets[${n}].measures[${o}].aggregate`,message:p?`measure "${m}" applies aggregate "${s}" to field "${c}", which ${Yr(u,i)} declares as ${qr(f)} \u2014 a list of values stored as JSON. "${s}" COMPARES the stored values for equality, and no two backends compare a JSON-stored value alike: one counts every row apart, one compares the serialized text, another has no equality for the type and fails at query time. "${s}" accepts: ${l.join(`, `)}, none of them with \`multiple: true\`.`:`measure "${m}" applies aggregate "${s}" to field "${c}", which ${Yr(u,i)} declares as \`${d}\`. That pair is refused by the aggregate \xD7 field-type compatibility table in @objectstack/spec, so the number a backend returns for it is a property of the SQL dialect rather than of the data \u2014 one coerces the stored form and answers something plausible, another has no such function and fails at query time. "${s}" accepts: ${l.join(`, `)}.`,hint:`Either point "${s}" at a field of an accepted type, or aggregate "${c}" with one its ${qr(f)} ${f.multiple===!0?`declaration`:`type`} accepts: ${Kr(f).join(`, `)}. \`count\` accepts every type because it reads no value, and \`count_distinct\` every type but the JSON-stored ones \u2014 a field declared \`multiple: true\` among them \u2014 whose values no two backends compare alike; a quantity that must be added up or averaged has to be STORED as a numeric field (a computed column) and aggregated as one. The compile leg refuses this same pair with \`400 DATASET_INVALID\` before any SQL is emitted, so this is the same fix made earlier.`})})}),t}var Qr=[`iteratorVariable`,`indexVariable`,`errorVariable`,`outputVariable`],$r=`assignment`,ei=[`variable`,`name`,`key`];function ti(e){let t=e.assignments,n=[];if(Array.isArray(t)){for(let e of t){if(!e||typeof e!=`object`)continue;let t=e;for(let e of ei){let r=t[e];if(typeof r==`string`&&r){n.push(r);break}}}return n}return Object.keys(t&&typeof t==`object`?t:e)}function ni(e,t){let n=new Set,r=e.variables;if(Array.isArray(r))for(let e of r){if(!e||typeof e!=`object`)continue;let t=e;typeof t.name==`string`&&t.name&&n.add(t.name)}for(let e of t)for(let t of w(e.nodes)){typeof t.id==`string`&&t.id&&n.add(t.id);let e=t.config;if(!e||typeof e!=`object`||Array.isArray(e))continue;let r=e;for(let e of Qr){let t=r[e];typeof t==`string`&&t&&n.add(t)}if(t.type===$r)for(let e of ti(r))e&&n.add(e)}return n}var ri=64;function ii(e){let t=[];for(let n=0;n<ri;n++){let n=Tt(e,t);if(n===null||t.includes(n))break;t.push(n)}return t}function ai(e,t,n){if(t.size===0||n.length===0)return[];let r=new Set(n.filter(e=>t.has(e)));return r.size===0?[]:ii(e).filter(e=>r.has(e))}function oi(e,t){return`bare reference \`${e}\` is BOTH a declared flow variable and a field on \`${t}\` \u2014 a flow run seeds its declared variables FIRST and flattens the record's fields only where nothing is bound yet, so this reads the VARIABLE, the field is unreachable under its own name, and nothing reports the collision. Write \`record.${e}\` if you meant the field, or rename the variable if you meant the variable.`}var si=`Guard it with '!= null' — 'has(x)' does NOT do that: a declared field holding null is still PRESENT, so has(x) is true.`,ci=new Set([`<`,`<=`,`>`,`>=`,`+`,`-`,`*`,`/`,`%`]),li=[`record`,`previous`];function ui(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function di(e){return ui(e)&&e.op===`value`&&e.args===null}function fi(e,t){if(!ui(e)||e.op!==`.`&&e.op!==`.?`)return null;let n=e.args;if(!Array.isArray(n)||n.length<2)return null;let[r,i]=n;if(typeof i!=`string`||!ui(r)||r.op!==`id`)return null;let a=r.args;return typeof a!=`string`||!t.includes(a)?null:{operand:`${a}.${i}`,field:i}}function pi(e){let t=e.args;if(ui(t))return[t];if(!Array.isArray(t))return[];let n=[];for(let e of t)if(ui(e))n.push(e);else if(Array.isArray(e))for(let t of e)ui(t)&&n.push(t);return n}function mi(e){if(e.op!==`call`)return null;let t=e.args;return!Array.isArray(t)||typeof t[0]!=`string`?null:t[0]}function hi(e){let t=e.args;return!Array.isArray(t)||!Array.isArray(t[1])?[]:t[1]}function gi(e,t){return new Set([...e,...t])}function _i(e,t){let n=new Set;for(let r of e)t.has(r)&&n.add(r);return n}function vi(e,t){if(!ui(e))return new Set;switch(e.op){case`!=`:{let[n,r]=e.args??[];if(di(r)){let e=fi(n,t);return e?new Set([e.operand]):new Set}if(di(n)){let e=fi(r,t);return e?new Set([e.operand]):new Set}return new Set}case`&&`:{let[n,r]=e.args;return gi(vi(n,t),vi(r,t))}case`||`:{let[n,r]=e.args;return _i(vi(n,t),vi(r,t))}case`!_`:return yi(e.args,t);case`?:`:{let[,n,r]=e.args;return _i(vi(n,t),vi(r,t))}default:return new Set}}function yi(e,t){if(!ui(e))return new Set;switch(e.op){case`==`:{let[n,r]=e.args??[];if(di(r)){let e=fi(n,t);return e?new Set([e.operand]):new Set}if(di(n)){let e=fi(r,t);return e?new Set([e.operand]):new Set}return new Set}case`||`:{let[n,r]=e.args;return gi(yi(n,t),yi(r,t))}case`&&`:{let[n,r]=e.args;return _i(yi(n,t),yi(r,t))}case`!_`:return vi(e.args,t);case`call`:{if(mi(e)!==`isBlank`)return new Set;let[n]=hi(e),r=fi(n,t);return r?new Set([r.operand]):new Set}default:return new Set}}function bi(e,t,n){if(ui(e)){if(mi(e)===`has`)for(let r of hi(e)){let e=fi(r,t);e&&n.add(e.operand)}for(let r of pi(e))bi(r,t,n)}}function xi(e,t){if(typeof e!=`string`||!e.trim()||t.nullableFields.size===0)return[];let n=t.roots??li,r=Rt(e);if(!r)return[];let i=new Set;bi(r,n,i);let a=[],o=new Set,s=(e,r,s)=>{let c=fi(e,n);if(!c||!t.nullableFields.has(c.field)||s.has(c.operand))return;let l=`${c.operand}\0${r}`;o.has(l)||(o.add(l),a.push({operand:c.operand,field:c.field,operator:r,hasOnlyGuard:i.has(c.operand)}))},c=(e,t)=>{if(!ui(e))return;let r=e.op;if(r===`&&`){let[r,i]=e.args;c(r,t),c(i,gi(t,vi(r,n)));return}if(r===`||`){let[r,i]=e.args;c(r,t),c(i,gi(t,yi(r,n)));return}if(r===`?:`){let[r,i,a]=e.args;c(r,t),c(i,gi(t,vi(r,n))),c(a,gi(t,yi(r,n)));return}if(r!==`call`||mi(e)!==`has`){if(ci.has(r)){let[n,i]=e.args;s(n,r,t),s(i,r,t),c(n,t),c(i,t);return}if(r===`-_`){s(e.args,`-`,t),c(e.args,t);return}for(let n of pi(e))c(n,t)}};return c(r,new Set),a}var Si={"fail-closed":`so the rule enforces nothing and the write is rejected fail-closed (#4649/#4763)`,"fail-open":"so the predicate is SKIPPED fail-open — the field is never actually required, the write proceeds unchecked, and the only trace is a `requiredWhen … failed to evaluate — skipped` log line (#4649/#4811)"};function Ci(e,t,n,r=`fail-closed`){let i=t?`'${t}'`:`this object`,a=n.hasOnlyGuard?` \`has(${n.operand})\` does not guard it.`:``;return`${e} applies \`${n.operator}\` to \`${n.operand}\`, which ${i} declares as nullable (no \`required: true\`, no \`defaultValue\`).${a} At runtime the operand is null, CEL has no \`${n.operator}\` overload for null, and the whole predicate aborts \u2014 ${Si[r]}. The predicate compares a value that is null. ${si}`}var wi=/^(NOW|TODAY)\s*\(\s*\)\s*(?:([+\-])\s*(\S+))?$/,Ti=/^[A-Za-z_$][\w$]*(?:\.(?:[A-Za-z_$][\w$]*|\d+))*$/,Ei=/^[\w\s+\-*/%().,?:<>=!&|"'$]+$/,Di=/([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)/g,Oi=/^\s*\(/,ki=new Set([`true`,`false`,`null`,`undefined`]),Ai=[`NOW`,`TODAY`],ji=[`round`,`floor`,`ceil`,`abs`,`min`,`max`],Mi=new Set(ji);function Ni(e){let t=e.trim();if(!t)return{kind:`unresolvable-shape`};let n=wi.exec(t);if(n)return{kind:`date-function`,name:n[1]};if(t.startsWith(`$User.`))return{kind:`user-context`};if(Ti.test(t))return{kind:`variable-path`,head:t.split(`.`)[0]};if(!Ei.test(t))return{kind:`unresolvable-shape`};for(let e of t.matchAll(Di)){let n=e[0];if(ki.has(n))continue;let r=t.slice((e.index??0)+n.length);if(Oi.test(r)&&!Mi.has(n))return{kind:`unknown-function`,name:n}}return{kind:`unresolvable-shape`}}var Pi=/\{([^{}]+)\}/g,Fi=/[+\-*/%<>=!&|?]/,Ii=RegExp(`\\b(?:${ji.join(`|`)})\\s*\\(`);function Li(e){Pi.lastIndex=0;for(let t=Pi.exec(e);t!==null;t=Pi.exec(e)){let e=t[1].trim();if(Ni(e).kind===`unresolvable-shape`&&Ei.test(e)&&(Fi.test(e)||Ii.test(e)))return t[0]}}function Ri(e){return`\`${e}\` is a \`{\u2026}\` template-dialect expression. This slot also accepts a CEL value envelope \u2014 \`{ dialect: 'cel', source: '\u2026' }\` \u2014 evaluated by the engine flow conditions use, with the whole CEL stdlib; the template form keeps working unchanged. When moving arithmetic to CEL, give a division a decimal operand: CEL divides two integers as integers, so \`round(x * 100) / 100\` drops the decimals there \u2014 write \`round(x * 100) / 100.0\`.`}function zi(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=n.fields,i=[];Array.isArray(r)?i=w(r).map(e=>e.name).filter(e=>typeof e==`string`):r&&typeof r==`object`&&(i=Object.keys(r)),t.set(e,[...new Set([...i,...Pn(n)])])}return t}var Bi=[`record`,`previous`];function Vi(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function Hi(e){let t=new Map,n=Rt(e);if(!n)return t;let r=[n];for(;r.length>0;){let e=r.pop();if(!Vi(e))continue;if((e.op===`.`||e.op===`.?`)&&Array.isArray(e.args)&&e.args.length>=2){let[n,r]=e.args;typeof r==`string`&&Vi(n)&&n.op===`id`&&typeof n.args==`string`&&Bi.includes(n.args)&&(t.has(r)||t.set(r,`${n.args}.${r}`))}let n=e.args;if(Vi(n))r.push(n);else if(Array.isArray(n)){for(let e of n)if(Vi(e))r.push(e);else if(Array.isArray(e))for(let t of e)Vi(t)&&r.push(t)}}return t}function Ui(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=n.fields,i={};if(Array.isArray(r))for(let e of r){let t=e?.name,n=e?.type;typeof t==`string`&&typeof n==`string`&&(i[t]=n)}else if(r&&typeof r==`object`)for(let[e,t]of Object.entries(r)){let n=t?.type;typeof n==`string`&&(i[e]=n)}t.set(e,i)}return t}function Wi(e){let t=e.fields;return Array.isArray(t)?t.filter(e=>e&&typeof e==`object`&&typeof e.name==`string`).map(e=>[e.name,e]):t&&typeof t==`object`?Object.entries(t).filter(([,e])=>!!e&&typeof e==`object`).map(([e,t])=>[e,t]):[]}function Gi(e){if(e.required===!0||e.defaultValue!==void 0&&e.defaultValue!==null||e.type===`autonumber`)return!1;let t=e.options;return!(Array.isArray(t)&&t.some(e=>!!e&&typeof e==`object`&&e.default===!0))}function Ki(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=new Set;for(let[e,t]of Wi(n))Gi(t)&&r.add(e);t.set(e,r)}return t}function qi(e){let t=Ft(e);return t.ok&&t.roots.includes(`parent`)}function Ji(e){let t=0;for(let[,n]of Wi(e)){if(n.type!==`master_detail`)continue;let e=be({reference:n.reference},`validate-expressions masterDetailCount`);e!==void 0&&e.trim()!==``&&(t+=1)}return t}function Yi(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`){let t=e;if(typeof t.dialect==`string`&&t.dialect!==`cel`)return;if(typeof t.source==`string`)return t.source}}function Xi(e,t){let n=[],r=typeof e.name==`string`?e.name:`?`,i=t?`${t} \u2192 '${r}'`:`'${r}'`,a=e.condition;a!=null&&n.push({label:`validation rule ${i}`,raw:a}),e.when!=null&&n.push({label:`validation rule ${i} when-predicate`,raw:e.when});for(let t of[`then`,`otherwise`]){let r=e[t];r&&typeof r==`object`&&!Array.isArray(r)&&n.push(...Xi(r,`${i} ${t}`))}return n}var Zi=[`record`,`previous`,`parent`],Qi=[`app`],$i=[...Ue,...Qi],ea=[`current_user`,`user`,`ctx`,`os`],ta=`the predicate faults, and a faulting rule never produces the verdict you declared — each slot resolves the fault to its own fallback, and none of those fallbacks is yours`,na={visibleWhen:"the predicate no longer merely faults — and BOTH of its outcomes are wrong, in opposite directions. Under a host that publishes a predicate scope the renderer RESOLVES it (plugin-form's `sectionFields` copies this object rule onto the runtime form field and `resolveFieldRuleState` evaluates it with the host scope bound, objectui#6010) — so the control is hidden in that one form while NO server-side gate evaluates a field-level `visibleWhen` at all: the record still carries the value and every other reader still returns it, a SILENT enforcement gap. Where no host publishes a scope (the console public `/f/:slug` route, and every non-form reader) the root is unbound, the predicate faults and the renderer falls back to VISIBLE (`resolveFieldRuleState` evaluates visibility with `fallback: true`), leaving the field the test was meant to hide showing for everyone (#6146). The gap is the WORSE of the two — a visible fail-open gets reported, and a silent one does not",readonlyWhen:"the predicate faults — and the two ends fault in OPPOSITE directions. The server treats the field as LOCKED (`isReadonlyWhenLocked` will not waive a declared lock it could not evaluate, #4889) and drops your value from the payload, while the form still renders the field editable (`fallback: false`). The server is the one that decides: the field looks writable, the save reports success, and the value silently never lands",requiredWhen:`the predicate faults on every write that reaches that root, and the server REFUSES a write whose requirement it cannot evaluate (ADR-0137 D2: the refusal names the field and the rule) — while the form does not mark the field required, so nothing on screen says why the save failed`,conditionalRequired:ta};function ra(e,t){let n=Ft(t);if(!n.ok)return null;let r=$i.filter(e=>!Zi.includes(e)&&n.roots.includes(e));if(r.length===0)return null;let i=ea.find(e=>r.includes(e))??r[0],a=ea.includes(i)?"To gate the CHOICES of a select by user, move the predicate to the option's own `visibleWhen` (`options: [{ …, visibleWhen: … }]`) — the rule validator evaluates that one against `current_user` and its ADR-0068 aliases on every write, so the gate holds server-side. To hide the FIELD by role, declare field-level security on a permission set (`fields: { '<object>.<field>': { readable: false } }`), which the server enforces. To gate on record state, rewrite the predicate against `record`. Note that a form VIEW's own field predicate HAS bound these roots since objectui#6010 — but only in the renderer, so moving a server-enforced object rule there swaps a loud error for a silent enforcement gap; it is not a fourth answer.":i===`data`?"`data` is the root of a METADATA form (a `*.form` module — the metadata row being edited); this is an OBJECT field, whose runtime form binds the row as `record` — one key name, two form kinds, two roots. Rewrite `data.<key>` as `record.<field>`.":Qi.includes(i)?`\`${i}\` is NOT declared platform-wide, and no evaluation site binds it \u2014 not this one, and not any other: it is absent from the engine's declared scope, and decision batch #67 ruled that declared scope to be the contract, so the renderer that once mounted it beside \`current_user\` / \`user\` / \`ctx\` / \`os\` / \`data\` / \`features\` was aligned to the same set and no longer binds it either. The predicate therefore faults wherever it is written, and there is no surface to move it to. \u26D4 Do NOT write \`record.${i}\`: \`${i}\` is not a field on this object, so that spelling only trades this diagnostic for an \`unknown field\` error on \`${i}\`. Rewrite the predicate against \`record\` (plus \`previous\`, and \`parent\` on a master-detail line item) \u2014 gate on record state, not on this root.`:`\`${i}\` is declared platform-wide and bound at OTHER evaluation sites (flow, automation, screen and action predicates), never at the field level. Rewrite the predicate against \`record\` (plus \`previous\`, and \`parent\` on a master-detail line item), or move the decision to a surface that binds \`${i}\`.`;return{root:i,message:`\`${e}\` reads \`${i}\`, but a field-level conditional rule binds only \`record\` (plus \`previous\`, and \`parent\` on a master-detail line item) \u2014 \`${i}\` is unbound here, so ${na[e]??ta}. `+a}}function ia(e,t){return t.some(t=>e.startsWith(`bare reference \`${t}\``))}var aa={requiredWhen:`The server REFUSES every write that reaches this predicate — a requirement it cannot evaluate refuses the write, naming the field and the rule (ADR-0137 D2)`,readonlyWhen:`The server REFUSES every update that writes this field — a lock it cannot evaluate refuses the write rather than dropping the value (ADR-0137 D2) — so the field can never be changed once the record exists`,"option visibleWhen":`The server evaluates an option predicate fail-OPEN: it faults on every write that picks this option, the fault is logged, and the value is admitted — so the gate is never enforced`};function oa(e,t,n,r,i,a){let o=Array.from(i,e=>`\`${e}\``).join(`, `),s="`"+t+`.`+n+"`",c=t===`record`?"Only a `validations[]` rule's `condition` reads one hop through a reference — the related record is loaded before it runs. Express the check as a `validations[]` `script` rule, or read a column this object declares."+(e===`option visibleWhen`?" For a choice, the rule's `condition` states the FAILURE — this option picked while the related column disqualifies it; the option is then offered to everyone and refused on save.":``):t===`previous`?`\`previous\` is the stored row and is never read through a reference \u2014 not here, and not in a \`validations[]\` rule either \u2014 so there is no surface to move this read to. Compare ${s} itself (it holds the id), or read a column this object declares.`:`\`parent\` is the master-detail header as stored, so its references hold bare ids too, and no \`validations[]\` rule binds \`parent\` at all. Read a column '${a}' declares instead (denormalise the value you need onto '${a}').`;return`\`${e}\` reads ${o} through ${s}, a \`${r}\` field \u2014 but a field-level predicate never reads the related record: there ${s} holds the related record's bare id, so the read faults on every row. ${aa[e]}. ${c}`}function sa(e){let t=[];for(let[,n]of Wi(e)){if(n.type!==`master_detail`)continue;let e=be({reference:n.reference},`validate-expressions singleMasterOf`);e!==void 0&&e.trim()!==``&&t.push(e.trim())}return t.length===1?t[0]:void 0}function ca(e){let t=typeof e==`string`?e:e.source;if(typeof t!=`string`)return;let n=oe.safeParse(t);if(!n.success)return{message:n.error.issues[0]?.message??"An expression in an evaluated slot needs a non-blank `source`: the expression engine evaluates `source` (the canonical persisted form) and cannot evaluate `ast` alone, so an envelope carrying only `ast`, or a `source` that is blank after trimming, would validate and register and then fault at run time. Write `{ dialect: 'cel', source: '…' }`.",source:t}}function la(e){let t=[],n=w(e.objects),r=zi(n),i=Ui(n),s=Ki(n),c=new Map;for(let e of n){let t=typeof e.name==`string`?e.name:void 0;if(!t)continue;let n=In(e);n.size>0&&c.set(t,n)}let l=(e,n,r)=>{if(!r)return;let i=c.get(r);if(!i)return;let a=Yi(n);if(a)for(let[n,o]of Hi(a))i.has(n)&&t.push({where:e,message:`\`${o}\` reads '${n}', an injected system column with NO storage behind it: '${r}' is an external object (ADR-0015), so the remote database owns its schema and the platform registers this anchor without provisioning a column. The predicate can never match a real value \u2014 on SQLite it silently degrades to constant-false (HTTP 200, zero rows, no error). If the remote table really carries this column, declare '${n}' in the object's own fields (mapped through the external binding's columnMap) so the reference resolves to a column you vouch for; otherwise drop the reference, or opt the object out of the injection (\`ownership: 'none'\` for the ownership anchors, \`systemFields: { audit: false }\` for the audit family).`,source:a,severity:`warning`})},u=(e,n,r,i,a=`fail-closed`)=>{if(!i)return;let o=s.get(i);if(!o||o.size===0)return;let c=Yi(r);if(c)for(let r of xi(c,{nullableFields:o}))t.push({where:e,message:Ci(n,i,r,a),source:c,severity:`error`})},d=(e,n,a,o=`flattened`,s,c)=>{if(n==null)return;let u=a?r.get(a):void 0,d=a?i.get(a):void 0,f=ve(`predicate`,n,a?{objectName:a,fields:u,fieldTypes:d,scope:o,traversalHydration:c}:{scope:o});for(let n of f.errors)s&&ia(n.message,Qi)||t.push({where:e,message:n.message,source:n.source,severity:`error`});for(let n of f.warnings)t.push({where:e,message:n.message,source:n.source,severity:`warning`});l(e,n,a)},f=(e,t)=>{let n=Yi(t);if(!n)return null;let r=ra(e,n);return r?{...r,source:n}:null},p=(e,n,r,i)=>{let a=Yi(r);if(a)for(let{root:r,types:o,owner:s}of i){let i=ht(a,r)?.traversals;for(let[c,l]of i??[]){let i=o[c];typeof i==`string`&&y.has(i)&&t.push({where:e,message:oa(n,r,c,i,[...l].sort(),s),source:a,severity:`error`})}}},m=(e,n)=>{let r=o(n);if(r)return t.push({where:e,message:r.message,source:r.source,severity:`error`}),{refused:!0};let i=ve(`predicate`,n);for(let n of i.errors)t.push({where:e,message:n.message,source:n.source,severity:`error`});for(let n of i.warnings)t.push({where:e,message:n.message,source:n.source,severity:`warning`});return{refused:!1}},h=(e,n)=>{if(n==null)return;let r=Yi(n)??``,i=Ne.safeParse(n);if(!i.success){for(let n of i.error.issues)t.push({where:e,message:n.message,source:r,severity:`error`});return}let a=ve(`value`,n);for(let n of a.errors)t.push({where:e,message:`${Ht} ${n.message}`,source:n.source,severity:`error`});for(let n of a.warnings)t.push({where:e,message:n.message,source:n.source,severity:`warning`})};for(let n of w(e.flows)){let e=typeof n.name==`string`?n.name:`(unnamed flow)`,i=w(n.nodes),o=w(n.edges),s=i.find(e=>e.type===`start`)?.config??{},c=typeof s.objectName==`string`?s.objectName:void 0,l=a({...n,nodes:i,edges:o}),u=ni(n,l),f=(e,n)=>{if(!c)return;let i=Yi(n);if(i)for(let n of ai(i,u,r.get(c)??[]))t.push({where:e,message:oi(n,c),source:i,severity:`warning`})},p=(e,n)=>{if(n==null)return{refused:!1};let r=ct(n);if(r)return t.push({where:e,message:r.message,source:r.source,severity:`error`}),{refused:!0};let i=ca(n);return i?(t.push({where:e,message:i.message,source:i.source,severity:`error`}),{refused:!0}):{refused:!1}};for(let n of l){let r=n.scope?`flow '${e}' \xB7 ${n.scope}`:`flow '${e}'`;for(let e of w(n.nodes)){let n=e.config??{},i=`${r} \xB7 node '${e.id}' (${e.type}) condition`;p(i,n.condition).refused||(d(i,n.condition,c),f(i,n.condition));let a=typeof e.type==`string`?e.type:``,o=zt(a,e.config).filter(e=>a!==`script`||e.path!==`function`);for(let n of o)t.push({where:`${r} \xB7 node '${e.id}' (${a}) config.${n.path}`,message:n.message,source:n.source,severity:`error`});for(let t of le(a,n)){let n=`${r} \xB7 node '${e.id}' (${a}) ${t.entry.label} at config.${t.path}`;if(t.entry.role===`value`){h(n,t.value);continue}t.entry.role===`predicate`&&(m(n,t.value).refused||f(n,t.value))}for(let i of ut(a,n)){if(typeof i.value!=`string`)continue;let n=Li(i.value);n!==void 0&&t.push({where:`${r} \xB7 node '${e.id}' (${a}) ${i.entry.label} at config.${i.path}`,message:Ri(n),source:i.value,severity:`warning`})}if(e.type===`script`){let i=(typeof n.function==`string`?n.function.trim():``)||(typeof n.functionName==`string`?n.functionName.trim():``),a=typeof n.actionType==`string`?n.actionType.trim():``,o=[`actionType`,`template`,`recipients`,`variables`,`script`].filter(e=>n[e]!=null);o.length>0?t.push({where:`${r} \xB7 node '${e.id}' (script) callable`,message:`script node carries \`${o.map(e=>`config.${e}`).join("`, `")}\` \u2014 retired in @objectstack/spec 17 (#4343). The built-in 'email'/'slack' actions were logger-backed stubs that delivered nothing, and inline \`config.script\` was never executed. `+(a&&a!==`invoke_function`&&![`email`,`slack`].includes(a)?`\`actionType: '${a}'\` named a registered function \u2014 move it to \`function: '${a}'\`. `:"Use a `notify` node for mail, a `connector_action` (Slack connector) or `http` node for Slack, and a registered function for logic. ")+"Run `os migrate meta --from 16` to list the mechanical edits for existing sources; apply them by hand.",source:JSON.stringify({id:e.id,type:e.type,config:n})}):i||t.push({where:`${r} \xB7 node '${e.id}' (script) callable`,message:"script node declares no `function` — it would do nothing at runtime. Name a registered function (`function: 'my_fn'`, registered via `defineStack({ functions })`).",source:JSON.stringify({id:e.id,type:e.type,config:n})})}}for(let e of w(n.edges)){let t=`${r} \xB7 edge '${e.id}' (${e.source}\u2192${e.target}) condition`;p(t,e.condition).refused||(d(t,e.condition,c),f(t,e.condition))}}}for(let e of n){let n=typeof e.name==`string`?e.name:void 0,a=e.validations;for(let e of w(a)){let t=`object '${n}' \xB7 validation '${e.name??`?`}'`;d(t,e.condition,n,`record`,void 0,!0),d(`${t} when`,e.when,n,`record`);for(let t of Xi(e,``))u(`object '${n}' \xB7 ${t.label}`,t.label,t.raw,n)}let o=e.fields,s=Array.isArray(o)?o.filter(e=>!!e&&typeof e==`object`).map(e=>[typeof e.name==`string`?e.name:`?`,e]):o&&typeof o==`object`?Object.entries(o).filter(([,e])=>!!e&&typeof e==`object`).map(([e,t])=>[e,t]):[],c=Ji(e),m=n?i.get(n):void 0,h=c===1?sa(e):void 0,g=h?i.get(h):void 0,_=n&&m?[{root:`record`,types:m,owner:n},{root:`previous`,types:m,owner:n}]:[],v=h&&g?[..._,{root:`parent`,types:g,owner:h}]:_;for(let[e,a]of s){for(let r of[`requiredWhen`,`readonlyWhen`,`conditionalRequired`,`visibleWhen`]){let i=`object '${n}' \xB7 field '${e}' ${r}`,o=a[r],s=f(r,o);d(i,o,n,`record`,s!==null),s&&t.push({where:i,message:s.message,source:s.source,severity:`error`})}for(let[t,r]of w(a.options).entries()){let i=`object '${n}' \xB7 field '${e}' option ${typeof r.value==`string`?`'${r.value}'`:`#${t}`} visibleWhen`;d(i,r.visibleWhen,n,`record`),p(i,`option visibleWhen`,r.visibleWhen,_)}for(let[r,i,o]of[[`readonlyWhen`,a.readonlyWhen,`the field would be locked on every write`],[`requiredWhen`,a.requiredWhen,"writes would be refused — the predicate faults wherever it reads `parent`, and the server refuses a write whose requirement it cannot evaluate"]]){let a=Yi(i);c!==1&&a&&qi(a)&&t.push({where:`object '${n}' \xB7 field '${e}' ${r}`,message:`\`${r}\` reads \`parent\`, but object '${n}' declares ${c===0?`no`:`${c}`} \`master_detail\` relationship${c===1?``:`s`} \u2014 so the server has no header record to bind as \`parent\` and ${o}. `+(c===0?"Declare the owning relationship as `Field.masterDetail('<master>')`, or rewrite the predicate against `record`.":"`parent` needs exactly one master; name the header explicitly through `record.<fk>` state instead, or model the extra relationship as a `lookup`."),source:a,severity:`error`})}u(`object '${n}' \xB7 field '${e}' requiredWhen`,`field '${e}' requiredWhen`,a.requiredWhen,n,`fail-closed`);for(let[t,r]of[[`requiredWhen`,a.requiredWhen],[`readonlyWhen`,a.readonlyWhen]])p(`object '${n}' \xB7 field '${e}' ${t}`,t,r,v);if(a.expression){let o=ve(`value`,a.expression,n?{objectName:n,fields:r.get(n),fieldTypes:i.get(n),scope:`record`}:{scope:`record`}),s=`object '${n}' \xB7 field '${e}' expression`;for(let e of o.errors)t.push({where:s,message:e.message,source:e.source,severity:`error`});for(let e of o.warnings)t.push({where:s,message:e.message,source:e.source,severity:`warning`});l(s,a.expression,n)}}}let g=new Set,_=(e,t,n)=>{let r=n??(typeof t.objectName==`string`?t.objectName:void 0),i=typeof t.name==`string`?t.name:`?`,a=`${r??``}:${i}`;g.has(a)||(g.add(a),d(`${e} \xB7 action '${i}' visible`,t.visible,r,`record`),typeof t.disabled!=`boolean`&&d(`${e} \xB7 action '${i}' disabled`,t.disabled,r,`record`))};for(let t of w(e.actions))_(`stack`,t);for(let e of n){let t=typeof e.name==`string`?e.name:void 0;for(let n of w(e.actions))_(`object '${t}'`,n,t)}for(let t of w(e.sharingRules)){let e=typeof t.object==`string`?t.object:void 0;d(`sharingRule '${t.name??`?`}'${e?` (${e})`:``} condition`,t.condition,e,`record`)}for(let n of w(e.hooks)){let e=n.name??`?`;if(typeof n.object==`string`){d(`hook '${e}' (${n.object}) condition`,n.condition,n.object,`record`),u(`hook '${e}' (${n.object}) condition`,`hook '${e}' condition`,n.condition,n.object);continue}let r=Array.isArray(n.object)?n.object.filter(e=>typeof e==`string`&&e!==`*`):[];if(r.length===0){d(`hook '${e}' condition`,n.condition,void 0,`record`);continue}let i=t.length,a=new Set,o=[];for(let i of r){let r=t.length;d(`hook '${e}' (${i}) condition`,n.condition,i,`record`),u(`hook '${e}' (${i}) condition`,`hook '${e}' condition`,n.condition,i);for(let e=r;e<t.length;e++){let n=t[e],r=`${n.message}\0${n.source??``}`;a.has(r)||(a.add(r),o.push(n))}}t.length=i,t.push(...o)}return t}function ua(e,t,n,r){let i=e.createSourceFile(t,n,r.target,r.setParentNodes,r.scriptKind),a=i.parseDiagnostics;if(!a||a.length===0)return{sourceFile:i};let o=a[0],{line:s,character:c}=i.getLineAndCharacterOfPosition(o.start??0),l=r.synthesizedLinesBefore??0;return{sourceFile:i,failure:{message:e.flattenDiagnosticMessageText(o.messageText,` `),line:Math.max(1,s+1-l),column:c+1,count:a.length}}}function da(e){let t=e.count>1?`; ${e.count} syntax errors in total`:``;return`line ${e.line}, column ${e.column}: ${e.message}${t}`}var fa=`The source is parsed (never executed) so it can be checked. A source with syntax errors is only partially recovered, so the checks that follow may have skipped real problems — fix the syntax error and re-run to get a verdict that covers the whole source.`,pa=null;function ma(){if(pa)return pa;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{pa=(0,S.createRequire)(e)(`typescript`)}catch(e){throw Error(`@objectstack/lint: checking plugin source for startup registry verdicts requires the "typescript" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "typescript" in the image; it is only loaded when plugin source is actually checked.`)}return pa}var ha=`startup-open-vocabulary-verdict`,ga=`startup-verdict-assertive-wording`,_a=`startup-source-unparseable`,va=new Map([[`getRegisteredNodeTypes`,`ADR-0018 keeps the flow node-type vocabulary open and runtime-extensible — a plugin registers its executor from its own init()/start(), which can be after this line (#4771)`],[`knownNodeTypes`,`ADR-0018 keeps the flow node-type vocabulary open and runtime-extensible — a plugin registers its executor from its own init()/start(), which can be after this line (#4771)`],[`getUnknownNodeTypeAudit`,`the unknown-node-type audit is a snapshot of an OPEN vocabulary a plugin can still extend during boot; it is read-only by design and answers "unknown as of now", never "unknown for this deployment" (#4771)`],[`getActionDescriptors`,`ADR-0018 action descriptors are published by plugins during boot, so a type missing from them here means "not published YET" (#4771)`],[`getRegisteredExecutors`,`executors are contributed by plugins during boot — an executor missing here may simply be a plugin that has not started`],[`listExecutors`,`executors are contributed by plugins during boot — an executor missing here may simply be a plugin that has not started`],[`getRegisteredTools`,`AI tools are contributed by plugins during boot, so the registered set is not final until every plugin has started`],[`listConnectors`,`connectors are contributed by plugins during boot (StackSchema.connectors documents provider-bound instances registered by plugins), so the list is not final until every plugin has started`],[`getRegisteredConnectors`,`connectors are contributed by plugins during boot, so the registered set is not final until every plugin has started`],[`listCapabilities`,`ADR-0066 capabilities are declared by every installed package, so the set is not final until every plugin has contributed its declarations`],[`getRegisteredCapabilities`,`ADR-0066 capabilities are declared by every installed package, so the set is not final until every plugin has contributed its declarations`],[`listProviders`,`providers are contributed by plugins during boot — a provider missing here may simply be a plugin that has not started`],[`getRegisteredProviders`,`providers are contributed by plugins during boot — a provider missing here may simply be a plugin that has not started`]]),ya=new Map([[`constructor`,`the constructor runs at composition time — before ANY plugin has been initialized`],[`init`,`another plugin's init() may not have run yet (ADR-0116), so the vocabulary is still filling`],[`start`,`sibling plugins' start() have not all run, and ADR-0018 lets a plugin register its contributions from start() — the vocabulary is still filling`]]),ba=[`seal`],xa=new Set([`warn`,`error`,`fatal`]),Sa=new Set([`warn`,`error`,`fatal`,`info`,`debug`,`trace`,`log`]),Ca=new Set([`insert`,`insertOne`,`update`,`updateOne`,`upsert`,`save`,`saveMetaItem`]),wa=[`will fail`,`fails at execution`,`nothing will register`,`no plugin provides`,`is not installed`,`is not configured`,`you need`,`you must install`,`must be provisioned`],Ta=[`not yet`,`yet been registered`,`so far`,`as of`,`may still`,`might still`,`still be registered`,`has started`,`have started`],Ea='Take one of the three shapes the fixes took: (1) resolve where the value is USED, not where you start — a lazy accessor or a `kernel:ready`/`kernel:bootstrapped` hook sees a provider that registered later (`createLazyCacheRateLimitStorage()` in plugin-auth, #4772); (2) seal the vocabulary, then judge — have the host declare the moment it can no longer grow and draw the conclusion there (`AutomationEngine.sealNodeTypeVocabulary()`, called at `kernel:bootstrapped`, #4771); (3) order the verdict AFTER the mutation it describes, so it cannot attest to a state this same boot goes on to contradict (the ADR-0104 attestation, #4769). If the conclusion must stay here, keep the two worlds apart in the wording: "no executor registered YET (as of plugin start)" is true; "will fail at execution time" is a claim about a world that has not finished forming.';function Da(e,t){return e.isFunctionDeclaration(t)||e.isFunctionExpression(t)||e.isArrowFunction(t)||e.isMethodDeclaration(t)||e.isConstructorDeclaration(t)||e.isGetAccessorDeclaration(t)||e.isSetAccessorDeclaration(t)}function Oa(e,t,n){t.forEachChild(t=>{Da(e,t)||e.isClassDeclaration(t)||e.isClassExpression(t)||(n(t),Oa(e,t,n))})}function ka(e,t,n){t.forEachChild(t=>{n(t),ka(e,t,n)})}function Aa(e,t){if(!e.isCallExpression(t))return;let n=t.expression;if(e.isIdentifier(n))return n.text;if(e.isPropertyAccessExpression(n)&&e.isIdentifier(n.name))return n.name.text}function ja(e,t){if(!e.isCallExpression(t))return;let n=t.expression;if(!e.isPropertyAccessExpression(n)||!e.isIdentifier(n.name))return;let r=n.name.text;if(!Sa.has(r))return;let i=n.expression,a;if(e.isIdentifier(i)?a=i.text:e.isPropertyAccessExpression(i)&&e.isIdentifier(i.name)&&(a=i.name.text),a)return/^(logger|log|console)$/i.test(a)?r:void 0}function Ma(e,t){let n=[],r=t=>{(e.isStringLiteralLike(t)||e.isTemplateHead(t)||e.isTemplateMiddle(t)||e.isTemplateTail(t))&&n.push(t.text)};return r(t),ka(e,t,r),n.join(` `).toLowerCase()}function Na(e,t){let n=!1,r=t=>{if(!n&&e.isIdentifier(t)){let e=t.text.toLowerCase();ba.some(t=>e.includes(t))&&(n=!0)}};return r(t),ka(e,t,r),n}function Pa(e,t){let n=new Set;for(let r of t.statements)if(e.isVariableStatement(r)&&!(r.declarationList.flags&e.NodeFlags.Const))for(let t of r.declarationList.declarations)e.isIdentifier(t.name)&&n.add(t.name.text);return n}function Fa(e,t){let n=new Map;return ka(e,t,t=>{e.isFunctionDeclaration(t)&&t.name&&t.body||e.isMethodDeclaration(t)&&e.isIdentifier(t.name)&&t.body?n.set(t.name.text,t.body):e.isVariableDeclaration(t)&&e.isIdentifier(t.name)&&t.initializer&&(e.isArrowFunction(t.initializer)||e.isFunctionExpression(t.initializer))&&t.initializer.body&&n.set(t.name.text,t.initializer.body)}),n}function Ia(e,t){let n=[],r=t=>{let r=[],i=!1;for(let n of t.members)e.isMethodDeclaration(n)&&e.isIdentifier(n.name)?(n.name.text===`init`||n.name.text===`start`)&&(i=!0):e.isPropertyDeclaration(n)&&e.isIdentifier(n.name)&&(n.name.text===`init`||n.name.text===`start`)&&n.initializer&&(e.isArrowFunction(n.initializer)||e.isFunctionExpression(n.initializer))&&(i=!0);if(i){for(let n of t.members)e.isConstructorDeclaration(n)&&n.body?r.push({phase:`constructor`,body:n.body}):e.isMethodDeclaration(n)&&e.isIdentifier(n.name)&&n.body?ya.has(n.name.text)&&r.push({phase:n.name.text,body:n.body}):e.isPropertyDeclaration(n)&&e.isIdentifier(n.name)&&ya.has(n.name.text)&&n.initializer&&(e.isArrowFunction(n.initializer)||e.isFunctionExpression(n.initializer))&&n.initializer.body&&r.push({phase:n.name.text,body:n.initializer.body});r.length&&n.push({label:t.name?.text??`<anonymous class>`,phases:r})}},i=t=>{let r=[],i,a=!1;for(let n of t.properties){if(!e.isPropertyAssignment(n)||!e.isIdentifier(n.name))continue;let t=n.name.text;t===`name`&&e.isStringLiteralLike(n.initializer)&&(i=n.initializer.text),(t===`init`||t===`start`)&&Da(e,n.initializer)&&(a=!0),ya.has(t)&&(e.isArrowFunction(n.initializer)||e.isFunctionExpression(n.initializer))&&n.initializer.body&&r.push({phase:t,body:n.initializer.body})}i&&a&&r.length&&n.push({label:`${i} (object plugin)`,phases:r})};return ka(e,t,t=>{e.isClassDeclaration(t)||e.isClassExpression(t)?r(t):e.isObjectLiteralExpression(t)&&i(t)}),n}function La(e,t={}){if(!e||!e.trim())return[];let n=!1;for(let t of va.keys())if(e.includes(t)){n=!0;break}if(!n)return[];let r=ma(),i=t.file??`source`,{sourceFile:a,failure:o}=ua(r,i,e,{target:r.ScriptTarget.Latest,setParentNodes:!0,scriptKind:r.ScriptKind.TS}),s=[];o&&s.push({severity:`warning`,rule:_a,where:i,path:`${i}:${o.line}`,message:`source did not parse (${da(o)}), so this rule read a partially recovered tree \u2014 a startup verdict in the unread part is not reported.`,hint:fa});let c=Pa(r,a),l=Fa(r,a),u=e=>a.getLineAndCharacterOfPosition(e.getStart(a)).line+1;for(let e of Ia(r,a))for(let{phase:t,body:n}of e.phases){let a=[],o=new Set,d=(e,t)=>{a.push(e),!(t>=2)&&Oa(r,e,e=>{let n=Aa(r,e);if(!n||o.has(n))return;let i=l.get(n);i&&(o.add(n),d(i,t+1))})};d(n,0);let f=[];for(let e of a)Oa(r,e,e=>{let t=Aa(r,e);t&&va.has(t)&&f.push({probe:t,node:e})});if(!f.length||a.some(e=>Na(r,e)))continue;let p=[];for(let e of a)Oa(r,e,e=>{let t=ja(r,e);if(t&&xa.has(t)){p.push({kind:`announced`,detail:`${t} log`,line:u(e),node:e});return}let n=Aa(r,e);if(n&&Ca.has(n)){p.push({kind:`persisted`,detail:`${n}()`,line:u(e),node:e});return}if(r.isBinaryExpression(e)&&e.operatorToken.kind===r.SyntaxKind.EqualsToken){let t=e.left,n;r.isPropertyAccessExpression(t)&&r.isIdentifier(t.name)?n=t.expression.kind===r.SyntaxKind.ThisKeyword?`this.${t.name.text}`:`<obj>.${t.name.text}`:r.isIdentifier(t)&&c.has(t.text)&&(n=`module-level \`${t.text}\``),n&&p.push({kind:`cached`,detail:n,line:u(e),node:e})}});if(!p.length)continue;let m=f[0],h=p[0],g=`${e.label}.${t}${t===`constructor`?``:`()`}`,_=va.get(m.probe),v=ya.get(t);s.push({severity:`warning`,rule:ha,where:g,path:`${i}:${u(m.node)}`,message:`\`${m.probe}()\` reads a vocabulary that is still filling, and the conclusion is recorded (${h.kind}: ${h.detail}, line ${h.line}). ${_}; ${v}. "absent" here has two meanings the recorded verdict cannot tell apart \u2014 no provider in this deployment, or a provider that registers later in this same boot \u2014 and nothing retracts the record when the second one turns out to be the case (#4771 / #4772).`,hint:Ea});for(let e of p){if(e.kind!==`announced`)continue;let t=Ma(r,e.node);if(!t||Ta.some(e=>t.includes(e)))continue;let n=wa.find(e=>t.includes(e));n&&s.push({severity:`warning`,rule:ga,where:g,path:`${i}:${e.line}`,message:`the diagnostic says "${n}" about a vocabulary that can still grow during this boot. #4771 printed "will fail at execution time" for eight approval flows 0.8s before the executor that runs them was registered, and a deployment that genuinely lacked the plugin printed the identical eight \u2014 so the line could not tell an operator which of the two they had. #4772's remedy ("you need Redis") sent operators to fix a problem they did not have, and connecting Redis did not change the message.`,hint:Ea})}}return s}var Ra=`list-view-filters-in-views-mode`;function za(e,t,n,r){if(!e||typeof e!=`object`)return;let i=e;i.quickFilters!=null&&r.push({severity:`error`,rule:Ra,where:t,path:`${n}.quickFilters`,message:'`quickFilters` is a page filters-mode control and is ignored on an object list view ("views" mode) — the ViewTabBar owns nav here.',hint:'Move `quickFilters` to a page list (InterfaceListPage, "filters" mode), or remove it. See ADR-0047.'});let a=i.userFilters;if(a&&typeof a==`object`){let e=a;(e.element===`tabs`||e.tabs!=null)&&r.push({severity:`error`,rule:Ra,where:t,path:`${n}.userFilters`,message:'`userFilters` with `element: "tabs"` is page-only and is ignored on an object list view ("views" mode) — it would collide with the ViewTabBar.',hint:'Use `listViews` for named presets on an object (each becomes a segmented tab), switch to `element: "dropdown"` for value chips, or move the `tabs` filter to a page list (InterfaceListPage, "filters" mode). See ADR-0047.'})}}function Ba(e,t,n,r){if(e&&typeof e==`object`)for(let[i,a]of Object.entries(e))za(a,`${t} \u203A listViews.${i}`,`${n}.listViews.${i}`,r)}function Va(e){let t=[];return w(e.objects).forEach((e,n)=>{let r=typeof e.name==`string`?`object "${e.name}"`:`objects[${n}]`;Ba(e.listViews,r,`objects[${n}]`,t)}),w(e.views).forEach((e,n)=>{let r=typeof e.objectName==`string`?e.objectName:typeof e.name==`string`?e.name:void 0,i=r?`view "${r}"`:`views[${n}]`;za(e.list,`${i} \u203A list`,`views[${n}].list`,t),Ba(e.listViews,i,`views[${n}]`,t)}),t}var Ha=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Ua(e){return Array.isArray(e)?e.flatMap((e,t)=>Ha(e)?[{name:String(e.name??t),def:e,key:`[${t}]`}]:[]):Ha(e)?Object.entries(e).flatMap(([e,t])=>Ha(t)?[{name:e,def:{name:e,...t},key:`.${e}`}]:[]):[]}function Wa(e,t,n,r){for(let i of t)e.push({severity:i.severity,rule:i.rule,where:n,path:`${r}.${i.path}`,message:i.message,hint:i.fix})}function Ga(e){let n=[];if(!Ha(e))return n;for(let[r,i]of Ua(e.objects).entries())for(let e of Ua(i.def.fields))Wa(n,t(e.def),`object "${i.name}" \u203A fields.${e.name}`,`objects[${r}].fields${e.key}`);let r=new Map(Ua(e.objects).map(e=>[e.name,e.def])),i=e=>typeof e==`string`&&e?e:void 0,a=e=>e?r.get(e):void 0,o=e=>Ha(e.data)?i(e.data.object):void 0,s=(e,t)=>a(o(e)??i(t.objectName)??i(t.object));for(let[t,r]of Ua(e.views).entries()){let e=r.def.object?`view container "${r.name}"`:`view container [${t}]`;Ha(r.def.list)&&Wa(n,Xe(r.def.list,s(r.def.list,r.def)),`${e} \u203A list`,`views[${t}].list`);for(let i of Ua(r.def.listViews))Wa(n,Xe(i.def,s(i.def,r.def)),`${e} \u203A listViews.${i.name}`,`views[${t}].listViews${i.key}`)}for(let[t,r]of Ua(e.objects).entries()){let e=`object "${r.name}"`;Ha(r.def.list)&&Wa(n,Xe(r.def.list,a(o(r.def.list)??r.name)),`${e} \u203A list`,`objects[${t}].list`);for(let i of Ua(r.def.listViews))Wa(n,Xe(i.def,a(o(i.def)??r.name)),`${e} \u203A listViews.${i.name}`,`objects[${t}].listViews${i.key}`)}for(let t of Ua(e.webhooks))Wa(n,Mt(t.def),`webhook "${t.name}"`,`webhooks${t.key}`);return n}var Ka=`object/managed-api-method-unaffordable`,qa=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Ja(e){return Array.isArray(e)?e.flatMap((e,t)=>qa(e)?[{name:String(e.name??t),def:e,key:`[${t}]`}]:[]):qa(e)?Object.entries(e).flatMap(([e,t])=>qa(t)?[{name:e,def:{name:e,...t},key:`.${e}`}]:[]):[]}function Ya(e){let t=[];if(!qa(e))return t;for(let[n,r]of Ja(e.objects).entries()){let e=mt(r.def);if(e.length===0)continue;let i=e.map(e=>e.verb).join(`, `),a=[...new Set(e.map(e=>e.needs))];t.push({severity:`error`,rule:Ka,where:`object "${r.name}"`,path:`objects[${n}].enable.apiMethods`,message:`\`managedBy: '${String(r.def.managedBy)}'\` object "${r.name}" `+Ut(e)+` The registry STRIPS [${i}] at registration, so this declaration and the API you actually get already disagree \u2014 today the only trace is a line in the boot log.`,hint:`Either add \`userActions: { ${a.map(e=>`${e}: true`).join(`, `)} }\` to the object \u2014 only if the write is genuinely one a user context may perform, and only once the guard enforcing it exists (ADR-0092 D4: affordance never ships ahead of the guard) \u2014 or remove [${i}] from \`enable.apiMethods\`, which is what the runtime does for you today.`})}return t}var Xa=`flow-trigger-unknown-object`,Za=`flow-draft-status-ambiguous`,Qa=`flow-trigger-unknown-event`,$a=`flow-time-relative-descriptor-invalid`,eo=`flow-time-relative-descriptor-unroutable`,to=`flow-trigger-unroutable`,no=`flow-api-trigger-secret-missing`,ro=/^record-(?:before|after)-(?:create|insert|update|delete|write)$/;function io(e){let t=typeof e;return t===`string`||t===`number`||t===`boolean`?`${JSON.stringify(e)} (a ${t})`:t===`bigint`?`${String(e)}n (a bigint)`:`a ${t}`}function ao(e){if(typeof e==`string`)return`'${e}'`;let t=JSON.stringify(e);return t===void 0?`a ${typeof e}`:t}function oo(e,t){if(!e)return`it has no start node, so nothing declares a config.secret`;let n=t.secret;return typeof n==`string`?n.trim()===``?`its start node's config.secret is blank`:void 0:n===void 0?`its start node declares no config.secret`:`its start node's config.secret is ${n===null?`null`:Array.isArray(n)?`an array`:`a ${typeof n}`}, not a string`}function so(e){return Array.isArray(e.triggerType)&&e.triggerType.some(e=>typeof e==`string`&&e.startsWith(`record-`))}function co(e){let t=Array.isArray(e.nodes)?e.nodes:[],n=t.findIndex(e=>e?.type===`start`);return n>=0?{node:t[n],index:n}:void 0}function lo(e){let t=[],n=w(e.flows);if(n.length===0)return t;let i=new Set(w(e.objects).map(e=>typeof e.name==`string`?e.name:void 0).filter(e=>!!e));return n.forEach((e,n)=>{let a=typeof e.name==`string`?e.name:`#${n}`,o=co(e),s=o?.node.config??{},c=typeof s.triggerType==`string`?s.triggerType:void 0,l=!!c&&c.startsWith(`record-`),u=so(s),d=s.timeRelative!=null&&typeof s.timeRelative==`object`,f=r(e)!==void 0;if(l&&o){let e=typeof s.objectName==`string`?s.objectName:void 0;e&&!i.has(e)&&!e.startsWith(`sys_`)&&t.push({severity:`warning`,rule:Xa,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.objectName`,message:`targets object '${e}', which this stack does not define \u2014 if the name is wrong, the flow will never fire (and the runtime stays silent about it).`,hint:`Object names match exactly. Check config.objectName against the object's registered name (e.g. 'app_candidate', not 'candidate'). If the object comes from another installed package, this warning can be ignored.`})}if(d&&o){let e=s.timeRelative,r=typeof e.object==`string`?e.object:void 0;r&&!i.has(r)&&!r.startsWith(`sys_`)&&t.push({severity:`warning`,rule:Xa,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.timeRelative.object`,message:`sweeps object '${r}', which this stack does not define \u2014 if the name is wrong, the sweep will match nothing (and the runtime stays quiet about it).`,hint:`Object names match exactly. Check config.timeRelative.object against the object's registered name. If the object comes from another installed package, this warning can be ignored.`});let c=It.safeParse(e);if(!c.success){let e=c.error.issues.map(e=>`${e.path.join(`.`)||`(root)`}: ${e.message.replace(/\s+/g,` `).trim()}`).join(`; `);t.push({severity:`error`,rule:$a,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.timeRelative`,message:`has a config.timeRelative descriptor the time-relative trigger REFUSES at bind time, so the sweep is never installed \u2014 the flow declares a time-relative trigger and then never runs (the only trace is one warn in the server log). ${e}`,hint:`Those messages are TimeRelativeTriggerSchema's own — the same schema the trigger safeParses at bind time, so a descriptor that satisfies them binds. An unrecognized key names the declared key it was probably meant to be; see content/docs/references/automation/time-relative-trigger.mdx.`})}}if(o&&l&&!ro.test((c??``).trim())&&t.push({severity:`error`,rule:Qa,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.triggerType`,message:`triggerType '${c}' is not a recognized record trigger \u2014 the flow binds to the record-change trigger but never fires (the runtime stays silent about it).`,hint:`Use record-{before,after}-{create,update,delete,write}. 'write' fires on create OR update in one flow (#3427); create/insert are synonyms. There is no "any change" token — pick the specific event(s).`}),o&&u&&t.push({severity:`error`,rule:Qa,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.triggerType`,message:`triggerType is an array (${JSON.stringify(s.triggerType)}), which is not supported \u2014 a start node takes a single trigger event, so the flow binds to nothing and never fires (the runtime stays silent about it).`,hint:`Use one triggerType string. For "created or updated" use record-after-write (one flow, both events, #3427). For any other combination, author one flow per event — multi-event arrays are deferred (#3457).`}),o&&s.timeRelative!=null&&typeof s.timeRelative!=`object`){let r=l||u?`its record-change trigger`:s.schedule!=null||e.type===`schedule`?"its plain `config.schedule` cadence":c===`api`||e.type===`api`?`its api trigger`:void 0,i=r?`The flow still binds through ${r}, so the descriptor is silently DROPPED \u2014 it fires on that trigger's terms (once per firing, with no record on the context) instead of once per matching record, and nothing anywhere reports the difference.`:`Nothing else on this start node declares a trigger either, so the flow binds to NOTHING and never fires — with zero diagnostics at any layer, not even the one bind-time warn a descriptor that IS an object gets when the trigger refuses it.`;t.push({severity:`error`,rule:eo,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.timeRelative`,message:`has config.timeRelative = ${io(s.timeRelative)}, which is not the descriptor OBJECT this slot takes \u2014 the engine routes a flow to the time-relative sweep only when config.timeRelative is an object, so this one is never routed there and the sweep is never installed. ${i}`,hint:`config.timeRelative describes WHICH records to sweep — an object: { object, dateField, and exactly one of withinDays | offsetDays } (plus optional filter / maxRecords). A cadence like 'daily' is not a descriptor: HOW OFTEN the sweep runs is the sibling key config.schedule on the same start node (it defaults to daily, so it is usually omitted). See TimeRelativeTriggerSchema and content/docs/references/automation/time-relative-trigger.mdx.`})}let p=l||u||d||s.schedule!=null||e.type===`schedule`||e.type===`api`||c===`api`;if(o&&e.type===`record_change`&&!p){let e=s.triggerType!=null;t.push({severity:`error`,rule:to,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.triggerType`,message:`declares type: 'record_change' but `+(e?`its start node's triggerType is ${ao(s.triggerType)}, which the engine routes to NO trigger`:`its start node has no triggerType at all, so there is nothing for the engine to route`)+` — it binds a record-change flow only for a token starting with 'record-', so this flow is demoted to a manual one and never fires. Nothing NAMES it: the unbound-flow audit resolves the same binding and skips the flow as "manual — nothing to bind", so neither the boot warning nor the startup summary lists it; the only trace is the banner's flow count being one higher than its bound count.`,hint:`Use record-{before,after}-{create,update,delete,write} ('write' is create OR update in one flow, #3427; create/insert are synonyms). If the flow really is launched by hand or from a screen, declare type: 'autolaunched' or 'screen' instead of 'record_change' — those types have no trigger to be missing.`})}f&&(e.status==null||e.status===`draft`)&&t.push({severity:`warning`,rule:Za,where:`flow "${a}"`,path:`flows[${n}].status`,message:`has status 'draft' (the default when none is authored). Draft flows DO still fire their triggers (only 'obsolete'/'invalid' disable), so the intent is ambiguous.`,hint:`Declare status: 'active' to arm it deliberately, or status: 'obsolete' to disable it.`})}),t}function uo(e,t={}){let n=[];return w(e.flows).forEach((e,i)=>{let a=typeof e.name==`string`?e.name:`#${i}`,o=co(e),s=o?.node.config??{},c=typeof s.triggerType==`string`?s.triggerType:void 0,l=!so(s)&&r(e)===`api`,u=o?`flows[${i}].nodes[${o.index}].config.secret`:void 0;if(u!==void 0&&t.restoredCredentialPaths?.has(u))return;let d=l?oo(o,s):void 0;if(!d)return;let f=[e.type===`api`?`type: 'api'`:void 0,c===`api`?`start-node triggerType: 'api'`:void 0].filter(e=>e!==void 0);n.push({severity:`error`,rule:no,where:o?`flow "${a}" \u203A start node`:`flow "${a}"`,path:u??`flows[${i}].nodes`,message:`binds the inbound api trigger (${f.join(` and `)}) but ${d}. An inbound hook is armed only with a per-flow secret that every post is HMAC-verified against (ADR-0041), so the automation engine refuses to register this flow, whatever its status, and it never receives a post.`,hint:`Set a non-blank string config.secret on the start node, and sign each post with it: the x-objectstack-signature header carries 'sha256=' and the hex HMAC-SHA256 of the raw body. A flow that is only ever started explicitly and never receives inbound posts is type: 'autolaunched', with no triggerType: 'api' on its start node — that flow needs no secret.`})}),n}function fo(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function po(e){return typeof e==`string`&&e.length>0?e:void 0}var mo=new Map([...tt].map(([e,t])=>[e,t.map(e=>e.key)])),ho=16;function go(e,t){return po(e.label)??po(e.id)??`#${t}`}var _o=[];function vo(e){let t=po(e);return(t?mo.get(t):void 0)??_o}function yo(e,t){if(!fo(e))return;let n=t instanceof Set?t:new Set(t);if(n.size===0)return e;let r;for(let t of Object.keys(e))n.has(t)&&(r??={...e},delete r[t]);return r??e}function bo(e,t){let n=[];if(!fo(e))return n;let r=(e,t,i,a)=>{!Array.isArray(e)||a>ho||e.forEach((e,o)=>{if(!fo(e))return;let s=`${t}[${o}]`,c=vo(e.type);n.push({node:e,path:s,localConfig:yo(e.config,c),regionTrail:i,depth:a});let l=po(e.type),u=c.length>0?c:void 0;if(!u||!fo(e.config))return;let d=e.config,f=`${l} "${go(e,o)}"`;for(let e of u){let t=d[e];if(e===`branches`){if(!Array.isArray(t))continue;t.forEach((e,t)=>{if(!fo(e))return;let n=po(e.name)??`#${t}`;r(e.nodes,`${s}.config.branches[${t}].nodes`,xo(i,`${f} \u203A branch ${n}`),a+1)});continue}fo(t)&&r(t.nodes,`${s}.config.${e}.nodes`,xo(i,`${f} \u203A ${e}`),a+1)}})};return r(e.nodes,`${t}.nodes`,``,0),n}function xo(e,t){return e?`${e} \u203A ${t}`:t}var So=`flow-template-unknown-field`,Co=`flow-template-lookup-traversal`,wo=`flow-template-field-unprovisioned`,To=new Set([...Nn,`name`,`owner`,`record_type`]),Eo=new Set([`lookup`,`master_detail`,`user`,`tree`]),Do=new Set([`get_record`,`update_record`,`delete_record`]);function Oo(e){let t=new Map;for(let n of w(e.fields))typeof n.name==`string`&&t.set(n.name,typeof n.type==`string`?n.type:``);return t}function ko(e){let t=[],n=/\{([^{}]+)\}/g,r;for(;(r=n.exec(e))!==null;){let e=r[1].trim();if(!/^[A-Za-z_$][\w$]*(?:\.(?:[A-Za-z_$][\w$]*|\d+))*$/.test(e))continue;let n=e.split(`.`),i=n.slice(1);i.length>0&&t.push({root:n[0],rest:i})}return t}function Ao(e,t){if(typeof e==`string`){e.includes(`{`)&&t.push(e);return}if(Array.isArray(e)){for(let n of e)Ao(n,t);return}if(e&&typeof e==`object`)for(let n of Object.values(e))Ao(n,t)}var jo=[`config`,`notify`,`update_record`,`create_record`,`http`,`script`,`screen`,`wait`,`approval`,`connector_action`,`subflow`,`decision`,`start`];function Mo(e,t){let n=[],r=[];for(let i of jo){if(!(i in e))continue;let a=e[i];if(t&&a&&typeof a==`object`&&!Array.isArray(a)){let{filter:e,...t}=a,i=[];Ao(e,i);for(let e of i)n.push({text:e,inFilter:!0});let o=[];Ao(t,o);for(let e of o)r.push({text:e,inFilter:!1});continue}let o=[];Ao(a,o);for(let e of o)r.push({text:e,inFilter:!1})}return[...n,...r]}function No(e,t){if(e.type===`record_change`)return!0;let n=typeof t.triggerType==`string`?t.triggerType:void 0;return!!n&&n.startsWith(`record-`)}function Po(e){let t=w(e.nodes).find(e=>e.type===`start`);if(!t)return;let n=t.config??{},r=t.start??{},i=typeof n.objectName==`string`?n.objectName:void 0,a=typeof r.objectName==`string`?r.objectName:void 0;return i??a}function Fo(e){let t=(w(e.nodes).find(e=>e.type===`start`)?.config??{}).expand;return typeof t==`string`?new Set(t?[t]:[]):Array.isArray(t)?new Set(t.filter(e=>typeof e==`string`&&e.length>0)):new Set}var Io=new Set,Lo=new Set([`record`,`previous`]),Ro=/^[A-Za-z_$][\w$]*$/;function zo(e){if(typeof e!=`string`)return;let t=e.trim();if(!t)return;let n=/^\{([^{}]+)\}$/.exec(t);return(n?n[1]:t).trim()}function Bo(e,t){let n=new Map,r=new Map,i=new Set,a=e=>{typeof e==`string`&&e&&(i.add(e),n.delete(e),r.delete(e))},o=(e,t,o)=>{if(i.has(t))return;let s=e===n?r:n,c=e.get(t);if(s.has(t)||c!==void 0&&c!==o){a(t);return}e.set(t,o)},s=[];for(let{node:t}of e){a(t.id);let e=t.config;if(!e||typeof e!=`object`||Array.isArray(e))continue;let i=e,c=typeof t.type==`string`?t.type:``;if(a(i.indexVariable),a(i.errorVariable),c===`assignment`){let e=i.assignments;if(Array.isArray(e))for(let t of e){if(!t||typeof t!=`object`)continue;let e=t;a(e.variable),a(e.name),a(e.key)}else if(e&&typeof e==`object`)for(let t of Object.keys(e))a(t);else for(let e of Object.keys(i))a(e)}let l=i.outputVariable;if(typeof l==`string`&&l){let e=typeof i.objectName==`string`?i.objectName:``;c!==`get_record`||!e?a(l):typeof i.limit==`number`&&i.limit>1?o(r,l,e):o(n,l,e)}let u=i.iteratorVariable;typeof u==`string`&&u&&(c===`loop`?s.push({collection:i.collection,iterator:u}):a(u))}for(let{collection:e,iterator:t}of s){let i=zo(e),s=i&&Ro.test(i)?r.get(i):void 0;s?o(n,t,s):a(t)}let c=new Map;for(let[e,r]of n)i.has(e)||Lo.has(e)||e.startsWith(`$`)||t.has(e)||c.set(e,r);return c}function Vo(e){let t=[],n=w(e.flows);if(n.length===0)return t;let r=new Map;for(let t of w(e.objects))typeof t.name==`string`&&r.set(t.name,t);let i=new Map,a=(e,t)=>{let n=i.get(e);return n||(n=Oo(t),i.set(e,n)),n};return n.forEach((e,n)=>{let i=typeof e.name==`string`?e.name:`#${n}`,o=w(e.nodes).find(e=>e.type===`start`)?.config??{},s=new Map;if(No(e,o)){let t=Po(e),n=t?r.get(t):void 0;t&&n&&s.set(`record`,{objectName:t,fieldTypes:a(t,n),isTrigger:!0,unprovisionedAnchors:In(n),expand:Fo(e)})}let c=bo(e,`flows[${n}]`),l=s.get(`record`),u=l?new Set([...l.fieldTypes.keys(),...To]):Io;for(let[e,t]of Bo(c,u)){let n=r.get(t);n&&s.set(e,{objectName:t,fieldTypes:a(t,n),isTrigger:!1,unprovisionedAnchors:Io,expand:Io})}s.size!==0&&c.forEach(({node:e,path:n,regionTrail:r,localConfig:a},o)=>{let c=typeof e.type==`string`?e.type:typeof e.id==`string`?e.id:`#${o}`,l=r?`flow "${i}" ${r} node "${c}"`:`flow "${i}" node "${c}"`,u=typeof e.type==`string`?e.type:``,d=Do.has(u),f=Mo(a!==void 0&&a!==e.config?{...e,config:a}:e,d);if(f.length===0)return;let p=new Set,m=new Set,h=new Set;for(let e of f){let r=e.inFilter;for(let{root:i,rest:a}of ko(e.text)){let e=s.get(i);if(!e)continue;let o=e.objectName,c=`${i}.${a.join(`.`)}`,d=a[0],f=a.length>1&&!/^\d+$/.test(a[1]),g=e.fieldTypes.has(d)||To.has(d);if(e.unprovisionedAnchors.has(d)&&(h.has(d)||(h.add(d),t.push({severity:`warning`,rule:wo,where:l,path:n,message:(r?`${u} filter references `:`template references `)+`'{${c}}', and ${zn(o,d)} \u2014 `+(r?`the token resolves to nothing on every run, which DROPS the condition from the query instead of narrowing it; the node then refuses to run at execution time (#3810).`:`the token resolves to an empty string on every run (silently).`),hint:Bn(o,d)}))),!g){if(p.has(c))continue;p.add(c),t.push({severity:r?`error`:`warning`,rule:So,where:l,path:n,message:r?`${u} filter references '{${c}}', but '${d}' is not a field on object '${o}' \u2014 the token resolves to nothing, which DROPS the condition from the query instead of narrowing it. The node refuses to run at execution time (#3810).`:`template references '{${c}}', but '${d}' is not a field on object '${o}' \u2014 it resolves to an empty string at runtime (silently).`,hint:e.isTrigger?r?`Check the field name against the object's field definitions (e.g. '{record.full_name}', not '{record.full_naem}'); system columns like id/created_at/owner are also addressable. This gates the build rather than warning: an absent condition WIDENS the query, so the runtime has already decided to refuse this node.`:`Check the field name against the object's field definitions (e.g. '{record.full_name}', not '{record.full_naem}'). System columns like id/created_at/owner are also addressable.`:r?`Check the field name against object '${o}'s field definitions \u2014 '${i}' is bound to a '${o}' record by this flow; system columns like id/created_at/owner are also addressable. This gates the build rather than warning: an absent condition WIDENS the query, so the runtime has already decided to refuse this node.`:`Check the field name against object '${o}'s field definitions \u2014 '${i}' is bound to a '${o}' record by this flow. System columns like id/created_at/owner are also addressable.`});continue}if(f){let a=e.fieldTypes.get(d)??``;if(Eo.has(a)&&!e.expand.has(d)){if(m.has(c))continue;m.add(c),t.push({severity:r?`error`:`warning`,rule:Co,where:l,path:n,message:r?`${u} filter references '{${c}}', a cross-object hop through the ${a} field '${d}' \u2014 the ${e.isTrigger?`flow record`:`'${i}' record`} carries '${d}' as a scalar id, not an expanded object, so the token resolves to nothing and the condition is DROPPED from the query instead of narrowing it. The node refuses to run at execution time (#3810).`:`template references '{${c}}', a cross-object hop through the ${a} field '${d}' \u2014 the ${e.isTrigger?`flow record`:`'${i}' record`} carries '${d}' as a scalar id, not an expanded object, so this resolves to an empty string at runtime (silently).`,hint:e.isTrigger?r?`Opt in to resolve it: add '${d}' to the start node's config.expand (#3475) and the engine re-reads it as the run's identity. Otherwise filter on the foreign-key id directly ('{record.${d}}'), or project the value via a formula field on '${o}'. This gates the build rather than warning: an absent condition WIDENS the query.`:`Opt in to resolve it: add '${d}' to the start node's config.expand (#3475) and the engine re-reads it as the run's identity. Otherwise reference the foreign-key id directly ('{record.${d}}'), or project the value via a formula field on '${o}'.`:r?`A record read into a flow variable is not expanded either \u2014 config.expand is the START node's opt-in and covers the trigger record alone. Filter on the foreign-key id directly ('{${i}.${d}}'), project the value via a formula field on '${o}', or add a get_record node that reads the related record. This gates the build rather than warning: an absent condition WIDENS the query.`:`A record read into a flow variable is not expanded either \u2014 config.expand is the START node's opt-in and covers the trigger record alone. Reference the foreign-key id directly ('{${i}.${d}}'), project the value via a formula field on '${o}', or add a get_record node that reads the related record.`})}}}}})}),t}var Ho=`flow-update-readonly-field`,Uo=`flow-update-readonly-when-field`,Wo=`create_record`,Go=new Set([`update_record`,Wo]);function Ko(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=new Map,i=(e,t)=>{let n=t?.readonlyWhen,i=n!=null&&(typeof n!=`string`||n.trim()!==``);r.set(e,{readonly:t?.readonly===!0,readonlyWhen:i})},a=n.fields;if(Array.isArray(a))for(let e of a){let t=e?.name;typeof t==`string`&&i(t,e)}else if(a&&typeof a==`object`)for(let[e,t]of Object.entries(a))i(e,t);t.set(e,r)}return t}var qo=new Set([`engine-owned`,`append-only`,`better-auth`]);function Jo(e){let t=new Set;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;e&&(typeof n.managedBy==`string`&&qo.has(n.managedBy)||e.startsWith(`sys_`))&&t.add(e)}return t}function Yo(e){let t=e.objectName??e.object;if(!(typeof t!=`string`||t.includes(`{`)))return t||void 0}function Xo(e){let t=[],n=w(e.flows);if(n.length===0)return t;let r=w(e.objects),i=Ko(r),a=Jo(r);return n.forEach((e,n)=>{let r=e.runAs===`user`||e.runAs===`system`?e.runAs:`user`,o=r===`system`,s=typeof e.name==`string`?e.name:`#${n}`;bo(e,`flows[${n}]`).forEach(({node:e,path:n,regionTrail:c},l)=>{let u=e?.type;if(typeof u!=`string`||!Go.has(u))return;let d=u===Wo,f=e.config??{},p=Yo(f);if(!p)return;let m=i.get(p);if(!m||d&&a.has(p))return;let h=f.fields;if(!h||typeof h!=`object`||Array.isArray(h))return;let g=go(e,l),_=c?`flow "${s}" \u203A ${c} \u203A node "${g}"`:`flow "${s}" \u203A node "${g}"`;for(let e of Object.keys(h)){let i=m.get(e);i&&(i.readonly&&!o?t.push({severity:`error`,rule:Ho,where:_,path:`${n}.config.fields.${e}`,message:d?`writes field '${e}', which object '${p}' declares readonly:true. Under runAs:'${r}' the engine silently strips readonly fields from the INSERT payload too (the same strip the UPDATE path runs), so the row is created WITHOUT this column (it falls back to the field's defaultValue) \u2014 while the create_record step still reports success, with only a run-time warning naming the dropped field.`:`writes field '${e}', which object '${p}' declares readonly:true. Under runAs:'${r}' the engine silently strips readonly fields from the UPDATE payload (#2948), so this write never lands \u2014 while the step still reports success.`,hint:d?`Seeding a readonly column at create time is a SYSTEM act: declare the flow runAs:'system' (the intended channel \u2014 readonly governs the end-user/API surface, not trusted system writers). Otherwise remove '${e}' from this create_record node, or stamp it in a beforeInsert hook on '${p}' \u2014 a hook-assigned key is the hook's write, not a caller-supplied one, and survives the strip.`:`If automation is meant to maintain this field, declare the flow runAs:'system' (the intended channel \u2014 readonly governs the end-user/API surface, not trusted system writers). Otherwise remove '${e}' from this update_record node.`}):i.readonlyWhen&&!d&&t.push({severity:`warning`,rule:Uo,where:_,path:`${n}.config.fields.${e}`,message:`writes field '${e}', which object '${p}' declares readonlyWhen. On records where that predicate is TRUE, a runAs:'${r}' UPDATE strips the field (#3042), so this write may silently not land depending on the record's state.`,hint:`Elevation is not a workaround here: unlike the static readonly strip, the conditional lock is NOT waived by a system context, so runAs:'system' strips this field on a locked record exactly as this run does. Either confirm this node only targets records whose readonlyWhen predicate is FALSE, or derive '${e}' in a beforeUpdate hook on '${p}' - a hook-derived value is not caller-supplied and does land, even on a locked record. Otherwise remove '${e}' from this update_record node. This warning never blocks a build.`}))}})}),t}var Zo=null;function Qo(){if(Zo)return Zo;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{Zo=(0,S.createRequire)(e)(`typescript`)}catch(e){throw Error(`@objectstack/lint: checking an L2 (language:'js') hook body requires the "typescript" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "typescript" in the image; it is only loaded when a hook with a JS body is validated.`)}return Zo}var $o=`hook-body-write-unknown-field`,es=`hook-body-source-unparseable`,ts=`hook-body-write-unprovisioned-anchor`,ns=[{id:`input-property-assign`,syntax:`ctx.input.<field> = … | ctx.input['<field>'] ⟨op⟩= …`,example:{source:`ctx.input.total = 0; ctx.input['status'] ??= 'open'; ctx.input.retries += 1;`,writes:[{field:`total`},{field:`status`},{field:`retries`}]}},{id:`input-object-assign`,syntax:`Object.assign(ctx.input, { <field>: … })`,example:{source:`Object.assign(ctx.input, { total: 5, 'status': 'open', discount });`,writes:[{field:`total`},{field:`status`},{field:`discount`}]}},{id:`record-property-assign`,syntax:`ctx.record.<field> = … | ctx.record['<field>'] ⟨op⟩= …`,example:{source:`ctx.record.stage = 'won'; ctx.record['amount'] += 1;`,writes:[{field:`stage`},{field:`amount`}]}},{id:`api-crud-literal`,syntax:`ctx.api.object('<object>').insert({…}) | .update({…}) | .updateById(id, {…})`,example:{source:`await ctx.api.object('audit_log').insert({ event: 'won' }); await ctx.api.object('crm_deal').updateById(id, { stage: 'won' });`,writes:[{field:`event`,object:`audit_log`},{field:`stage`,object:`crm_deal`}]}}],rs=[`input-property-assign`,`input-object-assign`,`api-crud-literal`],is=[{id:`record-property-assign`,reason:"a hook sandbox context has no `ctx.record` at all — `buildSandboxContext` never sets it (a hook’s record IS `ctx.input`), so the expression throws at run time rather than silently no-op’ing. A loud failure the author sees on the first run is not this advisory rule’s business"}],as=new Set(rs),os=new Map([[`insert`,0],[`update`,0],[`updateById`,1]]),ss=new Set([`id`,`options`,`ast`,`data`]),cs=new Set([...Nn,`_id`,`name`,`space`,`owner`,`record_type`]);function ls(){return`so the value can never land: the anchor exists only in the registered schema, which is what carries it PAST the write-path validator that refuses an undeclared name outright (INVALID_FIELD). The remote database is what rejects it — on a SQL remote with an untyped driver error ('no such column') that aborts the whole statement, so the correctly named fields in the same payload never land either; on a schemaless remote the key is persisted into a column no read surface returns (#4271).`}var us=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function ds(e,t,n){return typeof e.handler==`string`&&n?.loweredHookRefs?.has(e.handler)?{path:`hooks[${t}].handler`,messageSuffix:` (judged on the metadata body lowered from the inline handler)`}:{path:`hooks[${t}].body.source`,messageSuffix:``}}function fs(e){let t=new Map;for(let n of w(e.objects)){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=new Set;for(let e of w(n.fields))typeof e.name==`string`&&e.name&&r.add(e.name);t.set(e,r)}return t}function ps(e,t){let n=e.get(t);if(n&&n.size!==0)return n}function ms(e){return hs(e).writes}function hs(e){if(!/\bctx\b/.test(e)&&!/\bObject\b/.test(e))return{writes:[],ctxRecordEscapes:!1};let t=Qo(),{sourceFile:n,failure:r}=ua(t,`hook-body.ts`,`async function __body(ctx) {
3
+ ${e}
4
+ }`,{target:t.ScriptTarget.Latest,setParentNodes:!1,scriptKind:t.ScriptKind.TS,synthesizedLinesBefore:1}),i=[],a=[],o=new Set,s=(e,n)=>t.isPropertyAccessExpression(e)&&t.isIdentifier(e.expression)&&e.expression.text===`ctx`&&e.name.text===n,c=(e,n)=>{if(t.isPropertyAccessExpression(e)&&t.isIdentifier(e.name)&&s(e.expression,n))return e.name.text;if(t.isElementAccessExpression(e)&&s(e.expression,n)){let n=e.argumentExpression;if(t.isStringLiteral(n)||t.isNoSubstitutionTemplateLiteral(n))return n.text}},l=e=>{if(!t.isObjectLiteralExpression(e))return[];let n=[];for(let r of e.properties)t.isPropertyAssignment(r)?(t.isIdentifier(r.name)||t.isStringLiteral(r.name))&&n.push(r.name.text):t.isShorthandPropertyAssignment(r)&&n.push(r.name.text);return n},u=e=>{if(t.isBinaryExpression(e)&&e.operatorToken.kind>=t.SyntaxKind.FirstAssignment&&e.operatorToken.kind<=t.SyntaxKind.LastAssignment){let t=c(e.left,`input`);t!==void 0&&!ss.has(t)&&i.push({patternId:`input-property-assign`,field:t});let n=c(e.left,`record`);n!==void 0&&i.push({patternId:`record-property-assign`,field:n})}if((t.isPropertyAccessExpression(e)||t.isElementAccessExpression(e))&&s(e.expression,`record`)&&o.add(e.expression),t.isBinaryExpression(e)){let n=e.operatorToken.kind;(n===t.SyntaxKind.AmpersandAmpersandToken||n===t.SyntaxKind.BarBarToken||n===t.SyntaxKind.QuestionQuestionToken)&&s(e.left,`record`)&&o.add(e.left)}if(t.isPrefixUnaryExpression(e)&&e.operator===t.SyntaxKind.ExclamationToken&&s(e.operand,`record`)&&o.add(e.operand),t.isTypeOfExpression(e)&&s(e.expression,`record`)&&o.add(e.expression),(t.isIfStatement(e)||t.isWhileStatement(e)||t.isDoStatement(e))&&s(e.expression,`record`)&&o.add(e.expression),t.isConditionalExpression(e)&&s(e.condition,`record`)&&o.add(e.condition),s(e,`record`)&&a.push(e),t.isCallExpression(e)){let n=e.expression;if(t.isPropertyAccessExpression(n)&&t.isIdentifier(n.expression)&&n.expression.text===`Object`&&n.name.text===`assign`&&e.arguments.length>=2&&s(e.arguments[0],`input`))for(let t of e.arguments.slice(1))for(let e of l(t))ss.has(e)||i.push({patternId:`input-object-assign`,field:e});if(t.isPropertyAccessExpression(n)&&t.isIdentifier(n.name)){let r=os.get(n.name.text),a=n.expression;if(r!==void 0&&t.isCallExpression(a)&&t.isPropertyAccessExpression(a.expression)&&a.expression.name.text===`object`&&s(a.expression.expression,`api`)&&a.arguments.length===1){let o=a.arguments[0],s=t.isStringLiteral(o)||t.isNoSubstitutionTemplateLiteral(o)?o.text:void 0,c=e.arguments[r];if(s&&c!==void 0)for(let e of l(c))i.push({patternId:`api-crud-literal`,object:s,method:n.name.text,field:e})}}}t.forEachChild(e,u)};return u(n),{writes:i,ctxRecordEscapes:a.some(e=>!o.has(e)),...r?{parseFailure:r}:{}}}function gs(e,t){let n=[],r=w(e.hooks);if(r.length===0)return n;let i=null,a=null;return r.forEach((r,o)=>{let s=r.body;if(!us(s)||s.language!==`js`)return;let c=s.source;if(typeof c!=`string`||c.trim()===``)return;let l=hs(c),u=typeof r.name==`string`&&r.name?r.name:`#${o}`,d=ds(r,o,t);l.parseFailure&&n.push({severity:`warning`,rule:es,where:`hook "${u}" \u203A body`,path:d.path,message:`L2 body did not parse (${da(l.parseFailure)}), so its write set was read from a partially recovered tree \u2014 an undeclared field write in the unread part is not reported.${d.messageSuffix}`,hint:fa});let f=l.writes.filter(e=>as.has(e.patternId));if(f.length===0)return;i??=fs(e),a??=Rn(e);let p=(Array.isArray(r.object)?r.object:[r.object]).filter(e=>typeof e==`string`&&e.trim()!==``),m=p.map(e=>ps(i,e)),h=p.length>0&&!p.includes(`*`)&&m.every(e=>e!==void 0),g=`hook "${u}" \u203A body`,_=d.path,v=new Set;for(let e of f){let t=`${e.object??``}\0${e.field}`;if(!v.has(t)){if(e.object===void 0){if(!h)continue;if(cs.has(e.field)){if(!p.every(t=>a.get(t)?.has(e.field)))continue;v.add(t);let r=p.length===1?p[0]:p.join(`, `);n.push({severity:`warning`,rule:ts,where:g,path:_,message:`body writes '${e.field}' to its input, and ${zn(r,e.field)} \u2014 `+ls()+d.messageSuffix,hint:Bn(r,e.field)});continue}if(m.some(t=>t.has(e.field)))continue;v.add(t);let r=p.length===1?`object '${p[0]}'`:`none of its target objects (${p.join(`, `)})`,i=p.length===1?`declares no such field`:`declare that field`;n.push({severity:`warning`,rule:$o,where:g,path:_,message:`body writes '${e.field}' to its input, but ${r} ${i}. The sandboxed script runs clean and the value is copied back onto the record payload unfiltered, so the write is then REFUSED at run time \u2014 INVALID_FIELD / 400, identically on every driver (#4271). The record is never written, and the refusal names the field far from the body that wrote it.`+d.messageSuffix,hint:vs(e.field,_s(m))})}else{let r=ps(i,e.object);if(!r||r.has(e.field))continue;if(cs.has(e.field)){if(!a.get(e.object)?.has(e.field))continue;v.add(t),n.push({severity:`warning`,rule:ts,where:g,path:_,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', and ${zn(e.object,e.field)} \u2014 ${ls()}`+d.messageSuffix,hint:Bn(e.object,e.field)});continue}v.add(t),n.push({severity:`warning`,rule:$o,where:g,path:_,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', but object '${e.object}' declares no such field. ctx.api is a scoped handle on the running engine, so the payload arrives as an ordinary CALLER write and the declared-field door REFUSES it at run time \u2014 INVALID_FIELD / 400, identically on every driver (#4271), before any statement is built. The nested write lands nothing, and the refusal escapes the body and fails the operation that triggered the hook.`+d.messageSuffix,hint:vs(e.field,[...r])})}}}}),n}function _s(e){let t=new Set;for(let n of e)for(let e of n??[])t.add(e);return[...t]}function vs(e,t){let n=me(ee(e,[...t,...cs]));return(n?`${n} `:``)+`Fix the field name, or declare '${e}' on the object. Only the literal write patterns in HOOK_BODY_WRITE_PATTERNS are checked \u2014 computed keys, spreads and aliased input are not \u2014 and this warning never blocks a build.`}var ys=`hook-api-update-readonly-field`,bs=`hook-api-update-readonly-when-field`,xs=[`api-crud-literal`],Ss=[{id:`input-property-assign`,reason:"a `ctx.input.<field> = ...` stamp is a SERVER value, not a caller-supplied one - stripReadonlyFields drops a key only while it is still Object.is-equal to what the caller supplied, so the stamp survives. readonly + a before-hook stamp is the CORRECT pairing this rule must never flag"},{id:`input-object-assign`,reason:`Object.assign(ctx.input, { ... }) reaches the same in-flight payload as the property form and survives the strip for the same reason - the channel is what decides, not the syntax`},{id:`record-property-assign`,reason:`a hook sandbox context has no ctx.record at all, so the expression throws at run time rather than silently no-op-ing - a loud failure on the first run is not this rule’s business (the action surface owns that shape)`}],Cs=new Set(xs),ws=new Set([`update`,`updateById`,`insert`]),Ts=new Set([`update`,`updateById`]),Es=new Set([`update`]),Ds=`id`;function Os(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function ks(e,t){let n=[],r=w(e.hooks);if(r.length===0)return n;let i=null,a=null;return r.forEach((r,o)=>{let s=r.body;if(!Os(s)||s.language!==`js`)return;let c=s.source;if(typeof c!=`string`||c.trim()===``||r.runAs===`system`)return;let l=hs(c);if(l.parseFailure)return;let u=l.writes.filter(e=>Cs.has(e.patternId)&&typeof e.object==`string`&&e.method!==void 0&&ws.has(e.method));if(u.length===0)return;i??=Ko(w(e.objects)),a??=Jo(w(e.objects));let d=`hook "${typeof r.name==`string`&&r.name?r.name:`#${o}`}" > body`,f=ds(r,o,t),p=f.path,m=new Set;for(let e of u){let t=e.object,r=e.method;if(e.field===Ds&&Es.has(r))continue;let o=i.get(t);if(!o||o.size===0)continue;let s=o.get(e.field);if(!s)continue;let c=`${t} ${e.field}`;if(m.has(c))continue;let l=`ctx.api.object('${t}').${r}(...)`,u=!Ts.has(r);u&&a.has(t)||(s.readonly?(m.add(c),n.push({severity:`error`,rule:ys,where:d,path:p,message:(u?`body writes field '${e.field}' through ${l}, and object '${t}' declares it readonly:true. A hook's ctx.api is a ScopedContext over the TRIGGERING operation's context, so on every non-system trigger the engine strips readonly keys from that INSERT payload exactly as it does from an UPDATE - the row is created WITHOUT this column (it falls back to the field's defaultValue), while the call still returns success.`:`body writes field '${e.field}' through ${l}, and object '${t}' declares it readonly:true. A hook's ctx.api is a ScopedContext over the TRIGGERING operation's context, so on every non-system trigger the engine strips readonly keys from that UPDATE payload - the write never lands, while the call still returns success.`)+f.messageSuffix,hint:u?`Seeding a readonly column at create time is a SYSTEM act. To keep writing it from here, declare runAs: 'system' on this hook: the strip skips a system context, so the write lands, and the triggering user is still stamped on the record. Or stamp it on '${t}''s OWN beforeInsert hook - ctx.input.${e.field} = ... is a server value and survives the strip. Note that ctx.api.sudo() is NOT an option from a body: sudo() lives on the in-process ScopedContext and is not marshalled into the sandbox, so calling it here is a TypeError at run time. Otherwise drop '${e.field}' from this payload, or drop readonly:true from the field.`:`If automation is meant to maintain '${e.field}', stamp it on the record's OWN hook - ctx.input.${e.field} = ... in beforeInsert/beforeUpdate survives the strip, and is the recommended shape. To keep writing it CROSS-OBJECT from here, declare runAs: 'system' on this hook: the strip skips a system context, so the write lands, and the triggering user is still stamped on the record. Note that ctx.api.sudo() is NOT an option from a body: sudo() lives on the in-process ScopedContext and is not marshalled into the sandbox, so calling it here is a TypeError at run time. Otherwise drop readonly:true from '${e.field}'.`})):s.readonlyWhen&&!u&&(m.add(c),n.push({severity:`warning`,rule:bs,where:d,path:p,message:`body writes field '${e.field}' through ${l}, and object '${t}' declares it readonlyWhen. On records whose predicate is TRUE that UPDATE strips the field, so this write may silently not land depending on the record's state.`+f.messageSuffix,hint:`Either confirm this call only targets records whose readonlyWhen predicate is FALSE, or derive '${e.field}' in a beforeUpdate hook on '${t}' - a hook-derived value is not caller-supplied and does land, even on a locked record. Elevation is not a workaround here: a system context does not waive the conditional lock (unlike the static readonly strip), so neither runAs: 'system' nor ctx.api.sudo() helps - and sudo() is not marshalled into the sandbox in any case (calling it from a body is a TypeError at run time). Otherwise drop '${e.field}' from this payload. This warning never blocks a build.`})))}}),n}var As=`action-body-write-unknown-field`,js=`action-record-write-discarded`,Ms=`action-body-source-unparseable`,Ns=`action-body-write-unprovisioned-anchor`,Ps=[`api-crud-literal`],Fs=[`record-property-assign`],Is=[{id:`input-property-assign`,reason:"an action's ctx.input is its params bag (`input: unwrapProxyToPlain(actionCtx?.params)`), not a record — `ctx.input.<name>` writes a declared PARAMETER, which object fields cannot judge"},{id:`input-object-assign`,reason:`same surface as input-property-assign — Object.assign(ctx.input, …) targets the params bag`}],Ls=ns.filter(e=>Ps.includes(e.id)),Rs=ns.filter(e=>Fs.includes(e.id)),zs=new Set(Ps),Bs=new Set(Fs),Vs=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Hs(e,t){return typeof e.object==`string`&&e.object?e.object:typeof e.objectName==`string`&&e.objectName?e.objectName:t}function Us(e){let t=[],n=new Set,r=(e,r,i)=>{w(e).forEach((e,a)=>{if((typeof e.type==`string`?e.type:`script`)!==`script`)return;let o=e.body;if(!Vs(o)||o.language!==`js`)return;let s=o.source;if(typeof s!=`string`||s.trim()===``)return;let c=typeof e.name==`string`&&e.name?e.name:`#${a}`,l=`${Hs(e,i)??``}\0${c}\0${s}`;n.has(l)||(n.add(l),t.push({name:c,source:s,path:`${r}[${a}].body.source`}))})};return r(e.actions,`actions`),w(e.objects).forEach((e,t)=>{let n=typeof e.name==`string`&&e.name?e.name:void 0;r(e.actions,`objects[${t}].actions`,n)}),t}function Ws(e){let t=[];if(!Vs(e))return t;let n=Us(e);if(n.length===0)return t;let r=null,i=null;for(let a of n){if(!/\bapi\b/.test(a.source)&&!/\brecord\b/.test(a.source))continue;let{writes:n,ctxRecordEscapes:o,parseFailure:s}=hs(a.source),c=n.filter(e=>zs.has(e.patternId)),l=n.filter(e=>Bs.has(e.patternId)),u=`action "${a.name}" \u203A body`;if(s&&t.push({severity:`warning`,rule:Ms,where:u,path:a.path,message:`L2 body did not parse (${da(s)}), so its write set was read from a partially recovered tree \u2014 an undeclared field write in the unread part is not reported.`,hint:fa}),c.length===0&&l.length===0)continue;if(l.length>0&&!o){let e=new Set;for(let n of l)e.has(n.field)||(e.add(n.field),t.push({severity:`warning`,rule:js,where:u,path:a.path,message:`body assigns ctx.record.${n.field}, but an action's ctx.record is a plain snapshot the runtime never writes back \u2014 the action returns success and the assignment is discarded, whether or not '${n.field}' is a declared field (#4345).`,hint:`To persist it, write through the API: ctx.api.object('<object>').updateById(ctx.recordId, { ${n.field}: \u2026 }). Reported only because ctx.record is never passed anywhere in this body \u2014 mutating the snapshot and then handing it to an API write is a live payload and is not flagged. This warning never blocks a build.`}))}if(c.length===0)continue;r??=fs(e),i??=Rn(e);let d=new Set;for(let e of c){if(e.object===void 0)continue;let n=`${e.object}\0${e.field}`;if(d.has(n))continue;let o=ps(r,e.object);if(o&&!o.has(e.field)){if(cs.has(e.field)){if(!i.get(e.object)?.has(e.field))continue;d.add(n),t.push({severity:`warning`,rule:Ns,where:u,path:a.path,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', and ${zn(e.object,e.field)} \u2014 ${ls()}`,hint:Bn(e.object,e.field)});continue}d.add(n),t.push({severity:`warning`,rule:As,where:u,path:a.path,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', but object '${e.object}' declares no such field. ctx.api is a scoped handle on the running engine, so the payload arrives as an ordinary CALLER write and the declared-field door REFUSES it at run time \u2014 INVALID_FIELD / 400, identically on every driver (#4271), before any statement is built. The write lands nothing, and the refusal escapes the body and fails the action.`,hint:Gs(e.field,[...o])})}}}return t}function Gs(e,t){let n=me(ee(e,[...t,...cs]));return(n?`${n} `:``)+`Fix the field name, or declare '${e}' on the object. Only the literal write patterns in ACTION_BODY_WRITE_PATTERNS are checked \u2014 an action's ctx.input is its params bag, so it is not a record-write surface and is never resolved against fields \u2014 and this warning never blocks a build.`}var Ks=`action-api-update-readonly-when-field`,qs=[`api-crud-literal`],Js=[{id:`record-property-assign`,reason:"an action's ctx.record is a DEAD SNAPSHOT - `buildActionSandboxContext` binds `record: unwrapProxyToPlain(actionCtx?.record)` and `boundActionHandler` returns `result.value` with no write-back (`applyMutationsToInput` is the hook path’s alone), so the assignment never reaches the engine and no readonly strip is ever consulted. A readonly verdict on a write that reaches no write path at all would be a false positive on every occurrence. The shape is not left unreported: `action-record-write-discarded` owns it, and states the true reason (the write is discarded for DECLARED and undeclared fields alike)"},{id:`input-property-assign`,reason:"an action's ctx.input is its PARAMS BAG (`input: unwrapProxyToPlain(actionCtx?.params)`), not a record payload - the names it writes are declared parameters, which object field metadata cannot judge"},{id:`input-object-assign`,reason:`same surface as input-property-assign - Object.assign(ctx.input, ...) targets the params bag`}],Ys=new Set(qs),Xs=new Set([`update`,`updateById`]),Zs=new Set([`update`]),Qs=`id`,$s=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function ec(e){let t=[];if(!$s(e))return t;let n=Us(e);if(n.length===0)return t;let r=null;for(let i of n){if(!/\bapi\b/.test(i.source))continue;let n=hs(i.source);if(n.parseFailure)continue;let a=n.writes.filter(e=>Ys.has(e.patternId)&&typeof e.object==`string`&&e.method!==void 0&&Xs.has(e.method));if(a.length===0)continue;r??=Ko(w(e.objects));let o=`action "${i.name}" > body`,s=new Set;for(let e of a){let n=e.object,a=e.method;if(e.field===Qs&&Zs.has(a))continue;let c=r.get(n);if(!c||c.size===0)continue;let l=c.get(e.field);if(!l||!l.readonlyWhen)continue;let u=`${n} ${e.field}`;if(s.has(u))continue;s.add(u);let d=`ctx.api.object('${n}').${a}(...)`;t.push({severity:`warning`,rule:Ks,where:o,path:i.path,message:`body writes field '${e.field}' through ${d}, and object '${n}' declares it readonlyWhen. An action body runs elevated, which exempts it from the STATIC readonly strip but NOT from the conditional one - on records whose predicate is TRUE that UPDATE still drops the field, so this write may silently not land depending on the record's state.`,hint:`Elevation is not a workaround here: an action body is already system-elevated and the readonlyWhen lock still applies, so ctx.api.sudo() changes nothing. Either confirm this call only targets records whose readonlyWhen predicate is FALSE, or derive '${e.field}' in a beforeUpdate hook on '${n}' (a hook-written value is not caller-supplied and does land, even on a locked record). Otherwise drop '${e.field}' from this payload. This warning never blocks a build.`})}}return t}var tc=`view-container-shape`,nc=[`list`,`form`,`listViews`,`formViews`];function rc(e){return Array.isArray(e)?e.map((e,t)=>({key:`[${t}]`,value:e})):e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({key:`.${e}`,value:t})):[]}function ic(e){let t=e=>e&&typeof e==`object`&&!Array.isArray(e)?Object.keys(e).length:0;return+!!e.list+ +!!e.form+t(e.listViews)+t(e.formViews)}function ac(e){let t=[];if(!e||typeof e!=`object`)return t;let n=e.viewItems;n!=null&&rc(n).length>0&&t.push({severity:`error`,rule:tc,where:`viewItems`,path:`viewItems`,message:"`viewItems` is the machine-assembled channel for non-container view artifacts in runtime-assembled manifests (package export, environment artifacts) — it is not an authoring surface.",hint:"Author views as defineView containers in `views:`; author a standalone view through the metadata door (Studio / `PUT /api/v1/meta/view`), not in stack source."});for(let{key:n,value:r}of rc(e.views)){if(!r||typeof r!=`object`||Array.isArray(r))continue;let e=r;if(e.viewKind!=null){let r=typeof e.name==`string`?` ("${e.name}")`:``;t.push({severity:`error`,rule:tc,where:`views${n}${r}`,path:`views${n}`,message:"A ViewItem record is not a view container: the stack `views:` collection carries containers only — `viewKind` belongs to a single VIEW, not to the container. The registration loop refuses this entry (#5320).",hint:"Wrap it in a defineView container: defineView({ list: { type, data, columns, ... }, listViews: { ... } }) — or author the standalone view through the metadata door (Studio / `PUT /api/v1/meta/view`). Machine-assembled manifests carry it under `viewItems:`."});continue}if(ic(e)>0)continue;let i=typeof e.name==`string`?` ("${e.name}")`:``,a=!nc.some(t=>t in e)&&[`type`,`columns`,`data`,`filter`,`sort`].some(t=>t in e);t.push({severity:`error`,rule:tc,where:`views${n}${i}`,path:`views${n}`,message:a?"Flat list-view object is not a view container: `ViewSchema` strips its keys, so it parses to an EMPTY container — zero views register and the Console renders no view for it.":"View container defines no views — all of `list` / `form` / `listViews` / `formViews` are absent or empty, so nothing registers.",hint:`Wrap every view in a defineView container: defineView({ list: { type, data, columns, ... }, listViews: { ... }, formViews: { ... } }). See examples/app-showcase/src/ui/views/task.view.ts.`})}return t}var oc=`style-node-missing-id`,sc=`style-classname-tailwind`,cc=`style-responsive-no-base`,lc=`style-unknown-css-property`,uc=`style-unknown-token`,dc=[`large`,`medium`,`small`,`xsmall`],fc=new Set(`space-1.space-2.space-3.space-4.space-5.space-6.space-8.space-10.space-12.radius.radius-sm.radius-md.radius-lg.radius-xl.shadow-sm.shadow-md.shadow-lg.surface.surface-sunken.text-strong.text-muted.brand.brand-foreground.hairline.background.foreground.card.card-foreground.popover.popover-foreground.primary.primary-foreground.secondary.secondary-foreground.muted.muted-foreground.accent.accent-foreground.destructive.destructive-foreground.border.input.ring.success.success-foreground.warning.warning-foreground.chart-1.chart-2.chart-3.chart-4.chart-5`.split(`.`)),pc=new Set(`display.position.top.right.bottom.left.inset.zIndex.overflow.overflowX.overflowY.visibility.boxSizing.float.clear.width.height.minWidth.minHeight.maxWidth.maxHeight.aspectRatio.margin.marginTop.marginRight.marginBottom.marginLeft.marginInline.marginBlock.padding.paddingTop.paddingRight.paddingBottom.paddingLeft.paddingInline.paddingBlock.flex.flexDirection.flexWrap.flexGrow.flexShrink.flexBasis.alignItems.alignContent.alignSelf.justifyContent.justifyItems.justifySelf.gap.rowGap.columnGap.order.placeItems.placeContent.grid.gridTemplate.gridTemplateColumns.gridTemplateRows.gridTemplateAreas.gridColumn.gridRow.gridArea.gridAutoFlow.gridAutoColumns.gridAutoRows.color.backgroundColor.background.backgroundImage.backgroundSize.backgroundPosition.backgroundRepeat.backgroundClip.opacity.mixBlendMode.fontSize.fontWeight.fontFamily.fontStyle.lineHeight.letterSpacing.textAlign.textTransform.textDecoration.textOverflow.whiteSpace.wordBreak.overflowWrap.fontVariantNumeric.verticalAlign.textShadow.border.borderTop.borderRight.borderBottom.borderLeft.borderColor.borderWidth.borderStyle.borderRadius.borderTopLeftRadius.borderTopRightRadius.borderBottomLeftRadius.borderBottomRightRadius.outline.outlineOffset.boxShadow.transform.transformOrigin.transition.transitionProperty.transitionDuration.transitionTimingFunction.transitionDelay.animation.filter.backdropFilter.willChange.cursor.pointerEvents.userSelect.objectFit.objectPosition.content`.split(`.`)),mc=/var\(\s*--([a-zA-Z0-9-]+)\s*[,)]/g,hc=/^(sm|md|lg|xl|2xl|hover|focus|active|disabled|dark|group-hover|peer-[a-z]+|first|last|odd|even):/,gc=/^-?(p|m|px|py|pt|pb|pl|pr|mx|my|mt|mb|ml|mr|gap|gap-x|gap-y|space-x|space-y|w|h|min-w|max-w|min-h|max-h|size|text|leading|tracking|bg|border|rounded|shadow|ring|opacity|inset|top|bottom|left|right|z|order|col|row|grid-cols|grid-rows|basis)-(\d+(\.\d+)?|\d+\/\d+|px|full|auto|none|screen|min|max|fit|xs|sm|md|lg|xl|2xl|3xl|4xl|5xl|6xl)$/,_c=/^(flex|grid|block|inline|inline-block|inline-flex|hidden|contents|table|flow-root|grow|shrink|truncate|italic|underline|uppercase|lowercase|capitalize|antialiased|absolute|relative|fixed|sticky|static|isolate|flex-col|flex-row|flex-wrap|flex-nowrap|items-center|items-start|items-end|items-stretch|justify-center|justify-between|justify-around|justify-start|justify-end|text-center|text-left|text-right|font-bold|font-semibold|font-medium|font-normal|tabular-nums)$/;function vc(e){return e.split(/\s+/).some(e=>e?!!(hc.test(e)||/\[[^\]]+\]/.test(e)||gc.test(e)||_c.test(e)):!1)}function yc(e){let t=e.properties??{},n=[];for(let r of[e.children,t.children,e.body,t.body])Array.isArray(r)&&n.push(...r.filter(e=>e&&typeof e==`object`));return n}function bc(e,t,n,r){let i=typeof e.id==`string`?e.id:void 0,a=typeof e.type==`string`?e.type:`node`,o=`page "${t}" \u203A ${i?`node "${i}"`:`<${a}>`}`,s=e.responsiveStyles,c=!!s&&typeof s==`object`&&dc.some(e=>s[e]);if(c&&!i&&r.push({severity:`error`,rule:oc,where:o,path:n,message:"Node has responsiveStyles but no `id`; scoped CSS cannot be generated and the styles are silently dropped.",hint:"Add a stable `id` to this node."}),c&&!s.large&&dc.slice(1).some(e=>s[e])&&r.push({severity:`warning`,rule:cc,where:o,path:n,message:"responsiveStyles sets a smaller breakpoint but no `large` base; the node is unstyled at desktop width.",hint:"Put the unconditional/base styles under `responsiveStyles.large` (desktop-first)."}),typeof e.className==`string`&&e.className.trim()&&vc(e.className)&&r.push({severity:`warning`,rule:sc,where:o,path:n,message:`\`className\` contains Tailwind-looking utilities ("${e.className.trim().slice(0,60)}"); these are not compiled from metadata and will silently do nothing.`,hint:"Style this node with `responsiveStyles` + design tokens instead of `className` (ADR-0065)."}),s&&typeof s==`object`)for(let e of dc){let t=s[e];if(t&&typeof t==`object`){for(let[i,a]of Object.entries(t))if(!i.startsWith(`--`)&&!pc.has(i)&&r.push({severity:`warning`,rule:lc,where:o,path:`${n}.responsiveStyles.${e}`,message:`Unknown CSS property "${i}" (typo?); if unintended it will not apply.`,hint:"Use a camelCase CSS property name (e.g. `flexDirection`, `backgroundColor`)."}),typeof a==`string`){let t;for(mc.lastIndex=0;t=mc.exec(a);){let a=t[1];!fc.has(a)&&!a.startsWith(`tw-`)&&r.push({severity:`warning`,rule:uc,where:o,path:`${n}.responsiveStyles.${e}.${i}`,message:`References unknown design token \`var(--${a})\` (typo?); it will not resolve.`,hint:"Use a token from the ADR-0065 palette (e.g. `var(--space-6)`, `var(--surface)`, `hsl(var(--primary))`)."})}}}}let l=yc(e);for(let e=0;e<l.length;e++)bc(l[e],t,`${n}.children[${e}]`,r)}function xc(e){let t=[],n=w(e.pages);for(let e=0;e<n.length;e++){let r=n[e],i=typeof r.name==`string`?r.name:`pages[${e}]`,a=w(r.regions);for(let n=0;n<a.length;n++){let r=w(a[n].components);for(let a=0;a<r.length;a++)bc(r[a],i,`pages[${e}].regions[${n}].components[${a}]`,t)}}return t}function Sc(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function O(e,t){if(Array.isArray(e)){let n=[];for(let r=0;r<e.length;r++)Sc(e[r])&&n.push({rec:e[r],path:`${t}[${r}]`});return n}return Sc(e)?Object.entries(e).filter(([,e])=>Sc(e)).map(([e,n])=>({rec:{name:e,...n},path:`${t}.${e}`})):[]}function Cc(e,t={}){let n=[];for(let{rec:r,path:i}of O(e.pages,`pages`)){if(!r||r.kind!==`html`&&r.kind!==`jsx`)continue;let e=String(r.name??i),a=r.source;if(typeof a!=`string`||a.trim()===``){n.push({severity:`error`,rule:`jsx-page-empty-source`,where:`page "${e}"`,path:`${i}.source`,message:`kind:'${r.kind}' page has no \`source\`.`,hint:"Author the page as a constrained JSX/Tailwind string in `source`."});continue}let{diagnostics:o}=t.manifest?Mn(a,t.manifest):Qt(a);for(let t of o)n.push({severity:t.severity,rule:`jsx-${t.code}`,where:t.tag?`page "${e}" \u203A <${t.tag}>`:`page "${e}"`,path:`${i}.source`,message:t.message,hint:`The source is parsed (never executed) and compiled to the SDUI tree at save time — fix the JSX.`})}return n}var wc=null;function Tc(){if(wc)return wc;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{wc=(0,S.createRequire)(e)(`sucrase`).transform}catch(e){throw Error(`@objectstack/lint: validating a kind:'react' page requires the "sucrase" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "sucrase" in the image; it is only loaded when a react-source page is validated.`)}return wc}function Ec(e){let t=[];for(let{rec:n,path:r}of O(e.pages,`pages`)){if(!n||n.kind!==`react`)continue;let e=String(n.name??r),i=n.source;if(typeof i!=`string`||i.trim()===``){t.push({severity:`error`,rule:`react-page-empty-source`,where:`page "${e}"`,path:`${r}.source`,message:"kind:'react' page has no `source`.",hint:"Author the page as a real React component string in `source`."});continue}let a=Tc();try{a(i,{transforms:[`jsx`,`typescript`],production:!0})}catch(n){let i=n instanceof Error?n.message:String(n);t.push({severity:`error`,rule:`react-page-syntax`,where:`page "${e}"`,path:`${r}.source`,message:`kind:'react' source has a syntax error: ${i.split(`
5
+ `)[0]}`,hint:`The source is transpiled (never executed) at build to catch syntax errors early — fix the JS/JSX.`})}}return t}var Dc=`searchable-field-unknown`,Oc=`searchable-field-unsearchable`,kc=`searchable-field-unprovisioned`;function k(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Ac(e){return typeof e==`string`&&e.length>0?e:void 0}function jc(e){let t=e.fields;if(!t||typeof t!=`object`)return null;let n=new Set,r={};for(let e of w(t)){let t=Ac(e.name);t&&(n.add(t),r[t]={type:typeof e.type==`string`?e.type:void 0,hidden:e.hidden===!0})}return n.size===0?null:{names:n,fields:r,searchableFields:Array.isArray(e.searchableFields)?e.searchableFields.filter(e=>typeof e==`string`):void 0,displayField:Ac(e.nameField)??Ac(e.displayNameField)}}function Mc(e){let t=e.fields,n=(e.searchableFields??[]).filter(t=>!e.names.has(t)&&Nn.has(t));if(n.length>0){t={...t};for(let e of n)t[e]={}}let{allowed:r,source:i}=Ae({fields:t,searchableFields:e.searchableFields,displayField:e.displayField});return{allowed:new Set(r),source:i,declaredList:r}}function Nc(e){let t=new Map;if(!k(e))return t;for(let n of w(e.objects)){let e=Ac(n.name);e&&t.set(e,jc(n))}return t}function Pc(e,t,n,r,i,a,o=`narrowing`,s){let c=[];if(!Array.isArray(e)||e.length===0||!t||!n.has(t))return c;let l=n.get(t);if(!l)return c;let u=l.names,d=s?.get(t),f=o===`narrowing`?Mc(l):void 0;for(let n=0;n<e.length;n++){let s=e[n],p=Ac(s);if(!p)continue;if(!u.has(p)&&!Nn.has(p)){let e=p.includes(`.`);c.push({severity:`error`,rule:Dc,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" is not a field on object "${t}". The declaration is stale: searching it can never match, and the engine silently drops it \u2014 leaving a narrower search than declared, or the auto-default set once every entry is dropped.`+(e?``:E(p,u)),hint:(e?`'search' scans this object's own columns, so a related record's column cannot be a search target — expand the relation and search the related object, or copy the value onto a stored text field here. `:`Fix the name, or add "${p}" to ${t}.fields. `)+`Clients echo this declaration verbatim as the '$searchFields' override, so a stale entry becomes a 400 INVALID_FIELD on list search (#4254), not just a quietly narrowed one.`+(u.size>0?` Object fields: ${[...u].sort().join(`, `)}.`:``)});continue}if(d?.has(p)&&c.push({severity:`warning`,rule:kc,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" resolves on object "${t}", but ${zn(t,p)}`+(o===`narrowing`?` — clients echo this declaration verbatim as the '$searchFields' override, so every toolbar search on this list scans a column that is empty on every record: it reads as search coverage and matches nothing.`:` — 'search' scans it on every record and it can never match, so the object's searchable set is narrower than it declares. Should it be the ONLY entry that resolves, the set scans nothing at all.`),hint:Bn(t,p)}),h(l.fields[p])){let e=l.fields[p]?.type;c.push({severity:`error`,rule:Oc,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" on object "${t}" is a virtual '${e}' field: its value is computed on read and never stored, so no driver materializes a column for 'search' to scan and the entry can never match. It reads as search coverage and delivers none \u2014 the runtime used to admit it verbatim because the declaration named it (#6674).`,hint:`Mirror the computed value onto a stored text field on "${t}" and declare that instead, or drop "${p}". At runtime the ingress gate now refuses this entry with 400 INVALID_FIELD, the same answer a stale entry gets (#4254).`});continue}if(!f||f.allowed.has(p)||!u.has(p))continue;let m=l.fields[p];if(f.source===`declared`){c.push({severity:`error`,rule:Oc,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" is outside object "${t}"'s declared searchableFields (${f.declaredList.join(`, `)}) \u2014 the set 'search' scans. Clients echo this declaration verbatim as the '$searchFields' override, and the runtime refuses an entry outside the allowed set: every toolbar search on this list returns 400 INVALID_FIELD (#4254).`,hint:`Add "${p}" to ${t}.searchableFields, or drop it from this view \u2014 a view narrows the object's searchable set, never widens it (ADR-0061).`});continue}let g=m?.type===`lookup`||m?.type===`master_detail`,_;if(pe.has(p))_=`a system/audit column, which the auto-default set never includes`;else if(m?.hidden)_=`hidden`;else if(typeof m?.type==`string`)_=`of type '${m.type}', which 'search' cannot scan`;else continue;c.push({severity:`error`,rule:Oc,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" on object "${t}" is ${_}. With no 'searchableFields' declared on the object, 'search' scans its text-like columns (${[...Me,...Ee].join(` / `)}). Clients echo this declaration verbatim as the '$searchFields' override, and the runtime refuses it: every toolbar search on this list returns 400 INVALID_FIELD (#4254).`,hint:(g?`A ${m?.type} column stores only the referenced record's id, so it cannot be a keyword target \u2014 drop "${p}" from this view and, to search by the related record's title, mirror it onto a stored text field here and declare that instead. `:`Drop "${p}" from this view, or target a text-like field instead. `)+`Declaring 'searchableFields' on object "${t}" chooses the searchable set explicitly.`})}return c}function Fc(e){let t=[];if(!k(e))return t;let n=w(e.objects),r=Nc(e),i=Rn(e),a=(e,n,a,o,s,c)=>{t.push(...Pc(e,n,r,a,o,s,c,i))};for(let e=0;e<n.length;e++){let t=n[e];if(!k(t))continue;let r=Ac(t.name),i=r?`object "${r}"`:`objects[${e}]`;if(a(t.searchableFields,r,i,`objects[${e}].searchableFields`,`searchableFields`,`canonical`),k(t.listViews))for(let[n,o]of Object.entries(t.listViews))k(o)&&a(o.searchableFields,Ic(o)??r,`${i} \u203A listViews.${n}`,`objects[${e}].listViews.${n}.searchableFields`,`list-view searchableFields`,`narrowing`)}let o=w(e.views);for(let e=0;e<o.length;e++){let t=o[e];if(!k(t))continue;let n=Ac(t.name)??Ac(t.objectName)??`#${e}`,r=Ac(t.objectName)??Ac(t.object);if(t.viewKind===`list`&&!k(t.config)&&a(t.searchableFields,Ic(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}].searchableFields`,`list-view searchableFields`,`narrowing`),t.viewKind===`list`&&k(t.config)&&a(t.config.searchableFields,Ic(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config.searchableFields`,`list-view searchableFields`,`narrowing`),k(t.list)&&a(t.list.searchableFields,Ic(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list.searchableFields`,`list-view searchableFields`,`narrowing`),k(t.listViews))for(let[i,o]of Object.entries(t.listViews))k(o)&&a(o.searchableFields,Ic(o)??r,`view "${n}" \u203A listViews.${i}`,`views[${e}].listViews.${i}.searchableFields`,`list-view searchableFields`,`narrowing`)}return t}function Ic(e){let t=e.data;return k(t)?Ac(t.object):void 0}function Lc(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Rc(e){return typeof e==`string`&&e.length>0?e:void 0}var zc=new Set([`html`,`react`,`jsx`]);function Bc(e){let t=Rc(e.kind);return t!==void 0&&zc.has(t)}function Vc(e,t){let n=[];if(!Lc(e)||Bc(e))return n;let r=Rc(e.object),i=fe().filter(e=>!e.retired),a=new Set,o=(e,t,r)=>{if(!Lc(e)||a.has(e))return;let s=Lc(e.properties)?e.properties:void 0,c=Rc((Lc(e.dataSource)?e.dataSource:void 0)?.object)??Rc(s?.object)??r;if(n.push({component:e,path:t,objectName:c}),s){a.add(e);try{for(let{key:e,panelKey:n}of i){let r=s[e];if(Array.isArray(r)){if(n===void 0){for(let n=0;n<r.length;n++)o(r[n],`${t}.properties.${e}[${n}]`,c);continue}for(let i=0;i<r.length;i++){let a=r[i];if(!Lc(a))continue;let s=a[n];if(Array.isArray(s))for(let r=0;r<s.length;r++)o(s[r],`${t}.properties.${e}[${i}].${n}[${r}]`,c)}}}}finally{a.delete(e)}}},s=Array.isArray(e.regions)?e.regions:[];for(let e=0;e<s.length;e++){let n=s[e];if(Lc(n)&&Array.isArray(n.components))for(let i=0;i<n.components.length;i++)o(n.components[i],`${t}.regions[${e}].components[${i}]`,r)}let c=Lc(e.slots)?e.slots:void 0;if(c)for(let[e,n]of Object.entries(c)){let i=Array.isArray(n)?n:[n],a=Array.isArray(n);for(let n=0;n<i.length;n++)o(i[n],`${t}.slots.${e}${a?`[${n}]`:``}`,r)}return n}function Hc(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Uc(e){return typeof e==`string`&&e.length>0?e:void 0}function Wc(e){let t=new Map;if(!Hc(e))return t;for(let n of w(e.objects)){let e=Uc(n.name);if(!e)continue;let r=new Set;for(let e of w(n.fieldGroups)){let t=Uc(e.key)??Uc(e.name);t&&r.add(t)}t.set(e,r)}return t}function Gc(e,t,n=`.`){if(!Array.isArray(e))return[];let r=[];for(let i=0;i<e.length;i++){let a=e[i];if(!Hc(a))continue;let o=Uc(a.group);o&&r.push({key:o,path:`${t}[${i}]${n}group`})}return r}function Kc(e,t,n,r,i){let a=[];if(!t)return a;let o=n.get(t);if(!o)return a;for(let n of e)o.has(n.key)||a.push({severity:`warning`,rule:i,where:r,path:n.path,message:`section references field group "${n.key}", which object "${t}" does not declare \u2014 the section inherits its members from that group, so it resolves to no fields and the whole section silently does not render`,hint:`Fix the key, or declare it: \`fieldGroups: [{ key: '${n.key}', label: '\u2026' }]\` on ${t}, with each member field carrying \`group: '${n.key}'\`. `+(o.size>0?`Declared groups on ${t}: ${[...o].sort().join(`, `)}.`:`${t} declares no field groups at all, so no section on it can reference one yet \u2014 enumerate the members with \`fields\` until it does.`)});return a}var qc=`page-field-unknown`,Jc=`page-field-unprovisioned`,Yc=`page-section-group-unknown`;function A(e){return typeof e==`string`&&e.length>0?e:void 0}function Xc(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function j(e,t){let n=[],r=(e,t)=>{let r=A(e);if(r){n.push({name:r,path:t});return}if(!Xc(e))return;let i=A(e.field)??A(e.name);i&&n.push({name:i,path:`${t}.${A(e.field)?`field`:`name`}`})};if(Array.isArray(e))for(let n=0;n<e.length;n++)r(e[n],`${t}[${n}]`);else r(e,t);return n}function Zc(e,t){if(typeof e==`string`){let n=e.trim().split(/\s+/)[0];return n?[{name:n,path:t}]:[]}return j(e,t)}var Qc={"record:highlights":{props:[`fields`]},"record:details":{props:[`fields`,`hideFields`],nestedSections:[`sections`]},"record:path":{props:[`statusField`]},"element:number":{props:[`field`]},"element:record_picker":{props:[`labelField`]}},$c=`record:related_list`;function el(e,t,n,r=`.`){let i=Qc[e];if(!i)return null;let a=[];for(let e of i.props??[])a.push(...j(t[e],`${n}${r}${e}`));for(let e of i.nestedSections??[]){let i=Array.isArray(t[e])?t[e]:[];for(let t=0;t<i.length;t++){let o=i[t];Xc(o)&&a.push(...j(o.fields,`${n}${r}${e}[${t}].fields`))}}return a}function tl(e,t,n,r=`.`){let i=Qc[e];if(!i)return null;let a=[];for(let e of i.nestedSections??[])a.push(...Gc(t[e],`${n}${r}${e}`,r));return a}function nl(e,t,n=`.`){let r=Xc(e.add)?e.add:void 0,i=r&&Xc(r.picker)?r.picker:void 0,a=e=>`${t}${n}${e}`;return{relatedObject:A(e.objectName),related:[...j(e.columns,a(`columns`)),...Zc(e.sort,a(`sort`)),...j(e.filter,a(`filter`)),...j(e.relationshipField,a(`relationshipField`)),...r?j(r.linkField,a(`add.linkField`)):[]],parent:j(e.relationshipValueField,a(`relationshipValueField`)),pickerObject:i?A(i.object):void 0,picker:i?[...j(i.valueField,a(`add.picker.valueField`)),...j(i.labelField,a(`add.picker.labelField`))]:[]}}function rl(e){let t=new Map;if(!Xc(e))return t;for(let n of w(e.objects)){let e=A(n.name);if(!e)continue;let r=new Set;for(let e of w(n.fields)){let t=A(e.name);t&&r.add(t)}t.set(e,r)}return t}function il(e,t,n,r,i=`skipped`,a){let o=[];if(!t)return o;let s=n.get(t);if(!s)return o;let c=a?.get(t);for(let n of e)if(!n.name.includes(`.`)){if(s.has(n.name)||Nn.has(n.name)){c?.has(n.name)&&o.push({severity:`warning`,rule:Jc,where:r,path:n.path,message:`field "${n.name}" resolves on object "${t}", but ${zn(t,n.name)}`+(i===`queried`?` — it is used in a QUERY, so the predicate can never match a real value: on SQLite it silently degrades to constant-false and the surface renders an empty result that looks exactly like "there is no data".`:` — the component renders it, blank, on every record.`),hint:Bn(t,n.name)});continue}o.push({severity:i===`queried`?`error`:`warning`,rule:qc,where:r,path:n.path,message:`field "${n.name}" is not a field on object "${t}" \u2014 `+(i===`queried`?`it is used in a QUERY, so the predicate can never match: the surface renders an empty result that looks exactly like "there is no data".`:`the component silently skips it, so it never renders.`),hint:`Fix the field name, or add "${n.name}" to ${t}. References must match the object's field names exactly.`+(s.size>0?` Object fields: ${[...s].sort().join(`, `)}.`:``)})}return o}function al(e){let t=[];if(!e||typeof e!=`object`)return t;let n=rl(e),r=Rn(e),i=Wc(e),a=w(e.pages);for(let e=0;e<a.length;e++){let o=a[e];if(!o||typeof o!=`object`)continue;let s=A(o.name)??`#${e}`,c=(e,i,a)=>{t.push(...il(e,i,n,a,`skipped`,r))};for(let{component:n,path:r,objectName:a}of Vc(o,`pages[${e}]`)){let e=A(n.type),o=Xc(n.properties)?n.properties:void 0;if(!e||!o)continue;let l=`page "${s}" \xB7 ${e}`,u=`${r}.properties`;if(e===$c){let e=nl(o,u);c(e.related,e.relatedObject,l),c(e.parent,a,l),c(e.picker,e.pickerObject,l);continue}let d=el(e,o,u);d&&(c(d,a,l),t.push(...Kc(tl(e,o,u)??[],a,i,l,Yc)))}let l=Xc(o.interfaceConfig)?o.interfaceConfig:void 0;if(l){let t=A(l.source)??A(o.object),n=`pages[${e}].interfaceConfig`,r=[...j(l.columns,`${n}.columns`),...Zc(l.sort,`${n}.sort`),...j(l.filterBy,`${n}.filterBy`)],i=Xc(l.userFilters)?l.userFilters:void 0;i&&r.push(...j(i.fields,`${n}.userFilters.fields`)),c(r,t,`page "${s}" \xB7 interfaceConfig`)}}return t}var ol=e=>!!e&&typeof e==`object`&&!Array.isArray(e),sl=(e,t)=>{let n=e;for(let e of t){if(!ol(n)&&!Array.isArray(n))return;n=n[e]}return n},cl=e=>{let t;try{t=JSON.stringify(e)??String(e)}catch{t=String(e)}return t.length>80?`${t.slice(0,77)}\u2026`:t};function ll(e,t,n=0){let r=n===0?sl(t,e.path):void 0,i=n>0||e.code===`custom`||e.message.includes(`received `)?``:r===void 0?` (nothing is set there)`:` (received ${cl(r)})`,a=e.code===`invalid_union`?e.errors:void 0;if(!a||a.length===0)return`${e.message}${i}`;let o=a.map(e=>e.map(e=>`${e.path.length?`${e.path.join(`.`)} \u2014 `:``}${ll(e,t,n+1)}`).join(`; `)).filter(e=>e.length>0);return o.length===0?`${e.message}${i}`:`${e.message}${i} \u2014 no accepted form matched: `+o.map((e,t)=>`(${t+1}) ${e}`).join(` `)}var ul=null;function dl(){if(ul)return ul;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{ul=(0,S.createRequire)(e)(`typescript`)}catch(e){throw Error(`@objectstack/lint: validating a kind:'react' page requires the "typescript" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "typescript" in the image; it is only loaded when a react-source page is validated.`)}return ul}var fl=new Map(Ot.map(e=>[e.tag,{requiredBindings:e.interactions.filter(e=>e.required).map(e=>e.name),knownProps:new Set(e.interactions.map(e=>e.name)),deprecated:new Map(e.interactions.filter(e=>e.deprecated).map(e=>[e.name,e.deprecated])),retired:new Map(Object.entries(Le[e.tag]??{})),requiredDescriptions:new Map(e.interactions.filter(e=>e.required).map(e=>[e.name,e.description]))}]));function pl(e,t,n=2){if(Math.abs(e.length-t.length)>n)return n+1;let r=Array.from({length:e.length+1},(e,t)=>t);for(let n=1;n<=t.length;n++){let i=r[0];r[0]=n;for(let a=1;a<=e.length;a++){let o=r[a];r[a]=Math.min(r[a]+1,r[a-1]+1,i+(e[a-1]===t[n-1]?0:1)),i=o}}return r[e.length]}function ml(e,t){if(t.has(e))return null;let n=null,r=3;for(let i of t){let t=pl(e,i);t<r&&(r=t,n=i)}return r<=2?n:null}var M=Symbol(`not-static`);function hl(e,t,n){if(!n)return M;if(e.isParenthesizedExpression(n))return hl(e,t,n.expression);if(e.isStringLiteral(n)||e.isNoSubstitutionTemplateLiteral(n))return n.text;if(e.isNumericLiteral(n))return Number(n.text);if(n.kind===e.SyntaxKind.TrueKeyword)return!0;if(n.kind===e.SyntaxKind.FalseKeyword)return!1;if(n.kind===e.SyntaxKind.NullKeyword)return null;if(e.isArrayLiteralExpression(n)){let r=[];for(let i of n.elements){let n=hl(e,t,i);if(n===M)return M;r.push(n)}return r}if(e.isObjectLiteralExpression(n)){let r={};for(let i of n.properties){if(!e.isPropertyAssignment(i))return M;let n=e.isIdentifier(i.name)||e.isStringLiteral(i.name)?i.name.text:null;if(n===null)return M;let a=hl(e,t,i.initializer);if(a===M)return M;r[n]=a}return r}return M}function gl(e,t,n){let r=n.initializer;return r?e.isStringLiteral(r)?r.text:e.isJsxExpression(r)?hl(e,t,r.expression):M:!0}function _l(e,t,n){let r=n.initializer;if(!r||!e.isJsxExpression(r))return M;let i=n=>n?e.isParenthesizedExpression(n)?i(n.expression):e.isArrayLiteralExpression(n)?n.elements.map(e=>i(e)):hl(e,t,n):M;return i(r.expression)}var vl=`react-page-source-unparseable`,yl=`react-prop-deprecated`,bl=`react-prop-retired`,xl=`react-chart-field-unknown`,Sl=`react-chart-field-unprovisioned`,Cl=`react-chart-aggregate-invalid`,wl=`react-chart-axis-unknown`,Tl=`react-chart-drilldown-invalid`;function El(e,t){if(e===void 0||e===M)return;if(!N(e)){t(`error`,Tl,`drillDown must be a configuration object, not ${Array.isArray(e)?`an array`:typeof e}.`,`Write drillDown={{ … }} — or, to turn the drill on with all defaults, drillDown={{}}. Omit the prop entirely to leave drill off.`);return}let n=rt.safeParse(e);if(!n.success)for(let e of n.error.issues)t(`error`,Tl,`${e.path.length?`drillDown.${e.path.join(`.`)}`:`drillDown`}: ${e.message}`,`The drill config is declared by ChartDrillDownSchema (@objectstack/spec/ui) — the rejection above carries the fix.`)}function Dl(e,t){if(e===void 0||e===M)return;if(!N(e)){t(`error`,Cl,`aggregate must be a configuration object, not ${Array.isArray(e)?`an array`:typeof e}.`,`Write aggregate={{ function: "count", groupBy: "<field>" }} — or bind data={…} instead to chart precomputed rows.`);return}let n=e.groupBy===void 0;n&&t(`warning`,Cl,`aggregate.groupBy is not set, so the aggregate returns ONE ungrouped row and the chart plots a single point.`,`Add aggregate.groupBy (a field name, or { field, dateGranularity } to bucket dates) to give the chart a category axis. objectstack#5583 ruled that an ungrouped single-value chart is NOT a supported <ObjectChart> shape — groupBy stays required, and a single number belongs in an object-metric block instead. This stays a warning rather than an error only because promoting it is its own step.`);let r=wt.safeParse(e);if(!r.success)for(let i of r.error.issues)n&&i.path[0]===`groupBy`||t(`error`,Cl,`${i.path.length?`aggregate.${i.path.join(`.`)}`:`aggregate`}: ${ll(i,e)}`,`The aggregate is declared by ChartAggregateSchema (@objectstack/spec/ui) — the rejection above carries the fix.`)}var N=e=>!!e&&typeof e==`object`&&!Array.isArray(e),P=e=>typeof e==`string`&&e.length>0?e:void 0;function Ol(e,t,n,r=new Map){let{values:i,where:a,path:o}=e,s=(e,t,r,i)=>n.push({severity:e,rule:t,where:a,path:o,message:r,hint:i});if(El(i.get(`drillDown`),s),i.has(`data`))return;let c=i.get(`aggregate`);if(Dl(c,s),c===void 0||c===M||!N(c))return;let l=P(c.function),u=P(c.field),d=c.groupBy,f=P(d)??(N(d)?P(d.field):void 0),p=P(i.get(`objectName`)),m=p?t.get(p):void 0;if(p&&m){let e=r.get(p),t=(t,n)=>{if(t&&!t.includes(`.`)){if(m.has(t)||Nn.has(t)){e?.has(t)&&s(`warning`,Sl,`aggregate.${n} "${t}" resolves on object "${p}", but ${zn(p,t)} \u2014 the aggregate query reads a column that is empty on every row, so the chart ${n===`groupBy`?`groups everything into one empty bucket`:`aggregates nothing`} instead of failing.`,Bn(p,t));return}s(`error`,xl,`aggregate.${n} "${t}" is not a field on object "${p}" \u2014 the aggregate query has nothing to ${n===`groupBy`?`group by`:`aggregate`}, so the chart comes back empty.`,`Fix the field name, or add "${t}" to ${p}.`+(m.size>0?` Object fields: ${[...m].sort().join(`, `)}.`:``))}};t(u,`field`),t(f,`groupBy`)}let h=x({field:u,function:l,groupBy:d}),g=[h.category,h.value].filter(e=>!!e);if(g.length===0)return;let _=(e,t)=>{e&&(g.includes(e)||h.comparison&&e===h.comparison||s(`error`,wl,`"${e}" is not a column this aggregate returns, so the axis plots nothing. Object-bound aggregate rows are keyed by the RAW FIELD NAMES (unlike a dataset, whose rows are keyed by measure name).`,`Result columns: ${g.join(`, `)}`+(h.comparison?` (plus "${h.comparison}" with a comparison overlay)`:``)+`. Bind ${t} to one of them.`))},v=i.get(`xAxis`),y=P(i.get(`xAxisKey`))??P(v)??(N(v)?P(v.field):void 0),b=i.has(`xAxisKey`)?`xAxisKey`:`xAxis.field`;_(y,b);let ee=i.get(`yAxis`),te=Array.isArray(ee)?ee:ee===void 0?[]:[ee];for(let e of te)_(P(e)??(N(e)?P(e.field):void 0),`yAxis[].field`);let ne=i.get(`series`);if(Array.isArray(ne))for(let e of ne){if(!N(e))continue;let t=P(e.dataKey);_(t??P(e.name),t?`series[].dataKey`:`series[].name`)}y&&h.category&&y!==h.category&&y===h.value&&s(`error`,wl,`${b} "${y}" is the aggregate's VALUE column, not its category column.`,`The category axis is keyed by groupBy \u2014 bind it to "${h.category}".`)}var kl={ListView:{fields:[`fields`,`columns`,`hiddenFields`,`fieldOrder`,`filterableFields`],sorts:[`sort`],nestedFields:[`userFilters`,`grouping`],filterArrays:[`filters`]},ObjectForm:{fields:[`fields`],keyedByField:[`initialValues`],sections:[`sections`,`groups`]},ObjectChart:{filterArrays:[`filter`]}},Al=` › `,jl=new Map(Ot.map(e=>[e.tag,e.schemaType])),Ml=new Set(Object.values(kl).flatMap(e=>e.filterArrays??[]));function Nl(e){let t={};for(let[n,r]of e)r!==M&&(t[n]=r);return t}function Pl(e,t){let n=[],r=[];if(!Array.isArray(e))return{child:n,parent:r};for(let i=0;i<e.length;i++){let a=e[i];if(!N(a))continue;let o=e=>`${t}[${i}].${e}`;n.push({objectName:P(a.childObject),refs:[...j(a.columns,o(`columns`)),...j(a.relationshipField,o(`relationshipField`)),...j(a.amountField,o(`amountField`))]}),r.push(...j(a.totalField,o(`totalField`)))}return{child:n,parent:r}}function Fl(e,t,n){if(!Array.isArray(e)||e.length===0)return;let r=e[0];if(typeof r==`string`&&(r.toLowerCase()===`and`||r.toLowerCase()===`or`)){for(let r=1;r<e.length;r++)Fl(e[r],`${t}[${r}]`,n);return}if(Array.isArray(r)){for(let r=0;r<e.length;r++)Fl(e[r],`${t}[${r}]`,n);return}typeof r==`string`&&r.length>0&&e.length>=2&&typeof e[1]==`string`&&vt.has(e[1].toLowerCase())&&n.push({name:r,path:`${t}[0]`})}function Il(e,t,n){let r=[],i=[],a=e=>{let n=t.get(e);return n===M?void 0:n},o=e=>`${n}${Al}${e}`;for(let t of e.fields??[])r.push(...j(a(t),o(t)));for(let t of e.sorts??[])r.push(...Zc(a(t),o(t)));for(let t of e.nestedFields??[]){let e=a(t);N(e)&&r.push(...j(e.fields,o(`${t}.fields`)))}for(let t of e.sections??[]){let e=a(t);if(Array.isArray(e))for(let n=0;n<e.length;n++){let i=e[n];N(i)&&r.push(...j(i.fields,o(`${t}[${n}].fields`)))}}for(let t of e.keyedByField??[]){let e=a(t);if(N(e))for(let n of Object.keys(e))r.push({name:n,path:o(`${t}.${n}`)})}for(let n of e.filterArrays??[])Fl(t.get(n),o(n),i);return{own:r,queried:i}}function Ll(e,t){if(e!==`ListView`)return P(t.get(`objectName`));let n=t.get(`data`);return N(n)&&n.provider===`object`?P(n.object):void 0}function Rl(e,t,n,r,i,a){let o=Ll(e,t),s=[],c=kl[e];if(c){let{own:e,queried:l}=Il(c,t,i);s.push(...il(e,o,n,r,`skipped`,a)),s.push(...il(l,o,n,r,`queried`,a))}if(e===`ObjectForm`){let e=t.get(`subforms`),c=Pl(e===M?void 0:e,`${i}${Al}subforms`);for(let e of c.child)s.push(...il(e.refs,e.objectName,n,r,`skipped`,a));s.push(...il(c.parent,o,n,r,`skipped`,a))}let l=e===`Block`?P(t.get(`type`)):jl.get(e);return l&&Qc[l]&&s.push(...il(el(l,Nl(t),i,Al)??[],o,n,r,`skipped`,a)),s}var zl=`react-block-needs-record-context`,Bl="author the page as `type:'record'` — a record page mounts the record context these blocks render from.";function Vl(e,t,n,r){return{severity:`error`,rule:zl,where:n,path:r,message:`<${e}> renders "${t}", which reads its record from the record context a record page mounts \u2014 a kind:'react' page never mounts one, so the block renders empty no matter how it is bound (its objectName/recordId are not read by the renderer).`,hint:`On a react page bind the record yourself: ${st[t]??Bl}`}}function Hl(e,t){let n=new Set,r=t=>{(e.isFunctionDeclaration(t)&&t.name||e.isVariableDeclaration(t)&&e.isIdentifier(t.name)||e.isImportSpecifier(t))&&n.add(t.name.text),e.forEachChild(t,r)};return r(t),n}function Ul(e){let t=[],n=rl(e),r=Rn(e),i=Nc(e);for(let{rec:a,path:o}of O(e.pages,`pages`)){if(!a||a.kind!==`react`)continue;let e=a.source;if(typeof e!=`string`||e.trim()===``)continue;let s=String(a.name??o),c=dl(),{sourceFile:l,failure:u}=ua(c,`page.tsx`,e,{target:c.ScriptTarget.Latest,setParentNodes:!0,scriptKind:c.ScriptKind.TSX});u&&t.push({severity:`warning`,rule:vl,where:`page "${s}"`,path:`${o}.source`,message:`kind:'react' source did not parse (${da(u)}), so the component-contract checks read a partially recovered tree and may have missed real problems.`,hint:fa});let d=Hl(c,l),f=e=>{if(c.isJsxOpeningElement(e)||c.isJsxSelfClosingElement(e)){let a=e.tagName.getText(l),u=`page "${s}" \u203A <${a}>`,p=`${o}.source`,m=yt.get(a);if(m&&!d.has(a)){t.push(Vl(a,m,u,p)),c.forEachChild(e,f);return}let h=fl.get(a);if(h){let o=!1,s=new Set,d=new Map;for(let t of e.attributes.properties){if(c.isJsxSpreadAttribute(t)){o=!0;continue}if(c.isJsxAttribute(t)){let e=t.name.getText(l);s.add(e),d.set(e,Ml.has(e)?_l(c,l,t):gl(c,l,t))}}if(a===`Block`){let n=P(d.get(`type`));if(n&&we(n)){t.push(Vl(a,n,u,p)),c.forEachChild(e,f);return}}if(!o)for(let e of h.requiredBindings){if(s.has(e))continue;let n=h.deprecated.get(e);n&&s.has(n.replacedBy)||[...s].some(t=>h.retired.get(t)?.replacedBy===e)||t.push({severity:`error`,rule:`react-prop-missing-required`,where:u,path:p,message:n?`<${a}> is missing its "${e}" binding \u2014 pass ${n.replacedBy}={\u2026} (canonical) or ${e}={\u2026} (deprecated).`:`<${a}> is missing the required prop "${e}".`,hint:n?n.note:h.requiredDescriptions.get(e)??`Pass ${e}={\u2026}. See the react-tier component contract.`})}for(let e of s){let n=h.retired.get(e);if(n){t.push({severity:`error`,rule:bl,where:u,path:p,message:`<${a}> prop "${e}" is retired \u2014 the contract's only spelling is "${n.replacedBy}".`,hint:n.note});continue}let r=h.deprecated.get(e);r&&t.push({severity:`warning`,rule:yl,where:u,path:p,message:`<${a}> prop "${e}" is the deprecated spelling of the metadata-tier "${r.replacedBy}": the react tier converges on the metadata-tier vocabulary, so this spelling keeps working through the deprecation window and is removed after it.`,hint:r.note});let i=ml(e,h.knownProps);i&&t.push({severity:`warning`,rule:`react-prop-typo`,where:u,path:p,message:`<${a}> has prop "${e}" \u2014 did you mean "${i}"?`,hint:`Likely a typo of a contract prop. Fix it or remove it.`})}a===`ObjectChart`&&!o&&Ol({values:d,where:u,path:p},n,t,r),a===`ListView`&&!o&&t.push(...Pc(d.get(`searchableFields`),Ll(a,d),i,u,`${p} \u203A searchableFields`,`searchableFields`,`narrowing`,r)),o||t.push(...Rl(a,d,n,u,p,r))}}c.forEachChild(e,f)};f(l)}return t}var Wl=`page-source-className-tailwind`,Gl=/\bclassName\s*=\s*["'{]/g;function Kl(e){let t=[];for(let{rec:n,path:r}of O(e.pages,`pages`)){if(!n)continue;let e=n.kind;if(e!==`html`&&e!==`react`&&e!==`jsx`)continue;let i=n.source;if(typeof i!=`string`||i.trim()===``)continue;let a=String(n.name??r);Gl.lastIndex=0;let o=0;for(;Gl.exec(i)!==null;)o++;o!==0&&t.push({severity:`warning`,rule:Wl,where:`page "${a}"`,path:`${r}.source`,message:`${o} \`className\` attribute${o>1?`s`:``} in ${String(e)}-source page \u2014 Tailwind utilities in page source silently produce no CSS (the build never scans authored metadata; ADR-0065).`,hint:e===`react`?`Style with inline style={{}} using hsl(var(--token)) theme colors (e.g. color:'hsl(var(--foreground))', background:'hsl(var(--card))'); render drawer/modal via <ObjectForm formType="drawer"|"modal"> instead of hand-rolled overlays.`:`Lay out with the components' structured props (<flex direction gap>, <grid columns>) and add CSS via a JSON style object style={{"color":"hsl(var(--foreground))"}}; do not use Tailwind className.`})}return t}var ql=`title-format-retired`,Jl=`title-unresolvable`;function Yl(e){let t=[],n=w(e.objects);for(let e=0;e<n.length;e++){let r=n[e],i=typeof r.name==`string`?r.name:`(object ${e})`,a=`object "${i}"`,o=`objects[${e}]`;r.titleFormat!==void 0&&r.titleFormat!==null&&r.titleFormat!==``&&t.push({severity:`warning`,rule:ql,where:a,path:o,message:`${i}: titleFormat is retired (ADR-0079) \u2014 migrate to nameField (single field) or a formula field designated nameField`,hint:`titleFormat is a render-only template the server cannot return or query, and an explicit nameField now takes precedence. For a single-field title set nameField: '<field>'. For a composite title, add a formula field (returnType: 'text') and designate it via nameField.`}),he(r).status===`none`&&t.push({severity:`warning`,rule:Jl,where:a,path:o,message:`${i}: no resolvable record title \u2014 records will have no meaningful name (no nameField and no title-eligible field to derive one)`,hint:`Set nameField to a text/email field (or a formula field with returnType: 'text'), or add a text field named "name"/"title". The runtime auto-provisions a primary and falls back to "Record #<id>", but an explicit title is far more useful.`})}return t}var Xl=`field-group-undeclared`,Zl=`field-group-empty`,Ql=`field-group-shadowed`,$l=`semantic-role-field-unknown`,eu=`semantic-role-field-unprovisioned`;function tu(e){let t=[],n=w(e.objects);for(let e=0;e<n.length;e++){let r=n[e];if(!r||typeof r!=`object`)continue;let i=typeof r.name==`string`?r.name:`(object ${e})`,a=`object "${i}"`,o=`objects[${e}]`,s=r.fields&&typeof r.fields==`object`&&!Array.isArray(r.fields)?r.fields:{},c=new Set([...Object.keys(s),...Pn(r)]),l=In(r),u=(e,t)=>({severity:`warning`,rule:eu,where:a,path:`${o}.${e}`,message:`${i}: ${e} points at "${t}", an injected system column with no storage behind it \u2014 this object is external (ADR-0015), so the platform registers the anchor but the remote schema owns the table and no column backs it. Every consumer renders it empty on every record.`,hint:`If the remote table really carries "${t}", declare it in the object's own fields (mapped through the external binding's columnMap); otherwise point ${e} at a real remote column.`}),d=new Set((Array.isArray(r.fieldGroups)?r.fieldGroups:[]).filter(e=>!!e&&typeof e==`object`).map(e=>e.key).filter(e=>typeof e==`string`&&e.length>0)),f=new Set;for(let[e,n]of Object.entries(s)){let r=n?.group;typeof r==`string`&&r.length!==0&&(f.add(r),d.has(r)||t.push({severity:`warning`,rule:Xl,where:a,path:`${o}.fields.${e}.group`,message:`${i}.${e}: group "${r}" is not declared in fieldGroups \u2014 the field renders in the ungrouped bucket, not under "${r}"`,hint:`Declare { key: '${r}', label: '\u2026' } in ${i}.fieldGroups, or fix the field's group reference. Group keys are snake_case and must match exactly.`}))}for(let e of d)f.has(e)||t.push({severity:`warning`,rule:Zl,where:a,path:`${o}.fieldGroups`,message:`${i}: fieldGroups declares "${e}" but no field references it \u2014 the group never renders`,hint:`Assign at least one field via group: '${e}', or remove the unused group declaration.`});let p=r.stageField;typeof p==`string`&&p.length>0&&!c.has(p)?t.push({severity:`warning`,rule:$l,where:a,path:`${o}.stageField`,message:`${i}: stageField "${p}" is not a field on this object \u2014 consumers fall back to heuristic stage detection`,hint:`Point stageField at an existing select/status field, or set stageField: false to declare the object has no linear lifecycle.`}):typeof p==`string`&&l.has(p)&&t.push(u(`stageField`,p));let m=Array.isArray(r.highlightFields)?r.highlightFields:Array.isArray(r.compactLayout)?r.compactLayout:[];for(let e of m)typeof e==`string`&&e.length!==0&&c.has(e)&&l.has(e)&&t.push(u(`highlightFields`,e));let h=m.filter(e=>typeof e==`string`&&e.length>0);if(h.length>0&&d.size>0){let e=[r.nameField,r.displayNameField].find(e=>typeof e==`string`&&e.length>0&&c.has(e))??[`name`,`full_name`,`title`,`subject`,`display_name`].find(e=>c.has(e)),n=new Set(h.filter(t=>t!==e).slice(0,4)),l=new Set(n);e&&l.add(e);for(let e of d){let n=Object.entries(s).filter(([,t])=>t?.group===e&&t?.hidden!==!0).map(([e])=>e);n.length!==0&&n.every(e=>l.has(e))&&t.push({severity:`warning`,rule:Ql,where:a,path:`${o}.fieldGroups`,message:`${i}: every field in group "${e}" (${n.join(`, `)}) is hoisted into the detail highlight strip (or is the record title) \u2014 the group renders on forms but never on detail pages`,hint:`Keep at least one non-highlighted field in "${e}", or remove the group if the strip already covers it. (Detail pages show the first 4 highlightFields as the top strip and hide them from the body.)`})}}}return t}function nu(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function ru(e){return typeof e==`string`&&e.length>0?e:void 0}function iu(e){return ru(e.objectName)??ru(e.object)??(nu(e.data)?ru(e.data.object):void 0)}function au(e,t){if(!nu(e))return[];let n=[{view:e,path:t,surface:``,kind:`self`}];nu(e.form)&&n.push({view:e.form,path:`${t}.form`,surface:`form`,kind:`form`});for(let r of[`listViews`,`formViews`]){let i=e[r];if(!nu(i))continue;let a=r===`listViews`?`listView`:`formView`;for(let[e,o]of Object.entries(i))nu(o)&&n.push({view:o,path:`${t}.${r}.${e}`,surface:`${r}.${e}`,kind:a})}return n}function ou(e,t){return au(e,t).filter(e=>e.kind!==`listView`)}var su=`form-field-unknown`,cu=`form-section-group-unknown`;function lu(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function uu(e){return typeof e==`string`&&e.length>0?e:void 0}function du(e){if(typeof e==`string`)return e.length>0?e:null;if(e&&typeof e==`object`&&!Array.isArray(e)){let t=e.field;return typeof t==`string`&&t.length>0?t:null}return null}function fu(e){let t=[],n=new Map;for(let t of w(e.objects)){let e=typeof t.name==`string`?t.name:void 0;if(!e)continue;let r=t.fields&&typeof t.fields==`object`&&!Array.isArray(t.fields)?Object.keys(t.fields):[];n.set(e,new Set(r))}let r=Wc(e);for(let{rec:i,path:a}of O(e.views,`views`)){let e=uu(i.name)??uu(i.object)??a,o=iu(i),s=lu(i.list)?iu(i.list)??o:void 0;for(let c of ou(i,a)){let i=iu(c.view)??o??s,a=i?n.get(i):void 0,l=c.surface?`view "${e}" \xB7 ${c.surface}`:`view "${e}"`;for(let n of[`sections`,`groups`]){let o=Array.isArray(c.view[n])?c.view[n]:[];t.push(...Kc(Gc(o,`${c.path}.${n}`),i,r,l,cu));for(let r=0;r<o.length;r++){let s=o[r],u=lu(s)&&Array.isArray(s.fields)?s.fields:[];for(let o=0;o<u.length;o++){let s=u[o],d=du(s),f=`${c.path}.${n}[${r}].fields[${o}]`;d&&a&&!a.has(d)&&t.push({severity:`warning`,rule:su,where:l,path:f,message:`${e}: field "${d}" is not a field on object "${i}" \u2014 it is silently skipped and never renders on the form`,hint:`Fix the field name, or add "${d}" to ${i}. Section field references must match the object's field names exactly.`})}}}}}return t}function pu(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}var mu=new Set([`==`,`!=`]),hu=new Set([`all`,`exists`,`exists_one`,`map`,`filter`]);function gu(e){return pu(e)&&e.op===`id`&&typeof e.args==`string`?e.args:null}function _u(e){let t=new Set,n=new Set,r=(e,i)=>{if(Array.isArray(e)){for(let t of e)r(t,i);return}if(!pu(e))return;let a=e.args;if(e.op===`rcall`&&Array.isArray(a)&&typeof a[0]==`string`&&hu.has(a[0])){r(a[1],i),r(a[2],!1);return}if(typeof e.op==`string`&&mu.has(e.op)&&Array.isArray(a)&&a.length===2){let e=i?gu(a[1]):null;if(r(a[0],i),e!==null){t.add(e);return}r(a[1],i);return}let o=gu(e);if(o!==null){n.add(o);return}r(a,i)};r(e,!0);for(let e of n)t.delete(e);return t}function vu(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function yu(e){let t=e.data;if(vu(t)&&t.provider===`schema`)return typeof t.schemaId==`string`?t.schemaId:void 0}var bu=`visibility-root-mislayered`,xu=`visibility-bare-identifier`,Su=`visibility-predicate-syntax`,Cu=`visibility-predicate-over-budget`,wu=`visibility-predicate-unknown-function`,Tu=`visibleWhen`;function Eu(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`&&typeof e.source==`string`)return e.source}function Du(e,t){return RegExp(`(^|[^.\\w$])${t}\\.\\w`).test(e)}function Ou(e){return e.replace(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g,e=>` `.repeat(e.length))}var ku=[{wrote:`===`,cel:`==`,example:`record.country == 'USA'`,re:/===/},{wrote:`!==`,cel:`!=`,example:`record.country != 'USA'`,re:/!==/},{wrote:`<>`,cel:`!=`,example:`record.country != 'USA'`,re:/<>/},{wrote:`and`,cel:`&&`,example:`record.a == 1 && record.b == 2`,re:/(?<![.\w$])and(?![\w$])/i},{wrote:`or`,cel:`||`,example:`record.a == 1 || record.b == 2`,re:/(?<![.\w$])or(?![\w$])/i},{wrote:`not`,cel:`!`,example:`!record.archived`,re:/(?<![.\w$])not(?![\w$])/i},{wrote:`=`,cel:`==`,example:`record.status == 'open'`,re:/(?<![=!<>])=(?!=)/}];function Au(e){let t=e.replace(/\s+/g,` `).trim();return t.length>120?`${t.slice(0,117)}...`:t}function ju(e){if(!e.trim())return null;let t=Wt(e);if(t.ok||t.kind===`empty`)return null;if(t.kind===`bounds`)return{kind:`bounds`,overrun:t.overrun};let n=Ft(e),r=n.ok?`the expression could not be parsed`:n.error.split(`
6
+ `)[0].trim(),i=Ou(e);return{kind:`syntax`,detail:r,token:ku.find(e=>e.re.test(i))??null}}function Mu(e){return e.limit&&e.limitValue!==null?`the \`${e.limit}\` budget (platform limit ${e.limitValue})`:`one of the platform's parse budgets`}var Nu=[`current_user`,`page`];function Pu(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function Fu(e,t){if(Array.isArray(e)){for(let n of e)Fu(n,t);return}if(!Pu(e))return;let n=e.args;if(Array.isArray(n)){let r=e.op===`rcall`?n[1]:n[0];(e.op===`.`||e.op===`.?`||e.op===`[]`||e.op===`rcall`)&&Pu(r)&&r.op===`id`&&typeof r.args==`string`&&t.add(r.args)}Fu(n,t)}var Iu=`true`;function Lu(e,t,n){if(Array.isArray(e)){for(let r of e)if(!Lu(r,t,n))return!1;return!0}if(!Pu(e))return!0;let r=e.args;if(e.op===`call`&&Array.isArray(r)&&r[0]===`has`){let{start:r,end:i}=e;if(!Number.isInteger(r)||!Number.isInteger(i))return!1;let a=r,o=i;return a<0||o>t.length||o-a<Iu.length||!t.slice(a,o).startsWith(`has`)?!1:(n.push([a,o]),!0)}return Lu(r,t,n)}function Ru(e,t){let n=[];if(!Lu(t,e,n)||n.length===0)return e;let r=e;for(let[e,t]of n)r=r.slice(0,e)+Iu.padEnd(t-e,` `)+r.slice(t);return r}function zu(e,t){let n=Rt(e);if(!n)return null;let r=new Set;Fu(n,r);let i=t?_u(n):[];return Tt(Ru(e,n),[...Nu,...r,...i])}var Bu={runtime:`record`,metadata:`data`},Vu={runtime:{forbiddenRoot:`data`,message:"visibility predicate is rooted at `data.` — that is the root a metadata-editing form binds (the row under edit), not a runtime surface. A runtime view/page predicate that binds `data.` never matches and the element renders unconditionally (ADR-0089).",hint:"Runtime record surfaces bind `record` + `current_user` (pages also expose `page.<var>`). Use e.g. `record.status == 'open'` instead of `data.status == 'open'`."},metadata:{forbiddenRoot:`record`,message:"visibility predicate is rooted at `record.` — that is the root a runtime view/page surface binds (the live record), not the root a metadata-editing form binds. On a metadata-editing form — the row under edit — a `record.`-rooted predicate never matches and the element renders unconditionally (ADR-0089).",hint:"Metadata-editing forms bind `data` (the row under edit). Use e.g. `data.type == 'grid'` instead of `record.type == 'grid'`."}};function Hu(e,t,n,r,i,a=!1){let o=Eu(e[Tu]??e.visibleOn??e.visibility),s=Vu[r];o&&Du(o,s.forbiddenRoot)&&i.push({severity:`warning`,rule:bu,where:t,path:n,message:s.message,hint:s.hint});let c=o?ju(o):null;if(o&&c?.kind===`bounds`){let e=Mu(c.overrun),a=Bu[r];i.push({severity:`error`,rule:Cu,where:t,path:n,message:`visibility predicate is syntactically valid CEL but overruns ${e} (${c.overrun.summary}) (predicate: \`${Au(o)}\`). The canonical front end refuses it, so it can never evaluate, and the console falls OPEN: the element renders unconditionally and looks exactly like one with no predicate at all (#5149).`,hint:`There is no syntax or dialect error to correct here \u2014 this is a SIZE fault, not a dialect mistake, so re-spelling the predicate will not fix it. Make it smaller, or move the work off the predicate: (1) collapse a long \`${a}.f == 'a' || ${a}.f == 'b' || \u2026\` chain into a single \`${a}.f in ['a', 'b', \u2026]\`, which is far fewer AST nodes (\`maxListElements\` is 64, so a very large set needs option 2); (2) precompute the heavy part into a formula/rollup field on the object and test that one field instead. Logic genuinely this large is not element visibility \u2014 compute it once on the record rather than re-deriving it in every predicate that needs it.`})}o&&c?.kind===`syntax`&&i.push({severity:`error`,rule:Su,where:t,path:n,message:`visibility predicate is not valid CEL \u2014 ${c.detail} (predicate: \`${Au(o)}\`). A predicate that does not parse can never evaluate, and the console falls OPEN: the element renders unconditionally and looks exactly like one with no predicate at all (#5149).`,hint:c.token?`\`${c.token.wrote}\` is not a CEL operator \u2014 CEL spells it \`${c.token.cel}\`. Replace \`${c.token.wrote}\` with \`${c.token.cel}\`, e.g. \`${c.token.example}\`.`:"Visibility predicates are bare CEL, e.g. `record.status == 'open'`. Spellings from other languages do not parse: write `==` (not `===`), `!=` (not `!==` or `<>`), `&&` (not `and`), `||` (not `or`), `!` (not `not`)."});let l=o&&!c?_t(o):null;if(o&&l&&i.push({severity:`error`,rule:wu,where:t,path:n,message:`visibility predicate calls \`${l.name}\`, which the platform's CEL environment does not register \u2014 ${l.detail} (predicate: \`${Au(o)}\`). The predicate parses, so nothing else reports it, and it faults the moment it is evaluated: on a view/page surface the console falls OPEN and the element renders unconditionally, exactly like one carrying no predicate at all; on an action surface \u2014 evaluated with \`throwOnError: true\` \u2014 it falls CLOSED and the action disappears for EVERY user, including one who holds the grant, leaving one deduped \`console.warn\` as the only signal.`,hint:`\`${l.name}\` is not a function this platform registers \u2014 a NAME fault, not a dialect mistake, so re-spelling the predicate will not fix it. The callable names advertised for authoring are the \`functions\` list \`introspectScope\` returns (\`CEL_STDLIB_FUNCTIONS\`): pick one of those, or precompute the value into a formula field on the object and test that field instead.`}),o&&!c){let e=zu(o,a);if(e){let a=Bu[r];i.push({severity:`error`,rule:xu,where:t,path:n,message:`visibility predicate references \`${e}\` as a bare identifier. Values are bound under a namespace on this surface \u2014 they are never flattened to top level \u2014 so \`${e}\` resolves to nothing, the predicate can never evaluate, and the console falls OPEN: the element renders unconditionally and looks exactly like one with no predicate at all (#5149).`,hint:`Write \`${a}.${e}\` instead of \`${e}\``+(r===`runtime`?" (runtime view/page surfaces bind `record` + `current_user`; a page component also exposes page state as `page.<var>`).":" (a metadata-editing form binds the row under edit as `data`).")})}}}function Uu(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Wu(e,t={}){let n=t.layer??`runtime`,r=[];for(let{rec:t,path:i}of O(e.views,`views`)){let e=typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:i;for(let a of ou(t,i)){let t=a.surface?`view "${e}" \xB7 ${a.surface}`:`view "${e}"`,i=yu(a.view)!==void 0,o=i,s=i?`metadata`:n;for(let e of[`sections`,`groups`]){let n=Array.isArray(a.view[e])?a.view[e]:[];for(let i=0;i<n.length;i++){let c=n[i];if(!c||typeof c!=`object`)continue;let l=`${a.path}.${e}[${i}]`;Hu(c,t,l,s,r,o);let u=Array.isArray(c.fields)?c.fields:[];for(let e=0;e<u.length;e++){let n=u[e];Uu(n)&&Hu(n,t,`${l}.fields[${e}]`,s,r,o)}}}}}for(let{rec:t,path:i}of O(e.pages,`pages`)){let e=`page "${(typeof t.name==`string`?t.name:void 0)??i}"`;for(let a of Vc(t,i))Hu(a.component,e,a.path,n,r)}return r}var Gu=`predicate-path-unresolved`,Ku=`predicate-path-unrooted`,qu=`predicate-rhs-path-shaped`,Ju=[`visibleWhen`,`visibleOn`],F=`data`;function Yu(e){if(!e||typeof e!=`object`&&typeof e!=`function`)return;let t=e;return t.def??t._def}function Xu(e,t=0){if(!e||t>25)return e;let n=Yu(e);if(!n)return e;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`readonly`:case`catch`:case`nonoptional`:return Xu(n.innerType,t+1);case`lazy`:return Xu(n.getter(),t+1);case`pipe`:{let e=Xu(n.in,t+1);return Yu(e)?.type===`transform`?Xu(n.out,t+1):e}default:return e}}function Zu(e){return Array.isArray(e?.options)?e.options:[]}function Qu(e,t=0){if(t>25)return null;let n=Xu(e),r=Yu(n);if(r?.type===`object`)return Object.keys(r.shape??n.shape??{});if(r?.type===`union`||r?.type===`discriminated_union`){let e=new Set,n=!1;for(let i of Zu(r)){let r=Qu(i,t+1);if(r){n=!0;for(let t of r)e.add(t)}}return n?[...e]:null}if(r?.type===`intersection`){let e=Qu(r.left,t+1),n=Qu(r.right,t+1);return!e&&!n?null:[...new Set([...e??[],...n??[]])]}return null}function $u(e,t,n=0){if(n>25)return;let r=Xu(e),i=Yu(r);if(i?.type===`object`)return(i.shape??r.shape??{})[t];if(i?.type===`union`||i?.type===`discriminated_union`)for(let e of Zu(i)){let r=$u(e,t,n+1);if(r!==void 0)return r}if(i?.type===`intersection`)return $u(i.left,t,n+1)??$u(i.right,t,n+1)}function ed(e,t){let n=$u(e,t);if(n===void 0)return;let r=Xu(n);for(let e=0;e<25;e++){let e=Yu(r);if(e?.type===`array`)r=Xu(e.element);else if(e?.type===`record`)r=Xu(e.valueType);else return r}return r}function td(e,t){let n=Xu(e),r=Yu(n);if(r?.type===`record`)return{kind:`declared`,next:r.valueType};let i=Qu(n);return i===null?{kind:`opaque`}:i.includes(t)?{kind:`declared`,next:$u(n,t)}:{kind:`undeclared`,declared:i}}function nd(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function rd(e){if(!nd(e))return null;if(e.op===`id`&&typeof e.args==`string`)return[e.args];if(e.op===`.`&&Array.isArray(e.args)&&typeof e.args[1]==`string`){let t=rd(e.args[0]);return t?[...t,e.args[1]]:null}return null}function id(e,t){if(Array.isArray(e)){for(let n of e)id(n,t);return}if(nd(e)){if(e.op===`.`){let n=rd(e);if(n&&n[0]===F&&n.length>1){t.push(n.slice(1));return}}id(e.args,t)}}var ad=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/;function od(e,t){if(Array.isArray(e)){for(let n of e)od(n,t);return}if(!nd(e))return;let n=e.args;if(e.op===`rcall`&&Array.isArray(n)&&typeof n[0]==`string`&&hu.has(n[0])){od(n[1],t);return}typeof e.op==`string`&&mu.has(e.op)&&Array.isArray(n)&&n.length===2&&t.push({op:e.op,right:n[1]}),od(n,t)}function sd(e,t,n){if(Array.isArray(e)){for(let r of e)sd(r,t,n);return}if(!nd(e))return;let r=e.args;if(Array.isArray(r)){let t=e.op===`rcall`?r[1]:r[0];if((e.op===`.`||e.op===`.?`||e.op===`[]`||e.op===`rcall`)&&nd(t)&&t.op===`id`&&typeof t.args==`string`&&n.add(t.args),e.op===`rcall`&&typeof r[0]==`string`&&hu.has(r[0])){let e=r[2];if(Array.isArray(e)&&e.length>=2){let t=e[0];nd(t)&&t.op===`id`&&typeof t.args==`string`&&n.add(t.args)}}}if(e.op===`id`&&typeof e.args==`string`){t.add(e.args);return}sd(r,t,n)}function cd(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`&&typeof e.source==`string`)return e.source}function ld(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function ud(e,t,n,r,i){let a=Rt(e);if(!a)return;let o=[];id(a,o);for(let e of o){let a=t,o=[];for(let t of e){let e=td(a,t);if(e.kind===`opaque`)break;if(e.kind===`undeclared`){let a=[F,...o,t].join(`.`),s=o.length?`${F}.${o.join(`.`)}`:F;i.push({severity:`error`,rule:Gu,where:n,path:r,message:`predicate references \`${a}\`, which the target schema does not declare \u2014 \`${t}\` is not a key of \`${s}\`. The reference resolves to nothing, so the predicate can never evaluate and the console falls OPEN: the element renders unconditionally and looks exactly like one carrying no predicate at all (#5149).`,hint:`${Qe(We(t,e.declared))||`\`${s}\` declares: ${e.declared.slice(0,12).sort().join(`, `)}`} Every reference must resolve against the schema the form edits.`});break}o.push(t),a=e.next}}let s=Qu(t),c=_u(a);if(s){let e=new Set,t=new Set;sd(a,e,t);for(let a of e)t.has(a)||c.has(a)||!s.includes(a)||i.push({severity:`error`,rule:Ku,where:n,path:r,message:`predicate references \`${a}\` as a bare identifier, but \`${a}\` is a key of the schema this form edits \u2014 the binding root was dropped. Values are bound under \`${F}\` and are never flattened to top level, so \`${a}\` resolves to nothing, the predicate can never evaluate and the console falls OPEN: the element renders unconditionally and looks exactly like one carrying no predicate at all (#5149, #6254).`,hint:`Write \`${F}.${a}\` instead of \`${a}\`. A metadata-editing form binds the row under edit as \`${F}\` at every depth \u2014 inside a repeater \`${F}\` is the ROW, but it is still spelled \`${F}\` (there is no implicit row scope).`})}let l=[];od(a,l);for(let{op:e,right:t}of l){let a=rd(t);if(!a)continue;let o=a.join(`.`);if(!ad.test(o))continue;let s=a.length>1;i.push({severity:s?`error`:`warning`,rule:qu,where:n,path:r,message:s?`predicate compares against \`${o}\` on the RIGHT of \`${e}\`, which is a path but is not evaluated as one. A metadata-editing form resolves paths on the LEFT of \`${e}\` only; the right-hand side goes to the literal parser, so \`${o}\` is compared as the literal string "${o}". The verdict therefore does not depend on the right-hand path at all: \`a == ${o}\` is FALSE even when both sides hold the same value, and \`a != ${o}\` is correspondingly TRUE. An \`==\` written this way hides the element on every row, and nothing in the console says why (objectui#4049).`:`predicate compares against the unquoted word \`${o}\` on the RIGHT of \`${e}\`. The right-hand side of \`${e}\` is a literal, never a reference, so this is read as the literal string "${o}" \u2014 which is probably what you meant, and is why it appears to work. It is outside the declared subset all the same (\`path == 'literal'\`), and it stops working when this surface moves to the real CEL evaluator, where a bare \`${o}\` resolves to nothing (objectui#4049). The token also reads as a \`${F}.\` root someone dropped, so this one finding carries BOTH readings: which one you meant is the thing no linter can know, and it changes the fix (#7696).`,hint:s?`Two sanctioned spellings. (1) If you meant the TEXT, quote it: \`${e} '${o}'\`. (2) If you meant the PATH, restructure so the path is on the LEFT and a literal is on the right \u2014 comparing one path against another is outside the subset this surface renders, which is \`path == 'literal'\` / \`path != 'literal'\` and nothing wider. There is no third spelling that compares two paths here.`:`Two sanctioned spellings, and you must pick \u2014 they are not the same predicate. (1) If you meant the TEXT \`${o}\`, quote it: \`${e} '${o}'\`. That is what this renders as today, so it changes no behaviour and is the fix unless you know otherwise. (2) If you meant the FIELD \`${F}.${o}\`, move it to the LEFT and put a literal on the right, e.g. \`${F}.${o} == 'yes'\`. \u26D4 Do NOT simply add the root in place: \`${e} ${F}.${o}\` is a path on the RIGHT, which this surface parses as the literal string "${F}.${o}" \u2014 it is refused by this same rule at \`error\`, and it is FALSE on every row. The subset here is \`path == 'literal'\` and nothing wider.`})}}function dd(e,t,n,r,i,a){if(!(!Array.isArray(e)||a>12))for(let o=0;o<e.length;o++){let s=e[o];if(!ld(s))continue;let c=`${r}[${o}]`;for(let e of Ju){let r=cd(s[e]);if(r!==void 0&&r.trim()){ud(r,t,n,`${c}.${e}`,i);break}}if(Array.isArray(s.fields)&&s.fields.length>0&&typeof s.field==`string`){let e=t===void 0?void 0:ed(t,s.field);dd(s.fields,e,n,`${c}.fields`,i,a+1)}}}function fd(e,t={}){let n=t.resolveSchema??(e=>kt(e)),r=[];for(let{rec:t,path:i}of O(e.views,`views`)){let e=typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:i;for(let a of ou(t,i)){let t=yu(a.view);if(!t)continue;let i;try{i=n(t)}catch{i=void 0}let o=a.surface?`view "${e}" \xB7 ${a.surface} (schema "${t}")`:`view "${e}" (schema "${t}")`;for(let e of[`sections`,`groups`]){let t=Array.isArray(a.view[e])?a.view[e]:[];for(let n=0;n<t.length;n++){let s=t[n];if(!ld(s))continue;let c=`${a.path}.${e}[${n}]`;for(let e of Ju){let t=cd(s[e]);if(t!==void 0&&t.trim()){ud(t,i,o,`${c}.${e}`,r);break}}dd(s.fields,i,o,`${c}.fields`,r,0)}}}}return r}var pd=`capability-reference-unknown`;function md(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function hd(e){if(Array.isArray(e))return md(e).map(e=>({cap:e}));if(e&&typeof e==`object`){let t=[];for(let[n,r]of Object.entries(e))for(let e of md(r))t.push({cap:e,key:n});return t}return[]}function gd(e){let t=[];if(!e||typeof e!=`object`)return t;let n=new Set(c);for(let t of w(e.capabilities))typeof t.name==`string`&&t.name.length>0&&n.add(t.name);for(let t of w(e.permissions))for(let e of md(t.systemPermissions))n.add(e);for(let t of w(e.data))if(t.object===`sys_capability`)for(let e of Array.isArray(t.records)?t.records:[]){let t=e?.name;typeof t==`string`&&t.length>0&&n.add(t)}let r=(e,r,i)=>{n.has(e)||t.push({severity:`warning`,rule:pd,where:r,path:i,message:`requiredPermissions references capability "${e}" which is registered nowhere \u2014 no built-in capability, no permission set in this package grants it via systemPermissions, and no sys_capability seed declares it`,hint:`Fix the capability name, define it with defineCapability (stack.capabilities), declare it on a permission set’s systemPermissions, ship a sys_capability seed row, or ignore this if the capability is provided by another installed package (references fail closed at runtime).`})},i=w(e.objects);for(let e=0;e<i.length;e++){let t=i[e];if(!t||typeof t!=`object`)continue;let n=typeof t.name==`string`?t.name:`(object ${e})`,a=`objects[${e}]`;for(let{cap:e,key:i}of hd(t.requiredPermissions))r(e,`object "${n}"`,`${a}.requiredPermissions${i?`.${i}`:``}`);let o=w(t.fields);for(let e of o){let t=typeof e.name==`string`?e.name:`(field)`;for(let i of md(e.requiredPermissions))r(i,`field "${n}.${t}"`,`${a}.fields.${t}.requiredPermissions`)}for(let[e,i]of w(t.actions).entries()){let t=typeof i.name==`string`?i.name:`(action ${e})`;for(let o of md(i.requiredPermissions))r(o,`action "${n}.${t}"`,`${a}.actions[${e}].requiredPermissions`)}}for(let[t,n]of w(e.actions).entries()){let e=typeof n.name==`string`?n.name:`(action ${t})`;for(let i of md(n.requiredPermissions))r(i,`action "${e}"`,`actions[${t}].requiredPermissions`)}let a=w(e.apps);for(let e=0;e<a.length;e++){let t=a[e];if(!t||typeof t!=`object`)continue;let n=typeof t.name==`string`?t.name:`(app ${e})`,i=(e,t)=>{if(!e||typeof e!=`object`)return;if(Array.isArray(e)){e.forEach((e,n)=>i(e,`${t}[${n}]`));return}let a=e;for(let e of md(a.requiredPermissions))r(e,`app "${n}"`,`${t}.requiredPermissions`);a.navigation&&i(a.navigation,`${t}.navigation`),a.areas&&i(a.areas,`${t}.areas`),a.tabs&&i(a.tabs,`${t}.tabs`),a.children&&i(a.children,`${t}.children`),a.items&&i(a.items,`${t}.items`)};i(t,`apps[${e}]`)}return t}var _d=`approval-approver-not-membership-tier`,vd=`approval-approver-type-deprecated`,yd=`approval-approver-type-unknown`,bd=`approval-approver-type-unsupported`,xd=`approval-escalation-reassign-no-target`,Sd=`approval-approvers-may-resolve-empty`,Cd=`approval-expression-invalid`,wd=`approval-expression-no-empty-policy`,Td=`approval-decision-outputs-reserved`,Ed=`approval-approver-cross-org-unsupported`,Dd=new Set([`current`,`trigger`,`vars`]),Od=new Set([`decision`,`requestId`]),kd=new Set([`position`,`team`,`department`]),Ad=`sys_user.manager_id is not a profile column — the data API's managed-update whitelist is {name, image, locale} and the column is readonly on the user form, so it is never populated by editing the user in the Console. It has a dedicated admin operation instead: a platform admin POSTs { userId, managerId } to /api/v1/auth/admin/set-user-manager, with managerId set to null to clear the link.`,jd=`That endpoint is the route this platform gives you, and it refuses a link that would make a user their own manager, close a cycle, run past the chain depth cap, or point across an organization boundary. The column is also written by a seed, or by any other system-context write, which bypasses the managed-update whitelist. SCIM provisioning and directory sync can populate it too, but only through a provisioning path your own deployment supplies: this platform declares the SCIM 'manager' attribute without projecting it onto the column, and its admin bulk import does not write it either — and where an identity carries source 'idp_provisioned' the admin operation refuses, leaving that directory the one surface that authors its manager. Or declare onEmptyApprovers: 'fallback' on the node, with a fallbackApprovers list: an empty manager rung then opens the request on those people instead of on a slot nobody can act on, which needs no write to the column at all.`,Md=new Set(ot),Nd=ot.join(`/`),Pd={business_unit:`department`,bu:`department`};function Fd(e){let t=Array.isArray(e.data)?e.data:[];for(let e of t){if(!e||typeof e!=`object`||e.object!==`sys_user`)continue;let t=Array.isArray(e.records)?e.records:[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=e.manager_id;if(typeof t==`string`&&t.trim()!==``||typeof t==`number`)return!0}}return!1}function Id(e){let t=[];if(!e||typeof e!=`object`)return t;let n=w(e.flows),r=new Set(ft.options),i=Fd(e);for(let e=0;e<n.length;e++){let a=n[e];if(!a||typeof a!=`object`)continue;let o=typeof a.name==`string`?a.name:`(flow ${e})`,s=bo(a,`flows[${e}]`);for(let e=0;e<s.length;e++){let{node:n,path:a}=s[e];if(!n||n.type!==`approval`)continue;let c=typeof n.id==`string`?n.id:`(node ${e})`,u=n.config??{},d=Array.isArray(u.approvers)?u.approvers:[],f=`flow "${o}" \xB7 node "${c}"`;for(let e=0;e<d.length;e++){let n=d[e];if(!n||typeof n!=`object`)continue;let i=typeof n.type==`string`?n.type:``,o=typeof n.value==`string`?n.value:``,s=`${a}.config.approvers[${e}]`;if(i&&!r.has(i)){let e=Pd[i];t.push({severity:`warning`,rule:yd,where:f,path:`${s}.type`,message:`approver type '${i}' is not an ApproverType (${ft.options.join(` | `)}).`,hint:e?`Use the spec value: { type: '${e}', value: '${o}' }.`:`Pick one of the spec values; unmapped types degrade to an inert '${i}:${o}' literal at runtime.`});continue}let c=ge(i);if(c===`expression`){let e=o.trim();if(!e)t.push({severity:`error`,rule:Cd,where:f,path:`${s}.value`,message:`expression approver has an empty expression — the node fails at entry.`,hint:`Write a CEL expression over current.* (the record's live state at node entry), trigger.* (the submit-time snapshot) or vars.* (flow variables), e.g. current.approvers_dynamic or vars.approval_lead.picked_departments.`});else{let n=Ft(e);if(!n.ok)t.push({severity:`error`,rule:Cd,where:f,path:`${s}.value`,message:`expression approver does not parse as CEL: ${n.error}.`,hint:`Approver expressions are bare CEL (no {…} template braces), e.g. current.approvers_dynamic or vars.get_reviewers.record.owner_id.`});else{let e=n.roots.filter(e=>!Dd.has(e));if(e.length){let n=e.includes(`record`)||e.includes(`previous`);t.push({severity:`error`,rule:Cd,where:f,path:`${s}.value`,message:`expression approver references \`${e.join("`, `")}\` \u2014 only current.*, trigger.* and vars.* are available, and the node fails at entry on any other root.`,hint:n?'`record`/`previous` are not bound here (on this platform `record` always means "the record at event time", which is ambiguous at an approval node). Write current.<field> for the live value at node entry, trigger.<field> for the submit-time snapshot (vars.previous carries the pre-update row).':`Did you mean current.<field> (live record), trigger.<field> (submit snapshot), or vars.<name> (flow variable)?`})}}}}else n.resolveAs!=null&&t.push({severity:`info`,rule:Cd,where:f,path:`${s}.resolveAs`,message:`resolveAs has no effect on a '${i}' approver \u2014 it only applies to type 'expression'.`,hint:`Remove it, or switch this approver to { type: 'expression', value: '<CEL>', resolveAs: '${String(n.resolveAs)}' }.`});if(c===`org_membership_level`&&o&&!Md.has(o.toLowerCase()))t.push({severity:`warning`,rule:_d,where:f,path:`${s}.value`,message:`approver { type: '${i}', value: '${o}' } resolves against the better-auth org-membership tier (sys_member.role: ${Nd}) \u2014 '${o}' is not a membership tier, so this approver matches nobody and the request stalls.`,hint:`If '${o}' is an org position, author { type: 'position', value: '${o}' } (resolved via sys_user_position, ADR-0090 D3). Keep type 'org_membership_level' only for membership tiers (${Nd}) \u2014 the vocabulary is closed (ADR-0108), so a business role is always a position.`});else if(i in Ze){let e=ge(i);t.push({severity:`warning`,rule:vd,where:f,path:`${s}.type`,message:`approver type '${i}' is the deprecated spelling of '${e}' (ADR-0090 D3) and is removed in the next major.`,hint:`Author { type: '${e}', value: '${o}' }. It resolves identically today.`})}else Ie[c]?.source===`unsupported`&&t.push({severity:`warning`,rule:bd,where:f,path:`${s}.type`,message:`approver type '${i}' is declared but not implemented by the runtime (#3508) \u2014 the slot resolves to nobody and the request stalls.`,hint:`Route to people the engine can expand: { type: 'team' | 'department' | 'position', ... }. Queue approvers need a real ownership-queue implementation before they take effect.`});let l=n.organization;typeof l==`string`&&l.trim()!==``&&ft.options.includes(c)&&!ze(c)&&t.push({severity:`error`,rule:Ed,where:f,path:`${s}.organization`,message:`approver type '${i}' does not resolve through an organization directory, so 'organization: ${l}' has no effect (ADR-0105 D9) \u2014 the runtime refuses it.`,hint:`Drop 'organization' here. Cross-organization targeting applies to 'position', 'org_membership_level', 'department' and 'expression' approvers.`})}let p=d.filter(e=>e&&typeof e==`object`&&typeof e.type==`string`);if(p.length>0&&p.every(e=>kd.has(ge(String(e.type))))){let e=u.lockRecord!==!1;t.push({severity:`info`,rule:Sd,where:f,path:`${a}.config.approvers`,message:`every approver on this node routes to a group (position/team/department) whose members are runtime data — if none is staffed, the request resolves to an empty slate and waits forever`+(e?`, and (lockRecord) the record stays locked with no in-product recovery.`:`.`),hint:`Make sure at least one target is always staffed, or add a guaranteed-staffed approver entry, e.g. { type: 'org_membership_level', value: 'owner' }, or declare onEmptyApprovers: 'fallback' with a fallbackApprovers list for the node to open on when the groups come back empty. A request that still lands empty is recoverable only by a platform/tenant admin override (#3424).`})}if(!i&&p.length>0&&p.every(e=>ge(String(e.type))===`manager`)){let e=u.lockRecord!==!1;t.push({severity:`info`,rule:Sd,where:f,path:`${a}.config.approvers`,message:`every approver on this node is { type: 'manager' }, resolved at runtime from sys_user.manager_id of the record's owner — a static check cannot read that column, so this does not assert the slate IS empty; it reports that nothing else on the node can approve if it is. Where manager_id is unset the expansion returns nobody, the request resolves to an empty slate and waits forever`+(e?`, and (lockRecord) the record stays locked with no in-product recovery.`:`.`),hint:`${Ad} ${jd} Populate it for everyone who submits this request, or take the other escape that needs none of that: add a second approver entry which cannot resolve empty, e.g. { type: 'org_membership_level', value: 'owner' }. A request that still lands empty is recoverable only by a platform/tenant admin override.`})}d.some(e=>e&&typeof e==`object`&&ge(String(e.type??``))===`expression`)&&u.onEmptyApprovers==null&&t.push({severity:`info`,rule:wd,where:f,path:`${a}.config`,message:`this node resolves approvers from an expression but declares no onEmptyApprovers — an empty result falls back to the default ('admin_rescue': request opens, only a privileged admin can act).`,hint:`Declare the empty-slate policy explicitly: onEmptyApprovers: 'admin_rescue' (hold for admin takeover), 'fail' (fail the node — config bug), 'auto_approve' (wave through, output.autoApproved = true), or 'fallback' with a sibling fallbackApprovers list (open the request on those people instead).`});let m=l(u.decisionOutputs).map(e=>e.key).filter(e=>Od.has(e));m.length&&t.push({severity:`error`,rule:Td,where:f,path:`${a}.config.decisionOutputs`,message:`decisionOutputs declares reserved key(s) \`${m.join("`, `")}\` \u2014 the resume envelope owns them, so every decide carrying them is rejected.`,hint:`Rename the output key(s); any name other than 'decision'/'requestId' works.`});let h=u.escalation??null;h&&typeof h==`object`&&h.action===`reassign`&&(typeof h.escalateTo==`string`&&h.escalateTo.trim()||t.push({severity:`warning`,rule:xd,where:f,path:`${a}.config.escalation.escalateTo`,message:`escalation.action is 'reassign' but escalateTo is empty — at runtime the escalation degrades to a notify and the request stays with the original approvers.`,hint:`Set escalateTo to a position machine name (expanded via sys_user_position, ADR-0090 D3) or a specific user id, or change action to 'notify'.`}))}}return t}var Ld=`seed-insert-mode-duplicates-on-replay`;function Rd(e){let t=[];return(Array.isArray(e.data)?e.data:[]).forEach((e,n)=>{if(!e||typeof e!=`object`||e.mode!==`insert`)return;let r=typeof e.object==`string`?e.object:void 0,i=r?`seed "${r}"`:`data[${n}]`;t.push({severity:`warning`,rule:Ld,where:i,path:`data[${n}].mode`,message:"`mode: 'insert'` re-inserts every record on each replay boot (dev-server restart, package re-publish) with no existing-row check, so the dataset duplicates the table on every restart — seeds are replayed, not applied once.",hint:"Use `mode: 'ignore'` (skip rows that already exist) or `'upsert'` (create-or-update), and declare an `externalId` to match on: a single natural-key field (e.g. `externalId: 'code'`), or a COMPOSITE list of fields for a join / junction table with no single natural key (e.g. `externalId: ['team', 'project']`)."})}),t}var zd=`seed-value-outside-state-machine`;function Bd(e){let t=new Map;for(let n of e){if(!n||typeof n!=`object`)continue;let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=Array.isArray(n.validations)?n.validations:[],i=[];for(let e of r){if(!e||typeof e!=`object`||e.type!==`state_machine`)continue;let t=typeof e.field==`string`?e.field:void 0;if(!t)continue;let n=e.transitions&&typeof e.transitions==`object`?e.transitions:{},r=new Set;for(let t of Array.isArray(e.initialStates)?e.initialStates:[])r.add(String(t));for(let e of Object.keys(n)){r.add(String(e));let t=n[e];for(let e of Array.isArray(t)?t:[])r.add(String(e))}r.size>0&&i.push({field:t,states:r})}i.length>0&&t.set(e,i)}return t}function Vd(e,t,n){let r=(Array.isArray(t)?t.map(String):typeof t==`string`?[t]:[`name`]).map(t=>e[t]).filter(e=>e!=null&&e!==``);return r.length>0?r.map(String).join(` · `):`#${n}`}function Hd(e){let t=[],n=Array.isArray(e.objects)?e.objects:[],r=Array.isArray(e.data)?e.data:[];if(n.length===0||r.length===0)return t;let i=Bd(n);return i.size===0||r.forEach((e,n)=>{if(!e||typeof e!=`object`)return;let r=typeof e.object==`string`?e.object:void 0;if(!r)return;let a=i.get(r);a&&(Array.isArray(e.records)?e.records:[]).forEach((i,o)=>{if(i&&typeof i==`object`)for(let s of a){let a=i[s.field];a!=null&&a!==``&&typeof a==`string`&&(s.states.has(a)||t.push({severity:`warning`,rule:zd,where:`seed "${r}" (${Vd(i,e.externalId,o)})`,path:`data[${n}].records[${o}].${s.field}`,message:`seeds '${s.field}=${a}', which the '${r}' state machine does not declare (known states: ${[...s.states].sort().join(`, `)}). Seed writes are exempt from the state_machine rule (#3433), so this is NOT rejected at write time \u2014 a typo lands silently.`,hint:`If '${a}' is a real state, add it to the state machine (as an initial state or a transition endpoint). If it is a typo, correct it to a declared state. The exemption lets a seed be born mid-lifecycle; it is not a licence to write an unknown state.`}))}})}),t}var Ud=`security-owd-unset`,Wd=`security-owd-alias`,Gd=`security-external-wider-than-internal`,Kd=`security-wildcard-vama`,qd=`security-anchor-high-privilege`,Jd=`security-role-word`,Yd=`security-book-audience-unknown-set`,Xd=`security-private-no-readscope`,Zd=`security-master-detail-ungranted`,Qd=`security-fls-unqualified-key`,$d=`security-fls-unknown-field`,ef=`security-grant-expired-at-authoring`,tf=`security-delegation-missing-reason`,nf=`security-controlled-by-parent-no-relation`,rf=`security-controlled-by-parent-ambiguous-relation`,af=[`private`,`public_read`,`public_read_write`,`controlled_by_parent`],of={read:`public_read`,read_write:`public_read_write`,full:`public_read_write`},sf={public:`public_read_write`},cf={...of,...sf},lf={private:0,public_read:1,public_read_write:2};function uf(e){return e.sharingModel}function df(e){return of[e]?`is a retired alias (ADR-0090 D4)`:`is not an OWD value and never was \u2014 ADR-0090 D4 retired 'read', 'read_write' and 'full', not this. '${e}' is legal on the neighbouring keys 'access' (its 'default') and 'publicSharing' (its 'allowedAudiences'), just not on this one`}function ff(e){return e.isSystem===!0||String(e.name??``).startsWith(`sys_`)}function pf(e){return typeof e==`string`&&e.toLowerCase().split(/[^a-z0-9]+/).some(e=>e===`role`||e===`roles`)}function mf(e){return typeof e==`string`&&/\brole(s)?\b/i.test(e)}function hf(e){return be({reference:e.reference},`validate-security-posture refOf`)}function gf(e){for(let t of w(e.fields))if(t.type===`master_detail`)return{name:String(t.name??`?`),parent:hf(t)}}var _f=[{label:`required master_detail`,pred:e=>e.type===`master_detail`&&!!e.required},{label:`any master_detail`,pred:e=>e.type===`master_detail`},{label:`required lookup`,pred:e=>e.type===`lookup`&&!!e.required}];function vf(e){let t=w(e.fields);for(let{label:e,pred:n}of _f){let r=t.filter(e=>n(e)&&hf(e));if(r.length>0)return{tier:e,candidates:r.map(e=>({field:String(e.name??`?`),type:String(e.type),master:hf(e)}))}}}function yf(e){return vf(e)?.candidates[0]}function bf(e){return e.allowRead===!0||e.allowCreate===!0||e.allowEdit===!0||e.allowDelete===!0||e.viewAllRecords===!0||e.modifyAllRecords===!0}function xf(e,t){let n=[];if(!e||typeof e!=`object`)return n;let r=w(e.objects),i=w(e.permissions),a=w(e.capabilities).filter(e=>typeof e.name==`string`&&e.name.length>0),o=a.length>0?{declaredCapabilities:a}:void 0;for(let e=0;e<r.length;e++){let t=r[e];if(!t||typeof t!=`object`)continue;let i=typeof t.name==`string`?t.name:`(object ${e})`,a=`objects[${e}]`,o=uf(t),s=t.externalSharingModel;ff(t)||(o==null?n.push({severity:`error`,rule:Ud,where:`object "${i}"`,path:`${a}.sharingModel`,message:`custom object "${i}" declares no sharingModel (OWD). The runtime fails CLOSED to 'private' (ADR-0090 D1), but the baseline must be an authored decision, not an accident \u2014 this is the exact shape of the leave_request incident (objectui#2348).`,hint:`Declare sharingModel explicitly: 'private' (owner + shares; recommended default), 'public_read', 'public_read_write', or 'controlled_by_parent' (master-detail children).`}):typeof o==`string`&&cf[o]?n.push({severity:`error`,rule:Wd,where:`object "${i}"`,path:`${a}.sharingModel`,message:`sharingModel '${o}' ${df(o)}. The runtime fails CLOSED to 'private' on unknown values, so this object is NOT ${o===`read`?`readable`:`writable`} org-wide.`,hint:`Replace with the canonical value: sharingModel: '${cf[o]}'.`}):typeof o==`string`&&!af.includes(o)&&n.push({severity:`error`,rule:Wd,where:`object "${i}"`,path:`${a}.sharingModel`,message:`sharingModel '${o}' is not a canonical OWD value; the runtime fails CLOSED to 'private'.`,hint:`Use one of: ${af.join(`, `)}.`})),o===`controlled_by_parent`&&!yf(t)&&n.push({severity:`error`,rule:nf,where:`object "${i}"`,path:`${a}.sharingModel`,message:`"${i}" declares sharingModel 'controlled_by_parent' but has no relation the platform can derive access from. ADR-0055 resolves the master through a required master_detail, then any master_detail, then a required lookup \u2014 each of which must also name a reference target \u2014 and this object matches none of the three. At runtime every read is DENIED and every write is refused with 422 INVALID_METADATA (#7474), so the object is unusable rather than merely locked down.`,hint:`Add the master relation this object is derived from, e.g. fields.parent: { type: 'master_detail', reference: '<master_object>', required: true }. If the object has no master, its baseline is its own decision — use sharingModel: 'private' (owner + shares), 'public_read', or 'public_read_write'.`});let c=o===`controlled_by_parent`?vf(t):void 0;if(c&&c.candidates.length>1){let e=c.candidates[0],t=c.candidates.map(e=>`"${e.field}" (${e.type} -> "${e.master}")`).join(`, `);n.push({severity:`error`,rule:rf,where:`object "${i}"`,path:`${a}.fields`,message:`"${i}" declares sharingModel 'controlled_by_parent' and ${c.candidates.length} of its fields tie for the master relation: ${t}. ADR-0055 resolves the master through a required master_detail, then any master_detail, then a required lookup, and takes the FIRST match in the tier that wins \u2014 here the ${c.tier} tier \u2014 so which object this one derives its access from is decided by FIELD DECLARATION ORDER. Today "${e.field}" wins and every row's record-level access derives from "${e.master}"; reordering these fields moves that security boundary to another object, and the runtime reports nothing when it does.`,hint:`Leave exactly ONE candidate in the winning tier, so the master is authored rather than positional. Either promote the intended master into a higher tier — make it the object's only required master_detail ({ type: 'master_detail', reference: '<master_object>', required: true }) — or demote the others in this tier (drop required, or change the relation type). Precedence is required master_detail, then any master_detail, then a required lookup; only a tie inside the tier that WINS is ambiguous.`})}typeof s==`string`&&(cf[s]?n.push({severity:`error`,rule:Wd,where:`object "${i}"`,path:`${a}.externalSharingModel`,message:`externalSharingModel '${s}' ${df(s)}.`,hint:`Replace with the canonical value: externalSharingModel: '${cf[s]}'.`}):typeof o==`string`&&s in lf&&o in lf&&lf[s]>lf[o]&&n.push({severity:`error`,rule:Gd,where:`object "${i}"`,path:`${a}.externalSharingModel`,message:`externalSharingModel '${s}' is WIDER than the internal sharingModel '${o}' \u2014 the external baseline must never exceed the internal one (ADR-0090 D11).`,hint:`Narrow externalSharingModel to '${o}' or below (ordering: private < public_read < public_read_write).`}))}let s=qn(e);for(let e=0;e<i.length;e++){let t=i[e];if(!t||typeof t!=`object`)continue;let r=typeof t.name==`string`?t.name:`(permission set ${e})`,a=`permissions[${e}]`,c=t.objects&&typeof t.objects==`object`?t.objects:{},l=t.fields&&typeof t.fields==`object`?t.fields:{};for(let e of Object.keys(l))e.includes(`.`)||n.push({severity:`error`,rule:Qd,where:`permission set "${r}"`,path:`${a}.fields["${e}"]`,message:`field-permission key '${e}' is not object-qualified \u2014 the runtime matches FLS keys by '<object>.<field>' prefix, so a bare key is silently IGNORED and the declared masking never enforces.`,hint:`Qualify the key with its object, e.g. 'crm_opportunity.${e}': { readable: true, editable: false }.`});for(let e of Object.keys(l)){let t=e.indexOf(`.`);if(t<0)continue;let i=e.slice(0,t),o=e.slice(t+1);if(!s.has(i))continue;let c=s.get(i);if(!c||c.names.has(o)||c.injected.has(o))continue;let l=o.length===0,u=[...c.names].sort(),d=u.length<=12?u.join(`, `):`${u.slice(0,12).join(`, `)}, \u2026`,f=l?`field-permission key '${e}' names NO field \u2014 everything after the '${i}.' prefix is empty`:`field-permission key '${e}' is object-qualified but "${i}" declares no field '${o}'`,p=l?`A truncated key is what a half-finished edit leaves behind.`:`Unlike an unqualified key this one looks correct in review, and it is exactly what a field rename leaves behind.`;n.push({severity:`error`,rule:$d,where:`permission set "${r}"`,path:`${a}.fields["${e}"]`,message:`${f}. The runtime resolves an FLS key by stripping the '${i}.' prefix and looking the remainder up as a column, so this key matches NOTHING: the masking it declares NEVER ENFORCES, and the field it was meant to cover stays as readable and as editable as the object-level grant leaves it \u2014 for every holder of this set. Nothing reports that at runtime. ${p}`,hint:`Point the key at a field "${i}" really declares (${d}), or delete the entry if the field is gone \u2014 an entry that cannot match is not protection. If the masking is still wanted, renaming the key is the fix; if the field was renamed, the mask has been off since that rename.`})}let u=c[`*`];if(u&&(u.viewAllRecords===!0||u.modifyAllRecords===!0)&&n.push({severity:`error`,rule:Kd,where:`permission set "${r}"`,path:`${a}.objects.*`,message:`'*' wildcard carrying View All / Modify All Data — a package-authored superuser. Only the platform's own admin set may combine the wildcard with VAMA (ADR-0066).`,hint:`Enumerate the objects this set really needs, or drop viewAllRecords/modifyAllRecords from the wildcard entry. App-level admins belong in an ordinary set the customer binds to a position of their choosing (ADR-0090 D9).`}),t.isDefault===!0){let e=ue(t,`everyone`,o);e&&n.push({severity:`error`,rule:qd,where:`permission set "${r}"`,path:`${a}.isDefault`,message:`isDefault:true suggests binding this set to the 'everyone' audience anchor, but it carries ${e} \u2014 the runtime will refuse the binding (ADR-0090 D5/D9).`,hint:`Split the powerful bits into a separate set granted through ordinary positions, and keep the everyone-suggested set low-privilege.`})}}let c=new Set(i.map(e=>typeof e.name==`string`?e.name:void 0).filter(e=>!!e));for(let[t,r]of w(e.books).entries()){let e=r.audience;if(!e||typeof e!=`object`)continue;let i=e.permissionSet;typeof i==`string`&&i.length!==0&&(c.has(i)||n.push({severity:`warning`,rule:Yd,where:`book "${String(r.name??t)}"`,path:`books[${t}].audience.permissionSet`,message:`book audience references permission set "${i}", which this stack does not declare. The runtime fails closed \u2014 no holder means NO reader can open the book.`,hint:`Gate the book on one of this package's own permission sets (ADR-0090 D9, e.g. its admin set), or fix the typo. Ignore if the set is intentionally provided by another installed package.`}))}let l=new Set(r.filter(e=>e&&typeof e==`object`&&!ff(e)).filter(e=>{let t=uf(e);return t==null||t===`private`}).map(e=>String(e.name??``)));if(l.size>0)for(let e=0;e<i.length;e++){let t=i[e];if(!t||typeof t!=`object`)continue;let r=typeof t.name==`string`?t.name:`(permission set ${e})`,a=t.objects&&typeof t.objects==`object`?t.objects:{};for(let[t,i]of Object.entries(a)){if(!l.has(t))continue;let a=i??{};a.allowRead===!0&&a.readScope==null&&a.viewAllRecords!==!0&&n.push({severity:`info`,rule:Xd,where:`permission set "${r}"`,path:`permissions[${e}].objects.${t}.readScope`,message:`"${t}" is private (OWD) and this set grants allowRead without a readScope \u2014 holders see ONLY records they own (plus explicit shares).`,hint:`If that is intended (personal data), ignore this. Otherwise add readScope: 'own_and_reports' | 'unit' | 'unit_and_below' | 'org', or widen the object's sharingModel.`})}}if(i.length>0&&!i.some(e=>bf(e.objects?.[`*`]??{}))){let e=new Set;for(let t of i){let n=t.objects&&typeof t.objects==`object`?t.objects:{};for(let[t,r]of Object.entries(n))t!==`*`&&bf(r??{})&&e.add(t)}for(let t=0;t<r.length;t++){let i=r[t];if(!i||typeof i!=`object`||ff(i))continue;let a=typeof i.name==`string`?i.name:``;if(!a||e.has(a))continue;let o=gf(i);if(!o)continue;let s=o.parent?` \u2192 "${o.parent}"`:``;n.push({severity:`warning`,rule:Zd,where:`object "${a}"`,path:`objects[${t}].fields.${o.name}`,message:`detail object "${a}" (master_detail "${o.name}"${s}) has no object-level CRUD grant in any permission set. A master-detail child derives its RECORD-level access from the master (ADR-0055 controlled_by_parent), but object-level CRUD is a SEPARATE gate that is never derived \u2014 role-bound non-admin users are denied (403) before the parent-derived access is ever consulted (the silent "can't submit the subtable" trap).`,hint:`Grant "${a}" in at least one permission set that already grants its master${o.parent?` "${o.parent}"`:``} \u2014 e.g. permissions[i].objects.${a} = { allowRead: true, allowCreate: true, allowEdit: true }. If no role should ever touch it (a pure system/internal table), name it sys_* or set isSystem: true.`})}}let u=new Set([`sys_user_position`,`sys_user_permission_set`]),d=new Set([`sys_user_position`]),f=t?.nowMs??Date.now();for(let[t,r]of w(e.data).entries()){let e=typeof r.object==`string`?r.object:``;if(!u.has(e))continue;let i=Array.isArray(r.records)?r.records:[];for(let r=0;r<i.length;r++){let a=i[r]??{},o=`seed "${e}" record #${r}`,s=a.valid_until;if(s!=null&&s!==``){let e=typeof s==`number`?s<0xe8d4a51000?s*1e3:s:s instanceof Date?s.getTime():typeof s==`string`?Date.parse(s):NaN;(Number.isNaN(e)||e<=f)&&n.push({severity:`error`,rule:ef,where:o,path:`data[${t}].records[${r}].valid_until`,message:Number.isNaN(e)?`valid_until ${JSON.stringify(s)} is not a parseable timestamp \u2014 the resolver fails closed (ADR-0091 D2), so this grant will NEVER be active.`:`valid_until ${JSON.stringify(s)} is already in the past \u2014 this grant is expired at authoring time and will never resolve (ADR-0091 D2 filters it fail-closed).`,hint:`Set valid_until to a future instant (ISO-8601 UTC), or drop the column for an unbounded grant. If the row is a historical record, it belongs in audit history, not seed data.`})}let c=a.delegated_from;if(d.has(e)&&c!=null&&c!==``){let e=a.reason;(typeof e!=`string`||e.trim().length===0)&&n.push({severity:`error`,rule:tf,where:o,path:`data[${t}].records[${r}].reason`,message:`delegation row (delegated_from = ${JSON.stringify(c)}) has no reason. ADR-0091 D3 requires a mandatory reason on every delegation for the dual audit trail (granted_by = writer, delegated_from = authority source, reason = why).`,hint:`Add reason: 'vacation stand-in for 张三, 2026-08-01..15' (free text, required).`})}}}return n}function Sf(e){let t=[];if(!e||typeof e!=`object`)return t;let n=w(e.objects),r=w(e.permissions),i=(e,n,r,i,a,o=`name`)=>{pf(n)?t.push({severity:`error`,rule:Jd,where:i,path:a,message:`${e} ${o} "${String(n)}" uses the reserved word "role" \u2014 the platform vocabulary is permission_set (capability), position (distribution), business_unit (hierarchy) (ADR-0090 D3).`,hint:`Rename using 'position' for distribution groups or a domain word (e.g. 'function', 'duty').`}):mf(r)&&t.push({severity:`error`,rule:Jd,where:i,path:`${a.replace(/\.(?:name|key)$/,``)}.label`,message:`${e} label "${String(r)}" uses the reserved word "role" (ADR-0090 D3).`,hint:`Relabel with 'Position' (distribution) or a domain word — admins must meet ONE vocabulary.`})};for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`||ff(t))continue;let r=typeof t.name==`string`?t.name:`(object ${e})`;i(`object`,t.name,t.label,`object "${r}"`,`objects[${e}].name`);for(let n of w(t.fields))i(`field`,n.name,n.label,`field "${r}.${String(n.name??`?`)}"`,`objects[${e}].fields.${String(n.name??`?`)}.name`);for(let[n,a]of w(t.actions).entries())i(`action`,a.name,a.label,`action "${r}.${String(a.name??`?`)}"`,`objects[${e}].actions[${n}].name`);for(let[n,a]of w(t.fieldGroups).entries())i(`field group`,a.key,a.label,`field group "${r}.${String(a.key??`?`)}"`,`objects[${e}].fieldGroups[${n}].key`,`key`)}for(let e=0;e<r.length;e++){let t=r[e];t&&typeof t==`object`&&i(`permission set`,t.name,t.label,`permission set "${String(t.name??e)}"`,`permissions[${e}].name`)}for(let[t,n]of w(e.positions).entries())i(`position`,n.name,n.label,`position "${String(n.name??t)}"`,`positions[${t}].name`);for(let[t,n]of w(e.apps).entries())i(`app`,n.name,n.label,`app "${String(n.name??t)}"`,`apps[${t}].name`);for(let[t,n]of w(e.books).entries())i(`book`,n.name,n.label,`book "${String(n.name??t)}"`,`books[${t}].name`);return t}var Cf=`org-axis-permission-inheritance`,wf=`org-axis-cross-org-bu-grant`,Tf=`parent_organization_id`,Ef=new Set([`business_unit`,`unit_and_subordinates`]);function Df(e){return typeof e==`string`?e:``}function Of(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`){let t=e;if(typeof t.source==`string`)return t.source;if(t.ast!==void 0)return JSON.stringify(t.ast)??``}return``}function kf(e){let t=e.tenancy;if(t&&typeof t==`object`&&t.enabled===!1)return!0;let n=e.systemFields;return!!(n&&typeof n==`object`&&n.tenant===!1)}var Af=`Remove the ${Tf} reference. Cross-organization visibility comes from MEMBERSHIP: under the \`group\` tenancy posture the engine's Layer 0 wall is \`organization_id IN accessible_org_ids\`, so a user who should see several organizations is made a member of them (ADR-0105 D2). A Layer-1 policy cannot widen Layer 0 anyway, so this rule would not grant the access it appears to. For a hierarchy INSIDE one organization, use the business-unit tree (\`unit_and_subordinates\` sharing, or a depth scope anchored on \`sys_user_position\`).`;function jf(e){let t=[],n=e??{};w(n.permissions).forEach((e,n)=>{w(e.rowLevelSecurity).forEach((r,i)=>{for(let a of[`using`,`check`])Df(r[a]).includes(Tf)&&t.push({severity:`error`,rule:Cf,where:`permission set "${Df(e.name)||n}" policy "${Df(r.name)||i}"`,path:`permissions[${n}].rowLevelSecurity[${i}].${a}`,message:`RLS ${a} reads \`${Tf}\`, which builds a permission hierarchy along the organization axis. ADR-0105 D6 forbids it: the org tree is a REPORTING dimension only.`,hint:Af})})}),w(n.sharingRules).forEach((e,n)=>{let r=[{key:`condition`,text:Of(e.condition)},{key:`sharedWith`,text:JSON.stringify(e.sharedWith??``)??``}];for(let i of r)i.text.includes(Tf)&&t.push({severity:`error`,rule:Cf,where:`sharing rule "${Df(e.name)||n}"`,path:`sharingRules[${n}].${i.key}`,message:`Sharing rule ${i.key} reads \`${Tf}\`, granting access by walking the organization tree. ADR-0105 D6 forbids permission inheritance along the org axis.`,hint:Af})});let r=new Set(w(n.objects).filter(e=>kf(e)).map(e=>Df(e.name)).filter(Boolean));return w(n.sharingRules).forEach((e,n)=>{let i=Df(e.object);if(!i||!r.has(i))return;let a=e.sharedWith,o=Df(a?.type);if(!Ef.has(o))return;let s=o===`unit_and_subordinates`?`a business unit AND every descendant unit`:`a business unit`;t.push({severity:`error`,rule:wf,where:`sharing rule "${Df(e.name)||n}" on object "${i}"`,path:`sharingRules[${n}].sharedWith`,message:`Sharing rule recipient \`${o}\` (${s}) targets "${i}", which opted out of tenancy (\`tenancy.enabled: false\`). Platform-global objects carry no organization column, so this grant spans EVERY organization \u2014 a cross-organization business-unit grant, which ADR-0105 D6 forbids (BU trees are org-internal).`,hint:"Either scope the object to organizations (drop `tenancy.enabled: false` so Layer 0 walls it), or share it to a `user` / `team` / `position` audience instead — those expand flat, with no business-unit tree to resolve. A platform-global catalog that everyone should read wants an OWD of `public_read`, not a BU grant."})}),t}var Mf=`rls-predicate-unenforceable`,Nf=`rls-predicate-unparseable`,Pf=`rls-predicate-over-budget`,Ff=`rls-predicate-unknown-field`,If=`rls-predicate-unknown-user-variable`;function Lf(e){return typeof e==`string`?e:``}var Rf="The lowerable subset is: `==` `!=` `>` `<` `>=` `<=`, `in`, `&&` `||` `!`, `== null` / `!= null`, and the string methods `startsWith` / `endsWith` / `contains` — over SINGLE-column field paths (ADR-0058 D2), compared against a literal or a `current_user.*` value.";function zf(e){let t=Wt(e);return!t.ok&&t.kind===`bounds`?t.overrun:null}function Bf(e){return e.length>200?`${e.slice(0,197)}...`:e}var Vf=" On an `insert` or `all` policy the same `using` is also the single-record INSERT check whenever no applicable policy for the insert declares a `check` (ADR-0058 D4): when nothing else in that set compiles, every single-record insert it governs fails with `PermissionDeniedError`; when another policy's `using` compiles, that one alone decides the insert.",Hf=" That holds when no other applicable policy for the operation declares a `check` that compiles; when one does, that `check` alone decides and this one contributes nothing.",Uf='so `RLSCompiler` DROPS the policy at request time (one WARN line — "has an uncompilable predicate … and was DROPPED (no enforcement)" — is the only signal, and nothing reports it at authoring time). ',Wf='so `RLSCompiler` DROPS the policy on EVERY request (a request that resolves no value drops it too). The shape check passes, so the "uncompilable predicate" WARN is never logged; the only signal is a per-request "DENY (fail closed)" WARN, emitted only when nothing else applicable compiles, and nothing reports it at authoring time. ';function Gf(e,t=Uf){return e===`using`?t+"When it is the only applicable policy for that object and operation, `compileFilter` returns the `RLS_DENY_FILTER` sentinel instead, which is AND-ed onto the where clause: every select / update / delete on the object matches ZERO rows. When other policies also apply, this one just vanishes from the OR and grants none of the access it appears to."+Vf:t+"On the ADR-0058 D4 write path that leaves the post-image `check` as the `RLS_DENY_FILTER` sentinel, which no record can satisfy: every single-record insert and by-id update the policy governs fails with `PermissionDeniedError`. The policy reads as a write rule and behaves as a blanket refusal."+Hf}var Kf=new Set(qt),qf=[`__objectstack_lint_probe__`],Jf=`__objectstack_lint_probe__`,Yf={id:`userId`,organization_id:`tenantId`};function Xf(e){let t=Yf[e]??e,n=Oe.shape[t];return n?n.safeParse(qf).success?qf:Jf:qf}function Zf(e){let t=/variable "([^"]+)"/.exec(e);return t?t[1]:null}function Qf(){let e={};for(let t of Kf)e[t]=Xf(t);return e}function $f(e,t){return Ke(e,{variables:{current_user:t}})}function ep(e,t,n){let r={...t};tp(r,n,Jf);let i=$f(e,r);return i.ok?!0:i.reason===`unresolved-variable`&&Zf(i.detail)!==n}function tp(e,t,n){let r=t.split(`.`).slice(1);if(r.length===0)return;let i=e;for(let e=0;e<r.length-1;e++){let t=i[r[e]],n=t&&typeof t==`object`&&!Array.isArray(t)?t:{};i[r[e]]=n,i=n}i[r[r.length-1]]=n}function np(e){let t=e.split(`.`);return t.length===2&&t[0]===`current_user`&&Kf.has(t[1])}function rp(e){let t=Qf(),n=[],r=(e=null)=>({filter:null,unresolvedScalars:n,probe:t,refusal:e});for(let i=0;i<32;i++){let i=$f(e,t);if(i.ok)return{filter:i.filter,unresolvedScalars:n,probe:t,refusal:null};if(i.reason!==`unresolved-variable`)return r(i.reason===`unsupported`?i.detail:null);let a=Zf(i.detail);if(!a||!a.startsWith(`current_user.`)||np(a))return r();ep(e,t,a)?(n.push(a),tp(t,a,Jf)):tp(t,a,qf)}return r()}function ip(e,t){if(Array.isArray(e)){for(let n of e)ip(n,t);return}if(e&&typeof e==`object`)for(let[n,r]of Object.entries(e))n===`$field`&&typeof r==`string`&&r?t.add(r):ip(r,t)}function ap(e){let t=new Set,n=e=>{if(Array.isArray(e)){for(let t of e)n(t);return}if(e&&typeof e==`object`)for(let[r,i]of Object.entries(e)){if(r===`$and`||r===`$or`||r===`$not`){n(i);continue}r.startsWith(`$`)||(t.add(r),ip(i,t))}};return n(e),t}var op=`${Jf}swap`;function sp(e,t){let n=[],r=e=>{if(Array.isArray(e)){for(let t of e)r(t);return}if(e&&typeof e==`object`)for(let[i,a]of Object.entries(e)){if(i===`$and`||i===`$or`||i===`$not`){r(a);continue}if(!i.startsWith(`$`)){if(a&&typeof a==`object`&&!Array.isArray(a))for(let[e,r]of Object.entries(a))t(e,r)&&n.push({field:i,op:e,operand:r});else t(`==`,a)&&n.push({field:i,op:`==`,operand:a})}}};return r(e),n}function cp(e,t){let n=[];for(let e of Kf){let r=Array.isArray(t[e]),i=r?op:[op];n.push({variable:`current_user.${e}`,holds:r?`list`:`one value`,context:{...t,[e]:i},marker:i})}let r=Object.assign([op],t);n.push({variable:`current_user`,holds:`context object`,context:r,marker:r}),n.push({variable:`current_user`,holds:`context object`,context:op,marker:op});for(let t of n){let n=Ke(e,{variables:{current_user:t.context}});if(!n.ok)continue;let r=sp(n.filter,(e,n)=>n===t.marker);if(r.length>0)return{variable:t.variable,holds:t.holds,sites:r}}return null}function lp(e){return[...Kf].filter(t=>Array.isArray(Xf(t))===(e===`list`)).sort()}var up=new Map([[`$startsWith`,`startsWith`],[`$endsWith`,`endsWith`],[`$contains`,`contains`]]);function dp(e,t){let n=`record.${t.field}`,r=e.variable,i=up.get(t.op),a=lp(`one value`);if(e.holds===`list`){if(t.op===`==`)return`replace \`${n} == ${r}\` with \`${n} in ${r}\``;if(t.op===`$ne`)return`replace \`${n} != ${r}\` with \`!(${n} in ${r})\``;if(i)return`replace \`${n}.${i}(${r})\` with the membership test \`${n} in ${r}\`, or pass one value: `+a.map(e=>`\`${n}.${i}(current_user.${e})\``).join(` / `)}if(e.holds===`one value`&&t.op===`$in`)return`replace \`${n} in ${r}\` with \`${n} == ${r}\` (and \`!(${n} in ${r})\` with \`${n} != ${r}\`); for a set, name a membership key: `+lp(`list`).map(e=>`\`${n} in current_user.${e}\``).join(` / `);if(e.holds===`context object`){if(t.op===`$in`)return`replace \`${n} in current_user\` with the key that holds the set: `+lp(`list`).map(e=>`\`${n} in current_user.${e}\``).join(` / `)+`, or an app-staged \xA77.3.1 set \`${n} in current_user.<key>\``;if(i)return`replace \`${n}.${i}(current_user)\` with the key that holds the string: `+a.map(e=>`\`${n}.${i}(current_user.${e})\``).join(` / `)}return`rewrite the comparison on \`${n}\` so \`${r}\` sits where its value fits`}var fp={list:e=>`\`${e}\` is a membership set: \`ExecutionContext\` declares it, and the kernel resolves it, as a LIST on every request, so no request can ever put one value in this position.`,"one value":e=>`\`${e}\` holds ONE value: \`ExecutionContext\` declares it, and the kernel resolves it, as a scalar on every request, so no request can ever put a list in this position.`,"context object":()=>"`current_user` alone is the whole caller context object on every request, never one value and never one set."},pp={list:'`==` / `!=` compare ONE value and a string method takes ONE string; a membership set is tested with `in` — "one of these" is `x in set`, "none of these" is `!(x in set)`.',"one value":"`in` tests membership in a SET; one value is compared with `==` / `!=`.","context object":"`current_user` is the caller context, not a value: name the key that holds what you mean."};function mp(e,t,n){if(!Object.values(t).every(e=>typeof e==`string`||Array.isArray(e)))return null;try{return Re(e,void 0,n),te(e,void 0,n),null}catch(e){return e?.code===`INVALID_FILTER`?e instanceof Error?e.message:String(e):null}}var hp=new Map([[`$gt`,`>`],[`$gte`,`>=`],[`$lt`,`<`],[`$lte`,`<=`]]);function gp(e){return typeof e==`string`?JSON.stringify(e):String(e)}function _p(e){let t=[];for(let n of sp(e,(e,t)=>e===`$in`&&Array.isArray(t)&&t.includes(null)||hp.has(e)&&t===null)){let e=`record.${n.field}`;if(n.op===`$in`){let r=n.operand,i=`${e} in [${r.map(gp).join(`, `)}]`,a=r.filter(e=>e!==null);t.push(a.length===0?`replace \`${i}\` with \`${e} == null\``:`replace \`${i}\` with \`(${e} in [${a.map(gp).join(`, `)}] || ${e} == null)\` to keep matching a missing value, or drop the member: \`${e} in [${a.map(gp).join(`, `)}]\``)}else t.push(`replace \`${e} ${hp.get(n.op)} null\` with \`${e} != null\` (has a value) or \`${e} == null\` (has none), or compare against a real bound`)}return t}function vp(e){let t=e.indexOf(`. `);return t===-1?e:e.slice(0,t)}var yp='so `RLSCompiler` DROPS the policy on EVERY request: it runs that same check on every compiled policy filter, before any backend sees it. The shape check passes, so the "uncompilable predicate" WARN is never logged; the only signal is a per-request "DENY (fail closed)" WARN, emitted only when nothing else applicable compiles. ',bp=new Map([[`$eq`,`==`],[`$ne`,`!=`],...hp]);function xp(e){let t=e?.type;return t?Je.has(t)?`\`type: '${t}'\``:ie({type:t,multiple:e.multiple===!0})?e.multiple===!0?`\`type: '${t}'\`, \`multiple: true\``:`\`type: '${t}'\``:null:null}function Sp(e,t,n){let r=new Map,i=sp(n,(e,t)=>bp.has(e)&&!!t&&typeof t==`object`&&!Array.isArray(t)&&typeof t.$field==`string`);for(let n of i){let i=n.operand.$field,a=[];for(let r of new Set([n.field,i])){let n=T(e,t,r),i=n?.kind===`ok`?xp(n.meta):null;i&&a.push(`\`${r}\` is declared ${i}`)}if(a.length===0)continue;let o=`record.${n.field} ${bp.get(n.op)} record.${i}`;r.set(o,{written:o,columns:a})}return[...r.values()]}function Cp(e){let t="every single-record insert and by-id update whose record holds a list or an object in that column is refused (`INVALID_FILTER` / 400) and stores nothing, because the write check compares one value with one value and will not guess what a list means";return e===`using`?`every read this policy scopes is refused on the SQL drivers (\`INVALID_FILTER\` / 400: driver-sql refuses a cross-field comparison against such a column by its declared type), and every by-id update or delete it scopes fails closed (\`PERMISSION_DENIED\` / 403). On an \`insert\`, \`update\` or \`all\` policy the same \`using\` is also the write check whenever no applicable policy for that operation declares a \`check\` (ADR-0058 D4): then ${t}.`:`${t}. The policy reads as a comparison and behaves as a refusal of every write that leaves a list or an object in that column.`}var wp={numeric:`a number`,text:`text`,boolean:`a boolean`,date:`a date`,datetime:`a datetime`,time:`a time of day`},Tp={file:`a file field, which no row filter can compare with another column`,formula:`a formula field, which has no stored column a row filter can read`},Ep=g.map(e=>{let t=re.filter(t=>t.verdict.kind===`class`&&t.verdict.class===e).flatMap(e=>[...e.types]);return`${wp[e]} only with ${wp[e]} (${t.map(e=>`\`${e}\``).join(`, `)})`}).join(`; `);function Dp(e,t,n){let r=T(e,t,n);return r?.kind!==`ok`||!r.meta||typeof r.meta.type!=`string`?null:{name:n,type:r.meta.type,multiple:r.meta.multiple===!0,meta:r.meta}}function Op(e,t){let n=`\`${e.name}\` is declared \`type: '${e.type}'\``;return t.kind===`class`?`${n}, compared as ${wp[t.class]}`:t.reason===`list-or-object`?n:`${n}, ${Tp[t.reason]}`}function kp(e,t,n){let r=new Map,i=sp(n,(e,t)=>bp.has(e)&&!!t&&typeof t==`object`&&!Array.isArray(t)&&typeof t.$field==`string`);for(let n of i){let i=n.operand.$field,a=Dp(e,t,n.field),o=Dp(e,t,i);if(!a||!o||xp(a.meta)||xp(o.meta))continue;let s=Ct(a,o),c;if(s.verdict===`cross-class`)c=[Op(a,{kind:`class`,class:s.left}),Op(o,{kind:`class`,class:s.right})];else if(s.verdict===`no-class`)c=[...s.left.kind===`no-class`?[Op(a,s.left)]:[],...s.right.kind===`no-class`&&o.name!==a.name?[Op(o,s.right)]:[]];else continue;let l=`record.${n.field} ${bp.get(n.op)} record.${i}`;r.set(l,{written:l,columns:c})}return[...r.values()]}function Ap(e){return e.map(e=>`\`${e.written}\`, where ${e.columns.join(` and `)}`).join(`; `)}var jp=`Two columns are compared only within one comparison class — the class decides how their stored values order and equal, and across classes SQL and the in-memory evaluator answer differently — and a file field or a formula field has no class at all, so the platform defines no comparison between these columns`;function Mp(e){let t="the in-process write check refuses the comparison by the same classification (`INVALID_FILTER` / 400), so every insert or update it judges is refused and nothing is stored";return e===`using`?`every read this policy scopes is refused on the SQL drivers (\`INVALID_FILTER\` / 400: driver-sql refuses the comparison by the two columns' declared types), and every by-id update or delete it scopes fails closed (\`PERMISSION_DENIED\` / 403). On an \`insert\`, \`update\` or \`all\` policy the same \`using\` is also the write check whenever no applicable policy for that operation declares a \`check\` (ADR-0058 D4), and there ${t}.`:`${t[0].toUpperCase()}${t.slice(1)}. The policy reads as a write rule and admits no write at all.`}var Np=`Compare a field only with a field of the same comparison class: ${Ep}. A file field and a formula field cannot be compared with another column at all. If the two columns do hold comparable values, one of them is declared with the wrong type: fix the declaration, not the predicate.`;function Pp(e,t){if(t===`variable`){let t="The pushdown compiler answers `unresolved-variable` in EVERY position — including under `!` and in a trailing `||` arm — so `RLSCompiler` DROPS the policy at request time, and one WARN line is the only signal. ";return e===`using`?t+"When it is the only applicable policy for that object and operation the layer falls back to the `RLS_DENY_FILTER` sentinel, which is AND-ed onto the where clause: every select / update / delete matches ZERO rows, so the object DISAPPEARS for every holder of this permission set — not because they were denied, but because the narrowing they were granted resolves to nothing. When other policies also apply, this one vanishes from the OR and grants none of the access it appears to."+Vf:t+"On the ADR-0058 D4 write path that leaves the post-image `check` unsatisfiable: every single-record insert and by-id update the policy governs fails with `PermissionDeniedError`. The policy reads as a write rule and behaves as a blanket refusal for every holder of this permission set."+Hf}let n="`RLSCompiler` judges column existence on the COMPILED predicate, so the position and the polarity you wrote it in make no difference — a leading `field ==`, a negation (`field != x`, `!(field == x)`, `!(field in [...])`) and any arm after the first all lower to the same tree and all DROP the policy at request time, with one WARN line as the only signal. ";return e===`using`?n+"When it is the only applicable policy for that object and operation the layer falls back to the `RLS_DENY_FILTER` sentinel: every select / update / delete matches ZERO rows, so the object DISAPPEARS for every holder of this permission set — not because they were denied, but because the narrowing they were granted names a column that is not there. When other policies also apply, this one vanishes from the OR and grants none of the access it appears to."+Vf:n+"On the ADR-0058 D4 write path that leaves the post-image `check` unsatisfiable: every single-record insert and by-id update the policy governs fails with `PermissionDeniedError`. The policy reads as a write rule and behaves as a blanket refusal for every holder of this permission set."+Hf+` ⚠️ On a runtime older than that guard this clause failed OPEN rather than closed — the write path had no field-existence check at all, so a negated miss was satisfied VACUOUSLY by the post-image and PERMITTED exactly the writes the policy was written to refuse, on every driver. Fix the name rather than relying on either behaviour.`}var Fp=new Set([`select`,`all`]);function Ip(e){let t={},n=!1;for(let[r,i]of Object.entries(e))Kf.has(r)?t[r]=i:(t[r]=[],n=!0);return{probe:t,rebound:n}}function Lp(e,t,n,r,i){let{probe:a,rebound:o}=Ip(i);if(!Object.values(a).every(e=>typeof e==`string`||Array.isArray(e)))return null;let s=r;if(o){let e=$f(n,a);if(!e.ok)return null;s=e.filter}let c=e(t,s,{operation:`find`});return c.ok?null:c}var Rp=`This clause is part of the object's row-level READ SCOPE, and the analytics face hands the read scope to this same engine admission before it runs a query: every analytics query over the object that this policy scopes is refused.`;function zp(e){return e===`FILTER_TOKEN_UNKNOWN`||e===`FILTER_TOKEN_UNRESOLVED`?`A \`{\u2026}\` placeholder is saved-filter syntax, and an RLS predicate does not use it: the predicate is CEL, and the caller's values are the \`current_user\` keys (${$n(Kf)}). Write \`owner == current_user.id\`, not \`owner == '{current_user_id}'\`.`:e===`INVALID_FIELD`?`A row filter reaches only the stored columns of its own object. Denormalise the value the engine names onto this object (a stored field, written when the source changes) and test that column.`:"Rewrite the comparison the engine names so it can run: a text operator (`startsWith` / `endsWith` / `contains`) only on a field that holds a string, and a date or datetime field only against a value its storage can read. "+Rf}function Bp(e,t,n,r,i,a,o){let s=[],c=Ve(t),{filter:l,unresolvedScalars:u,probe:d,refusal:f}=rp(c);for(let o of ap(l)){let c=T(e,a,o);if(Xn(c)||!c)continue;let l=Yn(c,o,`RLS ${n} predicate field`);l&&s.push({severity:`error`,rule:Ff,where:r,path:i,message:`RLS ${n} \`${Bf(t)}\` lowers correctly but does not name a real column: ${l.message} `+Pp(n,`field`),hint:`${l.detail} Point the predicate at a column the object really declares, or delete the policy if the narrowing is gone \u2014 a policy naming a column that does not exist is not protection either way: it is an outage in one position and an open door in the other. If the field was RENAMED, this policy has been wrong since that rename \u2014 check WHICH way before you judge the blast radius, because a negated or non-leading miss has been granting, not denying. If the value was meant to live on another object, RLS cannot join to it (ADR-0055) \u2014 denormalise it onto "${a}" (a formula/rollup field) and test that column instead.`})}for(let e of u){let a=e.slice(13);s.push({severity:`error`,rule:If,where:r,path:i,message:`RLS ${n} \`${Bf(t)}\` reads \`${e}\`, which nothing pre-resolves. The kernel-resolved \`current_user\` keys are exactly ${$n(Kf)}, and the only other keys that can EVER appear are \xA77.3.1 membership sets, which the runtime stages as ARRAYS and which are therefore usable only as \`field in current_user.<key>\` \u2014 this reference is in a scalar position, so no request can ever supply it. `+Pp(n,`variable`),hint:`Use one of the pre-resolved context values (${$n(Kf)})${E(a,Kf)} \u2014 \`current_user.organization_id\` is the tenant, \`current_user.id\` the acting user, \`current_user.email\` their unique address. If "${a}" is meant to be an app-resolved set, it must be staged into \`ExecutionContext.rlsMembership\` by an \`IRlsMembershipResolver\` that DECLARES the key, and it can then only be tested with \`in\` (\`<field> in ${e}\`), never compared with \`==\`: the runtime stages membership sets as arrays and never as scalars.`})}let p=f===null?null:cp(c,d);f!==null&&p&&s.push({severity:`error`,rule:Mf,where:r,path:i,message:`RLS ${n} \`${Bf(t)}\` passes the shape check, but the compiler refuses it for the value \`${p.variable}\` holds on every request (${f}). ${fp[p.holds](p.variable)} `+Gf(n,Wf),hint:`${pp[p.holds]} In this predicate: ${p.sites.map(e=>dp(p,e)).join(`; `)}.`});let m=l?mp(l,d,n):null;if(l&&m!==null){let e=_p(l);s.push({severity:`error`,rule:Mf,where:r,path:i,message:`RLS ${n} \`${Bf(t)}\` lowers, but to a comparand the platform's shared filter check refuses (${vp(m)}), ${Gf(n,yp)}`,hint:e.length>0?`\`null\` has no place inside a list or opposite an ordering operator \u2014 the platform refuses both in every filter it is sent, because no two backends agree on what they match. Test for no value with \`== null\` and for a value with \`!= null\`: ${e.join(`; `)}.`:`Rewrite the comparand the check names inside the lowerable subset. `+Rf})}let h=l?Sp(e,a,l):[];h.length>0&&s.push({severity:`error`,rule:Mf,where:r,path:i,message:`RLS ${n} \`${Bf(t)}\` lowers, but compares a field with a field that holds a list or an object: ${h.map(e=>`\`${e.written}\`, where ${e.columns.join(` and `)}`).join(`; `)}. A column that holds a list or an object is not one comparable value, on either side of a field-to-field comparison, so the platform refuses the comparison instead of evaluating it: `+Cp(n),hint:"A field compared with a `json` or `multiple` field has no row-filter form: a row filter compares one value with one value, and cannot test membership in a list another column holds. Compare with a single-valued column, or with a literal or a `current_user` value — \"one of these values\" is `record.status in ['open', 'pending']` or `record.owner in current_user.org_user_ids` — or move the condition into a validation rule or a hook."});let g=l?kp(e,a,l):[];g.length>0&&s.push({severity:`error`,rule:Mf,where:r,path:i,message:`RLS ${n} \`${Bf(t)}\` lowers, but compares two fields that share no comparison class: ${Ap(g)}. ${jp}: ${Mp(n)}`,hint:`${Np} To keep the rule without a second column, compare with a literal or a \`current_user\` value, test a file field with \`!= null\`, or store the value you mean in a field of the right type and compare that \u2014 or move the condition into a validation rule or a hook.`});let _=o&&l&&s.length===0?Lp(o,a,c,l,d):null;return _&&s.push({severity:`error`,rule:Mf,where:r,path:i,message:`RLS ${n} \`${Bf(t)}\` lowers, but the engine refuses to run the lowered filter on "${a}" (${_.code} / ${_.status}): ${_.message} ${Rp}`,hint:zp(_.code)}),s}function Vp(e,t={}){let n=[],r=e??{},i=qn(r);return w(r.permissions).forEach((e,r)=>{w(e.rowLevelSecurity).forEach((a,o)=>{for(let s of[`using`,`check`]){let c=Lf(a[s]);if(!c.trim())continue;let l=Lf(e.name)||String(r),u=Lf(a.name)||String(o),d=Lf(a.object),f=`permission set "${l}" policy "${u}"`+(d?` on object "${d}"`:``),p=`permissions[${r}].rowLevelSecurity[${o}].${s}`;if(et(c)){let e=s===`using`&&d&&Fp.has(Lf(a.operation))?t.judgeFilter:void 0;n.push(...Bp(i,c,s,f,p,d,e));continue}let m=Ve(c),h=it(m),g=h.ok?``:h.detail,_=!h.ok&&h.reason===`parse-error`,v=_?zf(m):null,y=f,b=p;if(v){let e=v.limit??`an unnamed platform CEL bound`,t=v.limitValue===null?``:` (platform limit ${v.limitValue})`,r=v.measured===null?``:`, this predicate measures ${v.measured}`;n.push({severity:`error`,rule:Pf,where:y,path:b,message:`RLS ${s} \`${Bf(c)}\` is syntactically valid, lowerable CEL but overruns the platform parse bound ${e}${t}${r} (${v.summary}), `+Gf(s),hint:`There is no syntax or dialect error to correct here \u2014 the predicate is well-formed CEL and is simply too large for ${e}${t}, so the fix is to make it smaller or to move the work off the predicate. (1) Collapse a long \`field == a || field == b || \u2026\` chain into a single \`field in [a, b, \u2026]\`, which is far fewer AST nodes (\`maxListElements\` is 64, so a very large set needs option 2). (2) Pre-resolve the set into a membership key the runtime exposes and test \`field in current_user.<key>\` (ADR-0105 D11) \u2014 one comparison whatever the set size. (3) Denormalise a repeated sub-expression onto this object as a formula/rollup field and test that single column. (4) Split a TOP-LEVEL \`||\` across several \`rowLevelSecurity\` policies: applicable policies are OR-ed, so that is equivalent \u2014 but never split a top-level \`&&\` this way, which would WIDEN access rather than preserve it. Logic genuinely this large is not a row filter: move it to a hook or action body (\`ScriptBody { language: 'js' }\`, the L2 sandboxed surface).`});continue}if(_){n.push({severity:`error`,rule:Nf,where:y,path:b,message:`RLS ${s} \`${c}\` does not parse as CEL even after the legacy SQL bridge (\`=\` \u2192 \`==\`, \`IN\` \u2192 \`in\`) has been applied (${g}), `+Gf(s),hint:"Author the predicate in canonical CEL (ADR-0058 D1). The bridge covers only the historic SQL subset — a bare `=` and `IN` — so everything else must already be CEL: combine with `&&` / `||` rather than SQL `AND` / `OR`, negate with `!`, and use `startsWith` / `endsWith` / `contains` rather than `LIKE`. A subquery has no CEL spelling at all: RLS cannot join (ADR-0055), so pre-resolve the set into a membership key the runtime exposes (`field in current_user.<key>`, ADR-0105 D11) or denormalise the value onto this object."});continue}n.push({severity:`error`,rule:Mf,where:y,path:b,message:`RLS ${s} \`${c}\` is outside the pushdown subset the runtime can compile (${g}), `+Gf(s),hint:`Rewrite the predicate inside the lowerable subset. `+Rf+" Three traps in particular: (1) a function call — `size(record.tags) > 0`, `has(record.x)` — is correct in an object VALIDATION rule, which is INTERPRETED, and wrong here, where the predicate is COMPILED to a filter; write the null test as `field != null`. (2) A related-record path (`record.account.region`) is a join, which the compiler refuses by design (ADR-0055) — denormalise the value onto this object (a formula/rollup field) and test that column. (3) Arithmetic on a column (`amount * 2 > 100`) never lowers — precompute it into a field, or compare the column against the literal directly."})}})}),n}var Hp=`sharing-rule-unlowerable-condition`,Up=`sharing-rule-runtime-variable-condition`,Wp=`sharing-rule-object-not-shareable`,Gp=`sharing-rule-object-controlled-by-parent`;function Kp(e){return typeof e==`string`?e:``}function qp(e){if(typeof e==`string`)return e.trim()?e:null;if(e&&typeof e==`object`){let t=e.source;if(typeof t==`string`&&t.trim())return{source:t}}return null}function Jp(e){let t=qp(e);return typeof t==`string`?t:Kp(t?.source)}var Yp="The lowerable subset is: `==` `!=` `>` `<` `>=` `<=`, `in`, `&&` `||` `!`, `== null` / `!= null`, and the string methods `startsWith` / `endsWith` / `contains` — over SINGLE-column `record.<field>` paths (ADR-0058 D2).";function Xp(e,t,n,r){let i=Sp(e,t,n);return i.length===0?null:{severity:`error`,rule:Hp,where:r.where,path:r.path,message:`Sharing-rule condition \`${r.source}\` lowers, but compares a field with a field that holds a list or an object: ${i.map(e=>`\`${e.written}\`, where ${e.columns.join(` and `)}`).join(`; `)}. A column that holds a list or an object is not one comparable value, on either side of a field-to-field comparison, so the platform refuses the comparison instead of evaluating it: the rule is seeded into \`sys_sharing_rule\`, but every criteria query it runs is refused on the SQL drivers (\`INVALID_FILTER\` / 400: driver-sql refuses a cross-field comparison against such a column by its declared type), and \`SharingRuleService\` reads a refused query as matching no record. No \`sys_record_share\` grant is ever materialised, at boot or on any later write, and the only signal is a WARN line in the server log. The rule is declared and grants nothing.`,hint:"A field compared with a `json` or `multiple` field has no row-filter form: a row filter compares one value with one value, and cannot test membership in a list another column holds. Compare with a single-valued column, or with a literal — \"one of these values\" is `record.status in ['open', 'pending']` — or keep the value the rule keys on in a single-valued field and compare with that."}}function Zp(e,t,n,r){let i=kp(e,t,n);return i.length===0?null:{severity:`error`,rule:Hp,where:r.where,path:r.path,message:`Sharing-rule condition \`${r.source}\` lowers, but compares two fields that share no comparison class: ${Ap(i)}. ${jp}: the rule is seeded into \`sys_sharing_rule\`, but every criteria query it runs is refused on the SQL drivers (\`INVALID_FILTER\` / 400: driver-sql refuses the comparison by the two columns' declared types), and \`SharingRuleService\` reads a refused query as matching no record. No \`sys_record_share\` grant is ever materialised, at boot or on any later write, and the only signal is a WARN line in the server log. The rule is declared and grants nothing.`,hint:`${Np} To keep the rule without a second column, compare with a literal \u2014 "one of these values" is \`record.status in ['open', 'pending']\` \u2014 or test a file field with \`!= null\`.`}}function Qp(e){let t=e.sharingModel;return t===`private`?`private`:t===`public_read`?`read`:t===`public_read_write`||t===`controlled_by_parent`||t==null&&(e.isSystem===!0||Kp(e.name).startsWith(`sys_`))?`public`:`private`}function $p(e){for(let t of w(e.fields))if(t.type===`master_detail`){let e=be({reference:t.reference},`validate-sharing-rule-enforceability masterOf`);if(e)return e}}function em(e,t,n){let r=Kp(e.object);if(!r)return[];let i=n.get(r);if(!i)return[];let a=Kp(e.name)||String(t),o=`sharing rule "${a}" on object "${r}"`,s=`sharingRules[${t}].object`,c=i.sharingModel;if(c===`controlled_by_parent`){let e=$p(i);return[{severity:`error`,rule:Gp,where:o,path:s,message:`Sharing rule "${a}" is anchored on object "${r}", which declares sharingModel 'controlled_by_parent'. A detail record has no record-level access of its own \u2014 its visibility is DERIVED from its master (ADR-0055), so it holds no shares to widen. \`SharingService.assertNotInertGrant\` refuses the grant with SHARING_NOT_ENABLED ("'${r}' is controlled by its parent (master-detail); share the master record instead"), so the rule's boot backfill fails, no \`sys_record_share\` row is ever written, and the recipients this rule names get whatever the MASTER grants them \u2014 which may be nothing. The grant is declared and does not exist.`,hint:`Move the rule onto the MASTER object`+(e?` \u2014 "${r}" derives from "${e}" through its master_detail field, so share "${e}" and the detail rows follow`:`, and share that instead; the detail rows follow`)+`. If "${r}" is meant to carry a record-level baseline of its own, that is a different decision: change its sharingModel to 'private' (owner + shares) or 'public_read', and this rule becomes enforceable where it stands.`}]}return Qp(i)===`public`?[{severity:`error`,rule:Wp,where:o,path:s,message:`Sharing rule "${a}" is anchored on object "${r}", which ${c===`public_read_write`?`declares sharingModel 'public_read_write'`:"declares no sharingModel and is a system object (`isSystem: true` or a `sys_` name), which ADR-0090 D1 resolves to public"}. Its effective sharing model is therefore \`public\`, and sharing only ever WIDENS an OWD baseline \u2014 on the widest baseline there is nothing left to widen. \`SharingService.assertNotInertGrant\` refuses the grant with SHARING_NOT_ENABLED ("'${r}' is not under record-sharing enforcement"), so the rule's boot backfill fails and no \`sys_record_share\` row is ever written. Measured: \`buildReadFilter\` returns \`null\` for this object, i.e. NO record-level filter at all \u2014 every principal already reads every row, so this rule advertises a restriction that does not exist.`,hint:`Decide which half is wrong. If the ACCESS is right \u2014 everyone should read and write these records \u2014 the rule is dead metadata: delete it (ADR-0049 enforce-or-remove). If the RULE is right \u2014 only the named audience should reach these records \u2014 then "${r}"'s OWD is the defect: set sharingModel: 'private' (owner + shares) or 'public_read', and this rule starts enforcing. Do NOT re-home the rule onto another public object; that moves the inertness instead of removing it.`}]:[]}function tm(e){let t=[],n=e??{},r=new Map;for(let e of w(n.objects)){let t=Kp(e.name);t&&r.set(t,e)}let i=new Map,a=e=>{let t=r.get(e);if(!t)return null;let n=i.get(e);return n||(n=qn({objects:[t]}),i.set(e,n)),n};return w(n.sharingRules).forEach((e,n)=>{em(e,n,r).forEach(e=>t.push(e));let i=qp(e.condition);if(i===null)return;let o=Kp(e.name)||String(n),s=Kp(e.object),c=`sharing rule "${o}"${s?` on object "${s}"`:``}`,l=`sharingRules[${n}].condition`,u=Jp(e.condition),d=Ke(i,{variables:{}});if(d.ok){let e=s?a(s):null,n=e?Xp(e,s,d.filter,{where:c,path:l,source:u}):null;n&&t.push(n);let r=e?Zp(e,s,d.filter,{where:c,path:l,source:u}):null;r&&t.push(r);return}if(d.reason!==`parse-error`){if(d.reason===`unresolved-variable`){t.push({severity:`error`,rule:Up,where:c,path:l,message:`Sharing-rule condition \`${u}\` reads a runtime variable (${d.detail}), so \`bootstrapDeclaredSharingRules\` SKIPS the rule at boot: it is never written to \`sys_sharing_rule\`, no \`sys_record_share\` grant is ever materialised, and the only signal is one WARN line in the boot log. The rule is declared and grants nothing (ADR-0049: an unlowerable condition is never seeded as a permissive match-all).`,hint:'A criteria sharing rule is MATERIALISED: the seeder compiles ONE static `criteria_json` per rule and the evaluator writes `sys_record_share` rows from it, so there is no "current user" for the condition to read. WHICH mechanism replaces it depends on the anchor object\'s `sharingModel`, because the security layers are AND-composed (`getReadFilter` = RLS AND controlled-by-parent AND sharing) and an AND term can only REMOVE rows — it can never add one back. On `public_read` / `public_read_write` the sharing layer imposes nothing on reads (`buildReadFilter` constrains `private` only), so an RLS policy on a permission set (`rowLevelSecurity[].using`, where `current_user.*` IS resolved) is the right mechanism: it NARROWS an open baseline, the direction AND can express. On `private` — including a CUSTOM object that declares no `sharingModel`, which resolves to `private` (ADR-0090 D1) — that same policy CANNOT work: the sharing layer has already withheld the row, and AND-ing an RLS predicate onto it can only withhold more, so the policy lints clean, passes every gate and grants nothing. The two doors that widen a `private` object for a non-admin principal both key on WHO OWNS the row or on an explicit share row, never on a property of the record: the ADR-0057 D1 depth scopes (`readScope` / `writeScope` on the object permission — `own` | `own_and_reports` | `unit` | `unit_and_below` | `org`), which widen the owner-match to `owner_id IN (…)`; and a `sys_record_share` row, which on this path only a criteria sharing rule writes — i.e. THIS rule. So keep this rule for the part of the predicate that is a property of the RECORD (e.g. `record.stage == \'closed_won\'`) and name the audience through `sharedWith`. If the audience is genuinely record-relative ("the owner\'s manager", "this record\'s approver"), no mechanism expresses it today — `sharedWith` recipients resolve tenant-wide, so reaching for `position` shares every matched row with EVERY holder of that position (the skip-level, the manager two teams over): an over-broad grant, not the narrower one you meant. That is a known gap in the platform, not something a different spelling of this rule can close — leave the grant unauthored rather than widening it, and ask for record-relative sharing recipients.'});return}t.push({severity:`error`,rule:Hp,where:c,path:l,message:`Sharing-rule condition \`${u}\` is outside the pushdown subset the runtime can compile (${d.detail}), so \`bootstrapDeclaredSharingRules\` SKIPS the rule at boot: it is never written to \`sys_sharing_rule\`, no \`sys_record_share\` grant is ever materialised, and the only signal is one WARN line in the boot log. The rule is declared and grants nothing (ADR-0049: an unlowerable condition is never seeded as a permissive match-all).`,hint:`Rewrite the predicate inside the lowerable subset. `+Yp+" Two traps in particular: (1) `has(record.x)` is correct in an object VALIDATION rule, which is INTERPRETED, and wrong here, where the condition is COMPILED — write the null test as `record.x != null`; (2) a related-record path (`record.account.region`) is a join, which the compiler refuses by design (ADR-0055) — denormalise the value onto this object (a formula/rollup field) and test that column, or share the related object instead."})}}),t}var nm=`dashboard-action-target-undefined`,rm=`dashboard-action-route-unresolved`;function I(e){return typeof e==`string`&&e.length>0?e:void 0}var im={app:`apps`,apps:`apps`,object:`objects`,objects:`objects`,report:`reports`,reports:`reports`,dashboard:`dashboards`,dashboards:`dashboards`,page:`pages`,pages:`pages`,view:`views`,views:`views`};function am(e){return I(e.name)??I(e.id)??I(e.object)??I(e.list?.data&&e.list.data.object)??I(e.form?.data&&e.form.data.object)}function om(e){let t=new Set,n=new Set,r=new Set,i=new Set,a=new Set,o=new Set,s=new Set,c=(e,t,n)=>{for(let r of w(e)){if(!r||typeof r!=`object`)continue;let e=n(r);e&&t.add(e)}};c(e.actions,t,e=>I(e.name)),c(e.apps,n,e=>I(e.name));for(let n of w(e.objects)){if(!n||typeof n!=`object`)continue;let e=I(n.name);e&&r.add(e),c(n.actions,t,e=>I(e.name))}c(e.reports,i,e=>I(e.name)),c(e.dashboards,a,e=>I(e.name)),c(e.pages,o,e=>I(e.name)),c(e.views,s,am);for(let e of r)s.add(e);return{actions:t,apps:n,objects:r,reports:i,dashboards:a,pages:o,views:s}}function sm(e,t,n){return e===`modal`?n.pages.has(t):n.actions.has(t)}function cm(e,t){if(/^[a-z][a-z0-9+.-]*:\/\//i.test(e)||e.startsWith(`//`)||e.includes("${")||!e.startsWith(`/`))return[];let n=e.split(/[?#]/,1)[0].split(`/`).filter(Boolean),r=[];for(let e=0;e<n.length-1;e++){let i=im[n[e]];if(!i)continue;let a=n[e+1];t[i].has(a)||r.push({collection:n[e],name:a})}return r}function lm(e){let t=[];if(!e||typeof e!=`object`)return t;let n=w(e.dashboards);if(n.length===0)return t;let r=om(e),i=(e,n,i)=>{let a=I(e.actionUrl);if(!a||a.includes("${"))return;let o=I(e.actionType)??`url`;if(o===`script`||o===`modal`){if(sm(o,a,r))return;t.push({severity:`error`,rule:nm,where:n,path:i,message:o===`modal`?`modal action target "${a}" names no declared page \u2014 a modal target names a PAGE, only (objectstack#6739). The button renders but the runtime refuses the dispatch when clicked \u2014 a dangling reference (ADR-0049: a declared reference must resolve).`:`script action target "${a}" resolves to no defined action. The button renders but does nothing when clicked \u2014 a dangling reference the runtime cannot dispatch (ADR-0049: a declared reference must resolve).`,hint:o===`modal`?`Point actionUrl at a declared page (stack.pages), or use actionType: 'form' with an "<object>.<view>" form-view target to open an object's form, or remove the button.`:`Define a script action named "${a}" (stack.actions or the object's actions) with an inline body or a registered handler, or remove the button.`});return}if(o===`url`){let e=cm(a,r);for(let r of e)t.push({severity:`warning`,rule:rm,where:n,path:i,message:`url action target "${a}" points at ${r.collection}/${r.name}, but no ${r.collection.replace(/s$/,``)} named "${r.name}" is registered in this stack \u2014 the button likely navigates to a dead route.`,hint:`Check the path for a typo, define the referenced ${r.collection.replace(/s$/,``)}, or ignore this if the route is served by another installed package or a host/console route.`});return}};for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`)continue;let r=I(t.name)??`(dashboard ${e})`,a=`dashboards[${e}]`,o=w(t.header?.actions);for(let e=0;e<o.length;e++){let t=o[e];t&&typeof t==`object`&&i(t,`dashboard "${r}" \xB7 header action "${I(t.label)??I(t.actionUrl)??`#${e}`}"`,`${a}.header.actions[${e}].actionUrl`)}}return t}var um="Remove the key: on a dataset-bound widget it styles nothing. Presentation has declared homes instead: a number's face is the dataset measure's `format` and `currency`, a tile's accent is the widget's `colorVariant`, and a chart's look is the widget's `chartConfig`. A key with a genuine consumer outside the renderer can say so with `suppressWarnings: ['unconsumed-widget-option']` on the widget.",dm=e=>typeof e==`object`&&!!e&&!Array.isArray(e);function fm(e){let t=[],n=w(e.dashboards);for(let e=0;e<n.length;e++){let r=n[e],i=typeof r.name==`string`&&r.name!==``?r.name:`(dashboard ${e})`,a=Array.isArray(r.widgets)?r.widgets:[];for(let n=0;n<a.length;n++){let r=a[n],o=Array(a.length);o[n]=r;let s=_n({type:`dashboard`,widgets:o});if(s.length===0)continue;let c=dm(r)&&typeof r.id==`string`&&r.id!==``?r.id:`(widget ${n})`;for(let r of s)t.push({severity:r.severity,rule:r.code,where:`dashboard "${i}" \u203A widget "${c}"`,path:`dashboards[${e}].widgets[${n}].options`,message:r.message,hint:um})}}return t}var pm=`filter-token-unknown`,mm=de.join(`}, {`),hm=[{key:`dashboards`,kind:`dashboard`,noun:`a dashboard`},{key:`objects`,kind:`object`,noun:`an object definition (its list views and field filters)`},{key:`views`,kind:`view`,noun:`a view`},{key:`reports`,kind:`report`,noun:`a report`},{key:`datasets`,kind:`dataset`,noun:`a dataset`},{key:`pages`,kind:`page`,noun:`a page`},{key:`apps`,kind:`app`,noun:`an app`}],gm=`record`;function _m(e){let t=e.type===void 0?gm:e.type;return t===gm?{recordInContext:!0,surface:`a record page`}:{recordInContext:!1,surface:`a page of type ${JSON.stringify(t)}`}}function vm(e,t){let n=e.name??e.id;return typeof n==`string`&&n.length>0?n:`#${t}`}function ym(e,t,n,r,i){return{severity:`error`,rule:pm,where:r,path:n,message:`Filter value "${e}" stands for the record in context, and there is no record in context on this surface (${i.surface}). {${t}} resolves only in a filter on a component of a \`type: 'record'\` page, where the renderer knows which record is in view. Anywhere else the server refuses the query rather than counting every record or none.`,hint:"Move this filter onto a component of a record page (`type: 'record'`), or filter on a concrete id. To scope to the signed-in user instead, use {current_user_id}."}}function bm(e,t,n,r,i,a){if(e!=null){if(typeof e==`string`){let a=Ge(e);if(a?.kind===`record-context`&&!r.recordInContext)i.push(ym(e,a.token,t,n,r));else if(a?.kind===`unknown`){let r=a.suggestion;i.push({severity:`error`,rule:pm,where:n,path:t,message:`Filter value "${e}" is not a resolvable placeholder. It is sent to the data engine as a literal string, matches no record, and the surface renders empty.`,hint:r&&se(r)?`Did you mean "{${r}}"? It resolves only in a filter on a component of a \`type: 'record'\` page, to the id of the record in view.`:r?`Did you mean "{${r}}"? Context tokens are {${mm}}; time-based values use date macros such as {today} or {30_days_ago}.`:`Resolvable placeholders are the context tokens {${mm}} and the date macros (e.g. {today}, {week_start}, {30_days_ago}). To filter on a literal value that happens to look like a placeholder, this is not supported \u2014 rename the value.`})}return}if(typeof e==`object`&&!a.has(e)){if(a.add(e),Array.isArray(e)){e.forEach((e,o)=>bm(e,`${t}[${o}]`,n,r,i,a));return}for(let[o,s]of Object.entries(e))bm(s,`${t}.${o}`,n,r,i,a)}}}function xm(e){if(!e||typeof e!=`object`)return[];let t=[],n=e=>({value:n,path:r,where:i})=>{bm(n,r,i,e,t,new Set)};for(let t of hm){if(t.kind===`page`){w(e[t.key]).forEach((e,r)=>{nr(e,`${t.key}[${r}]`,`${t.kind} "${vm(e,r)}"`,n(_m(e)))});continue}rr(e,[t],n({recordInContext:!1,surface:t.noun}))}return t}var Sm=`flow-filter-token-unknown`,Cm=[{key:`flows`,kind:`flow`}];function wm(e){if(Ai.includes(e))return`${e}() is supported only as the whole token, with an optional \xB1 N day offset \u2014 write {${e}() + 7}.`;let t=(e.includes(`.`)?e.slice(e.lastIndexOf(`.`)+1):e).toLowerCase(),n=ji.includes(t)?t:Fe(t,ji),r=n?` Did you mean '${n}'?${e.includes(`.`)?` Method/namespace call syntax is not supported — write the bare form.`:``}`:``;return`Flow filter values resolve in two vocabularies: the flow template dialect \u2014 {NOW()} / {TODAY()} with an optional \xB1 N day offset, {$User.Id}, {record.<field>}, and the value functions ${ji.join(`, `)} \u2014 and, for a token the evaluator does not resolve, the filter placeholders ({current_user_id}, {today}, {30_days_ago}).${r}`}function Tm(e,t,n,r,i){if(e!=null){if(typeof e==`string`){let i=Ge(e);if(i?.kind!==`unknown`)return;let a=Ni(i.token);if(a.kind!==`unknown-function`)return;r.push({severity:`error`,rule:Sm,where:n,path:t,message:`Filter value "${e}" calls '${a.name}', which is not a function in the flow template dialect and is not a filter placeholder either. The node does not query with an unresolved condition \u2014 the template evaluator raises a guard refusal, so this node cannot run at all.`,hint:wm(a.name)});return}if(typeof e==`object`&&!i.has(e)){if(i.add(e),Array.isArray(e)){e.forEach((e,a)=>Tm(e,`${t}[${a}]`,n,r,i));return}for(let[a,o]of Object.entries(e))Tm(o,`${t}.${a}`,n,r,i)}}}function Em(e){if(!e||typeof e!=`object`)return[];let t=[];return rr(e,Cm,({value:e,path:n,where:r})=>{Tm(e,n,r,t,new Set)}),t}var Dm=`filter-preset-comparand`,Om=[{key:`dashboards`,kind:`dashboard`},{key:`objects`,kind:`object`},{key:`views`,kind:`view`},{key:`reports`,kind:`report`},{key:`datasets`,kind:`dataset`},{key:`pages`,kind:`page`},{key:`apps`,kind:`app`},{key:`flows`,kind:`flow`}],km=new Set([`$gt`,`$gte`,`$lt`,`$lte`]),Am=new Set([`>`,`>=`,`<`,`<=`]),jm=new Set([`greater_than`,`greater_than_or_equal`,`less_than`,`less_than_or_equal`,`before`,`after`]),Mm=new Set([`$eq`,`$ne`]),Nm=new Set([`$in`,`$nin`]),Pm=new Set([`=`,`!=`]),Fm=new Set([`in`,`nin`]),Im=new Set([`equals`,`not_equals`]),Lm=new Set([`in`,`not_in`]),Rm=new Set([`date`,`datetime`]),zm=32;function Bm(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&!(e instanceof Date)}function Vm(e){return typeof e==`string`&&e.length>0?e:void 0}function Hm(e){let t=Vm(e);return t&&!t.includes(`{`)?t:void 0}function L(e,t,n,r){return{severity:`error`,rule:Dm,where:e,path:t,message:bt(n,r),hint:`Presets belong to the dashboard date-filter bar (dateRange.defaultRange, a date global filter's defaultValue). In a filter comparand, write the {date-macro} window the message names, or an ISO date.`}}var Um=()=>!1;function Wm(e,t){return t?n=>{let r=T(e,t,n);if(!r||r.kind!==`ok`)return!1;let i=r.meta?.type;return typeof i==`string`&&Rm.has(i)}:Um}function Gm(e){let t=[];for(let n of e.split(`.`)){let e=/^([^[\]]+)((?:\[\d+\])*)$/.exec(n);if(!e)return null;t.push(e[1]);for(let n of e[2].match(/\d+/g)??[])t.push(Number(n))}return t}function Km(e,t){let n=Gm(t);if(!n||n.length<3)return null;let[r,i,...a]=n;if(typeof r!=`string`||typeof i!=`number`)return null;let o=w(e[r])[i];if(!o)return null;let s=[{key:r,node:o}],c=o,l=r;for(let e of a.slice(0,-1))if(typeof e==`string`&&(l=e),c=Array.isArray(c)||Bm(c)?c[e]:void 0,Bm(c))s.push({key:l,node:c});else if(!Array.isArray(c))break;return{collection:r,chain:s,filterKey:a[a.length-1]}}var qm=`lookupFilters`,Jm=`interfaceConfig`;function Ym(e,t,n){let r=Km(e,t);if(r){if(r.filterKey===qm){let e=r.chain[r.chain.length-1].node;return Object.prototype.hasOwnProperty.call(e,qm)?Hm(e.reference):void 0}return Xm(r.collection,r.chain,r.chain.length-1,n)}}function Xm(e,t,n,r){for(let i=n;i>=0;i--){let{key:n,node:a}=t[i];if(e===`pages`&&i===1&&n===Jm){let e=Hm(a.source);if(e)return e}let o=Hm(a.object)??Hm(a.objectName);if(o)return o;let s=Vm(a.dataset);if(s){let e=r.get(s);return e?Hm(e.object):void 0}if(Bm(a.data)){let e=a.data.provider;if(e!==void 0&&e!==`object`)return;let t=Hm(a.data.object);if(t)return t}if(Bm(a.config)){let e=Hm(a.config.objectName)??Hm(a.config.object);if(e)return e}if(Bm(a.dataSource)){let e=Hm(a.dataSource.object);if(e)return e}if(Bm(a.properties)){let e=Hm(a.properties.object)??Hm(a.properties.objectName);if(e)return e}}if(e===`objects`)return Vm(t[0].node.name)}function Zm(e,t,n,r,i,a,o){if(!(i>zm))for(let[c,l]of Object.entries(e)){let e=`${t}.${c}`;if(c===`$and`||c===`$or`){Array.isArray(l)&&l.forEach((t,s)=>{Bm(t)&&Zm(t,`${e}[${s}]`,n,r,i+1,a,o)});continue}if(c===`$not`){Bm(l)&&Zm(l,e,n,r,i+1,a,o);continue}if(c.startsWith(`$`))continue;let u=o?`${o}.${c}`:c;if(!Bm(l)){s(l)&&a(u)&&r.push(L(n,e,l,`$eq`));continue}if(!Object.keys(l).some(e=>e.startsWith(`$`))){Zm(l,e,n,r,i+1,a,u);continue}for(let[t,i]of Object.entries(l)){if(km.has(t)&&s(i)){r.push(L(n,`${e}.${t}`,i,t));continue}if(t===`$between`&&Array.isArray(i)){i.forEach((i,a)=>{s(i)&&r.push(L(n,`${e}.${t}[${a}]`,i,t))});continue}if(Mm.has(t)&&s(i)&&a(u)){r.push(L(n,`${e}.${t}`,i,t));continue}Nm.has(t)&&Array.isArray(i)&&a(u)&&i.forEach((i,a)=>{s(i)&&r.push(L(n,`${e}.${t}[${a}]`,i,t))})}}}function Qm(e,t,n,r,i){let a=ke(e.operator);if(typeof a!=`string`)return;let o=e.value;if(jm.has(a)&&s(o)){r.push(L(n,`${t}.value`,o,a));return}if(a===`between`&&Array.isArray(o)){o.forEach((e,i)=>{s(e)&&r.push(L(n,`${t}.value[${i}]`,e,a))});return}let c=Vm(e.field);if(c&&i(c)){if(Im.has(a)&&s(o)){r.push(L(n,`${t}.value`,o,a));return}Lm.has(a)&&Array.isArray(o)&&o.forEach((e,i)=>{s(e)&&r.push(L(n,`${t}.value[${i}]`,e,a))})}}function $m(e,t,n,r,i){let a=e[1];if(typeof a!=`string`)return;let o=He(a),c=e[2];if(Am.has(o)&&s(c)){r.push(L(n,`${t}[2]`,c,a));return}if(o===`between`&&Array.isArray(c)){c.forEach((e,i)=>{s(e)&&r.push(L(n,`${t}[2][${i}]`,e,a))});return}let l=Vm(e[0]);if(l&&i(l)){if(Pm.has(o)&&s(c)){r.push(L(n,`${t}[2]`,c,a));return}Fm.has(o)&&Array.isArray(c)&&c.forEach((e,i)=>{s(e)&&r.push(L(n,`${t}[2][${i}]`,e,a))})}}function eh(e,t,n,r,i,a){if(!(i>zm)){if(Array.isArray(e)){if(typeof e[0]==`string`&&typeof e[1]==`string`&&![`and`,`or`].includes(e[0].toLowerCase())&&vt.has(e[1].toLowerCase())){$m(e,t,n,r,a);return}e.forEach((e,o)=>{typeof e!=`string`&&eh(e,`${t}[${o}]`,n,r,i+1,a)});return}if(Bm(e)){if(typeof e.field==`string`&&typeof e.operator==`string`){Qm(e,t,n,r,a);return}Zm(e,t,n,r,i,a,``)}}}function th(e){if(!e||typeof e!=`object`)return[];let t=[],n=qn(e),r=new Map;for(let t of w(e.datasets)){let e=Vm(t.name);e&&r.set(e,t)}return rr(e,Om,({value:i,path:a,where:o})=>{let s=Wm(n,Ym(e,a,r));eh(i,a,o,t,0,s)}),t}var nh=`filter-empty-combinator`,rh=`filter-empty-node`,ih=[{key:`dashboards`,kind:`dashboard`},{key:`objects`,kind:`object`},{key:`views`,kind:`view`},{key:`reports`,kind:`report`},{key:`datasets`,kind:`dataset`},{key:`pages`,kind:`page`},{key:`apps`,kind:`app`},{key:`flows`,kind:`flow`}];function ah(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var oh={$and:m({$and:[]}),$or:m({$or:[]}),$not:m({$not:{}}),node:m({}),orWithEmptyBranch:m({$or:[{status:`open`},{}]})};function sh(e){return e===`true`?`matches EVERY row`:e===`false`?`matches NO row`:`carries a real predicate`}var ch="If you really do want a predicate that selects nothing, `{ <field>: { $in: [] } }` is the declared spelling for it (an empty `$in` list matches nothing, on every backend) — it says so where an empty combinator only implies it.",lh='To express "no filter", DELETE the key — an absent `filter` and a filter that reduces to TRUE run identically, and only the absent key says so to the next reader (and to the next AI author that copies this metadata).';function uh(e,t,n){let r=e===`$not`?"`$not: {}`":`\`${e}: []\``,i=e===`$and`?`\`$and: []\` is a conjunction of ZERO conditions. Under the #5322 identity ruling it ${sh(oh.$and)} \u2014 the key is authored, and it constrains nothing, so this surface reads as filtered and is not.`:e===`$or`?`\`$or: []\` is a disjunction of ZERO branches. Under the #5322 identity ruling it ${sh(oh.$or)}: this surface renders permanently empty, and on a read scope it hides every row (fail-closed by design \u2014 #5134).`:`\`$not: {}\` negates an EMPTY node. An empty node is TRUE and NOT TRUE is FALSE, so it ${sh(oh.$not)} \u2014 the opposite of the "no filter" an empty operand looks like.`,a=e===`$and`?`${lh} To express a constraint, put the conditions in the array. ${ch}`:e===`$or`?`If you meant "no filter", this is its OPPOSITE: emptying the array does not relax the filter, it closes it. ${lh} If you meant to offer alternatives, put the branches in the array. ${ch}`:`Put the condition you are negating inside \`$not\` (\`{ $not: { status: 'closed' } }\`). ${lh} ${ch}`;n.out.push({severity:`error`,rule:nh,where:n.where,path:t,message:`${i} A literal ${r} is not an authoring surface (#5330).`,hint:`${a} A PROGRAMMATIC producer that loops to zero operands keeps the runtime identity unchanged \u2014 this rule judges only what is written in the metadata.`})}function dh(e,t,n){if(e===`root`){n.out.push({severity:`error`,rule:rh,where:n.where,path:t,message:`An EMPTY filter node (\`{}\`) is authored here. Under the #5322 identity ruling an empty node is TRUE \u2014 it ${sh(oh.node)}, exactly as if the key were absent \u2014 so a filter is declared and enforces nothing.`,hint:`${lh} If you meant to constrain something, write the condition into the node. ${ch}`});return}if(e===`or-branch`){n.out.push({severity:`error`,rule:rh,where:n.where,path:t,message:`An EMPTY branch (\`{}\`) of a \`$or\`. An empty node is TRUE, and one TRUE disjunct ABSORBS the whole disjunction (\`{ $or: [{ status: 'open' }, {}] }\` ${sh(oh.orWithEmptyBranch)}), so every branch you wrote beside it is dead.`,hint:"Delete the empty branch — the `$or` then means what it looks like. If it was meant to carry a condition, write it. (A compiler that DROPPED the empty branch instead would silently NARROW the scope to the surviving branches, which is why the runtime absorbs rather than filters — #5297.)"});return}n.out.push({severity:`error`,rule:rh,where:n.where,path:t,message:"An EMPTY branch (`{}`) of a `$and`. An empty node is TRUE — the AND identity — so the branch contributes no condition and the conjunction means whatever its other branches mean.",hint:`Delete the empty branch, or write the condition it was meant to carry. A branch that constrains nothing is indistinguishable from one whose condition was lost in an edit.`})}function fh(e,t,n){for(let[r,i]of Object.entries(e)){if(r===`$and`||r===`$or`){if(!Array.isArray(i))continue;if(i.length===0){uh(r,`${t}.${r}`,n);continue}i.forEach((e,i)=>{ph(e,`${t}.${r}[${i}]`,r===`$and`?`and-branch`:`or-branch`,n)});continue}if(r===`$not`){if(!ah(i))continue;if(Object.keys(i).length===0){uh(`$not`,`${t}.$not`,n);continue}fh(i,`${t}.$not`,n);continue}}}function ph(e,t,n,r){if(ah(e)){if(Object.keys(e).length===0){dh(n,t,r);return}fh(e,t,r)}}function mh(e){if(!e||typeof e!=`object`)return[];let t=[];return rr(e,ih,({value:e,path:n,where:r})=>{ph(e,n,`root`,{where:r,out:t})}),t}var hh=[...i],gh=new Set([`lookup`,`master_detail`,`user`]),_h=`object-reference-unknown`,vh=`object-reference-unregistered-platform`;function R(e){return typeof e==`string`&&e.length>0?e:void 0}function yh(e){if(e.includes("${"))return!0;let t=e.indexOf(`{`);return t!==-1&&e.indexOf(`}`,t+2)!==-1}function bh(e){let t=[];for(let n of Un(e)){let e=n.manifest;if(e&&typeof e==`object`&&!Array.isArray(e))for(let n of w(e.objects)){let e=R(n.name);e&&t.push(e)}}return t}function xh(e){let t=[];if(!e||typeof e!=`object`)return t;let n=w(e.objects),r=new Set;for(let e of n){let t=R(e.name);t&&r.add(t)}let i=new Set(r);for(let t of bh(e))i.add(t);let a=(e,n,r,a,o)=>{let s=R(e);if(s&&!yh(s)&&!i.has(s)&&!d(s)){if(Se(s)){t.push({severity:`warning`,rule:vh,where:n,path:r,message:`${a} "${s}" carries a platform namespace prefix, but no platform package, official plugin, or cloud runtime object registers that name \u2014 and this stack does not define it either. If nothing provides it at runtime the reference resolves to nothing and fails silently.`+E(s,hh),hint:`Check the spelling against the object the providing package actually registers (e.g. "sys_approval_request", not "sys_approval_process" \u2014 the process object was removed when approval became a flow node, ADR-0019). If a third-party package genuinely provides it, this warning is expected. ${o}`});return}t.push({severity:`error`,rule:_h,where:n,path:r,message:`${a} "${s}" resolves to no object defined in this stack. The reference is inert at runtime \u2014 nothing reports the miss.`+E(s,i),hint:`Point it at one of this stack's objects, or at a platform object by its full name (the platform user object is "sys_user", not "user"). ${o}`+(i.size>0?` Defined objects: ${[...i].sort().join(`, `)}.`:``)})}};for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`)continue;let r=R(t.name)??`#${e}`,i=w(t.fields);for(let t=0;t<i.length;t++){let n=i[t],o=R(n.type);if(!o||!gh.has(o))continue;let s=R(n.name)??`#${t}`;a(Ce(n),`object "${r}" \xB7 field "${s}"`,`objects[${e}].fields.${s}.reference`,`${o} target`,"The record picker has no object to query, `$expand` has nothing to resolve, and the form renders a relationship control that can never resolve a value.")}}let o=R(e.manifest?.namespace),s=w(e.views);for(let e=0;e<s.length;e++){let t=s[e],n=R(t.object);if(!n)continue;let r=o?`${o}_${n}`:void 0,c=r&&!n.startsWith(`${o}_`)&&i.has(r)?` Object names carry the package namespace prefix (manifest.namespace "${o}"): write "${r}", not "${n}".`:``;a(n,`view ${R(t.name)?`"${R(t.name)}"`:`#${e}`}`,`views[${e}].object`,`view container object`,"The runtime indexes a container's views by this key (`getViewsByObject()` / `GET /meta/view?object=`), so a container bound to an object nothing registers is never found: none of its views appears for any object."+c)}let c=(e,t,n)=>{let r=w(e.params);for(let e=0;e<r.length;e++){let i=r[e];if(!i||typeof i!=`object`)continue;let o=`${n} \xB7 param "${R(i.name)??R(i.field)??`#${e}`}"`;a(be({reference:i.reference},`validate-object-references action param target`),o,`${t}.params[${e}].reference`,`record-picker target`,`Without a resolvable target the picker degrades to a raw record-id text input.`),a(R(i.objectOverride),o,`${t}.params[${e}].objectOverride`,`field-backed param object`,`The param inherits type/options from a field on this object, so an unknown object leaves it untyped.`)}},l=w(e.actions);for(let e=0;e<l.length;e++){let t=l[e];t&&typeof t==`object`&&c(t,`actions[${e}]`,`action "${R(t.name)??`#${e}`}"`)}for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`)continue;let r=R(t.name)??`#${e}`,i=w(t.actions);for(let t=0;t<i.length;t++){let n=i[t];n&&typeof n==`object`&&c(n,`objects[${e}].actions[${t}]`,`object "${r}" \xB7 action "${R(n.name)??`#${t}`}"`)}}let u=w(e.dashboards);for(let e=0;e<u.length;e++){let t=u[e];if(!t||typeof t!=`object`)continue;let n=R(t.name)??`#${e}`,r=w(t.globalFilters);for(let t=0;t<r.length;t++){let i=r[t];if(!i||typeof i!=`object`)continue;let o=i.optionsFrom;o&&typeof o==`object`&&a(R(o.object),`dashboard "${n}" \xB7 filter "${R(i.name)??`#${t}`}"`,`dashboards[${e}].globalFilters[${t}].optionsFrom.object`,`filter options source`,`The dropdown fetches its options from this object; an unknown one renders an always-empty filter.`)}}let f=w(e.datasets);for(let e=0;e<f.length;e++){let t=f[e];t&&typeof t==`object`&&a(R(t.object),`dataset "${R(t.name)??`#${e}`}"`,`datasets[${e}].object`,`dataset base object`,`A dataset is the FROM of every report and dashboard widget bound to it (ADR-0021), so an unknown base object leaves every one of those surfaces querying nothing.`)}let p=w(e.apps);for(let e=0;e<p.length;e++){let t=p[e];if(!t||typeof t!=`object`)continue;let n=R(t.name)??`#${e}`,r=(e,t)=>{let i=w(e);for(let e=0;e<i.length;e++){let o=i[e];if(!o||typeof o!=`object`)continue;let s=R(o.id)??`#${e}`,c=`app "${n}" \xB7 nav "${s}"`,l=`${t}[${e}]`;a(R(o.requiresObject),c,`${l}.requiresObject`,`capability gate object`,`The entry is hidden unless this object is registered, so a typo hides it permanently — and it suppresses the nav cross-reference check that would have caught the target.`),o.requiresObject&&R(o.objectName)&&a(R(o.objectName),c,`${l}.objectName`,`navigation target`,"Declaring `requiresObject` exempts this target from the build-time check, so it is only verified here."),Array.isArray(o.children)&&r(o.children,`${l}.children`)}};r(t.navigation,`apps[${e}].navigation`);let i=w(t.areas);for(let t=0;t<i.length;t++)r(i[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var Sh=`nav-target-unresolved`,Ch=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function wh(e){return typeof e==`string`&&e.length>0?e:void 0}var Th=e=>e.includes("${")||e.includes(`{`),Eh=[[`page`,`pageName`,`pages`,`page`],[`report`,`reportName`,`reports`,`report`],[`dashboard`,`dashboardName`,`dashboards`,`dashboard`]];function Dh(e){let t=new Set;for(let n of w(e)){let e=wh(n.name);e&&t.add(e)}return t}function Oh(e){let t=[];if(!Ch(e))return t;let n=w(e.apps);if(n.length===0)return t;let r=new Map;for(let[,,t]of Eh)r.set(t,Dh(e[t]));for(let[e,i]of n.entries()){let n=wh(i.name)??`#${e}`,a=(e,i)=>{if(Array.isArray(e))for(let[o,s]of e.entries()){if(!Ch(s))continue;let e=s,c=`${i}[${o}]`;for(let[i,a,s,l]of Eh){if(e.type!==i)continue;let u=wh(e[a]);if(!u||Th(u))continue;let d=r.get(s);if(d.has(u))continue;let f=d.size===0;t.push({severity:`warning`,rule:Sh,where:`app "${n}" \xB7 nav "${wh(e.id)??wh(e.label)??`#${o}`}"`,path:`${c}.${a}`,message:`Navigation targets ${l} '${u}', which this stack does not declare in \`${s}\`. `+(f?`The stack declares NO ${s} at all, so \`defineStack\`'s own cross-reference check skipped this entry entirely (it is gated on \`${s===`pages`?`pageNames`:s===`reports`?`reportNames`:`dashboardNames`}.size > 0\`) \u2014 nothing else will report it. `:``)+`The entry renders in the sidebar and resolves to nothing when clicked. If another package provides this ${l}, this is expected and advisory only.`,hint:`Declare the ${l} in \`${s}\`, correct the name, or remove the nav entry if the ${l} is gone.`})}Array.isArray(e.children)&&a(e.children,`${c}.children`)}};a(i.navigation,`apps[${e}].navigation`);for(let[t,n]of w(i.areas).entries())a(n.items,`apps[${e}].areas[${t}].items`),a(n.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var kh=`nav-object-unservable`,Ah=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function jh(e){return typeof e==`string`&&e.length>0?e:void 0}var Mh=e=>e.includes("${")||e.includes(`{`);function Nh(e){let t=[];if(!Ah(e))return t;let n=w(e.apps);if(n.length===0)return t;let r=new Map,i=w(e.objects);for(let[e,t]of i.entries()){let n=jh(t.name);n&&r.set(n,{enable:t.enable,path:`objects[${e}].enable`})}if(r.size===0)return t;for(let[e,i]of n.entries()){let n=jh(i.name)??`#${e}`,a=(e,i)=>{if(Array.isArray(e))for(let[o,s]of e.entries()){if(!Ah(s))continue;let e=s,c=`${i}[${o}]`;if(e.type===`object`){let i=jh(e.objectName),a=i&&!Mh(i)?r.get(i):void 0;if(i&&a&&!jt(a.enable,`list`)){let r=Ah(a.enable)?a.enable:{},s=r.apiEnabled===!1,l=s?"`enable.apiEnabled: false`":"`enable.apiMethods` does not grant `list`"+(Array.isArray(r.apiMethods)?` (declared: ${r.apiMethods.length===0?`[] — deny-all`:r.apiMethods.map(e=>`\`${String(e)}\``).join(`, `)})`:``),u=s?"404 `OBJECT_API_DISABLED`":"405 `OBJECT_API_METHOD_NOT_ALLOWED`",d=s?`${a.path}.apiEnabled`:`${a.path}.apiMethods`;t.push({severity:`error`,rule:kh,where:`app "${n}" \xB7 nav "${jh(e.id)??jh(e.label)??`#${o}`}"`,path:`${c}.objectName`,message:`Navigation targets object "${i}", which cannot serve a list: ${l} (\`${d}\`), so the list request answers ${u} for EVERY user \u2014 platform administrators included, since that gate reads only the object's \`enable\` block and never the caller. The entry cannot be rescued with \`requiredPermissions\`: they are independent conditions. The server prunes this entry from the served \`/meta\` payload (#7912), so publishing it ships a menu row that silently is not there.`,hint:`Remove the nav entry, or make "${i}" listable by setting \`enable.apiEnabled: true\` and granting \`list\` in \`enable.apiMethods\`. \u26D4 Do NOT open the API on an object that is disabled on purpose \u2014 several platform objects hold credential material and are API-disabled deliberately; for those the entry is the mistake, not the \`enable\` block.`})}}Array.isArray(e.children)&&a(e.children,`${c}.children`)}};a(i.navigation,`apps[${e}].navigation`);for(let[t,n]of w(i.areas).entries())a(n.items,`apps[${e}].areas[${t}].items`),a(n.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var Ph=`sort-field-unknown`,Fh=`sort-field-unsortable`,Ih=`sort-field-unprovisioned`;function z(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Lh(e){return typeof e==`string`&&e.length>0?e:void 0}function Rh(e){let t=(e,t)=>{let n=e.trim();if(!n)return;let r=n.startsWith(`-`)?n.slice(1).trim():n.split(/\s+/)[0];return r?{field:r,at:t}:void 0};if(typeof e==`string`)return e.split(`,`).map((n,r)=>t(n,e.includes(`,`)?`[${r}]`:``)).filter(e=>!!e);if(Array.isArray(e)){let n=[];for(let r=0;r<e.length;r++){let i=e[r];if(typeof i==`string`){let e=t(i,`[${r}]`);e&&n.push(e);continue}if(!z(i))continue;let a=Lh(i.field);a&&n.push({field:a.trim(),at:`[${r}]`})}return n}return[]}function zh(e,t,n,r,i,a,o){let s=[];if(e==null||!t||!n.has(t))return s;let c=n.get(t);if(!c)return s;let l=c.names,u=o?.get(t);for(let n of Rh(e)){let e=n.field,o=e.split(`.`)[0];if(Nn.has(o)){!e.includes(`.`)&&u?.has(o)&&s.push({severity:`warning`,rule:Ih,where:r,path:`${i}${n.at}`,message:`${a} orders by "${e}", which resolves on object "${t}", but ${zn(t,e)} \u2014 so the ORDER BY reaches the driver, finds no column, and is dropped. Measured on a federated object over a real remote table, 'asc' and 'desc' return BYTE-IDENTICAL row order under a 200 while the same query on a real column reverses. Unlike this rule's other two verdicts nothing refuses it: the REST ingress (#6994) and the engine (#7095) both judge only 'formula', so the view's FIRST fetch \u2014 and every fetch after it \u2014 silently answers in an arbitrary order, which 'limit'/'offset' then slice into an arbitrary page.`,hint:Bn(t,e)});continue}if(!l.has(o)){let c=e.includes(`.`);s.push({severity:`error`,rule:Ph,where:r,path:`${i}${n.at}`,message:`${a} orders by "${e}", which is not a field on object "${t}". The runtime refuses the sort rather than dropping it: every load of this view answers 400 INVALID_SORT (#6994), because a sort is the view's FIRST fetch and not an optional interaction.`+(c?``:E(o,l)),hint:(c?`'sort' reaches only whole columns of "${t}" itself, never a related record's column \u2014 denormalise the value onto "${t}" (a stored field, written when the source changes) and sort by that. `:`Fix the name, or add "${e}" to ${t}.fields. `)+(l.size>0?`Object fields: ${[...l].sort().join(`, `)}.`:``)});continue}let d=c.fields[e];if(h(d)){let o=d?.type;s.push({severity:`error`,rule:Fh,where:r,path:`${i}${n.at}`,message:`${a} orders by "${e}" on object "${t}", a virtual '${o}' field: its value is computed on read and never stored, so no driver materialises a column to ORDER BY. Measured, an unrefused sort on one returns 'asc' and 'desc' in byte-identical order \u2014 the rows carry the values they were asked to be ordered by, unordered, under a success.`,hint:`Denormalise the value onto "${t}" (a stored field, written when the source changes) and sort by that, or drop "${e}" from this sort. At runtime both doors now refuse it with 400 INVALID_SORT \u2014 the REST ingress (#6994) and the engine itself (#7095) \u2014 so the declaration breaks the view's first fetch, and every fetch after it.`})}}return s}function Bh(e){let t=[];if(!z(e))return t;let n=Array.isArray(e.objects)?e.objects:z(e.objects)?Object.entries(e.objects).map(([e,t])=>({name:e,...t})):[],r=Nc(e),i=Rn(e),a=(e,n,a,o,s)=>{t.push(...zh(e,n,r,a,o,s,i))};for(let e=0;e<n.length;e++){let t=n[e];if(!z(t))continue;let r=Lh(t.name),i=r?`object "${r}"`:`objects[${e}]`;if(z(t.listViews))for(let[n,o]of Object.entries(t.listViews))z(o)&&a(o.sort,Vh(o)??r,`${i} \u203A listViews.${n}`,`objects[${e}].listViews.${n}.sort`,`list-view sort`)}let o=Array.isArray(e.views)?e.views:[];for(let e=0;e<o.length;e++){let t=o[e];if(!z(t))continue;let n=Lh(t.name)??Lh(t.objectName)??`#${e}`,r=Lh(t.objectName)??Lh(t.object);if(t.viewKind===`list`&&!z(t.config)&&a(t.sort,Vh(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}].sort`,`list-view sort`),t.viewKind===`list`&&z(t.config)&&a(t.config.sort,Vh(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config.sort`,`list-view sort`),z(t.list)&&a(t.list.sort,Vh(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list.sort`,`list-view sort`),z(t.listViews))for(let[i,o]of Object.entries(t.listViews))z(o)&&a(o.sort,Vh(o)??r,`view "${n}" \u203A listViews.${i}`,`views[${e}].listViews.${i}.sort`,`list-view sort`)}return t}function Vh(e){let t=e.data;return z(t)?Lh(t.object):void 0}var Hh=`list-view-field-unknown`,Uh=`list-view-field-dotted`;function B(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Wh(e){return typeof e==`string`&&e.length>0?e:void 0}function Gh(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}var Kh={"":{lists:{filterableFields:`error`,hiddenFields:`warning`,fieldOrder:`warning`},entries:{columns:`error`}},grouping:{entries:{fields:`error`}},rowColor:{scalars:{field:`warning`}},userFilters:{entries:{fields:`error`}},kanban:{scalars:{groupByField:`error`,summarizeField:`warning`,titleField:`warning`},lists:{columns:`warning`}},calendar:{scalars:{startDateField:`error`,endDateField:`warning`,titleField:`warning`,colorField:`warning`,allDayField:`warning`}},gantt:{scalars:{startDateField:`error`,endDateField:`error`,titleField:`error`,progressField:`warning`,dependenciesField:`warning`,colorField:`warning`,parentField:`warning`,typeField:`warning`,baselineStartField:`warning`,baselineEndField:`warning`,groupByField:`warning`,assigneeField:`warning`,effortField:`warning`,borderColorField:`warning`,lockField:`error`,objectField:`error`},entries:{tooltipFields:`warning`,quickFilters:`error`}},timeline:{scalars:{startDateField:`error`,titleField:`error`,endDateField:`warning`,groupByField:`warning`,colorField:`warning`}},gallery:{scalars:{coverField:`warning`,titleField:`warning`},lists:{visibleFields:`warning`}},map:{scalars:{latitudeField:`error`,longitudeField:`error`,locationField:`error`,titleField:`warning`,descriptionField:`warning`}},tree:{scalars:{parentField:`error`,labelField:`warning`},lists:{fields:`warning`}}},qh={"":{columns:`projection`,filterableFields:`filter`},userFilters:{fields:`filter`}};function Jh(e,t){return qh[e]?.[t]}var Yh=[{block:`summary`,key:`field`,severity:`error`},{block:`prefix`,key:`field`,severity:`warning`}],Xh=`Nothing resolves the name at render time: the view renders successfully with a blank, empty or wrong result, and no gate reports the miss.`;function Zh(e,t,n,r,i,a){let o=`Denormalise the value onto "${r}" (a stored field, written when the source changes) and name that.`;if(e===`projection`)return{message:`${a} "${t}" is a dotted path. A list view declares no ADR-0021 \`include\`, so it compiles no joins, and the columns are sent as the query's projection \u2014 where a dotted entry is refused by name: \`assertProjectionHasNoDottedPaths\` on the engine boundary and \`assertProjectionFieldsExist\` at the REST ingress, both \`400 INVALID_FIELD\`. The view's FIRST fetch is refused, not rendered.`,hint:`Name a whole column of "${r}" \u2014 "${n}" \u2014 and read into its value in the client, or read the related record with \`expand\`. ${o}`};let s=Pt(i);if(s===null)return;let c=i?.type?`\`${i.type}\``:`an unreadable`;return{message:`${a} "${t}" is a dotted path ${s===`relation`?`whose head "${n}" is a ${c} field on object "${r}" \u2014 it stores the related record's id, not an embedded document, and a list view compiles no joins to traverse it`:s===`virtual`?`whose head "${n}" is a ${c} field on object "${r}" \u2014 its value is computed on read, so no driver materialises a column for the path to reach into`:`whose head "${n}" is a ${c} field on object "${r}" that stores a single scalar value \u2014 there is nothing beneath it for a path to reach`}. No backend serves the path, so the predicate can only match zero records: the query is REFUSED rather than answered with an empty list (\`assertFilterIsMaterializable\` and the REST ingress both answer \`400 INVALID_FIELD\`).`,hint:`Filter on a column of "${r}" itself. ${o}`}}function Qh(e){let t=[];if(!B(e))return t;let n=qn(e);if(n.size===0)return t;let r=(e,r,i,a,o,s,c=void 0)=>{let l=Wh(e);if(!l)return;let u=l.split(`.`)[0];if(!u)return;let d=T(n,r,u);if(Xn(d)||!d)return;let f=Yn(d,u,s),p=u!==l;if(!f){if(!p||!c)return;let e=Zh(c,l,u,r,d.kind===`ok`?d.meta:void 0,s);if(!e)return;t.push({severity:`error`,rule:Uh,where:a,path:o,message:e.message,hint:e.hint});return}t.push({severity:i,rule:Hh,where:a,path:o,message:f.message+(p?` (the head segment of the written reference "${l}"; a list view compiles no joins, so only the head can name a column here)`:``)+` ${Xh}`,hint:`Name a field that exists on "${r}", or drop the entry. ${f.detail}`})},i=(e,t,i,a)=>{if(!B(e))return;let o=e.data;if(B(o)){let e=Wh(o.provider);if(e&&e!==`object`)return}if(!t||!n.has(t)||!n.get(t))return;let s=t;for(let[t,n]of Object.entries(Kh)){let o=t===``?e:e[t];if(!B(o))continue;let c=t===``?a:`${a}.${t}`,l=t===``?i:`${i} \u203A ${t}`;for(let[e,t]of Object.entries(n.scalars??{}))r(o[e],s,t,l,`${c}.${e}`,e);for(let[e,i]of Object.entries(n.lists??{})){let n=o[e];if(!Array.isArray(n))continue;let a=Jh(t,e);n.forEach((t,n)=>{r(t,s,i,l,`${c}.${e}[${n}]`,`${e}[${n}]`,a)})}for(let[e,i]of Object.entries(n.entries??{})){let n=o[e];if(!Array.isArray(n))continue;let a=Jh(t,e);n.forEach((n,o)=>{let u=`${c}.${e}[${o}]`;if(typeof n==`string`){r(n,s,i,l,u,`${e}[${o}]`,a);return}if(B(n)&&(r(n.field,s,i,l,`${u}.field`,`${e}[${o}].field`,a),t===``&&e===`columns`))for(let t of Yh){let i=n[t.block];B(i)&&r(i[t.key],s,t.severity,`${l} \u203A ${e}[${o}].${t.block}`,`${u}.${t.block}.${t.key}`,`${t.block}.${t.key}`)}})}}let c=(e,t,n)=>{e!=null&&sr(e,n,({field:e,path:n})=>{r(e,s,`error`,t,n,`filter key`,`filter`)})};c(e.filter,`${i} \u203A filter`,`${a}.filter`);let l=(e,t,n)=>{Array.isArray(e)&&e.forEach((e,r)=>{if(!B(e))return;let i=Wh(e.name)??`#${r}`;c(e.filter,`${t}[${r}] "${i}" \u203A filter`,`${n}[${r}].filter`)})};l(e.tabs,`${i} \u203A tabs`,`${a}.tabs`),B(e.userFilters)&&l(e.userFilters.tabs,`${i} \u203A userFilters.tabs`,`${a}.userFilters.tabs`)},a=e=>{let t=e.data;return B(t)?Wh(t.object):void 0},o=Gh(e.objects);for(let e=0;e<o.length;e++){let t=o[e];if(!B(t))continue;let n=Wh(t.name),r=n?`object "${n}"`:`objects[${e}]`;if(B(t.listViews))for(let[o,s]of Object.entries(t.listViews))B(s)&&i(s,a(s)??n,`${r} \u203A listViews.${o}`,`objects[${e}].listViews.${o}`)}let s=Gh(e.views);for(let e=0;e<s.length;e++){let t=s[e];if(!B(t))continue;let n=Wh(t.name)??Wh(t.objectName)??`#${e}`,r=Wh(t.objectName)??Wh(t.object);if(t.viewKind===`list`&&!B(t.config)&&i(t,a(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}]`),t.viewKind===`list`&&B(t.config)&&i(t.config,a(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config`),B(t.list)&&i(t.list,a(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list`),B(t.listViews))for(let[o,s]of Object.entries(t.listViews))B(s)&&i(s,a(s)??r,`view "${n}" \u203A listViews.${o}`,`views[${e}].listViews.${o}`)}return t}var $h=`object-field-ref-unknown`;function eg(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function tg(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}var ng=[{block:``,key:`highlightFields`,retiredAlias:`compactLayout`,consequence:`Every consumer silently skips the entry: it drives the object's default list columns, record cards, previews and the detail highlight strip, and each of them renders one field short with no error anywhere.`,prescription:"Fix the field name, or drop the entry. `highlightFields` is ordered — the first entry wins where only one field fits (ADR-0085)."},{block:`publicSharing`,key:`redactFields`,consequence:`The redaction never applies, and it fails OPEN: records served through a share link still carry the field to whoever holds the link. A mis-spelled entry is silently indistinguishable from an entry that was never written.`,prescription:`Fix the field name so the redaction binds, or drop the entry if the field is meant to be served through share links.`}],rg={consequence:"The SQL driver skips the WHOLE index at sync. It logs the skip at error and `os migrate plan` reports the index as unbuildable, but the object keeps serving: a `unique` index is then unenforced until the name is fixed.",prescription:"Fix the column name. An index column is a field of this object, or a column the platform injects on it (`created_at`, `organization_id`, …), spelled exactly — never a dotted path."},ig=new Set([`lookup`,`master_detail`,`user`]);function ag(e){return typeof e==`string`&&e.length>0?e:void 0}function og(e){let t=ag(e);return t?{name:t,suffix:``}:void 0}function sg(e,t){let n=eg(e)?ag(e[t]):void 0;return n?{name:n,suffix:`.${t}`}:void 0}var cg=[{key:`relatedListColumns`,address:`owner`,verbatim:!1,read:og,consequence:`The related list the parent's detail page derives from this relationship asks the child object for a column it does not have, and the miss surfaces only when that page opens.`,prescription:`Fix the column name — a related-list column is a field of the object that declares this relationship (the child whose rows the list shows) — or drop the entry and let the columns derive.`},{key:`lookupColumns`,address:`reference`,verbatim:!0,read:e=>og(e)??sg(e,`field`),consequence:`The record picker renders that column empty for every candidate: a picker column is read off each record of the referenced object, and nothing reports the miss.`,prescription:`Fix the column name — a picker column is a field of the referenced object, not of the object that owns this field — or drop the entry and let the columns derive.`},{key:`lookupFilters`,address:`reference`,verbatim:!1,read:e=>sg(e,`field`),consequence:`The picker applies this filter to its query on the referenced object, which names a field that object does not have; the miss surfaces only when a user opens the picker.`,prescription:"Fix `field` — a picker filter runs on the referenced object, so it names a field of that object, not of the object that owns this field."},{key:`dependsOn`,address:`owner`,verbatim:!0,read:e=>og(e)??sg(e,`field`),consequence:`The form gates this field until that field has a value, and a field the record does not have never gets one: this field stays gated for good.`,prescription:"Fix the name — `dependsOn` names fields on the same record, i.e. of the object that owns this field — or drop the entry."},{key:`dependsOn`,address:`reference`,verbatim:!0,read:e=>og(e)??sg(e,`param`)??sg(e,`field`),consequence:`The picker scopes its candidates by this key on the referenced object — a bare name is the key on both sides — and that object has no such field; the miss surfaces only when a user opens the picker.`,prescription:"When the two sides are spelled differently, write the entry as `{ field: 'this_record_field', param: 'referenced_object_field' }`; otherwise fix the name."}];function lg(e,t,n,r){if(!r||!n.includes(`.`))return T(e,t,n);if(!e.has(t))return{kind:`unknowable`,reason:`object-not-in-stack`,object:t};let i=e.get(t);return i?{kind:`field-unknown`,object:t,field:n,candidates:i.names}:{kind:`unknowable`,reason:`no-field-map`,object:t}}function ug(e){let t=[];if(!eg(e))return t;let n=qn(e);if(n.size===0)return t;let r=e=>{let r=lg(n,e.against,e.name,e.verbatim);if(Xn(r)||!r)return!1;let i=Yn(r,e.name,e.subject);return i?(t.push({severity:`error`,rule:$h,where:e.where,path:e.path,message:`${i.message} ${e.consequence}`,hint:`${e.prescription} ${i.detail}`}),!0):!1},i=tg(e.objects);for(let e=0;e<i.length;e++){let t=i[e];if(!eg(t))continue;let a=typeof t.name==`string`&&t.name.length>0?t.name:void 0;if(!a)continue;let o=n.get(a);if(!o)continue;let s=`object "${a}"`,c=`objects[${e}]`;for(let e of ng){let n=e.block===``?t:t[e.block];if(!eg(n))continue;let i=e.block===``?c:`${c}.${e.block}`,o=Array.isArray(n[e.key])?e.key:e.retiredAlias&&Array.isArray(n[e.retiredAlias])?e.retiredAlias:void 0;o&&n[o].forEach((t,n)=>{typeof t==`string`&&t.length!==0&&r({against:a,name:t,verbatim:!1,subject:`${o}[${n}]`,where:`${s} \u203A ${o}`,path:`${i}.${o}[${n}]`,consequence:e.consequence,prescription:e.prescription})})}(Array.isArray(t.indexes)?t.indexes:[]).forEach((e,t)=>{eg(e)&&Array.isArray(e.fields)&&e.fields.forEach((e,n)=>{let i=ag(e);i&&r({against:a,name:i,verbatim:!0,subject:`indexes[${t}].fields[${n}]`,where:`${s} \u203A indexes[${t}].fields`,path:`${c}.indexes[${t}].fields[${n}]`,consequence:rg.consequence,prescription:rg.prescription})})});for(let e of w(t.fields)){let t=ag(e.name);if(!t)continue;let n=o.fields.get(t),i=n?.type&&ig.has(n.type)?n.reference:void 0,l=new Set;for(let n of cg){let o=e[n.key];if(!Array.isArray(o))continue;let u=n.address===`owner`?a:i;u&&o.forEach((e,i)=>{let a=n.read(e);if(!a)return;let o=`${n.key}[${i}]`;l.has(`${o}=${a.name}`)||r({against:u,name:a.name,verbatim:n.verbatim,subject:`fields.${t}.${o}${a.suffix}`,where:`${s} \u203A fields.${t}.${n.key}`,path:`${c}.fields.${t}.${o}${a.suffix}`,consequence:n.consequence,prescription:n.prescription})&&l.add(`${o}=${a.name}`)})}}}return t}var dg=`action-name-undefined`;function V(e){return typeof e==`string`&&e.length>0?e:void 0}function fg(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function pg(e){let t=new Set;for(let n of w(e.actions)){let e=V(n?.name);e&&t.add(e)}for(let n of w(e.objects))if(n&&typeof n==`object`)for(let e of w(n.actions)){let n=V(e?.name);n&&t.add(n)}return t}function mg(e){let t=[];if(!e||typeof e!=`object`)return t;let n=pg(e),r=(e,r,i,a,o=`with the location this surface needs`,s=`The button renders and does nothing when clicked — a dead affordance the runtime cannot dispatch.`)=>{n.has(e)||t.push({severity:`error`,rule:dg,where:r,path:i,message:`${a} names action "${e}", which is defined by no action in this stack (neither \`stack.actions\` nor any object's \`actions\`). ${s}`+E(e,n),hint:`Define an action named "${e}" (in \`stack.actions\` or the object's \`actions\`) ${o}, remove the reference, or ignore this if the action is contributed by another installed package.`+(n.size>0?` Defined actions: ${[...n].sort().join(`, `)}.`:``)})},i="(no `locations` entry needed — the selection bar places it by name)",a=(e,t,n,a)=>{if(!e||typeof e!=`object`)return;let o=e;for(let e of[`rowActions`,`bulkActions`]){let s=fg(o[e]);for(let o=0;o<s.length;o++)r(s[o],`${t} \xB7 ${n} \xB7 ${e}`,`${a}.${e}[${o}]`,e===`bulkActions`?`Bulk-action menu`:`Row-action menu`,e===`bulkActions`?i:void 0)}let s=Array.isArray(o.bulkActionDefs)?o.bulkActionDefs:[];for(let e=0;e<s.length;e++){let o=s[e];if(!o||typeof o!=`object`||o.execution!==`aggregate`||o.actionDef!==void 0)continue;let c=V(o.name);c&&r(c,`${t} \xB7 ${n} \xB7 bulkActionDefs[${e}]`,`${a}.bulkActionDefs[${e}].name`,`Aggregate bulk action`,i)}},o=w(e.views);for(let e=0;e<o.length;e++){let t=o[e];if(!t||typeof t!=`object`)continue;let n=`view "${V(t.name)??V(t.object)??`#${e}`}"`;a(t.list,n,`list`,`views[${e}].list`);let r=t.listViews;if(r&&typeof r==`object`&&!Array.isArray(r))for(let[t,i]of Object.entries(r))a(i,n,`listViews.${t}`,`views[${e}].listViews.${t}`)}let s=w(e.objects);for(let e=0;e<s.length;e++){let t=s[e];if(!t||typeof t!=`object`)continue;let n=t.listViews;if(!n||typeof n!=`object`||Array.isArray(n))continue;let r=`object "${V(t.name)??`#${e}`}"`;for(let[t,i]of Object.entries(n))a(i,r,`listViews.${t}`,`objects[${e}].listViews.${t}`)}let c=w(e.pages);for(let e=0;e<c.length;e++){let t=c[e];if(!t||typeof t!=`object`)continue;let n=V(t.name)??`#${e}`;for(let{component:i,path:a}of Vc(t,`pages[${e}]`)){let e=i.properties;if(!e||typeof e!=`object`)continue;let t=V(i.type),o=`page "${n}" \xB7 component "${t??`?`}"`,s=fg(e.actionNames);for(let e=0;e<s.length;e++)r(s[e],o,`${a}.properties.actionNames[${e}]`,`Quick-actions bar`);if(t===`record:alert`){let t=e.action,n=t&&typeof t==`object`&&!Array.isArray(t)?V(t.actionName):void 0;n&&r(n,o,`${a}.properties.action.actionName`,`Alert call-to-action`,"(no `locations` entry needed — the alert renders its call-to-action by name)",`The banner renders with no call-to-action button: the id resolves to nothing and the renderer drops it without a word.`)}if(t===`page:header`&&Array.isArray(e.actions)){let t=e.actions;for(let e=0;e<t.length;e++){let n=V(t[e]);n&&r(n,o,`${a}.properties.actions[${e}]`,`Page-header actions`,"with `record_header` or `record_more` in its `locations` (the header draws only actions placed at one of the two)",`The header draws no button for it: the id resolves to nothing and is dropped, with only a browser-console warning no author reads.`)}}}}let l=w(e.apps);for(let e=0;e<l.length;e++){let t=l[e];if(!t||typeof t!=`object`)continue;let n=V(t.name)??`#${e}`,i=(e,t)=>{let a=w(e);for(let e=0;e<a.length;e++){let o=a[e];if(!o||typeof o!=`object`)continue;let s=`${t}[${e}]`,c=o.actionDef,l=V(c?.actionName);o.type===`action`&&l&&r(l,`app "${n}" \xB7 nav "${V(o.id)??`#${e}`}"`,`${s}.actionDef.actionName`,`Navigation action item`);let u=V(o.runAction);o.type===`object`&&u&&r(u,`app "${n}" \xB7 nav "${V(o.id)??`#${e}`}"`,`${s}.runAction`,`Navigation deep-link auto-run`),Array.isArray(o.children)&&i(o.children,`${s}.children`)}};i(t.navigation,`apps[${e}].navigation`);let a=w(t.areas);for(let t=0;t<a.length;t++)i(a[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var hg=`action-dispatch-contract-mismatch`,gg=[`perRecord`,`aggregate`];function _g(e){return typeof e==`string`&&e.length>0?e:void 0}function vg(e){return gg.find(t=>t===e)}var yg={perRecord:"`execution: 'perRecord'` (the view's `bulkActions: ['<name>']` bare-string form) — the renderer promotes the action to a def and dispatches it ONCE PER selected row, each call carrying that row's `recordId` and NO `_selectedIds`",aggregate:"`execution: 'aggregate'` (a `bulkActionDefs` entry naming the action) — ONE dispatch for the whole selection, carrying every selected id in `params._selectedIds` and NO `recordId`"},bg={perRecord:'a body written per-record finds no `recordId` on the single aggregate call and typically throws its own "nothing selected" — which reads in the console like a selection bug rather than a wiring one',aggregate:"a body written for the aggregate call reads `_selectedIds` as `undefined` on every per-row dispatch, falls through to its single-record branch, and reports success for one row out of however many were selected"};function xg(e){let t=new Map,n=e=>{if(!e||typeof e!=`object`)return;let n=e,r=_g(n.name);if(!r)return;let i=vg(n.execution)??`none`;t.has(r)||t.set(r,new Set),t.get(r).add(i)};for(let t of w(e.actions))n(t);for(let t of w(e.objects))if(t&&typeof t==`object`)for(let e of w(t.actions))n(e);let r=new Map;for(let[e,n]of t){if(n.size!==1)continue;let t=[...n][0];t!==`none`&&r.set(e,t)}return r}function Sg(e){let t=[];if(!e||typeof e!=`object`)return t;let n=xg(e);if(n.size===0)return t;let r=(e,r,i,a,o)=>{let s=n.get(e);if(s===void 0||s===r)return;let c=r===`perRecord`?`move the wiring to \`bulkActionDefs: [{ name: '${e}', operation: 'custom', execution: 'aggregate' }]\``:`drop the def and name the action in the view's \`bulkActions: ['${e}']\` instead`;t.push({severity:`error`,rule:hg,where:i,path:a,message:`Action "${e}" declares ${yg[s]}, but ${o} wires it as ${yg[r]}. The two contracts deliver opposite input to the same body: ${bg[s]}. Nothing refuses this at runtime \u2014 \`recordId\` and \`_selectedIds\` are both builtin action params (ADR-0104), so the strict params gate admits either bag without a word.`,hint:`Pick the contract the body is actually written for and make both ends say it: either change the action's declaration to \`execution: '${r}'\` (if the body was written for the wiring), or ${c} (if the body was written for the declaration). If the two wirings are both wanted, they are two actions \u2014 one call and N calls have different side effects, which is why the platform will not silently unify them.`})},i=(e,t,n,i)=>{if(!e||typeof e!=`object`)return;let a=e,o=`${t} \xB7 ${n}`,s=Array.isArray(a.bulkActions)?a.bulkActions:[];for(let e=0;e<s.length;e++){let t=_g(s[e]);t&&r(t,`perRecord`,`${o} \xB7 bulkActions`,`${i}.bulkActions[${e}]`,o)}let c=Array.isArray(a.bulkActionDefs)?a.bulkActionDefs:[];for(let e=0;e<c.length;e++){let t=c[e];if(!t||typeof t!=`object`||t.execution!==`aggregate`||t.actionDef!==void 0)continue;let n=_g(t.name);n&&r(n,`aggregate`,`${o} \xB7 bulkActionDefs[${e}]`,`${i}.bulkActionDefs[${e}]`,o)}},a=w(e.views);for(let e=0;e<a.length;e++){let t=a[e];if(!t||typeof t!=`object`)continue;let n=`view "${_g(t.name)??_g(t.object)??`#${e}`}"`;i(t.list,n,`list`,`views[${e}].list`);let r=t.listViews;if(r&&typeof r==`object`&&!Array.isArray(r))for(let[t,a]of Object.entries(r))i(a,n,`listViews.${t}`,`views[${e}].listViews.${t}`)}let o=w(e.objects);for(let e=0;e<o.length;e++){let t=o[e];if(!t||typeof t!=`object`)continue;let n=t.listViews;if(!n||typeof n!=`object`||Array.isArray(n))continue;let r=`object "${_g(t.name)??`#${e}`}"`;for(let[t,a]of Object.entries(n))i(a,r,`listViews.${t}`,`objects[${e}].listViews.${t}`)}return t}var Cg=`action-no-placement`;function wg(e){return typeof e==`string`&&e.length>0?e:void 0}function Tg(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function Eg(e){let t=new Set,n=e=>{if(!e||typeof e!=`object`)return;let n=e;for(let e of[`rowActions`,`bulkActions`])for(let r of Tg(n[e]))t.add(r);for(let e of w(n.bulkActionDefs)){let n=wg(e?.name);n&&t.add(n)}},r=e=>{if(e&&typeof e==`object`&&!Array.isArray(e))for(let t of Object.values(e))n(t)};for(let t of w(e.views))t&&typeof t==`object`&&(n(t.list),r(t.listViews));for(let t of w(e.objects))t&&typeof t==`object`&&r(t.listViews);return t}function Dg(e){let t=[];if(!e||typeof e!=`object`)return t;let n=Eg(e),r=(e,r)=>{if(!e||typeof e!=`object`||`locations`in e)return;let i=wg(e.name);i&&(n.has(i)||t.push({severity:`warning`,rule:Cg,where:`action "${i}"`,path:r,message:`Action "${i}" declares no \`locations\` and no view places it by name, so it renders on no surface \u2014 the button exists in metadata and nowhere in the UI.`,hint:"Add the surface it belongs on, e.g. `locations: ['record_header']` (or `list_item`, `list_toolbar`, `record_more`, `record_section`, `record_related`); or place it from a list view's `bulkActions` / `bulkActionDefs` if it acts on a selection. If it is meant to be callable over REST / MCP / AI with no UI surface, say so explicitly with `locations: []` — an empty array is the documented headless shape and is never flagged."}))},i=w(e.actions);for(let e=0;e<i.length;e++)r(i[e],`actions[${e}]`);let a=w(e.objects);for(let e=0;e<a.length;e++){let t=a[e];if(!t||typeof t!=`object`)continue;let n=w(t.actions);for(let t=0;t<n.length;t++)r(n[t],`objects[${e}].actions[${t}]`)}return t}var Og=`page/visualization-without-binding`,kg=[{visualization:`kanban`,binding:`groupByField`,types:[`select`,`multiselect`,`radio`,`enum`,`boolean`],namePattern:`status|stage|state|priority|category|kind`,viewBlocks:[`kanban`]},{visualization:`calendar`,binding:`startDateField`,types:[`date`,`datetime`,`time`],namePattern:`date|due|start|end|deadline|schedule`,viewBlocks:[`calendar`]},{visualization:`timeline`,binding:`startDateField`,types:[`date`,`datetime`,`time`],namePattern:`date|due|start|end|deadline|schedule`,viewBlocks:[`timeline`,`calendar`]},{visualization:`gallery`,binding:`coverField`,types:[`image`,`file`,`attachment`,`avatar`,`photo`],namePattern:null,viewBlocks:[`gallery`]},{visualization:`gantt`,binding:`startDateField + endDateField`,types:[`date`,`datetime`,`time`],namePattern:null,viewBlocks:[`gantt`]},{visualization:`map`,binding:`locationField`,types:[`location`,`geo`,`geolocation`,`geopoint`,`point`],namePattern:`location|address|geo|coords?|place|venue`,viewBlocks:[`map`]}],Ag=`grid`,jg=new Map(kg.map(e=>[e.visualization,e])),Mg=/start|begin|kickoff/i,Ng=/end|due|finish|deadline|close/i;function H(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Pg(e){return typeof e==`string`&&e.length>0?e:void 0}function Fg(e){let t=e.fields;if(!H(t)&&!Array.isArray(t))return;let n=0,r=[];for(let e of w(t)){let t=Pg(e.name);t&&(n++,!(e.hidden===!0||e.system===!0||Nn.has(t))&&r.push({name:t,type:Pg(e.type)}))}return n===0?void 0:r}function Ig(e,t){return e.find(t)?.name}function Lg(e,t){let n=Ig(e,e=>!!e.type&&t.types.includes(e.type));if(n)return n;if(t.namePattern===null)return;let r=new RegExp(t.namePattern,`i`);return Ig(e,e=>r.test(e.name))}function Rg(e,t){let n=e=>!!e.type&&t.includes(e.type),r=Ig(e,e=>n(e)&&Mg.test(e.name))??Ig(e,n);if(!r)return;let i=Ig(e,e=>n(e)&&e.name!==r&&Ng.test(e.name))??Ig(e,e=>n(e)&&e.name!==r);if(i)return`${r} + ${i}`}function zg(e,t){return t.visualization===`gantt`?Rg(e,t.types):Lg(e,t)}function Bg(e,t,n){let r=new Map,i=(e,t)=>{H(t)&&!r.has(e)&&r.set(e,t)},a=H(t?.listViews)?t.listViews:H(t?.list_views)?t.list_views:void 0;if(a)for(let[e,t]of Object.entries(a))i(e,t);t&&H(t.list)&&i(`list`,t.list);for(let t of w(e.views)){let e=Pg(t.objectName)??Pg(t.object),r=t=>(H(t.data)?Pg(t.data.object):void 0)??e;if(H(t.listViews))for(let[e,a]of Object.entries(t.listViews))H(a)&&r(a)===n&&i(e,a);H(t.list)&&r(t.list)===n&&i(`list`,t.list)}return r}function Vg(e){return Array.isArray(e.columns)&&e.columns.length>0}function Hg(e,t,n){let r=[e.get(`${t}.${n}`),e.get(n),...n==="default"||n===`list`?[e.get(`list`)]:[]].filter(H);return r.find(Vg)??r[0]}function Ug(e,t){let n=H(e.options)?e.options:void 0;return t.viewBlocks.some(t=>H(e[t])||!!n&&H(n[t]))}function Wg(e){let t=`a field typed ${e.types.join(` / `)}`,n=e.namePattern===null?``:`, then a field whose NAME matches /${e.namePattern}/i`;return e.visualization===`gantt`?`two distinct fields typed ${e.types.join(` / `)} (a start and an end)`:`${t}${n}`}function Gg(e){let t=[];if(!H(e))return t;let n=new Map;for(let t of w(e.objects)){let e=Pg(t.name);e&&!n.has(e)&&n.set(e,t)}let r=w(e.pages);for(let i=0;i<r.length;i++){let a=r[i];if(a.type!==`list`)continue;let o=H(a.interfaceConfig)?a.interfaceConfig:void 0;if(!o)continue;let s=(H(o.appearance)?o.appearance:void 0)?.allowedVisualizations;if(!Array.isArray(s)||s.length===0)continue;let c=Pg(o.source)??Pg(a.object);if(!c)continue;let l=n.get(c);if(!l)continue;let u=Fg(l);if(!u)continue;let d=Pg(o.sourceView),f;if(d&&(f=Hg(Bg(e,l,c),c,d),!f))continue;let p=Pg(a.name)??`#${i}`,m=`page "${p}" \xB7 interfaceConfig.appearance`;for(let e=0;e<s.length;e++){let n=Pg(s[e]);if(!n||n===Ag)continue;let r=jg.get(n);if(!r||f&&Ug(f,r)||zg(u,r))continue;let a=e===0;t.push({severity:a?`error`:`warning`,rule:Og,where:m,path:`pages[${i}].interfaceConfig.appearance.allowedVisualizations[${e}]`,message:`page "${p}" whitelists the '${n}' visualization, but nothing supplies its \`${r.binding}\`: the renderer derives that binding from "${c}"'s fields \u2014 it looks for ${Wg(r)} \u2014 and "${c}" has none`+(d?`, while the referenced view "${d}" declares no \`${r.viewBlocks[0]}:\` block either.`:`, and this page references no view that declares it.`)+` `+(a?`'${n}' LEADS \`allowedVisualizations\`, so it becomes the page's forced view type: every visitor lands on the renderer's "configuration required" refusal screen.`:`'${n}' is filtered out of the visualization switcher SILENTLY \u2014 the switcher still appears (it is shown on whitelist length), the type is simply never there, with no message at build time or at run time.`),hint:`An interface page has no per-visualization binding key of its own \u2014 \`sourceView\` is the one schema-legal channel. Point this page at a "${c}" list view that declares a \`${r.viewBlocks[0]}:\` block (\`interfaceConfig.sourceView: '<view_key>'\`), give "${c}" a field the derivation can find (${Wg(r)}), or drop '${n}' from \`appearance.allowedVisualizations\`.`})}}return t}var Kg=`component-props-unknown-key`,qg=`component-props-invalid`;function Jg(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Yg(e){return typeof e==`string`&&e.length>0?e:void 0}var Xg=Lt,Zg=`object`;function Qg(e,t){return e.path.length!==1||e.path[0]!==Zg||Yg((Jg(t.dataSource)?t.dataSource:void 0)?.object)===void 0?!1:(Jg(t.properties)?t.properties:void 0)?.[Zg]===void 0}function $g(e){if(e.code!==`invalid_union`)return;let t=e.errors;if(!t||t.length===0)return;let n;for(let e of t){let t=e.filter(e=>e.code===`unrecognized_keys`);if(t.length!==0){if(t.length!==e.length||n)return;n=t[0]}}return n}function e_(e){let t=[];if(!Jg(e))return t;let n=w(e.pages);for(let e=0;e<n.length;e++){let r=n[e];if(!Jg(r))continue;let i=Yg(r.name)??`#${e}`;for(let{component:n,path:a}of Vc(r,`pages[${e}]`)){let e=Yg(n.type);if(!e)continue;let r=Xg[e];if(!r)continue;let o=Jg(n.properties)?n.properties:void 0;if(!o)continue;let s=`page "${i}" \xB7 ${e}`,c=`${a}.properties`;for(let n of gt(r,o,e,c))t.push({severity:`warning`,rule:Kg,where:s,path:n.path,message:`\`${n.key}\` is not a prop \`${e}\` declares (ComponentPropsMap, @objectstack/spec/ui), so nothing verifies it: \`properties\` is an untyped bag, the renderer spreads whatever it carries, and a key it does not read is ignored in silence.`+(n.suggestion?` Did you mean \`${n.suggestion}\`?`:``),hint:n.guidance??(n.suggestion?`Rename \`${n.key}\` \u2192 \`${n.suggestion}\`.`:`Remove \`${n.key}\`, or \u2014 if the component really does honour it \u2014 declare it on \`${e}\`'s props schema so the declaration and the renderer agree.`)});let l=r.safeParse(o);if(!l.success)for(let r of l.error?.issues??[]){if(Qg(r,n))continue;let i=r.path.length?`${c}.${r.path.join(`.`)}`:c,a=$g(r);if(a){for(let n of a.keys??[])t.push({severity:`warning`,rule:Kg,where:s,path:`${i}.${n}`,message:`\`${n}\` is not a prop \`${e}\` declares (ComponentPropsMap, @objectstack/spec/ui): ${a.message}`,hint:`Remove \`${n}\`, or declare it on \`${e}\`'s props schema if the component honours it.`});continue}if(r.code===`unrecognized_keys`){for(let n of r.keys??[])t.push({severity:`warning`,rule:Kg,where:s,path:`${i}.${n}`,message:`\`${n}\` is not a prop \`${e}\` declares (ComponentPropsMap, @objectstack/spec/ui): ${r.message}`,hint:`Remove \`${n}\`, or declare it on \`${e}\`'s props schema if the component honours it.`});continue}t.push({severity:`warning`,rule:qg,where:s,path:i,message:`${i.slice(c.length+1)||`properties`}: ${ll(r,o)}`,hint:`\`${e}\`'s props are declared by ComponentPropsMap (@objectstack/spec/ui) \u2014 the rejection above carries the fix. Advisory for now: the props bag is not parsed on the storage path either, so nothing rejects this today (objectstack#5068).`})}}}return t}var t_=`component-type-unknown`;function n_(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function r_(e){return typeof e==`string`&&e.length>0?e:void 0}function i_(e){let t=[];if(!n_(e))return t;let n=w(e.pages);for(let e=0;e<n.length;e++){let r=n[e];if(!n_(r))continue;let i=r_(r.name)??`#${e}`;for(let{component:n,path:a}of Vc(r,`pages[${e}]`)){let e=r_(n.type);if(!e)continue;let r=At.get(e);if(r!==void 0){t.push({severity:`error`,rule:t_,where:`page "${i}" \xB7 ${e}`,path:`${a}.type`,message:r,hint:`Apply the prescription above: \`${e}\` is a retired component type, refused by name at the parse door (\`PageComponentSchema.type\`), so this page cannot validate or publish while the node is present.`});continue}if(!_(e)||De(e))continue;let o=ee(e,ne),s=me(o);t.push({severity:`error`,rule:t_,where:`page "${i}" \xB7 ${e}`,path:`${a}.type`,message:`\`${e}\` is not a component type the platform vocabulary declares. Its namespace (\`${e.slice(0,e.indexOf(`:`))}:\`) belongs to the standard component vocabulary, so nothing will ever render this node \u2014 the page would validate, publish, and then draw a placeholder scaffold in front of the end user.`+(s?` ${s}`:``),hint:o.length?`Rename \`${e}\` \u2192 \`${o[0]}\`.`:`Use a declared component type from the standard vocabulary, or \u2014 for a custom component registered by your own plugin \u2014 give it its own namespace (e.g. \`my-plugin:${e.slice(e.indexOf(`:`)+1)}\`) so it cannot be mistaken for platform vocabulary.`})}}return t}var a_=`chart-dimension-unknown`,o_=`chart-measure-unknown`,s_=`chart-dataset-unknown`,c_=`chart-axis-not-selected`;function U(e){return typeof e==`string`&&e.length>0?e:void 0}function l_(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function u_(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function d_(e){let t=[...e].sort();return t.length?t.join(`, `):`(none)`}function f_(e){let t=new Map;for(let n of w(e.datasets)){let e=U(n.name);if(!e)continue;let r=new Set;for(let e of w(n.dimensions)){let t=U(e.name);t&&r.add(t)}let i=new Set;for(let e of w(n.measures)){let t=U(e.name);t&&i.add(t)}t.set(e,{dimensions:r,measures:i})}return t}var p_={"report-series":"On this surface `chart.series[]` is a per-measure DISPLAY-NAME override, not a binding: the renderer derives the series from the chart's own `xAxis`/`yAxis` query and pairs an authored entry with the derived series whose key it EQUALS, so an entry naming no declared measure is ignored. The override lands on nothing — the series is still drawn from the dataset selection.","page-series":"On this surface `series[]` is presentation, not a binding: the renderer derives one series per selected measure and REPLACES the authored array with the derived one, so this entry never reaches the chart at all. It lands on nothing — the chart is still drawn from `dimensions`/`values`.","page-axis":"On this surface `yAxis[].field` is axis PRESENTATION, not a binding: the entry keeps its slot (the count is what turns on a secondary axis) and its scale/chrome, while the plotted columns come from `values`. The key re-points nothing."},m_={"report-series":"`series[].name` selects WHICH derived series the label and per-series presentation land on; it cannot add, remove or re-point one.","page-series":"`series[].name` cannot add, remove or re-point a series on a dataset-bound chart — membership belongs to the dataset selection.","page-axis":"`yAxis[]` carries presentation only (title, min/max, position, gridlines); the plotted columns come from `values`."},h_={query:`the query does not return it, so the series plots nothing.`,"report-series":"this entry is a display-name override matched against the ONE series the chart derives (from its own `chart.yAxis` query), so unless it names that measure the override lands on nothing. The series drawn is unaffected.","page-series":"the series are derived from `values`, so none is derived for it and this entry lands on nothing. The chart drawn is unaffected.","page-axis":"the plotted columns come from `values`, so the axis entry re-points nothing. The chart drawn is unaffected."};function g_(e){let t=[];if(!e||typeof e!=`object`)return t;let n=f_(e);if(n.size===0&&!e.reports&&!e.views&&!e.pages)return t;let r=(e,r,i)=>{if(!e)return;let a=n.get(e);if(a)return a;t.push({severity:`error`,rule:s_,where:r,path:`${i}.dataset`,message:`binds dataset "${e}", which resolves to no declared dataset \u2014 there is no data to render.`,hint:`Declared datasets: ${d_(n.keys())}.${E(e,n.keys())} Define it with defineDataset() or fix the reference (ADR-0021).`})},i=(e,n,r)=>{let i=(i,a)=>{e.dimensions.has(i)||t.push({severity:`error`,rule:a_,where:r.where,path:a,message:`"${i}" is not a dimension declared by dataset "${n}". Post-ADR-0021 result rows are keyed by DIMENSION NAME, not the base field, so this axis renders with no categories.`,hint:`Dataset dimensions: ${d_(e.dimensions)}.${E(i,e.dimensions)} Declare the dimension on the dataset, or bind an existing one.`})},a=(i,a,o,s)=>{if(!e.measures.has(i)){t.push({severity:o===`query`?`error`:`warning`,rule:o_,where:r.where,path:a,message:`"${i}" is not a measure declared by dataset "${n}". `+(o===`query`?`Post-ADR-0021 result rows are keyed by MEASURE NAME (e.g. "sum_amount"), not the base field (e.g. "amount"), so this series comes back empty.`:p_[o]),hint:`Dataset measures: ${d_(e.measures)}.${E(i,e.measures)} `+(o===`query`?`Declare the measure on the dataset, or bind an existing one.`:`${m_[o]} Correct the name or drop the entry \u2014 this surface carries no \`suppressWarnings\` key to silence the advisory with.`)});return}s&&s.size>0&&!s.has(i)&&t.push({severity:`warning`,rule:c_,where:r.where,path:a,message:`"${i}" is a declared measure of "${n}" but is not in this chart's selected values (${d_(s)}) \u2014 ${h_[o]}`,hint:o===`report-series`?"Point the entry at the measure this chart plots (`chart.yAxis`), or drop it.":`Add "${i}" to \`values\`, or point the ${o===`query`?`axis`:`entry`} at a selected measure.`})};for(let e of r.dimensions??[])for(let t=0;t<e.names.length;t++)i(e.names[t],`${e.path}[${t}]`);let o=r.values,s=new Set(o?.names??[]),c=r.ownSelection?new Set(r.ownSelection):s;if(o)for(let e=0;e<o.names.length;e++)a(o.names[e],`${o.path}[${e}]`,`query`);r.xAxis&&i(r.xAxis.name,r.xAxis.path),r.yAxis&&a(r.yAxis.name,r.yAxis.path,`query`);for(let e of r.axes??[])a(e.name,e.path,`page-axis`,c);for(let e of r.series??[])a(e.name,e.path,e.kind,c)},a=e=>{let t=r(e.dataset,e.where,e.path);t&&e.dataset&&i(t,e.dataset,e)},o=w(e.reports);for(let e=0;e<o.length;e++){let t=o[e];if(!u_(t))continue;let n=U(t.name)??`#${e}`,a=(e,t,n,a)=>{let o=U(e.dataset),s=r(o,t,n);if(!s||!o||(i(s,o,{dimensions:[{names:l_(e.rows),path:`${n}.rows`},{names:l_(e.columns),path:`${n}.columns`}],values:{names:l_(e.values),path:`${n}.values`},where:t,path:n}),!a))return;let c=e.chart;if(!u_(c))return;let l=U(c.xAxis),u=U(c.yAxis);i(s,o,{xAxis:l?{name:l,path:`${n}.chart.xAxis`}:void 0,yAxis:u?{name:u,path:`${n}.chart.yAxis`}:void 0,ownSelection:u?[u]:[],series:w(c.series).map((e,t)=>({name:U(e.name),path:`${n}.chart.series[${t}].name`,kind:`report-series`})).filter(e=>!!e.name),where:`${t} \xB7 chart`,path:`${n}.chart`})};a(t,`report "${n}"`,`reports[${e}]`,t.type!==`joined`);let s=Array.isArray(t.blocks)?t.blocks:[];for(let t=0;t<s.length;t++){let r=s[t];u_(r)&&a(r,`report "${n}" \xB7 block "${U(r.name)??`#${t}`}"`,`reports[${e}].blocks[${t}]`,!1)}}let s=(e,t,n)=>{if(!u_(e))return;let r=e.chart;u_(r)&&a({dataset:U(r.dataset),dimensions:[{names:l_(r.dimensions),path:`${n}.chart.dimensions`}],values:{names:l_(r.values),path:`${n}.chart.values`},where:t,path:`${n}.chart`})},c=w(e.views);for(let e=0;e<c.length;e++){let t=c[e];if(!u_(t))continue;let n=U(t.name)??U(t.objectName)??`#${e}`;if(s(t.list,`view "${n}" \xB7 list chart`,`views[${e}].list`),u_(t.listViews))for(let[r,i]of Object.entries(t.listViews))s(i,`view "${n}" \xB7 listViews.${r} chart`,`views[${e}].listViews.${r}`)}let l=w(e.objects);for(let e=0;e<l.length;e++){let t=l[e];if(!u_(t)||!u_(t.listViews))continue;let n=U(t.name)??`#${e}`;for(let[r,i]of Object.entries(t.listViews))s(i,`object "${n}" \xB7 listViews.${r} chart`,`objects[${e}].listViews.${r}`)}let u=w(e.pages);for(let e=0;e<u.length;e++){let t=u[e];if(!u_(t))continue;let n=U(t.name)??`#${e}`;for(let{component:r,path:i}of Vc(t,`pages[${e}]`)){let e=u_(r.properties)?r.properties:void 0;if(!e||!U(e.dataset))continue;let t=w(e.yAxis).map((e,t)=>({name:U(e.field),path:`${i}.properties.yAxis[${t}].field`})).filter(e=>!!e.name),o=w(e.series).map((e,t)=>({name:U(e.name),path:`${i}.properties.series[${t}].name`,kind:`page-series`})).filter(e=>!!e.name);a({dataset:U(e.dataset),dimensions:[{names:l_(e.dimensions),path:`${i}.properties.dimensions`}],values:{names:l_(e.values),path:`${i}.properties.values`},axes:t,series:o,where:`page "${n}" \xB7 ${U(r.type)??`chart`}`,path:`${i}.properties`})}}return t}var __=`dataset-include-unknown`,v_=`dataset-field-unknown`,y_=`dataset-field-not-included`,b_=`dataset-filter-field-unknown`;function x_(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function S_(e){return typeof e==`string`&&e.length>0?e:void 0}var C_=`The path is compiled into the analytics query as written, so it addresses a column that does not exist: the surface renders successfully with empty or wrong numbers, and nothing reports the miss.`;function w_(e){let t=[];if(!x_(e))return t;let n=w(e.datasets);if(n.length===0)return t;let r=qn(e);return n.forEach((e,n)=>{let i=`dataset "${S_(e.name)??`#${n}`}"`,a=`datasets[${n}]`,o=S_(e.object);if(!o||!r.has(o)||!r.get(o))return;let s=Jn(e.include);(Array.isArray(e.include)?e.include:[]).forEach((e,n)=>{if(typeof e!=`string`||!e)return;let s=`${a}.include[${n}]`,c=T(r,o,e);if(Xn(c)||!c)return;let l=`Declare a relationship (lookup / master_detail) that exists on the join chain from "${o}", or drop the entry. ADR-0071 allows up to 3 hops and declaring "a.b" implicitly includes "a".`;if(c.kind===`ok`){let r=c.meta?.type;if(r&&Vn.has(r))return;t.push({severity:`error`,rule:__,where:i,path:s,message:`include[${n}] "${e}" names a${r?` \`${r}\``:`n ordinary`} field on object "${c.object}", not a relationship \u2014 no join can be derived from it, so every dimension or measure written against that prefix addresses nothing.`,hint:l});return}let u=Yn(c,e,`include[${n}]`);u&&t.push({severity:`error`,rule:__,where:i,path:s,message:`${u.message} Joins are COMPILED from \`include\` (ADR-0021), so an entry that resolves to nothing produces no join at all.`,hint:`${l} ${u.detail}`})});let c=(e,n,i,a,c,l)=>{let u=S_(e);if(!u)return;let d=T(r,o,u);if(Xn(d)||!d)return;let f=Yn(d,u,a);if(f){t.push({severity:`error`,rule:c,where:n,path:i,message:`${f.message} ${C_}`,hint:`${l} ${f.detail}`});return}let p=u.lastIndexOf(`.`);if(p<0)return;let m=u.slice(0,p);s.has(m)||t.push({severity:`error`,rule:y_,where:n,path:i,message:`${a} "${u}" resolves on the object graph, but its relationship prefix "${m}" is not declared in this dataset's \`include\` \u2014 and ADR-0021 joins ONLY declared paths, so no join is compiled and the column is out of the query's reach. ${C_}`,hint:`Add "${m}" to include (declaring "a.b" implicitly includes "a"), or bind this position to a field on "${o}" itself. Declared include paths: ${s.size>0?[...s].sort().join(`, `):`(none)`}.`})};w(e.dimensions).forEach((e,t)=>{let n=S_(e.name)??`#${t}`;c(e.field,`${i} \u203A dimension "${n}"`,`${a}.dimensions[${t}].field`,`dimension field`,v_,`Bind the dimension to a field on "${o}", or to a \`relationship[.relationship].field\` path whose prefix is declared in \`include\`.`)}),w(e.measures).forEach((e,t)=>{let n=S_(e.name)??`#${t}`;c(e.field,`${i} \u203A measure "${n}"`,`${a}.measures[${t}].field`,`measure field`,v_,`Bind the measure to a field on "${o}", or to a \`relationship[.relationship].field\` path whose prefix is declared in \`include\`.`)});let l=(e,t,n)=>{e!=null&&sr(e,n,({field:e,path:n})=>{c(e,t,n,`filter key`,b_,`Filter on a field that exists on "${o}" (or on a declared \`include\` path).`)})};l(e.filter,`${i} \u203A filter`,`${a}.filter`),w(e.measures).forEach((e,t)=>{let n=S_(e.name)??`#${t}`;l(e.filter,`${i} \u203A measure "${n}" \u203A filter`,`${a}.measures[${t}].filter`)})}),t}var T_=`mapping-target-field-unknown`;function E_(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function D_(e){return typeof e==`string`&&e.length>0?e:void 0}function O_(e){let t=new Map,n=e=>{for(let n of w(e)){let e=D_(n.extend);if(!e)continue;let r=w(n.fields);r.length!==0&&t.set(e,[...t.get(e)??[],...r])}};n(e.objectExtensions);for(let t of Un(e))E_(t.manifest)&&n(t.manifest.objectExtensions);return t}function k_(e){let t=[];if(!E_(e))return t;let r=w(e.mappings);if(r.length===0)return t;let i=new Map;for(let t of w(e.objects)){let e=D_(t.name);e&&i.set(e,t)}let a=O_(e);for(let e=0;e<r.length;e++){let o=r[e],s=D_(o.targetObject);if(!s)continue;let c=i.get(s);if(!c)continue;let l=a.get(s),u=l?{...c,fields:[...w(c.fields),...l]}:c,d=n(o.fieldMapping,u);if(d.length===0)continue;let f=Be(u),p=f?.names??new Set,m=f&&f.parts.size>0?[...f.parts].map(([e,t])=>`${e}: ${t.join(`, `)}`).join(`; `):``,h=D_(o.name)??`#${e}`,g=`mapping "${h}" \xB7 object "${s}"`;for(let n of d){if(n.reason===`collides`){let r=n.target.indexOf(`.`);t.push({severity:`error`,rule:T_,where:g,path:`mappings[${e}].${n.path}`,message:`Import mapping "${h}" writes the compound field "${n.target.slice(0,r)}" of object "${s}" both whole (${n.wholeAt}) and by its part "${n.target.slice(r+1)}" (${n.path}). One row carries one value for a field, so the two collide, and the import endpoint refuses this mapping before any row, on the dry run and the commit alike (INVALID_FIELD).`,hint:`Map the field whole or by its parts, not both. A declared part of a compound field is written field.part (${m}).`});continue}t.push({severity:`error`,rule:T_,where:g,path:`mappings[${e}].${n.path}`,message:`Import mapping "${h}" writes target "${n.target}", which names no field of object "${s}". The import endpoint refuses this mapping before any row, on the dry run and the commit alike (INVALID_FIELD), so it can import nothing.`+(n.head?.field?A_(n.head,n.target,s):E(n.target,p)),hint:`Point the target at a field "${s}" declares, or at a column the platform provisions on it`+(m?`, or at a declared part of a compound field as field.part (${m})`:``)+`. Addressable names: ${$n(p)}.`})}}return t}function A_(e,t,n){let r=e.type?`the ${e.type} field "${e.name}"`:`"${e.name}"`;if(e.parts){let n=t.slice(e.name.length+1);return` "${n}" is not a part of ${r}: the parts a target may name on it are ${e.parts.join(`, `)}.`+E(n,e.parts)}return e.type&&y.has(e.type)?` ${j_(r)} is a field of "${n}" with no parts: a dotted target never traverses a reference. Map the column to "${e.name}" with transform "lookup", which resolves the cell's display text to a record id.`:` ${j_(r)} is a field of "${n}" with no parts: only a compound field (one whose value declares parts, such as an address) takes a part target.`}function j_(e){return e.length>0?e[0].toUpperCase()+e.slice(1):e}var M_=`validation-rule-regex-uncompilable`,N_=`validation-rule-json-schema-uncompilable`,P_={allErrors:!0,strict:!1},F_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),I_=null,L_=null;function R_(){if(I_)return I_;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`,t;try{t=(0,S.createRequire)(e)(`ajv`)}catch(e){throw Error(`@objectstack/lint: checking a \`json_schema\` validation rule requires the "ajv" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "ajv" in the image; it is only loaded when a stack declares a \`json_schema\` validation rule.`)}let n=F_(t)&&`default`in t?t.default:t;return I_=n,n}function z_(){if(L_)return L_;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`,t;try{t=(0,S.createRequire)(e)(`ajv-formats`)}catch(e){throw Error(`@objectstack/lint: checking a \`json_schema\` validation rule requires the "ajv-formats" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "ajv-formats" in the image; it is only loaded when a stack declares a \`json_schema\` validation rule. The runtime registers it too, and this gate must compile in the SAME environment or it starts disagreeing with the write path.`)}let n=F_(t)&&`default`in t?t.default:t;return L_=n,n}function B_(){let e=new(R_())(P_);return z_()(e),e}function V_(){let e=Object.keys(B_().formats).sort();if(e.length===0)throw Error('@objectstack/lint: the runtime-parity ajv instance has no `format` registered. "ajv-formats" loaded but added nothing, so the set of legitimate format names is unknown — refusing to judge format names against an empty vocabulary, which would report every `format` in the stack as misspelled. Check that the installed "ajv-formats" is the real package and matches the version @objectstack/lint declares.');return e}function H_(e){return e instanceof Error?e.message:String(e)}var U_=16;function W_(e,t,n,r=0){let i=typeof e.name==`string`&&e.name?e.name:`?`,a=t?`${t} \u2192 '${i}'`:`'${i}'`,o=n?`${n}.${i}`:i,s=[{rule:e,label:a,path:o}];if(r>=U_)return s;for(let t of[`then`,`otherwise`]){let n=e[t];F_(n)&&s.push(...W_(n,a,`${o}.${t}`,r+1))}return s}function G_(e){let t=[];if(!F_(e))return t;for(let n of w(e.objects)){let e=typeof n.name==`string`?n.name:`(unnamed object)`,r=n.validations;for(let n of w(r))for(let{rule:r,label:i,path:a}of W_(n,``,``))t.push({rule:r,objectName:e,label:i,where:`object '${e}' \xB7 validation ${i}`,basePath:`objects.${e}.validations.${a}`})}return t}function K_(e){let t=[];for(let{rule:n,objectName:r,label:i,where:a,basePath:o}of G_(e)){if(n.type===`format`&&typeof n.regex==`string`&&n.regex!==``)try{new RegExp(n.regex)}catch(e){t.push({severity:`error`,rule:M_,where:a,path:`${o}.regex`,message:`\`format\` validation ${i} on object '${r}' declares a \`regex\` that does not compile: ${H_(e)}. The write path builds it with \`new RegExp(rule.regex)\` and SKIPS the rule when that throws (rule-validator.ts \`checkFormat\`), so the rule is declared, listed in the metadata, and enforces nothing on any record.`,hint:`Fix the pattern so \`new RegExp('${n.regex}')\` compiles \u2014 a literal \`(\`, \`[\` or \`\\\` must be escaped (\`\\\\(\`, \`\\\\[\`, \`\\\\\\\\\`), and the source is a STRING, so a backslash is written twice in TypeScript ('^\\\\d{2}-\\\\d{7}$'). Or drop \`regex\` and use a named \`format\` ('email' | 'url' | 'phone' | 'json').`})}if(n.type===`json_schema`&&F_(n.schema))try{B_().compile(n.schema)}catch(e){t.push({severity:`error`,rule:N_,where:a,path:`${o}.schema`,message:`\`json_schema\` validation ${i} on object '${r}' declares a \`schema\` ajv cannot compile: ${H_(e)}. The write path compiles it with the same ajv (\`new Ajv({ allErrors: true, strict: false })\` + \`ajv-formats\`) and SKIPS the rule when that throws (rule-validator.ts \`checkJsonSchema\`), so the rule is declared and enforces nothing on any record.`,hint:"Correct the schema so ajv compiles it — the message above names the offending keyword. `type` must be one of null|boolean|object|array|number|string|integer (or an array of those), `required` an array of strings, and every `$ref` must resolve. Vendor keywords are fine (the runtime runs `strict: false`); a MALFORMED standard keyword is not."})}}return t}var q_=`validation-rule-json-schema-unknown-format`,J_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),Y_=[`additionalItems`,`additionalProperties`,`contains`,`propertyNames`,`if`,`then`,`else`,`not`,`unevaluatedItems`,`unevaluatedProperties`],X_=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],Z_=[`properties`,`patternProperties`,`$defs`,`definitions`,`dependentSchemas`],Q_=32,$_=e=>e.replace(/~/g,`~0`).replace(/\//g,`~1`);function ev(e,t,n,r){if(!J_(e)||(typeof e.format==`string`&&n.push({pointer:`${t}/format`,name:e.format}),r>=32))return;for(let i of Y_)i in e&&ev(e[i],`${t}/${$_(i)}`,n,r+1);for(let i of X_){let a=e[i];Array.isArray(a)&&a.forEach((e,a)=>{ev(e,`${t}/${$_(i)}/${a}`,n,r+1)})}for(let i of Z_){let a=e[i];if(J_(a))for(let[e,o]of Object.entries(a))ev(o,`${t}/${$_(i)}/${$_(e)}`,n,r+1)}let i=e.items;Array.isArray(i)?i.forEach((e,i)=>ev(e,`${t}/items/${i}`,n,r+1)):J_(i)&&ev(i,`${t}/items`,n,r+1);let a=e.dependencies;if(J_(a))for(let[e,i]of Object.entries(a))J_(i)&&ev(i,`${t}/dependencies/${$_(e)}`,n,r+1)}function tv(e,t){let n=Array.from({length:t.length+1},(e,t)=>t);for(let r=1;r<=e.length;r++){let i=[r];for(let a=1;a<=t.length;a++)i[a]=Math.min(n[a]+1,i[a-1]+1,n[a-1]+(e[r-1]===t[a-1]?0:1));n=i}return n[t.length]}function nv(e,t){let n=Math.min(3,Math.floor(e.length/2));if(n<1)return null;let r=e.toLowerCase(),i=null,a=1/0;for(let e of[...t].sort()){let t=tv(r,e);t<a&&(a=t,i=e)}return a<=n?i:null}function rv(e){let t=[],n=[];for(let{rule:t,objectName:r,label:i,where:a,basePath:o}of G_(e)){if(t.type!==`json_schema`||!J_(t.schema))continue;let e=[];ev(t.schema,``,e,0);for(let t of e)n.push({use:t,where:a,label:i,objectName:r,basePath:o})}if(n.length===0)return t;let r=V_(),i=new Set(r);for(let{use:e,where:a,label:o,objectName:s,basePath:c}of n){if(i.has(e.name))continue;let n=nv(e.name,r),l=`#${e.pointer}`;t.push({severity:`error`,rule:q_,where:a,path:`${c}.schema${l}`,message:`\`json_schema\` validation ${o} on object '${s}' names \`format: '${e.name}'\` at \`${l}\`, which is not a registered format. ajv logs \`unknown format "${e.name}" ignored\` once at compile time and DROPS the keyword \u2014 in the write path (rule-validator.ts, \`strict: false\`) and in the publish gate alike \u2014 so the schema compiles, the rule ships and runs on every write, its \`type\`/\`required\` keywords are enforced, and this constraint is enforced on no record, ever. The record is ACCEPTED, so nothing downstream reports the gap either.`,hint:(n?`Did you mean \`format: '${n}'\`? `:``)+`The registered names are: ${r.join(`, `)} \u2014 the default \`ajv-formats\` set, the one \`rule-validator.ts\` registers (#5029). Names are case-sensitive and hyphenated (\`date-time\`, not \`datetime\`). If you meant a constraint ajv has no format for, express it with \`pattern\` instead \u2014 a regex is enforced, an unknown format name is not.`})}return t}function iv(e){let t=[];if(!e||typeof e!=`object`)return{version:1,entries:t};let n=new Map;for(let t of w(e.objects)){let e=typeof t.name==`string`?t.name:``;if(!e)continue;let r=t.sharingModel??t.security?.sharingModel;typeof r==`string`&&n.set(e,r)}for(let r of w(e.permissions)){let e=typeof r.name==`string`?r.name:``;if(!e)continue;let i=r.objects&&typeof r.objects==`object`?r.objects:{};for(let[r,a]of Object.entries(i)){let i=a??{},o=i,s={permissionSet:e,object:r,create:dt(o,`allowCreate`),read:dt(o,`allowRead`),edit:dt(o,`allowEdit`),delete:dt(o,`allowDelete`),viewAllRecords:i.viewAllRecords===!0,modifyAllRecords:i.modifyAllRecords===!0};typeof i.readScope==`string`&&(s.readScope=i.readScope),typeof i.writeScope==`string`&&(s.writeScope=i.writeScope);let c=n.get(r);c&&(s.sharingModel=c),t.push(s)}}return t.sort((e,t)=>e.permissionSet===t.permissionSet?e.object.localeCompare(t.object):e.permissionSet.localeCompare(t.permissionSet)),{version:1,entries:t}}var av=[[`create`,`create`],[`read`,`read`],[`edit`,`edit`],[`delete`,`delete`],[`viewAllRecords`,`View All Data`],[`modifyAllRecords`,`Modify All Data`]];function ov(e,t){let n=[],r=e=>`${e.permissionSet}\0${e.object}`,i=new Map((e?.entries??[]).map(e=>[r(e),e])),a=new Map((t?.entries??[]).map(e=>[r(e),e]));for(let[e,t]of i)a.has(e)||n.push(`'${t.permissionSet}' loses ALL access to '${t.object}' (entry removed)`);for(let[e,t]of a){let r=i.get(e);if(!r){let e=av.filter(([e])=>t[e]===!0).map(([,e])=>e);n.push(`'${t.permissionSet}' gains access to '${t.object}' (${e.join(`, `)||`no bits set`})`);continue}for(let[e,i]of av)r[e]!==t[e]&&n.push(`'${t.permissionSet}' ${t[e]?`gains`:`loses`} ${i} on '${t.object}'`);(r.readScope??`own`)!==(t.readScope??`own`)&&n.push(`'${t.permissionSet}' read depth on '${t.object}': ${r.readScope??`own`} \u2192 ${t.readScope??`own`}`),(r.writeScope??`own`)!==(t.writeScope??`own`)&&n.push(`'${t.permissionSet}' write depth on '${t.object}': ${r.writeScope??`own`} \u2192 ${t.writeScope??`own`}`),(r.sharingModel??``)!==(t.sharingModel??``)&&n.push(`'${t.object}' record baseline (OWD): ${r.sharingModel??`(unset)`} \u2192 ${t.sharingModel??`(unset)`} (affects every principal)`)}return n}var sv=`nav-object-ungranted`;function cv(e){return typeof e==`string`&&e.length>0?e:void 0}function lv(e){let t=[],n=w(e.apps);for(let e=0;e<n.length;e++){let r=n[e];if(!r||typeof r!=`object`)continue;let i=cv(r.name)??`#${e}`,a=(e,n)=>{let r=w(e);for(let e=0;e<r.length;e++){let o=r[e];if(!o||typeof o!=`object`)continue;let s=`${n}[${e}]`,c=cv(o.objectName);o.type===`object`&&c&&t.push({objectName:c,where:`app "${i}" \xB7 nav "${cv(o.id)??`#${e}`}"`,path:`${s}.objectName`}),Array.isArray(o.children)&&a(o.children,`${s}.children`)}};a(r.navigation,`apps[${e}].navigation`);let o=w(r.areas);for(let t=0;t<o.length;t++)a(o[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}function uv(e){let t=[];if(!e||typeof e!=`object`||w(e.permissions).length===0)return t;let n=lv(e);if(n.length===0)return t;let r=new Set;for(let t of w(e.objects)){let e=cv(t.name);e&&r.add(e)}let i=new Set;for(let t of iv(e).entries)t.read&&i.add(t.object);if(i.has(`*`))return t;let a=new Set;for(let e of n){let{objectName:n}=e;a.has(n)||d(n)||r.has(n)&&(i.has(n)||(a.add(n),t.push({severity:`warning`,rule:sv,where:e.where,path:e.path,message:`navigation exposes object "${n}", but no permission set this stack declares grants read on it \u2014 the entry renders, and opening it fails permission-denied for every principal except one holding the platform's built-in wildcard admin set. It works when you browse as an administrator and breaks for the users the app ships permission sets for.`,hint:`Add "${n}" to a permission set's \`objects\` with \`allowRead: true\` (or \`viewAllRecords\`), or drop the entry. Gating it with \`requiredPermissions\`/\`visible\` does not clear this: those gate visibility, not the object grant, so a holder can still open the entry and hit permission-denied. Ignore this if a permission set from another installed package grants it.`})))}return t}var dv=`field-no-consumers`;function fv(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function W(e){return typeof e==`string`&&e.length>0?e:void 0}var pv=[`objects`,`views`,`pages`,`apps`,`flows`,`dashboards`,`reports`,`datasets`,`actions`,`hooks`,`jobs`,`emailTemplates`,`agents`,`tools`,`skills`,`apis`,`webhooks`,`sharingRules`,`analyticsCubes`],mv=[`translations`,`data`,`mappings`,`permissions`],hv=new Set([`externalId`,`upsertKey`]),gv=new Set([`views`,`pages`,`apps`]),_v=new Set([`label`,`pluralLabel`,`description`,`message`,`successMessage`,`errorMessage`,`title`,`placeholder`,`helpText`,`emptyText`,`tooltip`,`subtitle`]),vv=new Set(`filter.filters.runtimeFilter.relatedListFilter.where.criteria.conditions.condition.defaultFilter.userFilters.quickFilters.filterableFields.sort.sortBy.defaultSort.grouping.groupBy.groupByField.groupField.startField.endField.dateField.startDateField.endDateField.coverField.titleField.colorField.latitudeField.longitudeField.locationField.addressField.parentField.statusField.kanban.calendar.gantt.timeline.map.tree.rowColor.rowTint.conditionalFormatting.expression.formula.visibleWhen.readonlyWhen.requiredWhen.validations.rules.summaryOperations.dimensions.measures.handler.body.script.nameField.displayNameField.externalId.upsertKey`.split(`.`)),yv=new Set([`highlightFields`,`searchableFields`,`indexes`,`columns`,`sections`,`groups`,`hideFields`,`hiddenFields`,`fieldOrder`,`visibleFields`,`labelField`,`displayField`,`descriptionField`,`tooltipFields`,`fieldGroups`,`recordTypes`,`listViews`]),bv=new Set([`filter`,`filters`,`runtimeFilter`,`relatedListFilter`,`where`,`criteria`,`defaultFilter`,`conditions`]),xv=new Set([`fields`,`values`,`set`,`record`,`data`,`input`,`defaults`,`records`]),Sv=new Set([`subforms`,`details`]),Cv=new Set([`amountField`,`relationshipField`]),wv=new Set(`type.reference.accept.provider.dialect.operator.aggregate.mode.severity.language.surface.format.icon.variant.colorVariant.align.order.defaultValue.value.sourceFormat.transform.name.id.events.locations.version.width.cardSize.coverFit.env.pinned.summary.chartType.dateGranularity.kind.template.status.runAs.sharingModel.objectName.object.targetObject.dataset.outputVariable.triggerType.event.currency.color.size.layout.function.direction.model.role.method.path.url.key.locale.namespace.engine.driver`.split(`.`)),Tv=[/\.([A-Za-z_][A-Za-z0-9_]*)\b/g,/['"`]([A-Za-z_][A-Za-z0-9_]*)['"`]/g,/\{([A-Za-z_][A-Za-z0-9_]*)\}/g,/\b([A-Za-z_][A-Za-z0-9_]*)\s*:/g],Ev=new Set([`source`,`expression`,`formula`,`condition`,`criteria`,`when`,`visibleWhen`,`readonlyWhen`,`requiredWhen`,`where`,`predicate`,`script`,`body`,`handler`,`code`]),Dv=/\b([A-Za-z_][A-Za-z0-9_]*)\b/g,Ov=2e5,kv=class{constructor(){this.fieldsByObject=new Map,this.objectsByField=new Map,this.datasetObject=new Map,this.fieldMapByObject=new Map,this.sites=new Map,this.unresolved=0}declare(e,t){let n=this.fieldsByObject.get(e);n||this.fieldsByObject.set(e,n=new Set),n.add(t);let r=this.objectsByField.get(t);r||this.objectsByField.set(t,r=new Set),r.add(e)}declares(e,t){return e!==void 0&&(this.fieldsByObject.get(e)?.has(t)??!1)}isObject(e){return typeof e==`string`&&this.fieldsByObject.has(e)}record(e,t,n){let r=`${e}.${t}`,i=this.sites.get(r);i?i.push(n):this.sites.set(r,[n])}mentionsIn(e){if(!this.mentionRe){let e=[...this.fieldsByObject.keys()].sort((e,t)=>t.length-e.length).map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`));this.mentionRe=e.length>0?RegExp(`\\b(?:${e.join(`|`)})\\b`,`g`):/(?!)/g}let t=[];for(let n of e.matchAll(this.mentionRe))t.push({end:(n.index??0)+n[0].length,object:n[0]});return t}};function Av(e,t,n){return mv.includes(e)?t.some(e=>hv.has(e))?`behaviour`:`carrier`:_v.has(n)?`carrier`:t.some(e=>vv.has(e))?`behaviour`:gv.has(e)||t.some(e=>yv.has(e))?`display`:`behaviour`}function jv(e,t,n,r,i,a,o){if(t.length===0||t.length>Ov||wv.has(o))return;let s=[],c=t.trim();e.objectsByField.has(c)&&s.push({token:c,at:0});let l=Ev.has(o)?[...Tv,Dv]:Tv;for(let n of l)for(let r of t.matchAll(n))e.objectsByField.has(r[1])&&s.push({token:r[1],at:(r.index??0)+r[0].indexOf(r[1])});if(s.length===0)return;let u=e.mentionsIn(t),d=[...t.matchAll(/\{[^{}]*\}/g)].map(e=>[e.index??0,(e.index??0)+e[0].length]),f=_v.has(o);for(let{token:t,at:c}of s){let s=d.some(([e,t])=>c>=e&&c<t),l=f&&!s?`carrier`:Av(r,a,s?``:o),p;for(let e of u)if(e.end<=c)p=e.object;else break;let m=p!==void 0&&p!==n?[p,n]:[n],h=!1;for(let n of m)e.declares(n,t)&&(e.record(n,t,{root:r,path:i,kind:l}),h=!0);h||(e.unresolved+=1)}}function Mv(e,t,n,r,i,a){Array.isArray(t)&&t.forEach((t,o)=>{let s=fv(t)?W(t.name):void 0;s!==void 0&&e.objectsByField.has(s)&&(e.declares(n,s)?e.record(n,s,{root:i,path:`${a}[${o}].name`,kind:r}):e.unresolved+=1)})}function Nv(e){return Array.isArray(e)&&e.length>0}function Pv(e,t,n,r,i){let a=t===void 0?void 0:e.fieldMapByObject.get(t);if(t!==void 0&&a!==void 0)for(let{name:o}of $e({fields:a},{relationshipField:n}))e.declares(t,o)&&e.record(t,o,{root:r,path:i,kind:`display`})}function Fv(e,t,n,r,i,a,o){let s=W(t);s!==void 0&&e.objectsByField.has(s)&&(e.declares(n,s)?e.record(n,s,{root:r,path:i,kind:Av(r,a,o)}):e.unresolved+=1)}function Iv(e,t,n){let r=t=>e.isObject(t)?t:void 0,i=(e,t)=>fv(e)?r(e[t]):void 0,a=fv(t.list)?t.list:void 0,o=typeof t.dataset==`string`?e.datasetObject.get(t.dataset):void 0;return r(t.object)??r(t.objectName)??r(t.targetObject)??i(t.data,`object`)??i(t.config,`objectName`)??i(t.config,`object`)??(a?i(a.data,`object`):void 0)??r(t.name)??o??(Array.isArray(t.nodes)?t.nodes.map(e=>fv(e)?i(e.config,`objectName`)??i(e.config,`object`):void 0).find(e=>e!==void 0):void 0)??n}function Lv(e,t,n,r,i,a,o){if(t==null)return;if(typeof t==`function`){jv(e,Function.prototype.toString.call(t),n,r,i,a,o);return}if(typeof t==`string`){jv(e,t,n,r,i,a,o);return}if(typeof t!=`object`)return;if(Array.isArray(t)){for(let s=0;s<t.length;s++)Lv(e,t[s],n,r,`${i}[${s}]`,a,o);return}let s=t,c=Iv(e,s,n),l=Sv.has(o);if(l){let t=W(s.childObject);Mv(e,s.columns,t,`display`,r,`${i}.columns`),Nv(s.columns)||Pv(e,t,W(s.relationshipField),r,`${i}.childObject`);for(let n of Cv)Fv(e,s[n],t,r,`${i}.${n}`,[...a,n],n)}for(let[t,n]of Object.entries(s)){if(l&&Cv.has(t))continue;let s=`${i}.${t}`,u=[...a,t];if(e.objectsByField.has(t)&&(bv.has(o)||xv.has(o))){if(e.declares(c,t)){let n=xv.has(o)?`carrier`:Av(r,u,o);e.record(c,t,{root:r,path:s,kind:n})}else e.unresolved+=1}Lv(e,n,e.isObject(t)?t:c,r,s,u,t)}}var Rv=new Set([`name`,`label`,`type`,`reference`]);function zv(e,t,n,r,i){for(let[i,a]of Object.entries(t))i!==`fields`&&i!==`name`&&Lv(e,a,n,`objects`,`${r}.${i}`,[i],i);for(let{rec:r,path:a}of O(t.fields,i)){let t=Ce(r),i=W(r.displayField);t&&i&&e.declares(t,i)&&e.record(t,i,{root:`objects`,path:`${a}.displayField`,kind:`display`}),Mv(e,r.inlineColumns,n,r.inlineEdit?`display`:`carrier`,`objects`,`${a}.inlineColumns`);let o=W(r.name);o!==void 0&&r.inlineEdit&&(r.type===`master_detail`||r.type===`lookup`)&&t&&!Nv(r.inlineColumns)&&Pv(e,n,o,`objects`,`${a}.inlineEdit`);for(let[t,i]of Object.entries(r))Rv.has(t)||t===`displayField`||Lv(e,i,n,`objects`,`${a}.${t}`,[t],t)}}function Bv(e){let t={};for(let{rec:n}of e){let e=W(n.name);e&&(t[e]=n)}return t}function Vv(e,t){return{nameField:W(e.nameField),displayNameField:W(e.displayNameField),fields:Bv(t)}}function Hv(e,t,n,r){let i=nt({fieldGroups:t.fieldGroups,fields:Bv(r)});if(i===null)return;let a=new Map;for(let{rec:e,path:t}of r){let n=W(e.name);n!==void 0&&a.set(n,t)}for(let t of i)if(t.key!==void 0)for(let r of t.fields){let t=a.get(r);t!==void 0&&e.record(n,r,{root:`objects`,path:`${t}.group`,kind:`display`})}}function Uv(e){return e.join(`, `)}function Wv(e){let t=[];if(!fv(e)||!pv.some(t=>t!==`objects`&&w(e[t]).length>0))return t;let n=new kv,r=[],i=O(e.objects,`objects`);for(let{rec:e,path:t}of i){let i=W(e.name);if(!i||!e.fields||typeof e.fields!=`object`)continue;let a=O(e.fields,`${t}.fields`),o=Pn(e),s=v(Vv(e,a));Hv(n,e,i,a);for(let{rec:e,path:t}of a){let a=W(e.name);if(!a)continue;n.declare(i,a);let c=n.fieldMapByObject.get(i);c||n.fieldMapByObject.set(i,c={}),c[a]=e;let l=o.has(a)||a===s||e.type===`master_detail`;r.push({object:i,field:a,path:t,exempt:l})}}if(r.length===0)return t;for(let t of w(e.datasets)){let e=W(t.name),r=W(t.object);e&&r&&n.datasetObject.set(e,r)}for(let{rec:e,path:t}of i){let r=W(e.name);r&&n.fieldsByObject.has(r)&&zv(n,e,r,t,`${t}.fields`)}for(let t of[...pv,...mv])t!==`objects`&&Lv(n,e[t],void 0,t,t,[],t);let a=[...pv,...mv];for(let{object:e,field:i,path:o,exempt:s}of r){if(s)continue;let r=n.sites.get(`${e}.${i}`)??[];if(r.some(e=>e.kind!==`carrier`))continue;let c=r.map(e=>e.path),l=c.length>0?`carrier-only`:`inert`,u=[...n.objectsByField.get(i)??[]].filter(t=>t!==e),d=l===`carrier-only`?`Verdict: carrier-only \u2014 ${c.length} carrier site(s) name it without reading it, and a removal must clean each: ${Uv(c)}.`:`Verdict: inert — no site of any kind names it.`,f=u.length>0?` The same name is declared on ${u.map(e=>`"${e}"`).join(`, `)}; verdicts are per object, so a consumer there does not cover this declaration.`:``;t.push({severity:`warning`,rule:dv,where:`object "${e}" \xB7 field "${i}"`,path:o,message:`field "${i}" on object "${e}" is declared but nothing in this stack reads or displays it: no view column, inline grid column, form section, page binding, flow node, dataset, widget, formula, validation, hook or action names it, no declared field group places it on the synthesized layout, and no seed or import mapping matches on it. A translation label, a seed value, an import-mapping target, a permission grant, a flow that only WRITES it, or an \`inlineColumns\` entry on a relationship field that does not set \`inlineEdit\` (no grid is drawn) is a carrier, not a consumer. ${d}${f}`,hint:`Give "${i}" a consumer \u2014 a view column, a form section, a page binding, a formula, a validation, a flow node, a dataset dimension, or a \`group\` naming one of this object's declared \`fieldGroups\` so the synthesized layout draws it \u2014 or remove the declaration`+(c.length>0?` together with its ${c.length} carrier site(s) listed above`:``)+`. Ignore this if the field is read only by an API client, by a hook or package this stack does not carry, or by a Studio-authored view. Roots scanned: ${pv.join(`, `)} (consumers) \xB7 ${mv.join(`, `)} (carriers); test fixtures are never scanned.`,object:e,field:i,verdict:l,carriers:c,rootsScanned:a})}return t}var Gv=`screen`,Kv=`translation-target-unknown`,qv=`translation-option-key-unknown`,Jv=`error`;function G(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function K(e){return typeof e==`string`&&e.length>0?e:void 0}function Yv(e,t){let n=K(e.name);n&&t.add(n),G(e.then)&&Yv(e.then,t),G(e.otherwise)&&Yv(e.otherwise,t)}function q(e,t){let n=[...t],r=n.find(t=>t.endsWith(`_${e}`)||t.startsWith(`${e}_`));return r?` Did you mean "${r}"?`:E(e,n)}function J(e,t=12){let n=[...e].sort();if(n.length===0)return``;let r=n.slice(0,t).join(`, `);return n.length>t?`${r}, \u2026 (${n.length} total)`:r}var Xv=new Set([...Nn,`_id`,`name`,`space`]);function Zv(){return{fields:new Map,views:new Set,actions:new Map,sections:new Set,validations:new Set,tabs:new Set}}function Qv(e,t){let n=iu(e),r=e=>iu(e)??n,i=(e,n)=>{e&&n&&t(e).views.add(n)},a=(e,n)=>{if(n)for(let r of w(e.sections)){let e=K(r.name);e&&t(n).sections.add(e)}},o=G(e.list)?r(e.list):void 0;G(e.list)&&i(o,ey(o,e)),i(n??o,K(e.name));let s=ty(e);for(let t of[`listViews`,`formViews`]){let n=e[t];if(!G(n))continue;let c=t===`listViews`?s.list:s.form,l=0;for(let e of Object.values(n)){if(!e||typeof e!=`object`)continue;let t=c[l++];if(!G(e))continue;let n=r(e)??o;i(n,t),a(e,n)}}G(e.form)&&a(e.form,r(e.form)??o),a(e,n??o)}function $v(e,t){let n=G(e.interfaceConfig)?e.interfaceConfig:void 0;if(!n)return;let r=G(n.userFilters)?n.userFilters:void 0;if(!r)return;let i=K(n.source)??K(e.object);if(i)for(let e of w(r.tabs)){let n=K(e.name);n&&t(i).tabs.add(n)}}function ey(e,t){if(!e||!G(t.list))return;let n=pt(e,t).find(e=>e.viewKind===`list`&&e.isDefault);if(!n)return;let r=`${e}.`;return n.name.startsWith(r)?n.name.slice(r.length):n.name}function ty(e){let t=`probe`,n=`${t}.`,r=e=>e.startsWith(n)?e.slice(n.length):e,i=e=>G(e)?Object.values(e).filter(e=>!!e&&typeof e==`object`).length:0,a=i(e.listViews),o=i(e.formViews);if(!a&&!o)return{list:[],form:[]};let s=pt(t,e),c=(e,t)=>s.filter(t=>t.viewKind===e).slice(0,t).map(e=>r(e.name));return{list:c(`list`,a),form:c(`form`,o)}}function ny(e){let t=e.options,n=new Set,r=new Map;if(Array.isArray(t))for(let e of t){if(typeof e==`string`){n.add(e);continue}if(!G(e))continue;let t=K(e.value);if(!t)continue;n.add(t);let i=K(e.label);i&&r.set(i.toLowerCase(),t)}else if(G(t))for(let[e,i]of Object.entries(t))n.add(e),typeof i==`string`&&i.length>0&&r.set(i.toLowerCase(),e);else return;return n.size>0?{values:n,byLabel:r}:void 0}function ry(e){let t=new Map,n=e=>{for(let n of w(e)){let e=K(n.app);if(!e)continue;let r=t.get(e)??[];r.push(n.items),t.set(e,r)}};n(G(e.manifest)?e.manifest.navigationContributions:void 0);for(let t of Un(e)){let e=t.manifest;G(e)&&n(e.navigationContributions)}return t}function iy(e){let t=new Map,n=e=>{for(let n of w(e)){let e=K(n.extend);if(!e)continue;let r=t.get(e)??[];r.push(n),t.set(e,r)}};n(e.objectExtensions);for(let t of Un(e)){let e=t.manifest;G(e)&&n(e.objectExtensions)}return t}function ay(e,t){let n=[];for(let r of Un(e)){let e=r.manifest;G(e)&&n.push(...w(e[t]))}return n}function oy(e){let t=new Map,n=e=>{let n=t.get(e);return n||(n=Zv(),t.set(e,n)),n},r=(e,{ownDeclaration:t})=>{let r=K(e.name);if(!r)return;let i=n(r);for(let n of w(e.fields)){let e=K(n.name);e&&(t||!i.fields.has(e))&&i.fields.set(e,n)}for(let n of w(e.actions)){let e=K(n.name);e&&(t||!i.actions.has(e))&&i.actions.set(e,n)}for(let t of w(e.views))Qv({...t,object:K(t.object)??r},n);Qv({object:r,listViews:e.listViews},n);for(let t of w(e.fieldGroups)){let e=K(t.key)??K(t.name);e&&i.sections.add(e)}for(let t of w(e.validations))Yv(t,i.validations)};for(let t of w(e.objects))r(t,{ownDeclaration:!0});for(let t of ay(e,`objects`))r(t,{ownDeclaration:!1});let i=iy(e),a=new Set(i.keys());for(let[e,n]of i){let r=t.get(e);if(r)for(let e of n){for(let t of w(e.fields)){let e=K(t.name);e&&(r.fields.has(e)||r.fields.set(e,t))}for(let t of w(e.validations))Yv(t,r.validations)}}for(let t of[...w(e.views),...ay(e,`views`)])Qv(t,n);let o=e=>{$v(e,n);for(let t of Vc(e,``)){if(!t.objectName)continue;let e=G(t.component.properties)?t.component.properties:void 0;if(e)for(let r of w(e.sections)){let e=K(r.name);e&&n(t.objectName).sections.add(e)}}};for(let t of w(e.pages))o(t);for(let t of ay(e,`pages`))o(t);let s=new Map,c=new Map,l=(e,{ownDeclaration:t})=>{let r=K(e.name);if(!r)return;let i=K(e.objectName)??K(e.object);if(i){let a=n(i);if(!t&&a.actions.has(r))return;a.actions.set(r,e),c.set(r,i)}else{if(!t&&s.has(r))return;s.set(r,e)}};for(let t of w(e.actions))l(t,{ownDeclaration:!0});for(let t of ay(e,`actions`))l(t,{ownDeclaration:!1});for(let[e,n]of t)for(let t of n.actions.keys())c.has(t)||c.set(t,e);let u=ry(e),d=new Map,f=(e,t)=>{for(let n of w(e)){let e=K(n.id);e&&t.add(e),n.children&&f(n.children,t)}},p=e=>{let t=K(e.name);if(!t)return;let n=d.get(t)??new Set;f(e.navigation,n);for(let t of w(e.areas)){let e=K(t.id);e&&n.add(e),f(t.navigation,n)}for(let e of u.get(t)??[])f(e,n);d.set(t,n)};for(let t of w(e.apps))p(t);for(let t of ay(e,`apps`))p(t);let m=new Set;for(let[e,t]of u){if(d.has(e))continue;let n=new Set;for(let e of t)f(e,n);d.set(e,n),m.add(e)}let h=new Map,g=(e,{ownDeclaration:t})=>{let n=K(e.name);if(!n||!t&&h.has(n))return;let r=new Set;for(let t of w(e.widgets)){let e=K(t.id)??K(t.name);e&&r.add(e)}let i=new Set,a=[...w(G(e.header)?e.header.actions:void 0),...w(e.actions)];for(let e of a){let t=K(e.actionUrl)??K(e.url)??K(e.name);t&&i.add(t)}h.set(n,{widgets:r,actions:i})};for(let t of w(e.dashboards))g(t,{ownDeclaration:!0});for(let t of ay(e,`dashboards`))g(t,{ownDeclaration:!1});let _=new Map,v=(e,{ownDeclaration:t})=>{let n=K(e.name);if(!n||!t&&_.has(n))return;let r=new Map,i=new Map;for(let{node:t}of bo(e,``)){let e=K(t.id);if(!e)continue;let n=K(t.type);if(n!==Gv){n&&!i.has(e)&&i.set(e,n);continue}let a=G(t.config)?t.config:void 0,o=new Set;for(let e of w(a?.fields)){let t=K(e.name);t&&o.add(t)}r.set(e,{fields:o,objectName:K(a?.objectName)})}_.set(n,{screens:r,otherNodes:i})};for(let t of w(e.flows))v(t,{ownDeclaration:!0});for(let t of ay(e,`flows`))v(t,{ownDeclaration:!1});return{objects:t,extended:a,apps:d,contributedOnlyApps:m,dashboards:h,flows:_,globalActions:s,actionOwners:c}}function sy(e,t){return`translations[${e}]${hy(t)}`}function cy(e){let t=[];if(!G(e))return t;let n=Array.isArray(e.translations)?e.translations:[];if(n.length===0)return t;let r=oy(e),i=(e,n,r,i)=>{t.push({severity:Jv,rule:Kv,where:e,path:n,message:r,hint:i})};for(let e=0;e<n.length;e++){let a=n[e];if(G(a))for(let[n,o]of Object.entries(a)){if(!G(o))continue;let a=sy(e,n),s=`locale "${n}"`;for(let[e,n]of Object.entries(Y(o.objects))){if(!G(n))continue;let o=`${a}.objects.${e}`,c=r.objects.get(e);if(!c){if(d(e)||r.extended.has(e))continue;i(`${s} \xB7 object "${e}"`,o,Se(e)?`Translations are keyed to "${e}", which carries a platform namespace prefix but is registered by no platform package, official plugin, or cloud runtime object \u2014 and this stack does not define it either. Nothing resolves these keys.`+q(e,r.objects.keys()):`Translations are keyed to "${e}", which no object in this stack defines. The resolver looks up keys derived from the metadata, so this whole subtree is dead weight \u2014 every label it carries renders untranslated.`+q(e,r.objects.keys()),`Rename the key to the object it was written for, drop it, or ignore this if the object is contributed by another installed package.`+(r.objects.size>0?` Defined objects: ${J(r.objects.keys())}.`:``));continue}for(let[r,a]of Object.entries(Y(n.fields))){let n=`${o}.fields.${r}`,l=c.fields.get(r);if(!l){if(Xv.has(r))continue;i(`${s} \xB7 object "${e}" \xB7 field "${r}"`,n,`Translations are keyed to field "${r}", which object "${e}" does not declare. The label renders untranslated in this locale \u2014 and because every neighbouring field DOES resolve, the hole reads as a styling quirk rather than a missing translation.`+q(r,c.fields.keys()),`Point the key at a declared field, or drop it if the field was removed or renamed.`+(c.fields.size>0?` Declared fields: ${J(c.fields.keys())}.`:``));continue}G(a)&&ly(t,{optionMap:a.options,field:l,fieldName:r,objectName:e,path:`${n}.options`,where:`${s} \xB7 object "${e}" \xB7 field "${r}"`})}for(let t of Object.keys(Y(n._views)))c.views.has(t)||i(`${s} \xB7 object "${e}" \xB7 view "${t}"`,`${o}._views.${t}`,`Translations are keyed to view "${t}", which no view of object "${e}" declares. The view tab keeps its source-locale label.`+q(t,c.views),"Match the key to the view's `name` (not its label), or drop it."+(c.views.size>0?` Declared views: ${J(c.views)}.`:``));for(let t of Object.keys(Y(n._sections)))c.sections.has(t)||i(`${s} \xB7 object "${e}" \xB7 section "${t}"`,`${o}._sections.${t}`,`Translations are keyed to section "${t}", which nothing on object "${e}" declares \u2014 no \`fieldGroups[].key\`, no named form-view section, no named \`record:details\` section. The section heading stays in the source locale.`+q(t,c.sections),"Sections are translatable only through a STABLE NAME: give the group/section a `key`/`name` and use it here, or drop the translation."+(c.sections.size>0?` Declared sections: ${J(c.sections)}.`:` Object "${e}" declares no named section at all.`));for(let t of Object.keys(Y(n._tabs)))c.tabs.has(t)||i(`${s} \xB7 object "${e}" \xB7 tab "${t}"`,`${o}._tabs.${t}`,`Translations are keyed to filter-preset tab "${t}", which no page over object "${e}" declares in \`interfaceConfig.userFilters.tabs\`. The tab keeps its source-locale label \u2014 above a grid whose every column resolves, so the hole reads as a styling quirk rather than a missing translation.`+q(t,c.tabs),"Match the key to the tab's `name` (not its label), or drop it if the preset was renamed or removed."+(c.tabs.size>0?` Declared tabs: ${J(c.tabs)}.`:` No page over "${e}" declares a filter-preset tab bar at all. Note only a page's \`interfaceConfig.userFilters.tabs\` is resolvable \u2014 a list view's own \`tabs\` has no renderer, so nothing reads a key written for one.`));for(let t of Object.keys(Y(n._validations)))c.validations.has(t)||i(`${s} \xB7 object "${e}" \xB7 validation "${t}"`,`${o}._validations.${t}`,`Translations are keyed to validation rule "${t}", which object "${e}" does not declare in \`validations[]\`. The rule's authored \`message\` keeps its source locale in every refusal.`+q(t,c.validations),"Match the key to the rule's `name`, or drop it if the rule was renamed or removed."+(c.validations.size>0?` Declared rules: ${J(c.validations)}.`:` Object "${e}" declares no named validation rules.`));for(let[r,a]of Object.entries(Y(n._actions))){let n=`${o}._actions.${r}`,l=c.actions.get(r);if(!l){i(`${s} \xB7 object "${e}" \xB7 action "${r}"`,n,`Translations are keyed to action "${r}", which is defined by neither object "${e}"'s \`actions\` nor a \`stack.actions\` entry bound to it. The button keeps its source-locale label.`+q(r,c.actions.keys()),`Match the key to a defined action name, move it under the object that owns the action, or drop it.`+(c.actions.size>0?` Actions on this object: ${J(c.actions.keys())}.`:``));continue}uy(t,{rawAction:a,action:l,path:n,where:`${s} \xB7 object "${e}" \xB7 action "${r}"`,subject:`action "${r}"`})}}for(let[e,n]of Object.entries(Y(o.globalActions))){let o=`${a}.globalActions.${e}`,c=r.globalActions.get(e);if(!c){let t=r.actionOwners.get(e);i(`${s} \xB7 global action "${e}"`,o,t?`Action "${e}" is bound to object "${t}", so the resolver looks it up under \`objects.${t}._actions.${e}\` \u2014 never under \`globalActions\`, which is only consulted for object-less actions. This key is never read.`:`Translations are keyed to global action "${e}", which no object-less action in this stack defines. The button keeps its source-locale label.`+q(e,r.globalActions.keys()),t?`Move these keys under \`objects.${t}._actions.${e}\`.`:`Match the key to an object-less action's name, or drop it.`+(r.globalActions.size>0?` Object-less actions: ${J(r.globalActions.keys())}.`:``));continue}uy(t,{rawAction:n,action:c,path:o,where:`${s} \xB7 global action "${e}"`,subject:`action "${e}"`})}for(let[e,t]of Object.entries(Y(o.apps))){let n=`${a}.apps.${e}`,o=r.apps.get(e);if(!o){i(`${s} \xB7 app "${e}"`,n,`Translations are keyed to app "${e}", which this stack neither defines nor contributes into. The app launcher shows the source-locale label.`+q(e,r.apps.keys()),"Match the key to an app's `name`, or drop it."+(r.apps.size>0?` Apps this stack defines or contributes into: ${J(r.apps.keys())}.`:``));continue}if(!G(t))continue;let c=r.contributedOnlyApps.has(e);for(let r of Object.keys(Y(t.navigation)))o.has(r)||i(`${s} \xB7 app "${e}" \xB7 navigation "${r}"`,`${n}.navigation.${r}`,c?`Translations are keyed to navigation item "${r}" of app "${e}", which this stack contributes into (\`manifest.navigationContributions\`) without declaring \u2014 and it contributes no item with that id. Only the ids contributed from here are addressable; the app's own entries are declared, and translated, by the package that owns it.`+q(r,o):`Translations are keyed to navigation item "${r}", which app "${e}" does not declare. The menu entry keeps its source-locale label.`+q(r,o),c?`Match the key to a contributed item's \`id\`, or move it to the package that owns app "${e}".`+(o.size>0?` Contributed navigation ids: ${J(o)}.`:` This stack contributes no identified item into "${e}" at all.`):"Match the key to the navigation item's `id`, or drop it."+(o.size>0?` Declared navigation ids: ${J(o)}.`:``))}for(let[e,t]of Object.entries(Y(o.dashboards))){let n=`${a}.dashboards.${e}`,o=r.dashboards.get(e);if(!o){i(`${s} \xB7 dashboard "${e}"`,n,`Translations are keyed to dashboard "${e}", which this stack does not define. The dashboard title stays in the source locale.`+q(e,r.dashboards.keys()),"Match the key to a dashboard's `name`, or drop it."+(r.dashboards.size>0?` Defined dashboards: ${J(r.dashboards.keys())}.`:``));continue}if(G(t)){for(let r of Object.keys(Y(t.widgets)))o.widgets.has(r)||i(`${s} \xB7 dashboard "${e}" \xB7 widget "${r}"`,`${n}.widgets.${r}`,`Translations are keyed to widget "${r}", which dashboard "${e}" does not declare. The widget title stays in the source locale.`+q(r,o.widgets),"Match the key to the widget's `id`, or drop it."+(o.widgets.size>0?` Declared widget ids: ${J(o.widgets)}.`:``));for(let r of Object.keys(Y(t.actions)))o.actions.has(r)||i(`${s} \xB7 dashboard "${e}" \xB7 action "${r}"`,`${n}.actions.${r}`,`Translations are keyed to header action "${r}", which dashboard "${e}" does not declare. The button keeps its source-locale label.`+q(r,o.actions),"Header-action translations are keyed by the action's `actionUrl`, not its label."+(o.actions.size>0?` Declared header actions: ${J(o.actions)}.`:``))}}for(let[e,t]of Object.entries(Y(o.flows))){let n=`${a}.flows.${e}`,o=r.flows.get(e);if(!o){i(`${s} \xB7 flow "${e}"`,n,`Translations are keyed to flow "${e}", which this stack does not define. The wizard renders its source-locale label and headings.`+q(e,r.flows.keys()),"Match the key to a flow's `name` (the machine name, not its label), or drop it."+(r.flows.size>0?` Defined flows: ${J(r.flows.keys())}.`:``));continue}if(G(t))for(let[r,a]of Object.entries(Y(t.screens))){let t=`${n}.screens.${r}`,c=o.screens.get(r);if(!c){let n=o.otherNodes.get(r);i(`${s} \xB7 flow "${e}" \xB7 screen "${r}"`,t,n?`Translations are keyed to screen "${r}", which flow "${e}" declares as a \`${n}\` node, not a \`screen\`. Only screen nodes render a heading and fields for a user to read, so nothing resolves these keys.`:`Translations are keyed to screen "${r}", which flow "${e}" declares no screen node for. The wizard step keeps its source-locale heading.`+q(r,o.screens.keys()),"Screen translations are keyed by the node's `id` (the client's `ScreenSpec.nodeId`), not its `label`."+(o.screens.size>0?` Declared screen node ids: ${J(o.screens.keys())}.`:` Flow "${e}" declares no \`type: 'screen'\` node at all.`));continue}if(G(a))for(let n of Object.keys(Y(a.fields))){if(c.fields.has(n))continue;let a=c.fields.size===0?c.objectName:void 0;i(`${s} \xB7 flow "${e}" \xB7 screen "${r}" \xB7 field "${n}"`,`${t}.fields.${n}`,a?`Translations are keyed to screen field "${n}", but screen "${r}" is an OBJECT-FORM screen (\`config.objectName: "${a}"\`) \u2014 it renders that object's own create/edit form, so its input labels come from \`objects.${a}.fields.*\` and nothing reads a field key here.`:`Translations are keyed to screen field "${n}", which screen "${r}" of flow "${e}" does not declare. The input keeps its source-locale label while every neighbouring field on the same screen resolves.`+q(n,c.fields),a?`Move this copy under \`objects.${a}.fields.${n}\`, or drop it.`:"Match the key to a `config.fields[].name` on that screen, or drop it."+(c.fields.size>0?` Declared screen field names: ${J(c.fields)}.`:` Screen "${r}" declares no \`config.fields\` at all.`))}}}}}return t}function Y(e){return G(e)?e:{}}function ly(e,t){let n=Object.keys(Y(t.optionMap));if(n.length===0)return;let r=ny(t.field);if(!r){e.push({severity:`warning`,rule:qv,where:t.where,path:t.path,message:`Option translations are keyed under field "${t.fieldName}" of object "${t.objectName}", which declares no \`options\` at all (field type "${K(t.field.type)??`unknown`}"). Nothing reads this map.`,hint:`Declare the options on the field, move the translations to the field that owns them, or drop them.`});return}for(let i of n){if(r.values.has(i))continue;let n=r.byLabel.get(i.toLowerCase());e.push({severity:`warning`,rule:qv,where:t.where,path:`${t.path}.${i}`,message:n?`Option translation is keyed by the DISPLAY LABEL "${i}" instead of the stored value "${n}". The resolver looks the option up by value, so this entry is never found and the option renders with its source-locale label.`:`Option translation is keyed by "${i}", which is not one of the values declared by field "${t.objectName}.${t.fieldName}". The option renders untranslated.`+q(i,r.values),hint:n?`Rename the key to "${n}".`:`Option keys are the stored \`value\`, not the label and not a variant spelling (\`direct_mail\`, not \`direct-mail\`). Declared values: ${J(r.values)}.`})}}function uy(e,t){dy(e,t),py(e,t),my(e,t)}function dy(e,t){let n=Y(G(t.rawAction)?t.rawAction.params:void 0);if(Object.keys(n).length===0)return;let r=new Map;for(let e of w(t.action.params)){let t=K(e.name)??K(e.field);t&&r.set(t,e)}let i=new Set(r.keys());for(let[a,o]of Object.entries(n)){let n=r.get(a);if(n){fy(e,{optionMap:G(o)?o.options:void 0,param:n,paramName:a,path:`${t.path}.params.${a}.options`,where:`${t.where} \xB7 param "${a}"`,subject:t.subject});continue}e.push({severity:Jv,rule:Kv,where:`${t.where} \xB7 param "${a}"`,path:`${t.path}.params.${a}`,message:`Translations are keyed to parameter "${a}", which ${t.subject} does not declare. The parameter's label and help text render untranslated in the action dialog.`+q(a,i),hint:"Match the key to a declared param `name`, or drop it."+(i.size>0?` Declared params: ${J(i)}.`:``)})}}function fy(e,t){let n=Object.keys(Y(t.optionMap));if(n.length===0)return;let r=t.param.options;if(!Array.isArray(r)&&K(t.param.field))return;let i=new Set,a=new Map;for(let e of Array.isArray(r)?r:[]){if(!G(e)||e.value===void 0)continue;let t=String(e.value);i.add(t);let n=K(e.label);n&&a.set(n.toLowerCase(),t)}if(i.size===0){e.push({severity:`warning`,rule:qv,where:t.where,path:t.path,message:`Option translations are keyed under parameter "${t.paramName}" of ${t.subject}, which declares no \`options\``+(Array.isArray(r)?``:` and references no field`)+`. Nothing reads this map.`,hint:`Declare the options on the param, move the translations to the param that owns them, or drop them.`});return}for(let r of n){if(i.has(r))continue;let n=a.get(r.toLowerCase());e.push({severity:`warning`,rule:qv,where:t.where,path:`${t.path}.${r}`,message:n?`Option translation is keyed by the DISPLAY LABEL "${r}" instead of the stored value "${n}". The resolver looks the option up by value, so this entry is never found and the option renders with its source-locale label.`:`Option translation is keyed by "${r}", which is not one of the values declared by parameter "${t.paramName}" of ${t.subject}. The option renders untranslated.`+q(r,i),hint:n?`Rename the key to "${n}".`:`Option keys are the stored \`value\`, not the label and not a variant spelling. Declared values: ${J(i)}.`})}}function py(e,t){let n=Object.keys(Y(G(t.rawAction)?t.rawAction.outcomeMessages:void 0));if(n.length===0)return;let r=new Set(Object.keys(Y(t.action.outcomeMessages)));for(let i of n)r.has(i)||e.push({severity:Jv,rule:Kv,where:`${t.where} \xB7 outcome "${i}"`,path:`${t.path}.outcomeMessages.${i}`,message:r.size>0?`Translations are keyed to outcome "${i}", which ${t.subject} does not declare in \`outcomeMessages\`. Only the outcomes the action declares are translated, so this copy is never shown.`+q(i,r):`Translations are keyed to outcome "${i}", but ${t.subject} declares no \`outcomeMessages\` at all, so nothing reads this map and this copy is never shown.`,hint:"Match the key to an outcome the action's `outcomeMessages` declares, declare the outcome there first, or drop it."+(r.size>0?` Declared outcomes: ${J(r)}.`:``)})}function my(e,t){let n=G(t.rawAction)?t.rawAction.resultDialog:void 0,r=Object.keys(Y(G(n)?n.fields:void 0));if(r.length===0)return;let i=G(t.action.resultDialog)?t.action.resultDialog:void 0,a=new Set;for(let e of i&&Array.isArray(i.fields)?i.fields:[])G(e)&&typeof e.path==`string`&&a.add(e.path);for(let n of r)a.has(n)||e.push({severity:Jv,rule:Kv,where:`${t.where} \xB7 result field "${n}"`,path:`${t.path}.resultDialog.fields${hy(n)}`,message:i?a.size>0?`Translations are keyed to result field "${n}", which ${t.subject}'s \`resultDialog.fields\` does not declare. Each label is looked up by a declared field's literal \`path\`, so this one is never shown.`+q(n,a):`Translations are keyed to result field "${n}", but ${t.subject}'s \`resultDialog\` declares no \`fields\` \u2014 it renders the whole response as JSON \u2014 so nothing reads this label.`:`Translations are keyed to result field "${n}", but ${t.subject} declares no \`resultDialog\`, so nothing reads this label.`,hint:"Match the key to a declared field's literal `path` (dots included), or drop it."+(a.size>0?` Declared paths: ${J(a)}.`:``)})}function hy(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?`.${e}`:`["${e}"]`}var gy=`translation-section-name-missing`;function _y(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function vy(e){return typeof e==`string`&&e.length>0?e:void 0}function yy(e){let t=vy(e.name);return t?`view "${t}"`:``}function by(...e){return e.filter(e=>e.length>0).join(` · `)}function xy(e,t,n,r){let i=iu(e),a=_y(e.list)?iu(e.list)??i:void 0;for(let o of au(e,t))r.push({path:`${o.path}.sections`,surface:by(n,o.surface),objectName:iu(o.view)??i??a,sections:o.view.sections})}function Sy(e){let t=new Set,n=Array.isArray(e.translations)?e.translations:[];for(let e of n)if(_y(e)){for(let n of Object.values(e))if(_y(n)&&_y(n.objects))for(let[e,r]of Object.entries(n.objects))_y(r)&&t.add(e)}return t}function Cy(e){let t=e.toLowerCase().replace(/&/g,` and `).replace(/[^a-z0-9]+/g,`_`).replace(/^_+|_+$/g,``);return t.length>0?t:void 0}function wy(e){let t=[];if(!_y(e))return t;let n=Sy(e);if(n.size===0)return t;let r=[];for(let{rec:t,path:n}of O(e.objects,`objects`)){let e=vy(t.name);if(e){for(let{rec:i,path:a}of O(t.views,`${n}.views`))xy({...i,object:vy(i.object)??e},a,yy(i),r);_y(t.listViews)&&xy({object:e,listViews:t.listViews},n,``,r)}}for(let{rec:t,path:n}of O(e.views,`views`))xy(t,n,yy(t),r);for(let{rec:t,path:n}of O(e.pages,`pages`)){let e=vy(t.name),i=e?`page "${e}"`:``;for(let e of Vc(t,n)){if(!e.objectName)continue;let t=_y(e.component.properties)?e.component.properties:void 0;if(!t)continue;let n=vy(e.component.type)??`component`;r.push({path:`${e.path}.properties.sections`,surface:by(i,n),objectName:e.objectName,sections:t.sections})}}for(let e of r){let r=e.objectName;if(r&&n.has(r)&&Array.isArray(e.sections))for(let n=0;n<e.sections.length;n++){let i=e.sections[n];if(!_y(i)||vy(i.name))continue;let a=vy(i.label);if(!a)continue;let o=Cy(a);t.push({severity:`warning`,rule:gy,where:by(`object "${r}"`,e.surface,`section "${a}"`),path:`${e.path}[${n}]`,message:`Section "${a}" declares a label but no \`name\`. Headings resolve through \`objects.${r}._sections.<name>.label\`, so a section with no name has no key a bundle can carry \u2014 this heading can never be translated and renders in the source locale in EVERY locale. Object "${r}" IS translated, which is what makes the hole invisible: every neighbouring label resolves and only the heading stays behind. The i18n coverage report cannot see it either \u2014 it walks \`sections[].name\`, and a nameless section contributes nothing to walk.`,hint:"Give the section a stable `name` (snake_case)"+(o?`, e.g. \`name: '${o}'\``:``)+`, then translate it as \`objects.${r}._sections.${o??`<name>`}.label\` in each locale bundle. The renderers look the heading up by name only \u2014 the name above is a suggestion to write down, never a key derived from the label, so renaming the heading later cannot break the lookup.`})}}return t}var Ty=`ai-skill-surface-mismatch`;function Ey(e){return typeof e==`string`&&e.length>0?e:void 0}function Dy(e){return typeof e==`string`&&e.length>0?e:`ask`}function Oy(e){let t=[];if(!e||typeof e!=`object`)return t;let n=new Map;for(let t of w(e.skills)){let e=Ey(t.name);e&&n.set(e,t)}let r=w(e.agents);for(let e=0;e<r.length;e++){let i=r[e],a=Ey(i.name)??`#${e}`,o=Dy(i.surface),s=Array.isArray(i.skills)?i.skills:[];for(let r=0;r<s.length;r++){let i=Ey(s[r]);if(!i)continue;let c=n.get(i);if(!c)continue;let l=Dy(c.surface);l!==`both`&&l!==o&&t.push({severity:`error`,rule:Ty,where:`agent "${a}" \xB7 skills`,path:`agents[${e}].skills[${r}]`,message:`Agent "${a}" (surface: '${o}') references skill "${i}" (surface: '${l}') \u2014 incompatible affinity (ADR-0064 \xA73). The runtime refuses this binding with a load error, so chatting with this agent fails at request time even though the stack parses and validates cleanly.`,hint:`A skill may only attach to an agent whose surface it matches. Move "${i}" to a '${l}'-surface agent, change its \`surface\` to '${o}', or \u2014 only if it is a genuinely shared, read-only capability \u2014 declare \`surface: 'both'\`.`})}}return t}var ky=`ai-skill-tool-unresolved`;function Ay(e){return typeof e==`string`&&e.length>0?e:void 0}function jy(e,t){for(let n of p)if(t.has(`${n}${e}`))return` Did you mean "${n}${e}"?`;return E(e,t)}var My=new Set([`script`,`api`,`flow`]),Ny=`update`;function Py(e){let t=e.ai;if(!t||typeof t!=`object`)return!1;let n=t;if(n.exposed!==!0||!Ay(n.description))return!1;if(e.operation===Ny)return!0;let r=Ay(e.type);return!r||!My.has(r)?!1:r===`script`?!!(e.target||e.body):!!e.target}function Fy(e){let t=new Set(xe);for(let n of w(e.tools)){let e=Ay(n.name);e&&t.add(e)}let n=e=>{for(let n of w(e)){let e=Ay(n.name);e&&Py(n)&&t.add(`action_${e}`)}};n(e.actions);for(let t of w(e.objects))n(t.actions);return t}function Iy(e){let t=new Set,n=e=>{for(let n of w(e)){let e=Ay(n.name);e&&!Py(n)&&t.add(e)}};n(e.actions);for(let t of w(e.objects))n(t.actions);return t}function Ly(e){let t=[];if(!e||typeof e!=`object`)return t;let n=Fy(e),r=Iy(e),i=e=>{if(e.endsWith(`*`)){let t=e.slice(0,-1);for(let e of n)if(e.startsWith(t))return!0;return!1}return n.has(e)},a=w(e.skills);for(let e=0;e<a.length;e++){let o=a[e],s=Ay(o.name)??`#${e}`,c=Array.isArray(o.tools)?o.tools:[];for(let a=0;a<c.length;a++){let o=Ay(c[a]);if(!o||i(o))continue;let l=o.endsWith(`*`),u=!l&&o.startsWith(`action_`)&&r.has(o.slice(7))?o.slice(7):void 0;t.push({severity:`warning`,rule:ky,where:`skill "${s}" \xB7 tools`,path:`skills[${e}].tools[${a}]`,message:l?`Skill "${s}" subscribes to tool family "${o}", which matches nothing this stack can resolve (no declared tool, no platform tool, and no AI-exposed declarative action materialises into it). The subscription contributes zero tools at runtime.`:u?`Skill "${s}" references tool "${o}", but the action "${u}" does not become an AI tool: the runtime materialises \`action_<name>\` only for an action that opts in with \`ai.exposed: true\` + \`ai.description\` (ADR-0011) AND has a headless path (type \`script\`/\`api\`/\`flow\` with a target or body \u2014 \`url\`/\`modal\`/\`form\` are UI-only). The reference is dropped at runtime, so the skill promises a capability the agent cannot call.`:`Skill "${s}" references tool "${o}", which resolves to nothing this stack can see: not a \`stack.tools\` record, not a platform-registered tool, and not a materialised action tool (\`action_<name>\`). The runtime silently drops the reference, so the skill's instructions claim a capability the agent does not have \u2014 the assistant will improvise or fail when asked to use it.`+jy(o,n),hint:u?`Either opt "${u}" in \u2014 set \`ai: { exposed: true, description: '\u2026' }\` (\u226540 chars, LLM-facing) and give it a headless type \u2014 or drop the reference and have the skill's instructions recommend the UI action instead. A \`modal\`/\`form\`/\`url\` action stays human-driven by design; that is a legitimate answer, not a gap.`:`Back "${o}" with a real executable: declare a declarative action (or flow), opt it in with \`ai.exposed: true\` + \`ai.description\`, and reference its materialised tool (\`action_<name>\` \u2014 the ADR-0109 default path, no tool record needed); or reference a platform tool by its registered name; or remove the reference and the instructions that mention it. Ignore this only if a runtime plugin outside the platform registry provides "${o}". Family prefixes materialised by the runtime: ${p.join(`, `)}.`})}}return t}var Ry=`agent-authoring-withdrawn`,zy=`default-agent-outside-roster`,By=`default-agent-legacy-alias`;function Vy(e){return typeof e==`string`&&e.length>0?e:void 0}var Hy=[`ask`,`build`],Uy=new Map([[`data_chat`,`ask`],[`metadata_assistant`,`build`]]),Wy=new Set([...Hy,...Uy.keys()]);function Gy(e){let t=[];if(!e||typeof e!=`object`)return t;let n=w(e.agents);for(let e=0;e<n.length;e++){let r=n[e],i=Vy(r.name)??`#${e}`,a=Wy.has(i),o=Array.isArray(r.skills)?r.skills.length:0;t.push({severity:`warning`,rule:Ry,where:`agent "${i}"`,path:`agents[${e}]`,message:a?`This stack declares an agent named "${i}", which is a PLATFORM agent id. The runtime serves its own record for that name and ignores this one \u2014 the declaration has no effect and will drift from the platform's definition.`:`This stack declares the agent "${i}", but tenant/app-package agents were withdrawn (ADR-0063 \xA72): the kernel ships exactly two agents (\`ask\`, \`build\`) and the surface the user is in binds one. The runtime filters this record out of the agent catalog and refuses to load it, so it never runs \u2014 it parses, validates, and ships as inert metadata.`,hint:a?`Remove the declaration; the platform owns "${i}". Extend it with skills instead.`:"Delete the agent and express its capability as skills. Everything an agent carried that a skill does not is persona text: move the useful parts of `instructions` into the skills' own instructions."+(o>0?` The ${o} skill${o===1?``:`s`} this agent references already carry the capability \u2014 they attach to the platform agent by \`surface\` affinity, so nothing is lost by dropping the persona.`:``)})}let r=Hy.join(`, `),i=w(e.apps);for(let e=0;e<i.length;e++){let n=i[e],a=Vy(n.defaultAgent);if(!a||Hy.includes(a))continue;let o=Vy(n.name)??`#${e}`,s=Uy.get(a);if(s){t.push({severity:`warning`,rule:By,where:`app "${o}".defaultAgent`,path:`apps[${e}].defaultAgent`,message:`app "${o}" pins \`defaultAgent\` to "${a}", the RETIRED alias of the platform agent "${s}". It still resolves \u2014 the alias registry maps legacy names to canonical ones for old bookmarks and persisted \`agent_id\`s (ADR-0063 \xA72) \u2014 so nothing is broken at runtime; what is wrong is the spelling in the artifact. It is also the weaker pin: resolution depends on the owning package's in-process alias registration having run, which the canonical id does not.`,hint:`Write \`defaultAgent: '${s}'\`. The aliases are back-compat resolution, not authoring vocabulary \u2014 always author the canonical id (${r}).`});continue}t.push({severity:`warning`,rule:zy,where:`app "${o}".defaultAgent`,path:`apps[${e}].defaultAgent`,message:`app "${o}" pins \`defaultAgent\` to "${a}", which is not a platform agent (${r}). The kernel ships exactly two agents (ADR-0063 \xA72) and resolves this key against them and their legacy aliases only \u2014 an unrecognized name is not rejected, it silently falls back to the platform default at runtime, so the pin has no effect and the value drifts from what actually serves the app.`,hint:`Set \`defaultAgent\` to one of the platform agent names: ${r}. If the goal is a dedicated persona or capability, express it as skills instead \u2014 they attach to "ask" / "build" by surface affinity, not as a custom \`defaultAgent\` value.`})}return t}var Ky=`flow-node-write-unknown-field`,qy=`flow-node-write-unprovisioned-anchor`,Jy=[`update_record`,`create_record`],Yy=[],Xy=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Zy(e){let t=e.objectName??e.object;if(!(typeof t!=`string`||t.includes(`{`)))return t||void 0}var Qy=new Set(Jy);function $y(e){let t=[];if(!Xy(e))return t;let n=w(e.flows);if(n.length===0)return t;let r=null,i=null;return n.forEach((n,a)=>{let o=typeof n.name==`string`&&n.name?n.name:`#${a}`;bo(n,`flows[${a}]`).forEach(({node:n,path:a,regionTrail:s},c)=>{if(typeof n.type!=`string`||!Qy.has(n.type))return;let l=Xy(n.config)?n.config:void 0;if(!l)return;let u=l.fields;if(!Xy(u))return;let d=Object.keys(u);if(d.length===0)return;let f=Zy(l);if(!f)return;r??=fs(e),i??=Rn(e);let p=ps(r,f);if(!p)return;let m=go(n,c),h=s?`${s} \u203A node "${m}"`:`node "${m}"`;for(let e of d)if(!p.has(e)){if(cs.has(e)){if(!i.get(f)?.has(e))continue;t.push({severity:`warning`,rule:qy,where:`flow "${o}" \u203A ${h}`,path:`${a}.config.fields.${e}`,message:`${n.type} writes '${e}', and ${zn(f,e)} \u2014 `+ls(),hint:Bn(f,e)});continue}e.includes(`.`)||t.push({severity:`error`,rule:Ky,where:`flow "${o}" \u203A ${h}`,path:`${a}.config.fields.${e}`,message:`${n.type} writes '${e}', but object '${f}' declares no such field. The node hands its fields map to the engine as an ordinary caller payload, so the declared-field door REFUSES the whole write \u2014 INVALID_FIELD / 400, identically on every datasource, before any statement is built. The correctly named fields in this same payload never land either${n.type===`create_record`?` and the record is never created at all`:``}, and the step fails the run.`,hint:eb(e,[...p])})}})}),t}function eb(e,t){let n=me(ee(e,[...t,...cs]));return(n?`${n} `:``)+`Fix the field name, or declare '${e}' on the object. This gates the build rather than warning: the key is literal and so is the object, so unlike the hook/action body rules there is nothing here that could have been mis-extracted.`}var tb=[`flow`],nb=[{name:`validateObjectReferences`,runtimeTypes:[`flow`,`dataset`],run:xh},{name:`validateSearchableFields`,runtimeTypes:[`flow`,`view`,`object`],run:Fc},{name:`validateSortableFields`,runtimeTypes:[`flow`,`view`],run:Bh},{name:`validateListViewFieldRefs`,runtimeTypes:[`flow`,`view`,`object`],run:Qh},{name:`validateObjectFieldRefs`,runtimeTypes:[`flow`,`object`],run:ug},{name:`validateActionNameRefs`,run:mg},{name:`validateActionDispatchContract`,run:Sg},{name:`validatePageFieldBindings`,run:al},{name:`validatePageVisualizationBindings`,run:Gg},{name:`validateChartBindings`,runtimeTypes:[`flow`,`report`],run:g_},{name:`validateDatasetReferences`,runtimeTypes:[`flow`,`dataset`],run:w_},{name:`validateMappingTargetFields`,run:k_},{name:`validateNavAccess`,run:uv},{name:`validateNavTargetRefs`,run:Oh},{name:`validateNavObjectServability`,run:Nh},{name:`validateTranslationReferences`,run:cy},{name:`validateTranslatableSections`,run:wy},{name:`validateFlowTemplatePaths`,run:Vo},{name:`validateAiSurfaceAffinity`,run:Oy},{name:`validateAiToolReferences`,run:Ly},{name:`validateAiAgentAuthoring`,run:Gy},{name:`validateHookBodyWrites`,run:(e,t)=>gs(e,t)},{name:`validateActionBodyWrites`,run:Ws},{name:`validateFlowNodeWrites`,run:$y},{name:`validateReadonlyFlowWrites`,run:Xo},{name:`validateReadonlyHookWrites`,run:(e,t)=>ks(e,t)},{name:`validateReadonlyActionWrites`,run:ec},{name:`validateReactPageProps`,run:Ul}];function rb(e,t){let n=[],r=t?.runtimeWriteType;for(let i of nb)(r===void 0||(i.runtimeTypes??tb).includes(r))&&n.push(...i.run(e,t));return n}function ib(e){return typeof e==`string`?e:e&&typeof e==`object`&&typeof e.source==`string`?e.source:``}var ab=`daysFromNow|daysAgo|today|now|date|datetime`,ob=RegExp(`\\b(?:${ab})\\s*\\(`),sb=RegExp(`(?:(?:${ab})\\s*\\([^)]*\\)\\s*(?:==|!=))|(?:(?:==|!=)\\s*(?:${ab})\\s*\\()`),cb=`flow-time-relative-antipattern`,lb=`flow-date-equality-filter`,ub=`flow-phantom-aggregation`,db=`flow-double-brace-interpolation`,fb=`flow-bare-dollar-reference`,pb=`flow-approval-revise-dead-end`,mb=`flow-approval-revise-unmarked-backedge`,hb=`flow-approval-revise-disabled`,gb=`flow-approval-revise-target-not-service-owned`,_b=`flow-runas-unscoped`,vb=`flow-error-label-not-fault`,yb=`flow-branch-label-unmatched`,bb=`flow-decision-unconditional-branch`,xb=`flow-default-edge-with-condition`,Sb=`flow-multiple-default-edges`,Cb=`flow-inert-node-condition`,wb=`flow-decision-mode-invalid`,Tb=`flow-decision-inclusive-overlap`,Eb=`flow-multi-write-unfiltered`,Db=`flow-loop-body-uncontained`,Ob=`flow-try-catch-without-catch`,kb=new Set([`decision`,`assignment`,`loop`,`parallel`,`try_catch`,`create_record`,`update_record`,`delete_record`,`get_record`,`http`,`notify`,`script`,`screen`,`wait`,`subflow`,`map`,`connector_action`,`approval`,`end`]),Ab=new Set([`get_record`,`create_record`,`update_record`,`delete_record`]),jb=new Set([`get_record`,`create_record`,`update_record`,`delete_record`,`http`,`notify`,`connector_action`,`script`,`subflow`,`map`,Dt]),Mb=`try_catch`,Nb=`loop`,Pb="`runAs:'user'` (the default when none is declared)";function Fb(e,t){for(let n of a({nodes:e,edges:t}))for(let e of w(n.nodes))if(Ab.has(typeof e.type==`string`?e.type:``))return{node:e,scope:n.scope};return null}var Ib=new Map([[`delete_record`,{verb:`deleted`,engineCall:`driver.deleteMany`,dispatchNote:"the engine's delete-dispatch case-set lists `multi with no predicate at all` as a legal `multi` call"}],[`update_record`,{verb:`overwritten`,engineCall:`driver.updateMany`,dispatchNote:"the engine takes its bulk branch on `options.multi` alone (`Update requires an ID or options.multi=true` is refused only when the declaration is absent)"}]]),Lb=new Set([`error`,`fault`,`failure`,`failed`,`catch`,`on_error`,`onerror`,`on error`]),Rb=new Set([`decision`,`approval`,`screen`,`try_catch`]);function zb(e,t){return e.type===`schedule`||typeof t.triggerType==`string`&&t.triggerType===`schedule`||t.schedule!=null}function Bb(e,t){return zb(e,t)?`schedule`:t.timeRelative!=null||typeof t.triggerType==`string`&&t.triggerType===`time_relative`?`time-relative`:e.type===`api`||typeof t.triggerType==`string`&&t.triggerType===`api`?`api`:null}var Vb=new Set([`aggregations`,`aggregate`,`groupBy`,`rollup`,`having`]);function Hb(e){if(e&&typeof e==`object`&&e.dialect===`cel`){let t=e.source;if(typeof t==`string`&&ob.test(t))return t}return null}var Ub=new Set([`$gte`,`$gt`,`$lte`,`$lt`,`$ne`]);function Wb(e,t,n){if(e&&typeof e==`object`&&!Array.isArray(e))for(let[r,i]of Object.entries(e)){if(r===`$or`||r===`$and`){if(Array.isArray(i))for(let e of i)Wb(e,t,n);continue}let e=Hb(i),a=e?{op:`==`,src:e}:null;if(!a&&i&&typeof i==`object`&&i.dialect!==`cel`){for(let[e,t]of Object.entries(i))if(!Ub.has(e)){if(e===`$eq`){let e=Hb(t);if(e){a={op:`$eq`,src:e};break}}else if(e===`$in`&&Array.isArray(t)){for(let e of t){let t=Hb(e);if(t){a={op:`$in`,src:t};break}}if(a)break}}}a&&n.push({where:t,message:`filter matches \`${r}\` by ${a.op} against a time value (\`${a.src}\`) \u2014 a date field carries a time component, so exact equality against \`${a.src}\` (re-computed each run) silently matches nothing.`,hint:`Use a one-day window instead: \`${r}: { $gte: daysFromNow(N), $lt: daysFromNow(N+1) }\` (wrap multiple tiers in \`$or\`). The abutting windows tile the timeline so each row matches exactly once. (#1874)`,rule:lb})}}var Gb=/\{\{\s*[\w$][\w$.\s]*\}\}/,Kb=/(?:^|[^{])\$[A-Za-z_]\w*\.[A-Za-z_]/,qb=new Set([`condition`,`expression`,`conditions`]);function Jb(e,t,n){if(!(t&&qb.has(t))){if(typeof e==`string`){n.push(e);return}if(Array.isArray(e)){for(let r of e)Jb(r,t,n);return}if(e&&typeof e==`object`)for(let[t,r]of Object.entries(e))Jb(r,t,n)}}function Yb(e){return typeof e.label==`string`?e.label.trim().toLowerCase():``}function Xb(e,t,n,r){let i=new Map;for(let e of t)typeof e.id==`string`&&i.set(e.id,typeof e.type==`string`?e.type:``);for(let t of n){let n=typeof t.label==`string`?t.label.trim().toLowerCase():``;if(!Lb.has(n)||t.type===`fault`||t.condition)continue;let a=typeof t.source==`string`?t.source:``;Rb.has(i.get(a)??``)||r.push({where:`${e} \xB7 edge '${a}' \u2192 '${String(t.target)}'`,message:`edge is labelled '${String(t.label)}' but its type is '${String(t.type??`default`)}', not 'fault' \u2014 so it is an ORDINARY out-edge. Unconditional out-edges all run in parallel, so '${String(t.target)}' executes on every SUCCESSFUL run of '${a}' and never on a failure. The error path the label describes does not exist, and the run still aborts when '${a}' fails.`,hint:"Add `type: 'fault'` to this edge. Only runtime failures route — a guard refusal (a filter token that resolved to nothing, a missing required config key, an unscoped run) stays fatal by design and must be fixed in the metadata, not handled. (#3863)",rule:vb})}}function Zb(e,t,n,r){let i=new Map;for(let e of n){if(e.type===`fault`)continue;let t=typeof e.source==`string`?e.source:``;t&&(i.has(t)||i.set(t,[]),i.get(t).push(e))}for(let[t,n]of i){for(let i of n)i.isDefault===!0&&i.condition&&r.push({where:`${e} \xB7 edge '${t}' \u2192 '${String(i.target)}'`,message:'edge sets `isDefault: true` AND a `condition` — contradictory. `isDefault` means "take this edge when NO sibling condition matched"; a condition makes it an ordinary guarded branch. The condition wins and the default marker routes nothing.',hint:'Drop one: keep `condition` for a guarded branch, or drop it and keep `isDefault: true` for the "otherwise" path. (#4414)',rule:xb,severity:`error`});let i=n.filter(e=>e.isDefault===!0&&!e.condition);i.length>1&&r.push({where:`${e} \xB7 node '${t}'`,message:`${i.length} out-edges are marked \`isDefault: true\` (${i.map(e=>`'${String(e.target)}'`).join(`, `)}) \u2014 a node has at most ONE default path. All of them are traversed together when no condition matches, which is a parallel fan-out, not an "otherwise".`,hint:"Keep `isDefault: true` on the single fallback edge and give the others a `condition` (or leave them unconditional if the fan-out really is intended). (#4414)",rule:Sb})}for(let n of t){let t=typeof n.type==`string`?n.type:``;if(!kb.has(t))continue;let i=n.config??{};i.condition!=null&&ib(i.condition).trim()!==``&&r.push({where:`${e} \xB7 node '${String(n.id)}' (${t})`,message:"`config.condition` is set but nothing reads it — the key is the trigger gate on a `start` node and is ignored on every other node type, so this predicate never gates anything. (It is still parse-validated at registration, which is why a malformed one is caught and an inert one is not.)",hint:t===`decision`?"Branching lives on the OUT-EDGES: give each branch its own `condition` and mark the fallback `isDefault: true`. If the edges already carry the predicate, delete this copy. (#4414)":"Delete it, or move the predicate to the incoming edge's `condition` if this step was meant to be conditional. (#4414)",rule:Cb})}for(let n of t){if(n.type!==`decision`)continue;let t=typeof n.id==`string`?n.id:``;if(!t)continue;let a=i.get(t)??[];if(a.length===0)continue;let o=n.config??{},s=new Set((Array.isArray(o.conditions)?o.conditions:[]).map(e=>typeof e?.label==`string`?e.label.trim().toLowerCase():``).filter(Boolean)),c=new Set(a.map(Yb).filter(Boolean)),l=xt.safeParse(o);if(!l.success)for(let n of l.error.issues)n.path[0]===`mode`&&r.push({where:`${e} \xB7 decision '${t}' \xB7 config.mode`,message:n.message,hint:"`registerFlow` refuses this flow with the same sentence, so it can never arm. Fix the node in the flow definition: an omitted `mode` is exclusive (the first true out-edge wins), `mode: 'inclusive'` takes every true out-edge, and a `conditions` list is first-match on its own and takes no `mode`.",rule:wb,severity:`error`});if(o.mode===`inclusive`){let n=a.filter(e=>e.condition&&ib(e.condition).trim()!==``);n.length>=2&&r.push({where:`${e} \xB7 decision '${t}'`,message:`declares \`mode: 'inclusive'\` with ${n.length} conditioned out-edge(s) (${n.map(e=>`'${String(e.target)}'`).join(`, `)}) \u2014 EVERY one whose condition holds runs, one after another, so where the conditions overlap more than one branch runs for one record. Nothing checks that they partition.`,hint:"If exactly one branch was meant, delete `mode`: an omitted `mode` is exclusive, and the first out-edge whose condition holds, in declaration order, wins (mark the fallback `isDefault: true`). Keep `mode: 'inclusive'` only where running every matching branch is the intent. A flow migrated by `os migrate meta --from 17` carries this key wherever two or more conditioned out-edges left a decision — delete it where the branches partition.",rule:Tb})}let u=[...s].filter(e=>!c.has(e));u.length>0&&r.push({where:`${e} \xB7 decision '${t}'`,message:`declares branch label(s) ${u.map(e=>`'${e}'`).join(`, `)} that no out-edge carries \u2014 out-edge labels are [${[...c].map(e=>`'${e}'`).join(`, `)||`none`}]. Traversal cannot honour a label nothing claims, so it falls back to considering EVERY out-edge and the branch the decision computed is ignored.`,hint:"Make an out-edge's `label` match the declared branch exactly, or drop `config.conditions` and branch on the edges instead (`condition` per branch + `isDefault: true` on the fallback) — one mechanism per decision, never both. (#4414)",rule:yb,severity:`error`});let d=a.filter(e=>e.condition||e.isDefault===!0),f=Array.isArray(o.conditions)&&o.conditions.length>0;if(d.length===0){f||r.push({where:`${e} \xB7 decision '${t}'`,message:`gates on NOTHING \u2014 none of its out-edge(s) (${a.map(e=>`'${String(e.target)}'`).join(`, `)}) carries a \`condition\` or \`isDefault\`, and the decision declares no \`config.conditions[]\`. With no branch to select, EVERY out-edge is traversed on EVERY pass, in parallel \u2014 the node is typed \`decision\` but routes exactly as a non-decision step would, so the gateway is decoration.`,hint:"Declare the branching one way and one way only: a `condition` per branch plus `isDefault: true` on the fallback, or `config.conditions[]` whose `label` matches an out-edge's. If the unconditional fan-out is what you meant, drop `type: 'decision'` and use the node it already behaves as.",rule:bb});continue}let p=a.filter(e=>!e.condition&&e.isDefault!==!0&&!s.has(Yb(e)));p.length>0&&r.push({where:`${e} \xB7 decision '${t}'`,message:`has guarded out-edge(s) alongside unconditional one(s) (${p.map(e=>`'${String(e.target)}'`).join(`, `)}) \u2014 an unconditional out-edge is traversed on EVERY pass, in parallel with whichever guarded branch matched, so the decision does not actually exclude it. A \`label\` alone does not select a path unless the decision declares a matching \`conditions[].label\`.`,hint:"Mark the fallback `isDefault: true` so it is taken only when no sibling condition matched (BPMN default flow), or give it its own `condition`. (#4414)",rule:bb})}}function Qb(e){return e==null?!0:typeof e!=`object`||Array.isArray(e)?!1:m(e)===`true`}function $b(e){return e==null?"no `filter` key":Object.keys(e).length===0?"an EMPTY `filter`":`a \`filter\` that REDUCES TO TRUE (\`${ex(e)}\`)`}function ex(e){try{let t=JSON.stringify(e);return typeof t==`string`?t.length>80?`${t.slice(0,77)}...`:t:typeof e}catch{return typeof e}}function tx(e,t,n){for(let r of t){let t=typeof r.type==`string`?r.type:``,i=Ib.get(t);if(!i)continue;let a=r.config??{};if(a.multi!==!0||!Qb(a.filter))continue;let o=typeof a.objectName==`string`&&a.objectName?a.objectName:`(unnamed object)`,s=$b(a.filter);n.push({where:`${e} \xB7 node '${String(r.id)}' (${t})`,message:`declares \`multi: true\` with ${s} \u2014 this is a WHOLE-OBJECT write, by declaration: every row of '${o}' is ${i.verb} on every run. The executor forwards the filter as \`where\` (an absent key becomes \`{}\`) plus the bulk intent, ${i.dispatchNote}, and it lands on \`${i.engineCall}\` bounded by nothing \u2014 a filter that reduces to TRUE constrains no row. Nothing refuses it at run time, so the only feedback is the step's \`acted\` row count \u2014 reported AFTER the rows are gone.`,hint:`Write the constraint you mean into \`filter\` (e.g. \`{ status: 'closed' }\` \u2014 see examples/app-showcase \`showcase_inquiry_purge\`, bulk intent bounded by a predicate). If emptying '${o}' really is the intent, keep it: this is a warning, not a gate, and the run-time path stays open. Distinct from the #3810 erased-condition guard, which REFUSES this node at run time when a condition you WROTE interpolated to nothing \u2014 that guard is keyed on "a written condition is gone" and deliberately not on "the filter is empty", which is the fact this rule judges at authoring time. (#5482, #5393)`,rule:Eb})}}function nx(e,t,n,r){let i=t.filter(e=>e.type===Dt);if(i.length===0)return;let a=new Set(t.map(e=>typeof e.id==`string`?e.id:``).filter(Boolean)),o=new Map(t.filter(e=>typeof e.id==`string`).map(e=>[e.id,typeof e.type==`string`?e.type:``])),s=new Map;for(let e of n){let t=typeof e.source==`string`?e.source:``;t&&(s.has(t)||s.set(t,[]),s.get(t).push(e))}for(let t of i){let i=typeof t.id==`string`?t.id:``;if(!i)continue;let c=n.filter(e=>e.source===i&&Yb(e)===`revise`).map(e=>typeof e.target==`string`?e.target:``).filter(e=>e&&a.has(e));if(c.length===0)continue;let l=`${e} \xB7 approval '${i}'`;for(let e of c){let t=o.get(e)??``;t!==`approval_revise`&&r.push({where:l,severity:`error`,message:`has a 'revise' out-edge into node '${e}' of type '${t||`(untyped)`}' \u2014 the revise window must be an '${at}' node. Send-back parks the run there while the record is unlocked, and only the approvals service may continue it (submitter-only, audited, and refusing a colliding pending request); \`sendBack\` refuses any other target, so this flow's revise branch cannot run.`,hint:`Set node '${e}' to \`type: '${at}'\` (drop any \`waitEventConfig\` \u2014 the window is ended by POST /api/v1/approvals/requests/:id/resubmit, not by a signal). ADR-0044 D3 originally said 'wait' here; its 2026-07-28 amendment reversed that, because a 'wait' is resumable by anyone with the run id (#3823, #3801).`,rule:gb})}(t.config??{}).maxRevisions===0&&r.push({where:l,message:"declares a 'revise' out-edge but `maxRevisions: 0` disables send-back — every revise auto-rejects, so the revise branch never runs.",hint:"Set `maxRevisions` >= 1 to allow N send-backs before auto-reject, or drop the 'revise' edge if send-back isn't intended (ADR-0044).",rule:hb});let u=new Set(c),d=[...c],f=[];for(;d.length;){let e=d.shift();for(let t of s.get(e)??[]){t.target===i&&f.push(t);let e=typeof t.target==`string`?t.target:``;e&&a.has(e)&&!u.has(e)&&(u.add(e),d.push(e))}}f.length===0?r.push({where:l,message:`has a 'revise' out-edge but no path loops back to it — the submitter reworks the record with nowhere to resubmit, so the revise branch dead-ends. (registerFlow accepts this — it's a valid DAG.)`,hint:`Close the loop: the 'revise' edge should reach an '${at}' node whose resubmit edge returns to '${i}' marked \`type: 'back'\` (ADR-0044). See examples/app-showcase showcase_budget_approval.`,rule:pb}):f.some(e=>e.type===`back`)||r.push({where:l,message:"has a 'revise' loop that returns to it, but the closing edge isn't declared `type: 'back'` — registerFlow rejects this as an un-declared cycle.",hint:`Mark the resubmit edge (whose target is '${i}') \`type: 'back'\` so cycle validation skips it while it still traverses at runtime; \`maxRevisions\` guards the loop (ADR-0044).`,rule:mb})}}var rx="`catch: { nodes: [ { id: 'handled', type: 'assignment', label: 'Handled' } ] }` — one bare `assignment` node with no `config` is the shortest handler that works; `edges` and `errorVariable` may both be omitted",ix="A `catch` region cannot be empty: its `nodes` is `.min(1)`, so `catch: {}` and `catch: { nodes: [] }` are both refused by the parse.";function ax(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e.nodes;return Array.isArray(t)?t:void 0}function ox(e,t,n){for(let r of t){if(r.type!==Nb)continue;let t=ax((r.config??{}).body);if(!t)continue;let i=typeof r.id==`string`&&r.id?r.id:`(unnamed loop)`,a=(t,r,o)=>{if(!(o>ho))for(let s of t){if(!s||typeof s!=`object`)continue;let t=typeof s.type==`string`?s.type:``;if(t===Mb||t===Nb)continue;let c=typeof s.id==`string`&&s.id?s.id:`(unnamed node)`;if(jb.has(t)){n.push({where:`${e} \xB7 ${r} \xB7 node '${c}' (${t})`,message:`runs inside loop '${i}' with no \`try_catch\` between them \u2014 a '${t}' node can return \`success: false\` or throw, and the loop body's failure propagates straight out of the container (\`loop-node.ts\` iterates with a bare \`await\` and has no \`try\`/\`catch\` at all). The first failing item therefore ends the whole run: every later item is never processed, and the work already done is not even reported (measured on the real engine \u2014 a 5-item sweep failing at item 3 touched 3 items and reported \`acted: 0\`).`,hint:`Contain the failure per iteration: put a \`try_catch\` INSIDE the body and move this node into its \`try\` region \u2014 \`loop { body: { nodes: [ { type: 'try_catch', config: { try, catch } } ] } }\`. ${ix} The minimal handler is ${rx}. Measured: with it, all 5 items are processed and the run completes. If this loop is MEANT to stop at the first failure, that is a legitimate reading and this stays a warning. See content/docs/automation/flows.mdx \xA7"Per-iteration containment".`,rule:Db});continue}let l=mo.get(t);if(!l)continue;let u=s.config??{};for(let e of l){let n=u[e];if(Array.isArray(n)){n.forEach((e,n)=>{let i=ax(e);i&&a(i,`${r} \u2192 ${t} '${c}' branch ${n}`,o+1)});continue}let i=ax(n);i&&a(i,`${r} \u2192 ${t} '${c}' ${e}`,o+1)}}};a(t,`loop '${i}' body`,0)}}function sx(e,t,n){for(let r of t){if(r.type!==Mb)continue;let t=r.config??{};if(t.catch!==void 0)continue;let i=typeof r.id==`string`&&r.id?r.id:`(unnamed node)`,a=t.retry!==void 0;n.push({where:`${e} \xB7 node '${i}' (${Mb})`,message:"declares no `catch` region, so it contains NOTHING — when the `try` region fails the container fails with it and the failure propagates exactly as if the nodes had never been wrapped (measured: the no-`catch` run and the unwrapped control produce identical output)."+(a?" Its `retry` policy re-runs the `try` region first, which delays that outcome rather than changing it.":``)+" Inside a `loop` body this is the silent one: the author has recognised the hazard, wrapped the node, and still loses every item after the first failure.",hint:`Add the handler: ${rx}. ${ix} If failing loudly really is the intent, a \`try_catch\` with only \`try\` (and optionally \`retry\`) is a legitimate retry-then-fail shape \u2014 this is a warning, not a gate. See content/docs/automation/flows.mdx \xA7"Per-iteration containment".`,rule:Ob})}}function cx(e){let t=[];for(let n of w(e.flows)){let e=typeof n.name==`string`?n.name:`(unnamed flow)`,r=w(n.nodes),i=w(n.edges),o=r.find(e=>e.type===`start`)?.config??{};if((typeof o.triggerType==`string`?o.triggerType:``).startsWith(`record-`)){let n=ib(o.condition).trim();n&&sb.test(n)&&t.push({where:`flow '${e}' \xB7 start condition`,message:`record-change trigger uses a date-EQUALITY time condition (\`${n}\`) \u2014 it only fires if the record happens to be written on that exact day, so unattended "N days before" rules never run.`,hint:"Use a SCHEDULE trigger (daily cron) + a range query instead — e.g. a scheduled flow whose get_record filters `end_date` BETWEEN {TODAY()} and {TODAY()+N}. (#1874)",rule:cb})}let s=typeof n.runAs==`string`?n.runAs:`user`,c=Bb(n,o);if(c&&s!==`system`){let n=Fb(r,i);if(n){let r=n.scope?`, in ${n.scope},`:``;t.push({where:`flow '${e}' \xB7 runAs`,message:`${c}-triggered flow runs under ${Pb}, but a ${c} run has no trigger user \u2014 so its data node '${n.node.id}' (${n.node.type})${r} has no identity to scope to and will be REFUSED at run time.`,hint:`Declare \`runAs:'system'\` to make the elevation explicit and intended (the run reads/writes every record). A ${c} flow cannot scope to a user \u2014 there is none. (ADR-0049, ADR-0073 D5, #1888, #3760)`,rule:_b,severity:`error`})}}for(let n of a({nodes:r,edges:i})){let r=n.scope?`flow '${e}' \xB7 ${n.scope}`:`flow '${e}'`,i=w(n.nodes),a=w(n.edges);for(let e of i){let n=`${r} \xB7 node '${e.id}' (${e.type})`,i=e.config??{};i.filter&&Wb(i.filter,`${n} filter`,t);for(let e of Object.keys(i))Vb.has(e)&&t.push({where:n,message:`node config has \`${e}\` \u2014 the automation engine has no aggregate node, so \`${e}\` is silently ignored and this node computes nothing at runtime.`,hint:"Aggregation belongs in the data layer: use `Field.summary` for a cross-object rollup (sum/count of children), or `Field.formula` for a per-record computed value. (#1870)",rule:ub});let a=[];Jb(yo(e.config,vo(e.type)),void 0,a);for(let e of a)Gb.test(e)&&t.push({where:n,message:`double-brace interpolation \`${e.trim().slice(0,80)}\` \u2014 flow node values use SINGLE braces.`,hint:"Use `{var}` (e.g. `{record.title}`). Double-brace `{{ }}` is the formula/template-field dialect, not flow node values. (#1315)",rule:db}),Kb.test(e)&&t.push({where:n,message:`\`${e.trim().slice(0,80)}\` looks like a reference written as a literal \u2014 a bare \`$ref.field\` is NOT interpolated.`,hint:"Wrap it and bind a variable: `{source.id}` (or `{$User.Id}` for the current user). (#1315)",rule:fb})}nx(r,i,a,t),Xb(r,i,a,t),Zb(r,i,a,t),tx(r,i,t),ox(r,i,t),sx(r,i,t)}}return t}var lx=new Set([`authorization`,`proxy-authorization`,`cookie`]),ux=new Set([`auth`,`token`,`secret`,`password`,`passwd`,`credential`,`credentials`,`apikey`,`bearer`,`jwt`,`session`]),dx=[`api-key`,`private-key`,`access-key`,`client-secret`],fx=/^\s*(?:bearer|basic|token|digest|apikey)\s+\S/i,px=/\{[^{}]+\}/;function mx(e){let t=e.toLowerCase().replace(/_/g,`-`);if(lx.has(t)||dx.some(e=>t.includes(e)))return!0;let n=e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase().replace(/_/g,`-`).split(`-`);if(n.some(e=>ux.has(e)))return!0;for(let e=0;e+1<n.length;e++)if(dx.includes(`${n[e]}-${n[e+1]}`))return!0;return!1}function hx(e,t){return typeof t!=`string`||t.trim()===``||px.test(t)?!1:mx(e)||fx.test(t)}var gx=e=>!!e&&typeof e==`object`&&!Array.isArray(e),_x=`flow-credential-literal`,vx=`A flow definition is served, as authored, to every member who can read flows, so this value is readable by all of them`,yx="; move it to a declarative connector whose `auth` is `bearer` or `api-key` (a header), with `auth.credentialRef` naming the secret, called from a `connector_action` node.",bx="; move it to a declarative connector whose `auth` is `api-key` with `paramName` (the query parameter), with `auth.credentialRef` naming the secret, called from a `connector_action` node.",xx="; drop it from `input` — the connector authenticates through its own `auth.credentialRef`.",Sx=" `credentialRef` names a secrets-layer reference that is resolved at boot (an environment variable in the open tier), so the secret never lands in metadata.",Cx="Declare a `connectors:` entry with a `provider` (`'rest'` for a plain HTTP API) and `auth: { type: 'bearer', credentialRef }` for a bearer token, or `auth: { type: 'api-key', headerName, credentialRef }` for a key in a named header (a Basic pair is `auth: { type: 'basic', username, credentialRef }`), and call it from a `connector_action` node."+Sx,wx="Declare a `connectors:` entry with a `provider` (`'rest'` for a plain HTTP API) and `auth: { type: 'api-key', paramName, credentialRef }`, which sends the key as that query parameter, and call it from a `connector_action` node."+Sx,Tx="The connector authenticates through its own declaration: give its `connectors:` entry `auth: { type: 'bearer' | 'api-key' | 'basic', credentialRef }` and drop the credential from `input`."+Sx,Ex=" A `{variable}` template is not a literal and draws nothing. This is an advisory: nothing is refused. See content/docs/automation/connectors.mdx.";function Dx(e){return/^[A-Za-z_$][\w$]*$/.test(e)?`.${e}`:`[${JSON.stringify(e)}]`}function Ox(e){try{return decodeURIComponent(e.replace(/\+/g,` `))}catch{return e}}function kx(e){let t=e.indexOf(`?`);if(t<0)return[];let n=e.indexOf(`#`,t),r=e.slice(t+1,n<0?void 0:n),i=[];for(let e of r.split(`&`)){if(!e)continue;let t=e.indexOf(`=`);i.push(t<0?[Ox(e),``]:[Ox(e.slice(0,t)),Ox(e.slice(t+1))])}return i}function Ax(e){let t=[];return w(e.flows).forEach((e,n)=>{let r=typeof e.name==`string`&&e.name?e.name:`#${n}`;for(let{node:i,path:a,regionTrail:o}of bo(e,`flows[${n}]`)){let e=typeof i.id==`string`&&i.id?i.id:`(unnamed node)`,n=typeof i.type==`string`&&i.type?i.type:`node`,s=o?`flow '${r}' \xB7 ${o} \xB7 node '${e}' (${n})`:`flow '${r}' \xB7 node '${e}' (${n})`,c=(e,n,r,i)=>{t.push({severity:`warning`,rule:_x,where:s,path:e,message:`${n} holds a literal value that reads as a credential. ${vx}${r}`,hint:`${i}${Ex}`})};if(i.type===`http`&&gx(i.config)){let{headers:e,url:t}=i.config;if(gx(e))for(let[t,n]of Object.entries(e))hx(t,n)&&c(`${a}.config.headers${Dx(t)}`,`header '${t}'`,yx,Cx);if(typeof t==`string`)for(let[e,n]of kx(t))hx(e,n)&&c(`${a}.config.url`,`the url's query parameter '${e}'`,bx,wx)}let l=i.connectorConfig;if(gx(l)&&gx(l.input)){let e=(t,n,r,i,a)=>{if(!(a>32)){if(Array.isArray(t)){t.forEach((t,o)=>e(t,n,`${r}[${o}]`,`${i}[${o}]`,a+1));return}if(gx(t)){for(let[n,o]of Object.entries(t))e(o,n,`${r}${Dx(n)}`,i?`${i}.${n}`:n,a+1);return}hx(n,t)&&c(r,`connector input '${i}'`,xx,Tx)}};e(l.input,``,`${a}.connectorConfig.input`,``,0)}}}),t}var jx=`liveness-dead-property`,Mx=`liveness-experimental-property`,Nx=`liveness-planned-property`,Px=`liveness-live-elsewhere-property`,Fx=`liveness-ledger-unreadable`;function Ix(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Lx(){try{let e=(0,S.createRequire)(import.meta.url).resolve(`@objectstack/spec/package.json`),t=(0,S.join)((0,S.dirname)(e),`liveness`);return(0,S.existsSync)(t)?t:null}catch{return null}}function Rx(e,t){let n=new Map,r=(0,S.join)(e,`${t}.json`);if(!(0,S.existsSync)(r))return{map:n,fault:`missing`};let i;try{i=JSON.parse((0,S.readFileSync)(r,`utf8`))}catch{return{map:n,fault:`unreadable`}}if(!Ix(i)||!Ix(i.props))return{map:n,fault:`unreadable`};let a=i.props;for(let[e,t]of Object.entries(a)){if(t?.children)for(let[r,i]of Object.entries(t.children))Bx(i)&&n.set(`${e}.${r}`,i);Bx(t)&&n.set(e,t)}return{map:n}}var zx=new Set([...new Set([`dead`,`live-elsewhere`]),`experimental`]);function Bx(e){return e?typeof e.status==`string`&&zx.has(e.status)||e.authorWarn===!0:!1}function Vx(e){return e==null?!1:typeof e!=`boolean`||e===!0}function Hx(e){if(e.status===`experimental`)return{kind:`is experimental — declared but NOT enforced at runtime`,rule:Mx,defaultHint:`It is declared in the spec as an experimental guarantee — not yet enforced at runtime.`};if(e.status===`planned`)return{kind:`is planned — declared, and a consumer is being built against it (not read YET)`,rule:Nx,defaultHint:`Keep it — a consumer is being built against this property; it has no runtime effect yet.`};if(e.status===`dead`)return{kind:`has no runtime effect (liveness: dead)`,rule:jx,defaultHint:`Remove it — it is declared in the spec but not consumed at runtime.`};if(e.status===`live-elsewhere`)return{kind:`is enforced in a sibling repo, not here (liveness: live-elsewhere)`,rule:Px,defaultHint:"Keep it — nothing reads it when the stack loads here, but a sibling repo enforces it (for `manifest.runtime`, the cloud marketplace publish gate); see the ledger row's evidence for the enforcer."};throw Error(`lintLivenessProperties: ledger entry has unrecognised status ${JSON.stringify(e.status)} \u2014 describe() only knows 'experimental' | 'planned' | 'dead' | 'live-elsewhere'. This is a shipped-ledger integrity bug, not an authoring error: either the ledger JSON has a typo, or a new status was added to the vocabulary without teaching describe() in lint-liveness-properties.ts about it (#11384).`)}function Ux(e){let t=Lx();return t?new Set(Rx(t,e).map.keys()):new Set}function Wx(e,t,n,r,i){for(let[a,o]of r){let r=a.includes(`.`)?Gx(t,a):[t[a]];for(let t of r instanceof Array?r:[r]){if(!Vx(t))continue;let{kind:r,rule:s,defaultHint:c}=Hx(o),l=o.authorHint??c;i.push({where:n,message:`sets \`${a}\` but this ${e} property ${r}.`,hint:l,rule:s});break}}}function Gx(e,t){let n=[e];for(let e of t.split(`.`)){let t=[];for(let r of n){if(typeof r!=`object`||!r)continue;let n=Array.isArray(r)?void 0:r[e];if(Array.isArray(r))for(let n of r)n&&typeof n==`object`&&t.push(n[e]);else t.push(n)}n=t}return n.flatMap(e=>Array.isArray(e)?e:[e])}var Kx=[{type:`flow`,key:`flows`},{type:`action`,key:`actions`},{type:`agent`,key:`agents`},{type:`tool`,key:`tools`},{type:`skill`,key:`skills`},{type:`dataset`,key:`datasets`},{type:`permission`,key:`permissions`},{type:`hook`,key:`hooks`},{type:`page`,key:`pages`},{type:`view`,key:`views`},{type:`webhook`,key:`webhooks`},{type:`datasource`,key:`datasources`},{type:`app`,key:`apps`},{type:`book`,key:`books`},{type:`job`,key:`jobs`},{type:`email_template`,key:`emailTemplates`},{type:`mapping`,key:`mappings`},{type:`dashboard`,key:`dashboards`}];function qx(e,t){let n=[],r=t(`object`),i=t(`field`);for(let t of w(e.objects)){if(!Ix(t))continue;let e=typeof t.name==`string`?t.name:`(unnamed object)`;if(r.size>0&&Wx(`object`,t,`object '${e}'`,r,n),i.size>0)for(let r of w(t.fields))Ix(r)&&Wx(`field`,r,`object '${e}' \xB7 field '${typeof r.name==`string`?r.name:`(unnamed field)`}'`,i,n)}let a=t(`translation`);if(a.size>0){let t=w(e.translations);for(let e=0;e<t.length;e++){let r=t[e];if(Ix(r))for(let[t,i]of Object.entries(r))Ix(i)&&Wx(`translation`,i,`translation bundle #${e} \xB7 locale '${t}'`,a,n)}}for(let{type:r,key:i}of Kx){let a=t(r);if(a.size!==0)for(let t of w(e[i]))Ix(t)&&Wx(r,t,`${r} '${typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:`(unnamed ${r})`}'`,a,n)}return n}var Jx={missing:`no ledger file was found for it`,unreadable:`its ledger file does not parse as a ledger`};function Yx(e){return[...e].map(([e,t])=>({where:`liveness ledger '${e}'`,message:`every author warning for \`${e}\` metadata is switched off: ${Jx[t]} (expected \`${e}.json\` beside the other liveness ledgers \`@objectstack/spec\` ships).`,hint:"This is a packaging fault in the platform, not an authoring error: nothing in the metadata being linted caused it, and this rule’s silence about this type means nothing until it is fixed. Reinstall or repair `@objectstack/spec` so its `liveness/` directory ships intact.",rule:Fx}))}function Xx(e,t){let n=new Map,r=new Map,i=qx(t,t=>{let i=n.get(t);if(i)return i;let{map:a,fault:o}=Rx(e,t);return n.set(t,a),o&&r.set(t,o),a});return[...Yx(r),...i]}function Zx(e){let t=Lx();return t?Xx(t,e):[]}var Qx=`permission-retired-lifecycle-residue`,$x=[[`allowRestore`,!1],[`allowPurge`,!1]],eS=/^\[REMOVED\]\s*/;function tS(e){let t=u.shape?.[e]?.description;if(typeof t!=`string`||t.length===0)return null;let n=t.replace(eS,``).trim();return n.length>0?n:null}function nS(e){let t=[],n=w(e.permissions);for(let e=0;e<n.length;e++){let r=n[e],i=r.objects;if(!i||typeof i!=`object`||Array.isArray(i))continue;let a=typeof r.name==`string`?r.name:`(unnamed permission set)`;for(let[n,r]of Object.entries(i)){if(!r||typeof r!=`object`||Array.isArray(r))continue;let i=r;for(let[r,o]of $x){if(!Object.prototype.hasOwnProperty.call(i,r)||i[r]!==o)continue;let s=tS(r);s!==null&&t.push({rule:Qx,severity:`warning`,where:`permission set '${a}' \xB7 object '${n}'`,path:`permissions[${e}].objects.${n}.${r}`,message:`sets \`${r}: ${JSON.stringify(o)}\`, the retired default of a key removed in @objectstack/spec 17 (ADR-0049). It is accepted as inert residue and silently stripped on parse, so it grants nothing and nothing reports it \u2014 this line has no effect.`,hint:s})}}}return t}var rS=`autonumber-references-unknown-field`,iS=`autonumber-references-optional-field`,aS=`autonumber-references-self`,oS=`autonumber-unrecognized-token`;function sS(e){let t=[];for(let n of w(e.objects)){let e=typeof n.name==`string`?n.name:`(unnamed object)`,r=w(n.fields),i=new Map;for(let e of r)typeof e.name==`string`&&i.set(e.name,{required:e.required===!0});for(let n of r){if(n.type!==`autonumber`)continue;let r=typeof n.name==`string`?n.name:`(unnamed field)`,a=b(n),o=Gt(a),s=f(o),c=`object '${e}' \xB7 field '${r}' (autonumber "${a}")`;for(let e of o){if(e.kind!==`literal`)continue;let n=e.text.match(/\{[^{}]*\}/g);if(n)for(let e of n){let n=e.slice(1,-1),r=/^0+$/.test(n);t.push({where:c,message:r?`format has a second sequence slot \`${e}\` \u2014 only the first \`{0..0}\` counts; this one renders literally as "${e}".`:`format has an unrecognized token \`${e}\` \u2014 it is not a counter/date/{field} token, so it renders literally as "${e}" in every record number.`,hint:r?"Use a single `{0000}` slot; fold any second number into a literal or a {field} token.":`Date tokens are case-sensitive and exact: {YYYY} {YY} {MM} {DD} {YYYYMMDD} (no spaces/punctuation inside). For a field value use {field_name}.`,rule:oS,severity:`warning`})}}for(let n of s){if(n===r){t.push({where:c,message:`format interpolates \`{${n}}\` \u2014 its own value, which does not exist yet when the number is generated.`,hint:"Reference a DIFFERENT field that is set before create (e.g. `{plan_no}{000}`), or drop the token.",rule:aS,severity:`error`});continue}let a=i.get(n);a?a.required||t.push({where:c,message:`format interpolates \`{${n}}\`, but '${n}' is optional \u2014 any record left blank fails autonumber generation at create time.`,hint:`Mark '${n}' as \`required: true\` so it is always set before the record number is rendered.`,rule:iS,severity:`warning`}):t.push({where:c,message:`format interpolates \`{${n}}\`, but object '${e}' has no field named '${n}' \u2014 generation will always throw.`,hint:`Reference an existing field, or remove the \`{${n}}\` token from the format.`,rule:rS,severity:`error`})}}}return t}var cS=`view-key-collision`,lS=`view-ref-form-target-missing`,uS=`view-ref-form-target-kind`,dS=`view-ref-nav-view-missing`,fS=e=>e.includes("${")||e.includes(`{`);function pS(e,t,n){if(t.has(e))return!0;let r=`${n}.`;return!!(!e.includes(`.`)&&t.has(r+e)||e.startsWith(r)&&t.has(e.slice(r.length)))}var mS=(e,t)=>e.startsWith(`${t}.`)?e.slice(t.length+1):e;function hS(e){return{list:e.list,form:e.form,listViews:e.listViews,formViews:e.formViews}}function gS(e){if(typeof e.name==`string`&&e.name)return e.name;if(typeof e.id==`string`&&e.id)return e.id;if(typeof e.object==`string`&&e.object)return e.object;if(typeof e.list?.data?.object==`string`)return e.list.data.object;if(typeof e.form?.data?.object==`string`)return e.form.data.object}function _S(e){let t=[],n=new Map,r=(e,t)=>{let r=n.get(e);r||n.set(e,r=new Set),r.add(t)},i=new Map,a=new Map,o=(e,t,n)=>{let r=n===`list`?i:a,o=r.get(e);o||r.set(e,o=new Set),o.add(t)},s=e=>{for(let t of[e.object,e.objectName,e.data?.object,e.list?.data?.object])if(typeof t==`string`&&t)return t},c=[];for(let t of w(e.views)){if(t.viewKind){let e=t.viewKind===`form`?`form`:`list`;if(typeof t.name==`string`){r(t.name,e);let n=s(t);n&&o(n,t.name,e)}continue}if(!St(t))continue;let e=gS(t);e&&c.push({object:e,container:t})}for(let t of w(e.objects)){let e=typeof t.name==`string`?t.name:void 0;e&&(t.list||t.form||t.listViews||t.formViews)&&c.push({object:e,container:hS(t)})}for(let{object:e,container:n}of c){let{items:i,collisions:a}=Nt(e,n);for(let t of i)r(t.name,t.viewKind),o(t.object??e,t.name,t.viewKind);for(let n of a)t.push({where:`object '${e}' \xB7 view key '${n.key}'`,message:`View key collision: the ${n.viewKind} view '${n.requested}' clashes with another view in the same container and was renamed to '${n.renamedTo}'. Anything referencing '${n.requested}' (a form action target, a navigation viewName) resolves to the OTHER view, not this one.`,hint:`Give the ${n.viewKind} view a unique key \u2014 the default list implicitly claims '<object>.default'. Renaming key '${n.key}' fixes both this collision and any reference that targets it.`,rule:cS,severity:`warning`})}let l=new Set,u=(e,r)=>{if(!e||e.type!==`form`)return;let i=e.target;if(typeof i!=`string`||!i||i.includes("${")||!i.includes(`.`))return;let a=typeof e.name==`string`?e.name:`(unnamed)`,o=`${a}\0${i}`;if(l.has(o))return;l.add(o);let s=r?`action '${a}' on object '${r}'`:`action '${a}'`,c=n.get(i);if(!c){t.push({where:s,message:`Form action target '${i}' does not resolve to any view. A type:'form' action must point at an existing form view; at runtime this opens a blank/broken form.`,hint:`Check for a typo, or a form view renamed by a key collision. Expected a form view named '<object>.<formViewKey>'.`,rule:lS,severity:`warning`});return}if(!c.has(`form`)){let e=[...c].join(`/`);t.push({where:s,message:`Form action target '${i}' resolves to a ${e} view, not a form view. Opening a ${e} view through a form action renders an empty form (and a submit can silently no-op) at runtime.`,hint:`Point target at a form view (viewKind 'form'). If the form view was renamed by a key collision, fix the colliding key so '${i}' names the form again.`,rule:uS,severity:`error`})}};for(let t of w(e.objects)){let e=typeof t.name==`string`?t.name:void 0;for(let n of w(t.actions))u(n,e)}for(let t of w(e.actions))u(t);let d=new Set,f=(e,n)=>{let r=typeof e.objectName==`string`?e.objectName:void 0,o=typeof e.viewName==`string`?e.viewName:void 0;if(!r||!o||fS(o)||typeof e.recordId==`string`&&e.recordId||e.requiresObject)return;let s=i.get(r);if(!s||s.size===0||pS(o,s,r))return;let c=typeof e.id==`string`&&e.id||typeof e.label==`string`&&e.label||`(unnamed)`,l=JSON.stringify([n,c,r,o]);if(d.has(l))return;d.add(l);let u=[...s].map(e=>mS(e,r)),f=a.get(r),p=!!f&&pS(o,f,r);t.push({where:`app '${n}' \xB7 nav '${c}'`,message:`Navigation entry opens view '${o}' on object '${r}', which declares no such list view. `+(p?`The name resolves to a FORM view of that object, which the object's view switcher never offers. `:``)+`At runtime the name does not resolve and the entry falls back to the object's default view, keeping its authored label and icon \u2014 so the sidebar still reads correctly while opening the wrong view. List views on '${r}': ${$n(u)}.`,hint:`Correct the name, declare '${o}' in the object's \`listViews\`, or drop \`viewName\` to open the default view.`+(p?` A form view is reachable from a type:'form' action target, not from navigation.`:``)+E(o,u),rule:dS,severity:`error`})},p=(e,t)=>{if(Array.isArray(e))for(let n of e){if(!n||typeof n!=`object`||Array.isArray(n))continue;let e=n;f(e,t),Array.isArray(e.children)&&p(e.children,t)}};for(let[t,n]of w(e.apps).entries()){let e=typeof n.name==`string`&&n.name?n.name:`#${t}`;p(n.navigation,e);for(let t of w(n.areas))p(t.items,e),p(t.navigation,e)}return t}function vS(e){return`object "${e?.name}"`}function yS(e,t,n,r){let i=(typeof t?.name==`string`&&t.name.trim()?`'${t.name.trim()}'`:``)||(r.length>0?`[${r.join(`, `)}]`:`#${n}`);return`${vS(e)} \xB7 index ${i}`}function bS(e,t){return`${vS(e)} \xB7 field '${t}'`}var xS=new Set([`lookup`,`master_detail`]),SS=new Set([`number`,`currency`,`integer`,`decimal`,`percent`,`float`,`double`]),CS=new Set([`select`,`multiselect`,`radio`,`enum`]);function wS(e){return Et.has(e)||ce.has(e)}var TS=[`name`,`title`,`subject`,`label`,`full_name`,`display_name`,`code`],ES=/_(line|lines|line_item|line_items|item|items|detail|details|entry|entries)$/,DS=[`comment`,`attachment`,`note`,`log`,`audit`,`activity`,`activities`,`history`,`event`,`reaction`,`like`,`mention`,`notification`,`message`];function OS(e){return ES.test(e)}function kS(e){let t=e.toLowerCase();return DS.some(e=>t===e||t.endsWith(`_${e}`)||t.endsWith(`_${e}s`))}function AS(e){return e?Array.isArray(e)?e.filter(e=>e&&e.name!=null).map(e=>({name:String(e.name),def:e})):Object.entries(e).map(([e,t])=>({name:e,def:t})):[]}function jS(e){return be({reference:e?.reference},`data-model-rules refOf`)}var MS=`unique/double-declaration`,NS=`unique/unscoped-declared-index`,PS=`unique/legacy-organization-composite`;function FS(e){let t=e?.tenancy?.tenantField;return typeof t==`string`&&t.trim()?t.trim():`organization_id`}function IS(e){return e===!0||e===`global`||e===`organization`}function LS(e){return e===`global`?`global`:`organization`}function RS(e){return e===`organization`?`organization`:`global`}function zS(e){let t=[];if(!Array.isArray(e)||e.length===0)return t;for(let n=0;n<e.length;n++){let r=e[n];if(!r?.name)continue;let i=Array.isArray(r.indexes)?r.indexes:[];for(let e=0;e<i.length;e++){let a=i[e];if(a?.unique!==!0)continue;let o=Array.isArray(a?.fields)?a.fields.filter(e=>typeof e==`string`):[],s=o.join(`, `),c=typeof a?.name==`string`&&a.name.trim()?` '${a.name.trim()}'`:``;t.push({severity:`warning`,rule:NS,where:yS(r,a,e,o),message:`"${r.name}" declares index${c} [${s}] with bare \`unique: true\` \u2014 a unique index whose scope is unstated (ADR-0120). Today the bare spelling materializes over exactly its \`fields\`, i.e. installation-wide; an author who meant "unique per organization" gets no per-organization constraint and no error. Protocol 18 rejects this spelling (#5082).`,path:`objects[${n}].indexes[${e}]`,fix:"State the scope: `unique: 'global'` (installation-wide — exactly today's behavior) or `unique: 'organization'` (one holder per organization — the driver prepends the NULL-safe organization key part at registration)."})}}return t}function BS(e){let t=[];if(!Array.isArray(e)||e.length===0)return t;for(let n=0;n<e.length;n++){let r=e[n];if(!r?.name)continue;let i=Array.isArray(r.indexes)?r.indexes:[];if(i.length===0)continue;let a=new Map;for(let e of i){if(!IS(e?.unique))continue;let t=Array.isArray(e?.fields)?e.fields.filter(e=>typeof e==`string`):[];t.length===1&&(a.has(t[0])||a.set(t[0],e))}if(a.size!==0)for(let{name:e,def:i}of AS(r.fields)){if(!IS(i?.unique))continue;let o=a.get(e);if(!o)continue;let s=LS(i.unique),c=RS(o.unique),l=typeof o?.name==`string`&&o.name.trim()?` '${o.name.trim()}'`:``,u=`\`unique: ${typeof i.unique==`string`?`'${i.unique}'`:i.unique}\``,d=`\`unique: ${typeof o.unique==`string`?`'${o.unique}'`:o.unique}\``,f,p;if(s===c){let t=s===`global`?`installation-wide`:`per-organization`;f=`"${r.name}.${e}" declares field-level ${u} AND a single-column unique index${l} (${d}) on the same column. Both ask for the same ${t} boundary \u2014 the same unique index declared twice (ADR-0120 D5b). Redundant, not contradictory: drop one so the intent has a single home.`,p=s===`global`?`Keep ONE spelling of installation-wide uniqueness: \`unique: 'global'\` on '${e}', or the declared index \u2014 not both.`:`Keep ONE spelling of per-organization uniqueness: \`unique: 'organization'\` on '${e}' (preferred), or the declared \`'organization'\` index \u2014 not both.`}else{let t=s===`global`?`field-level ${u}`:`declared index${l} (${d})`,n=s===`global`?`declared index${l} (${d})`:`field-level ${u}`;f=`"${r.name}.${e}" declares an installation-wide unique (${t}) AND a per-organization unique (${n}) on the same column \u2014 the two scopes CONTRADICT (ADR-0120 D5b). The installation-wide index is physically stricter and wins; the per-organization constraint can never be tripped, so one of the two intents you wrote is silently dead.`,p=`Pick ONE scope and say it once: for installation-wide uniqueness keep \`unique: 'global'\` and drop the per-organization declaration; for per-organization uniqueness set \`unique: 'organization'\` (field-level on '${e}', or on the declared index) and drop the installation-wide one.`}t.push({severity:`warning`,rule:MS,where:bS(r,e),message:f,path:`objects[${n}]`,fix:p})}}return t}function VS(e){let t=[];if(!Array.isArray(e)||e.length===0)return t;for(let n=0;n<e.length;n++){let r=e[n];if(!r?.name)continue;let i=FS(r),a=Array.isArray(r.indexes)?r.indexes:[];for(let e=0;e<a.length;e++){let o=a[e];if(!IS(o?.unique)||o.unique===`organization`)continue;let s=Array.isArray(o?.fields)?o.fields.filter(e=>typeof e==`string`):[];if(s.length<2||!s.includes(i))continue;let c=typeof o?.name==`string`&&o.name.trim()?` '${o.name.trim()}'`:``,l=`\`unique: ${typeof o.unique==`string`?`'${o.unique}'`:o.unique}\``,u=s.filter(e=>e!==i);t.push({severity:`warning`,rule:PS,where:yS(r,o,e,s),message:`"${r.name}" declares index${c} [${s.join(`, `)}] with ${l} and lists the organization column '${i}' itself \u2014 the hand-written per-organization composite that predates the scope vocabulary (ADR-0120 S6). It reads as "unique per organization" but materializes as a plain composite, and SQL UNIQUE is NULL-distinct: on every row whose '${i}' is NULL it enforces nothing (#5030) \u2014 which on a single-organization deployment is every row.`,path:`objects[${n}].indexes[${e}]`,fix:`State the scope instead: \`unique: 'organization'\` on this index (keep \`fields\` exactly as they are \u2014 the driver makes the listed '${i}' NULL-safe in place rather than prepending a second organization key part). ${u.length>0?`The constraint then really is "one ${u.join(` + `)} per organization". `:``}Opting in is a physical tightening: it surfaces as a \`recreate_index\` drift op gated by the duplicate pre-flight probe (ADR-0120 D4), so pre-existing duplicate NULL-organization rows block it with a report rather than failing a boot. Leaving it as-is stays valid indefinitely and forces no drift.`})}}return t}function HS(e){let t=[...zS(e),...BS(e),...VS(e)];if(!Array.isArray(e)||e.length===0)return t;let n={};for(let t of e)t?.name&&!(t.name in n)&&(n[t.name]=t);let r={};for(let t of e)if(t?.name)for(let{name:e,def:n}of AS(t.fields)){if(!xS.has(n?.type))continue;let i=jS(n);i&&(r[i]||(r[i]=[])).push({child:t,fieldName:e,def:n})}for(let i=0;i<e.length;i++){let a=e[i];if(!a?.name)continue;let o=`objects[${i}]`,s=AS(a.fields),c=!!a.nameField||s.some(e=>TS.includes(e.name));s.length>0&&!c&&t.push({severity:`suggestion`,rule:`object/missing-name-field`,message:`Object "${a.name}" has no nameField and no name-like field \u2014 records will display as raw IDs`,path:`${o}.fields`,fix:"Set `nameField: '<field>'` — ADR-0079's canonical primary-title pointer — to a stored text/autonumber field, or to a formula field with `returnType: 'text'` for a composite title. A `titleFormat` template does NOT count: it is retired (ADR-0079) and render-only, so the server can neither return nor query the title it renders."});for(let{name:e,def:r}of s){if(!r||typeof r!=`object`)continue;let i=`${o}.fields.${e}`,s=r.type;if(CS.has(s)&&(Array.isArray(r.options)&&r.options.length>0||typeof r.picklist==`string`&&r.picklist!==``||r.optionsFrom||r.dataSource||jS(r)||t.push({severity:`warning`,rule:`field/select-missing-options`,message:`${s} field "${a.name}.${e}" has no options`,path:`${i}.options`,fix:"Give the field ONE options source: inline `options: [{ label: '…', value: '…' }]`, or `picklist: '<name>'` naming a shared list — never both, because a field declaring `options` beside `picklist` is refused."})),s===`summary`){let o=r.summaryOperations,s=o?.function,c=o?.object,l=o?.field;if((s===`min`||s===`max`)&&typeof c==`string`&&c!==``&&typeof l==`string`&&l!==``){let r=n[c],o=(r?AS(r.fields).find(e=>e.name===l):void 0)?.def?.type;typeof o==`string`&&!wS(o)&&t.push({severity:`error`,rule:`rollup/non-numeric-aggregand`,message:`summary field "${a.name}.${e}" rolls up ${s}(${c}.${l}), but "${c}.${l}" is a ${o} field \u2014 ${s} answers with a value of the CHILD field's own type, while a summary field's value contract is a finite number (it is a member of the spec's NUMERIC_VALUE_TYPES class), so the answer does not fit the column the roll-up is stored in`,path:`${i}.summaryOperations.field`,fix:`Aggregate a numeric or boolean child field instead (min/max over those answer with a number), or use function: 'count' \u2014 which reads no value off the field. To carry a ${o} on "${a.name}", declare a ${o} field and maintain it from a flow; a roll-up cannot store one.`})}}if(!xS.has(s))continue;let c=jS(r);if(!c){t.push({severity:`error`,rule:`relationship/missing-reference`,message:`${s} field "${a.name}.${e}" is missing a reference target`,path:`${i}.reference`});continue}s===`master_detail`&&(r.required!==!0&&t.push({severity:`warning`,rule:`relationship/master-detail-required`,message:`master_detail "${a.name}.${e}" \u2192 ${c} should be required (a detail record cannot exist without its master)`,path:`${i}.required`,fix:`required: true`}),r.deleteBehavior===void 0&&t.push({severity:`suggestion`,rule:`relationship/delete-behavior`,message:`master_detail "${a.name}.${e}" \u2192 ${c} should declare deleteBehavior (cascade/restrict \u2014 set_null is not honored on master_detail; use a lookup field if children must survive the parent)`,path:`${i}.deleteBehavior`,fix:`deleteBehavior: 'cascade'`}),OS(a.name)&&r.inlineEdit!==!0&&t.push({severity:`suggestion`,rule:`relationship/line-items-inline-edit`,message:`"${a.name}" looks like line items of ${c}; consider inlineEdit: true on "${e}" so it is entered inline within the ${c} form`,path:`${i}.inlineEdit`,fix:`inlineEdit: true`})),s===`lookup`&&OS(a.name)&&t.push({severity:`suggestion`,rule:`relationship/line-item-should-be-master-detail`,message:`"${a.name}" looks like line items of ${c} but uses lookup; master_detail gives ownership + cascade + roll-ups`,path:`${i}.type`,fix:`type: 'master_detail'`}),r.inlineEdit===!0&&kS(a.name)&&t.push({severity:`warning`,rule:`relationship/association-inline-edit`,message:`"${a.name}" is an association (comments/audit/activity), not line items \u2014 inlineEdit clutters the ${c} entry form; surface it as a detail-page related list instead`,path:`${i}.inlineEdit`,fix:`remove inlineEdit (use relatedList on the detail page)`})}let l=r[a.name]||[],u=new Set(s.filter(e=>e.def?.type===`summary`).map(e=>e.def?.summaryOperations?.object||jS(e.def)).filter(Boolean)),d=new Set;for(let{child:e,def:n}of l){if(n?.type!==`master_detail`||!e?.name||d.has(e.name)||u.has(e.name))continue;let r=AS(e.fields).find(e=>SS.has(e.def?.type));r&&(d.add(e.name),t.push({severity:`suggestion`,rule:`rollup/missing-summary`,message:`"${a.name}" owns "${e.name}" (master_detail) with numeric field "${r.name}" but has no roll-up summary; consider a summary field (count/sum) on ${a.name}`,path:`${o}.fields`,fix:`summary field aggregating ${e.name}.${r.name}`}))}}return t}var US=[`validate`,`build`,`lint`],WS=[`cli`,`runtime-publish`],X=US,Z=[`cli`],Q=[`cli`,`runtime-publish`],$=`P2 (#4463): reads a stack-wide collection the per-write snapshot does not carry, so running it now would report the rest of the tenant's metadata as missing rather than judging this write.`,GS=`Not runtime-safe: parses authored source through typescript/sucrase, the two dependencies the kernel boot path must never load (lazy-deps.test.ts). Studio compiles page source on its own path.`,KS=`Advisory-tier object rule: it cannot refuse a write, and it is held off the runtime door for advisory VOLUME (~8 findings per object write measured on unswept metadata, rendered in Studio since #4717), not refusal risk. Crossing it is a UX decision with its own card (#4716).`,qS=`expression-invalid`,JS=[{name:`validateStackExpressions`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-expressions.ts`,surfaces:Q,runtimeTypes:[`flow`,`action`,`hook`],run:e=>la(e).map(e=>({severity:e.severity??`error`,rule:qS,where:e.where,path:e.where,message:e.message,hint:`source: \`${e.source}\``}))},{name:`validateListViewMode`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-list-view-mode.ts`,surfaces:Z,surfaceReason:$,run:e=>Va(e)},{name:`validateFunctionalCompleteness`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-functional-completeness.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>Ga(e)},{name:`validateManagedApiMethods`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-managed-api-methods.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>Ya(e)},{name:`validateViewContainers`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-view-containers.ts`,surfaces:Z,surfaceReason:$,run:e=>ac(e)},{name:`validateWidgetBindings`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-widget-bindings.ts`,surfaces:Q,runtimeTypes:[`dashboard`],run:e=>zr(e)},{name:`validateDatasetMeasureAggregates`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-dataset-measure-aggregates.ts`,surfaces:Q,runtimeTypes:[`dataset`],run:e=>Zr(e)},{name:`validateDashboardActionRefs`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-dashboard-action-refs.ts`,surfaces:Z,surfaceReason:$,run:e=>lm(e)},{name:`validateDashboardWidgetOptions`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-dashboard-widget-options.ts`,surfaces:Z,surfaceReason:`Advisory, dashboard-local: the per-write dashboard snapshot would carry its input. Held at the CLI doors by scope: crossing an advisory rule onto the Studio/REST/MCP door adds a warning to dashboard saves, a rollout decision over stored tenant rows the in-repo corpus does not measure.`,run:e=>fm(e)},{name:`validateFilterTokens`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-filter-tokens.ts`,surfaces:Z,surfaceReason:$,run:e=>xm(e)},{name:`validateFlowFilterTokens`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-flow-filter-tokens.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>Em(e)},{name:`validatePresetComparands`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-preset-comparands.ts`,surfaces:Q,runtimeTypes:[`dashboard`,`view`,`object`,`page`,`flow`,`report`],run:e=>th(e)},{name:`validateEmptyCombinators`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-empty-combinators.ts`,surfaces:Q,runtimeTypes:[`flow`,`report`],run:e=>mh(e)},{name:`validateReferenceIntegrity`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/reference-integrity-suite.ts`,surfaces:Q,runtimeTypes:[`flow`,`view`,`object`,`dataset`,`report`],run:(e,t)=>rb(e,t)},{name:`validateComponentProps`,tier:`advisory`,input:`normalized`,commands:X,source:`packages/lint/src/validate-component-props.ts`,surfaces:Z,surfaceReason:$,run:e=>e_(e)},{name:`validateComponentTypes`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-component-types.ts`,surfaces:Z,surfaceReason:`Gating rule held off the runtime door pending the #4716 crossing discipline: a measured false-refusal budget over stored tenant page rows (the in-repo 0-finding measurement covers authored config-file metadata only). Crossing is its own rollout card.`,run:e=>i_(e)},{name:`validateResponsiveStyles`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-responsive-styles.ts`,surfaces:Z,surfaceReason:$,run:e=>xc(e)},{name:`validateJsxPages`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-jsx-pages.ts`,surfaces:Z,surfaceReason:GS,run:(e,t)=>Cc(e,t.sduiManifest?{manifest:t.sduiManifest}:{})},{name:`validateReactPages`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-react-pages.ts`,surfaces:Z,surfaceReason:GS,run:e=>Ec(e)},{name:`validatePageSourceStyling`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-page-source-styling.ts`,surfaces:Z,surfaceReason:$,run:e=>Kl(e)},{name:`validateCapabilityReferences`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-capability-references.ts`,surfaces:Z,surfaceReason:`P2 (#4463): the ONE rule the runtime universe makes strictly stronger — the advisory hedge ("another installed package may provide it") is decidable against the live capability registry, so it graduates from advisory to gating there rather than merely being ported. That promotion is a severity change on a published rule id and belongs in its own PR, not riding a wiring change.`,run:e=>gd(e)},{name:`validateFlowTriggerReadiness`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-flow-trigger-readiness.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>lo(e)},{name:`validateFlowApiTriggerSecret`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-flow-trigger-readiness.ts`,surfaces:Q,runtimeTypes:[`flow`],run:(e,t)=>uo(e,{restoredCredentialPaths:t.restoredCredentialPaths})},{name:`validateApprovalApprovers`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-approval-approvers.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>Id(e)},{name:`validateRecordTitle`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-record-title.ts`,surfaces:Z,surfaceReason:KS,run:e=>Yl(e)},{name:`validateFieldConsumers`,tier:`advisory`,input:`normalized`,commands:X,source:`packages/lint/src/validate-field-consumers.ts`,surfaces:Z,surfaceReason:$,run:e=>Wv(e)},{name:`validateSemanticRoles`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-semantic-roles.ts`,surfaces:Z,surfaceReason:KS,run:e=>tu(e)},{name:`validateFormLayout`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-form-layout.ts`,surfaces:Z,surfaceReason:$,run:e=>fu(e)},{name:`validateActionLocations`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-action-locations.ts`,surfaces:Z,surfaceReason:$,run:e=>Dg(e)},{name:`validateSeedReplaySafety`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-seed-replay-safety.ts`,surfaces:Z,surfaceReason:$,run:e=>Rd(e)},{name:`validateSeedStateMachine`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-seed-state-machine.ts`,surfaces:Z,surfaceReason:$,run:e=>Hd(e)},{name:`validateVisibilityPredicates`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-visibility-predicates.ts`,surfaces:Q,runtimeTypes:[`view`],run:e=>Wu(e)},{name:`validatePredicatePathRefs`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-predicate-path-refs.ts`,surfaces:Q,runtimeTypes:[`view`],run:e=>fd(e)},{name:`lintFlowPatterns`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/lint-flow-patterns.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>cx(e).map(e=>({severity:e.severity??`warning`,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`lintFlowCredentialLiterals`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/lint-flow-credential-literals.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>Ax(e).map(e=>({severity:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.hint}))},{name:`lintLivenessProperties`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/lint-liveness-properties.ts`,surfaces:Q,runtimeTypes:[`email_template`,`mapping`,`datasource`],run:e=>Zx(e).map(e=>({severity:`warning`,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`validateRetiredPermissionResidue`,tier:`advisory`,input:`normalized`,commands:X,source:`packages/lint/src/validate-retired-permission-residue.ts`,surfaces:Q,runtimeTypes:[`permission`],run:e=>nS(e).map(e=>({severity:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.hint}))},{name:`lintAutonumberFormats`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/lint-autonumber-formats.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>sS(e).map(e=>({severity:e.severity,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`lintViewRefs`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/lint-view-refs.ts`,surfaces:Z,surfaceReason:$,run:e=>_S(e).map(e=>({severity:e.severity,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`lintUnscopedDeclaredIndexes`,tier:`advisory`,input:`parsed`,commands:[`validate`,`build`],source:`packages/lint/src/data-model-rules.ts`,surfaces:Z,surfaceReason:KS,scopeReason:"`os lint` already reports this rule through `lintDataModel`, which calls it directly ahead of R10 in its best-practice sweep — registering it for `lint` as well would report every finding twice. This is coverage recorded, not coverage missing: all three commands report the rule.",run:e=>zS(Array.isArray(e.objects)?e.objects:[]).map(e=>({severity:e.severity===`suggestion`?`info`:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.fix??``}))},{name:`lintUniqueDeclarations`,tier:`advisory`,input:`parsed`,commands:[`validate`,`build`],source:`packages/lint/src/data-model-rules.ts`,surfaces:Z,surfaceReason:KS,scopeReason:"`os lint` already reports this rule through `lintDataModel`, which calls it directly as R10 of its best-practice sweep — registering it for `lint` as well would report every finding twice. This is coverage recorded, not coverage missing: all three commands report the rule.",run:e=>BS(Array.isArray(e.objects)?e.objects:[]).map(e=>({severity:e.severity===`suggestion`?`info`:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.fix??``}))},{name:`lintLegacyOrganizationComposites`,tier:`advisory`,input:`parsed`,commands:[`validate`,`build`],source:`packages/lint/src/data-model-rules.ts`,surfaces:Z,surfaceReason:KS,scopeReason:"`os lint` already reports this rule through `lintDataModel`, which calls it directly alongside R10/R11 in its best-practice sweep — registering it for `lint` as well would report every finding twice. This is coverage recorded, not coverage missing: all three commands report the rule.",run:e=>VS(Array.isArray(e.objects)?e.objects:[]).map(e=>({severity:e.severity===`suggestion`?`info`:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.fix??``}))},{name:`validateSecurityPosture`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-security-posture.ts`,surfaces:Q,runtimeTypes:[`seed`,`permission`,`book`,`object`],run:e=>xf(e)},{name:`validateSecurityRoleWord`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-security-posture.ts`,surfaces:Q,runtimeTypes:[`object`,`permission`,`book`,`position`,`app`],run:e=>Sf(e)},{name:`validateOrgAxisRedLines`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-org-axis-red-lines.ts`,surfaces:Z,surfaceReason:$,run:e=>jf(e)},{name:`validateSharingRuleEnforceability`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-sharing-rule-enforceability.ts`,surfaces:Z,surfaceReason:"P2 (#4463): a sharing rule is not a `flow`, and P1 gates `flow` alone. This entry used to add that the rule reads ONLY `stack.sharingRules[].condition` and needs no other collection, so crossing was a lone `runtimeTypes` edit. #9698 FALSIFIED that: the anchor arm resolves `sharingRules[].object` against `stack.objects` to read the anchor's OWD, so the rule is now cross-collection. `objects` IS carried by the per-write snapshot (`CONTEXT_STACK_KEYS`, #8309), so the remaining gap is unchanged in SHAPE — the gate must accept a `sharing_rule` type and the snapshot must carry `sharingRules`, which it does not — but it is now TWO collections, not one. Crossing with `sharingRules` uncarried would enforce this id for zero of its inputs while the entry claimed the door (#7220). Recorded as pending rather than done, because a rule that has never run at a door should not claim it.",run:e=>tm(e)},{name:`validateRlsPredicateEnforceability`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-rls-predicate-enforceability.ts`,surfaces:Q,runtimeTypes:[`permission`],run:(e,t)=>Vp(e,{judgeFilter:t.judgeFilter})},{name:`validateRuleCompilability`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-rule-compilability.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>K_(e)},{name:`validateRuleSchemaFormats`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-rule-schema-formats.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>rv(e)}];function YS(e){return JS.filter(t=>t.commands.includes(e))}function XS(e,t){let n=[],r={sduiManifest:t.sduiManifest,loweredHookRefs:t.loweredHookRefs,judgeFilter:t.judgeFilter};for(let i of YS(e)){let e=i.input===`normalized`?t.normalized:t.parsed??t.normalized;n.push(...i.run(e,r))}return n}function ZS(e){return{errors:e.filter(e=>e.severity===`error`),advisories:e.filter(e=>e.severity!==`error`)}}var QS={flow:`flows`,object:`objects`,view:`views`,action:`actions`,page:`pages`,dashboard:`dashboards`,agent:`agents`,hook:`hooks`,seed:`data`,permission:`permissions`,book:`books`,dataset:`datasets`,report:`reports`,email_template:`emailTemplates`,mapping:`mappings`,position:`positions`,app:`apps`,datasource:`datasources`};function $S(e,t){if(!t||typeof t.packageId!=`string`||t.packageId===``)return e;let n=new Set([t.packageId,...t.dependencies]);return e.filter(e=>{if(!e||typeof e!=`object`)return!0;let t=e[eC];return typeof t!=`string`||t===``||t===tC||n.has(t)?!0:ff(e)})}var eC=`_packageId`,tC=`sys_metadata`,nC=Object.keys({objects:!0,permissions:!0,books:!0,datasets:!0});function rC(e){return JS.filter(t=>t.surfaces.includes(`runtime-publish`)&&(t.runtimeTypes??[]).includes(e))}function iC(){let e=new Set;for(let t of JS)if(t.surfaces.includes(`runtime-publish`))for(let n of t.runtimeTypes??[])e.add(n);return[...e].sort()}function aC(e){return QS[e]??null}var oC=e=>`${e.rule}\0${e.where}\0${e.path}\0${e.message}`;function sC(e){let t=aC(e.type);if(!t||!e.item||typeof e.item!=`object`)return null;let n=e.item,r=typeof n.name==`string`?n.name:void 0,i={};for(let n of nC){let a=e.context?.[n]??[],o=n===`objects`?$S(a,e.packageScope):a;i[n]=n===t?o.filter(e=>!r||e?.name!==r):o}return{baseline:i,candidate:{...i,[t]:[...i[t]??[],n]}}}function cC(e,t){let n=new Set(t);return e.filter(e=>n.has(e))}function lC(e){if(e.length===0)return/(?!)/;let t=e.map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)).join(`|`);return RegExp(`^(${t})\\[(\\d+)\\](.*)$`)}var uC=cC(nC,new Set(Object.values(QS))),dC=/^[A-Za-z_][A-Za-z0-9_]*$/,fC=lC(uC);function pC(e,t){let n=fC.exec(e);if(!n)return e;let[,r,i,a]=n;if(!uC.includes(r))return e;let o=t[r]?.[Number(i)],s=o&&typeof o==`object`?o.name:void 0;return typeof s!=`string`||!dC.test(s)?e:`${r}.${s}${a}`}function mC(e,t,n){let r=aC(t),i=r?e[r]:void 0;if(!r||!Array.isArray(i)||i.length===0)return new Set;let a=i.length-1,o=i[a],s=new Set;for(let e of n){let t=`${r}[${a}]`,n=o;for(let r of e.split(`.`))Array.isArray(n)&&/^(0|[1-9][0-9]*)$/.test(r)?(t+=`[${r}]`,n=n[Number(r)]):(t+=`.${r}`,n=typeof n==`object`&&n?n[r]:void 0);s.add(t)}return s}function hC(e,t,n){let r=[];for(let i of e)try{r.push(...i.run(t,n))}catch(e){r.push({severity:`warning`,rule:`authoring-rule-threw`,where:i.name,path:i.source,message:`rule ${i.name} threw while judging this write: ${e instanceof Error?e.message:String(e)}`,hint:`This is a bug in the rule, not in the metadata — the write was not blocked by it. Please report it with the body that triggered it.`})}return r}function gC(e){let t=rC(e.type),n={errors:[],advisories:[],rulesRun:[]};if(t.length===0)return n;let r=sC({type:e.type,item:e.item,...e.context===void 0?{}:{context:e.context},...e.packageScope===void 0?{}:{packageScope:e.packageScope}});if(!r)return n;let i={sduiManifest:e.sduiManifest,runtimeWriteType:e.type,judgeFilter:e.judgeFilter,...e.restoredCredentialPaths!==void 0&&e.restoredCredentialPaths.length>0?{restoredCredentialPaths:mC(r.candidate,e.type,e.restoredCredentialPaths)}:{}},a=new Set(hC(t,r.baseline,i).map(oC)),o=hC(t,r.candidate,i).filter(e=>!a.has(oC(e))).map(e=>{let t=pC(e.path,r.candidate);return t===e.path?e:{...e,path:t}});return{errors:o.filter(e=>e.severity===`error`),advisories:o.filter(e=>e.severity!==`error`),rulesRun:t.map(e=>e.name)}}var _C=e=>!!e&&typeof e==`object`&&!Array.isArray(e),vC=e=>_C(e)&&typeof e.dialect==`string`,yC=Lt;function bC(e){return e?e.issues.map(e=>`${e.path.map(String).join(`.`)||`(root)`}: ${e.message}`).join(` | `):`(no issues reported)`}function xC(e,t,n,r,i,a,o=new Set){if(typeof e==`string`){vC(t)&&t.source===e&&a.push({page:r,path:n,authored:e,door:i});return}if(typeof e==`object`&&e&&!o.has(e)){o.add(e);try{if(Array.isArray(e)){if(!Array.isArray(t))return;for(let s=0;s<e.length;s++)xC(e[s],t[s],`${n}[${s}]`,r,i,a,o);return}if(!_C(e)||!_C(t))return;for(let[s,c]of Object.entries(e)){let e=n?`${n}.${s}`:s,l=t[s];if(l===void 0&&typeof c==`string`&&c.length>0){let n=Object.entries(t).find(([,e])=>vC(e)&&e.source===c);if(n){a.push({page:r,path:e,authored:c,normalizedTo:n[0],door:i});continue}}xC(c,l,e,r,i,a,o)}}finally{o.delete(e)}}}function SC(e,t){let n={findings:[],componentParseErrors:[],unmappedTypes:[],unreadableProps:[],componentCount:0};if(!_C(e))return n.pageParseError=`not an object`,n;let r=[],i=qe.safeParse(e);i.success?xC(e,i.data,``,t,`PageSchema`,r):n.pageParseError=bC(i.error);let a=Vc(e,``);n.componentCount=a.length;for(let{component:e,path:i}of a){let a=i.replace(/^\./,``),o=typeof e.type==`string`?e.type:`(non-string type)`,s=je.safeParse(e);s.success?xC(e,s.data,a,t,`PageComponentSchema`,r):n.componentParseErrors.push({path:a,type:o,issues:bC(s.error)});let c=yC[o];if(!c){n.unmappedTypes.push({path:a,type:o});continue}if(!_C(e.properties))continue;let l=c.safeParse(e.properties);l.success?xC(e.properties,l.data,`${a}.properties`,t,`ComponentPropsMap`,r):n.unreadableProps.push({path:a,type:o,issues:bC(l.error)})}let o=new Set;for(let e of r){let t=`${e.page}::${e.path}`;o.has(t)||(o.add(t),n.findings.push(e))}return n.findings.sort((e,t)=>e.path.localeCompare(t.path)),n}function CC(e){return e.map(e=>{let t=e.normalizedTo?` (deprecated key \u2014 parse re-homes it to \`${e.normalizedTo}\`)`:``;return`${e.page} \xB7 ${e.path}${t}
7
+ authored BARE: ${JSON.stringify(e.authored)}
8
+ seen by: ${e.door}
9
+ fix: author the canonical envelope \u2014 P\`\u2026\` (or { dialect: 'cel', source: \u2026 }).
10
+ This page is a raw object literal: nothing parses it, so a bare string
11
+ reaches the wire verbatim and the console routes it to its LEGACY
12
+ evaluator, where a fail-soft predicate stops gating silently.`}).join(`
13
+
14
+ `)}export{Ks as ACTION_API_UPDATE_READONLY_WHEN_FIELD,Ms as ACTION_BODY_SOURCE_UNPARSEABLE,Is as ACTION_BODY_WRITE_EXCLUSIONS,Ls as ACTION_BODY_WRITE_PATTERNS,Ps as ACTION_BODY_WRITE_PATTERN_IDS,As as ACTION_BODY_WRITE_UNKNOWN_FIELD,Ns as ACTION_BODY_WRITE_UNPROVISIONED_ANCHOR,hg as ACTION_DISPATCH_CONTRACT_MISMATCH,dg as ACTION_NAME_UNDEFINED,Cg as ACTION_NO_PLACEMENT,js as ACTION_RECORD_WRITE_DISCARDED,Rs as ACTION_RECORD_WRITE_PATTERNS,Fs as ACTION_RECORD_WRITE_PATTERN_IDS,Ry as AGENT_AUTHORING_WITHDRAWN,Ty as AI_SKILL_SURFACE_MISMATCH,ky as AI_SKILL_TOOL_UNRESOLVED,Sd as APPROVAL_APPROVERS_MAY_RESOLVE_EMPTY,Ed as APPROVAL_APPROVER_CROSS_ORG_UNSUPPORTED,_d as APPROVAL_APPROVER_NOT_MEMBERSHIP_TIER,vd as APPROVAL_APPROVER_TYPE_DEPRECATED,yd as APPROVAL_APPROVER_TYPE_UNKNOWN,bd as APPROVAL_APPROVER_TYPE_UNSUPPORTED,Td as APPROVAL_DECISION_OUTPUTS_RESERVED,xd as APPROVAL_ESCALATION_REASSIGN_NO_TARGET,Cd as APPROVAL_EXPRESSION_INVALID,wd as APPROVAL_EXPRESSION_NO_EMPTY_POLICY,US as AUTHORING_COMMANDS,JS as AUTHORING_RULES,WS as AUTHORING_SURFACES,oS as AUTONUMBER_LITERAL_TOKEN,iS as AUTONUMBER_OPTIONAL_FIELD,aS as AUTONUMBER_SELF_REFERENCE,rS as AUTONUMBER_UNKNOWN_FIELD,pd as CAPABILITY_REFERENCE_UNKNOWN,c_ as CHART_AXIS_NOT_SELECTED,fr as CHART_CONFIG_MISSING,s_ as CHART_DATASET_UNKNOWN,mr as CHART_DIMENSIONS_MISSING,a_ as CHART_DIMENSION_UNKNOWN,dr as CHART_FIELD_UNKNOWN,pr as CHART_MEASURES_MISSING,o_ as CHART_MEASURE_UNKNOWN,qg as COMPONENT_PROPS_INVALID,Kg as COMPONENT_PROPS_UNKNOWN_KEY,t_ as COMPONENT_TYPE_UNKNOWN,rm as DASHBOARD_ACTION_ROUTE_UNRESOLVED,nm as DASHBOARD_ACTION_TARGET_UNDEFINED,Sr as DASHBOARD_FILTER_FIELD_NOT_INCLUDED,br as DASHBOARD_FILTER_FIELD_UNKNOWN,xr as DASHBOARD_FILTER_FIELD_UNPROVISIONED,y_ as DATASET_FIELD_NOT_INCLUDED,v_ as DATASET_FIELD_UNKNOWN,b_ as DATASET_FILTER_FIELD_UNKNOWN,__ as DATASET_INCLUDE_UNKNOWN,By as DEFAULT_AGENT_LEGACY_ALIAS,zy as DEFAULT_AGENT_OUTSIDE_ROSTER,Vr as DIMENSION_JSON_STORED_FIELD_REFUSED,qS as EXPRESSION_INVALID,mv as FIELD_CARRIER_ROOTS,pv as FIELD_CONSUMER_ROOTS,Zl as FIELD_GROUP_EMPTY,Ql as FIELD_GROUP_SHADOWED,Xl as FIELD_GROUP_UNDECLARED,dv as FIELD_NO_CONSUMERS,Zi as FIELD_RULE_BOUND_ROOTS,nh as FILTER_EMPTY_COMBINATOR,rh as FILTER_EMPTY_NODE,Dm as FILTER_PRESET_COMPARAND,pm as FILTER_TOKEN_UNKNOWN,no as FLOW_API_TRIGGER_SECRET_MISSING,pb as FLOW_APPROVAL_REVISE_DEAD_END,hb as FLOW_APPROVAL_REVISE_DISABLED,gb as FLOW_APPROVAL_REVISE_TARGET_NOT_SERVICE_OWNED,mb as FLOW_APPROVAL_REVISE_UNMARKED_BACKEDGE,fb as FLOW_BARE_DOLLAR_REF,yb as FLOW_BRANCH_LABEL_UNMATCHED,_x as FLOW_CREDENTIAL_LITERAL,lb as FLOW_DATE_EQUALITY_FILTER,Tb as FLOW_DECISION_INCLUSIVE_OVERLAP,wb as FLOW_DECISION_MODE_INVALID,bb as FLOW_DECISION_UNCONDITIONAL_BRANCH,xb as FLOW_DEFAULT_EDGE_WITH_CONDITION,db as FLOW_DOUBLE_BRACE_INTERP,Za as FLOW_DRAFT_STATUS_AMBIGUOUS,vb as FLOW_ERROR_LABEL_NOT_FAULT,Sm as FLOW_FILTER_TOKEN_UNKNOWN,Cb as FLOW_INERT_NODE_CONDITION,Db as FLOW_LOOP_BODY_UNCONTAINED,Sb as FLOW_MULTIPLE_DEFAULT_EDGES,Eb as FLOW_MULTI_WRITE_UNFILTERED,Ky as FLOW_NODE_WRITE_UNKNOWN_FIELD,qy as FLOW_NODE_WRITE_UNPROVISIONED_ANCHOR,ub as FLOW_PHANTOM_AGGREGATION,_b as FLOW_RUNAS_UNSCOPED,Ai as FLOW_TEMPLATE_DATE_FUNCTIONS,wo as FLOW_TEMPLATE_FIELD_UNPROVISIONED,Co as FLOW_TEMPLATE_LOOKUP_TRAVERSAL,So as FLOW_TEMPLATE_UNKNOWN_FIELD,ji as FLOW_TEMPLATE_VALUE_FUNCTIONS,cb as FLOW_TIME_RELATIVE_ANTIPATTERN,$a as FLOW_TIME_RELATIVE_DESCRIPTOR_INVALID,eo as FLOW_TIME_RELATIVE_DESCRIPTOR_UNROUTABLE,Qa as FLOW_TRIGGER_UNKNOWN_EVENT,Xa as FLOW_TRIGGER_UNKNOWN_OBJECT,to as FLOW_TRIGGER_UNROUTABLE,Ob as FLOW_TRY_CATCH_WITHOUT_CATCH,Ho as FLOW_UPDATE_READONLY_FIELD,Uo as FLOW_UPDATE_READONLY_WHEN_FIELD,Jy as FLOW_WRITE_NODE_TYPES,Yy as FLOW_WRITE_NODE_TYPES_DEFERRED,su as FORM_FIELD_UNKNOWN,cu as FORM_SECTION_GROUP_UNKNOWN,ys as HOOK_API_UPDATE_READONLY_FIELD,bs as HOOK_API_UPDATE_READONLY_WHEN_FIELD,es as HOOK_BODY_SOURCE_UNPARSEABLE,is as HOOK_BODY_WRITE_EXCLUSIONS,ns as HOOK_BODY_WRITE_PATTERNS,rs as HOOK_BODY_WRITE_PATTERN_IDS,$o as HOOK_BODY_WRITE_UNKNOWN_FIELD,ts as HOOK_BODY_WRITE_UNPROVISIONED_ANCHOR,Uh as LIST_VIEW_FIELD_DOTTED,Hh as LIST_VIEW_FIELD_UNKNOWN,Ra as LIST_VIEW_FILTERS_IN_VIEWS_MODE,jx as LIVENESS_DEAD_PROPERTY,Mx as LIVENESS_EXPERIMENTAL_PROPERTY,Fx as LIVENESS_LEDGER_UNREADABLE,Px as LIVENESS_LIVE_ELSEWHERE_PROPERTY,Nx as LIVENESS_PLANNED_PROPERTY,Ka as MANAGED_API_METHOD_UNAFFORDABLE,T_ as MAPPING_TARGET_FIELD_UNKNOWN,Q_ as MAX_SCHEMA_WALK_DEPTH,Br as MEASURE_AGGREGATE_FIELD_TYPE_REFUSED,_r as MEASURE_AGGREGATE_INCOHERENT,sv as NAV_OBJECT_UNGRANTED,kh as NAV_OBJECT_UNSERVABLE,Sh as NAV_TARGET_UNRESOLVED,si as NULL_GUARD_HINT,kg as OBJECTUI_DERIVATION_PREDICATES,$h as OBJECT_FIELD_REF_UNKNOWN,_h as OBJECT_REFERENCE_UNKNOWN,vh as OBJECT_REFERENCE_UNREGISTERED_PLATFORM,va as OPEN_VOCABULARY_PROBES,wf as ORG_AXIS_CROSS_ORG_BU_GRANT,Cf as ORG_AXIS_PERMISSION_INHERITANCE,qc as PAGE_FIELD_UNKNOWN,Jc as PAGE_FIELD_UNPROVISIONED,Yc as PAGE_SECTION_GROUP_UNKNOWN,Wl as PAGE_SOURCE_CLASSNAME,Og as PAGE_VISUALIZATION_WITHOUT_BINDING,fa as PARSE_FAILURE_HINT,Qx as PERMISSION_RETIRED_LIFECYCLE_RESIDUE,Gu as PREDICATE_PATH_UNRESOLVED,Ku as PREDICATE_PATH_UNROOTED,qu as PREDICATE_RHS_PATH_SHAPED,ya as PRE_SEAL_PHASES,zl as REACT_BLOCK_NEEDS_RECORD_CONTEXT,Cl as REACT_CHART_AGGREGATE_INVALID,wl as REACT_CHART_AXIS_UNKNOWN,Tl as REACT_CHART_DRILLDOWN_INVALID,xl as REACT_CHART_FIELD_UNKNOWN,Sl as REACT_CHART_FIELD_UNPROVISIONED,vl as REACT_PAGE_SOURCE_UNPARSEABLE,yl as REACT_PROP_DEPRECATED,bl as REACT_PROP_RETIRED,Js as READONLY_ACTION_WRITE_EXCLUSIONS,qs as READONLY_ACTION_WRITE_PATTERN_IDS,Ss as READONLY_HOOK_WRITE_EXCLUSIONS,xs as READONLY_HOOK_WRITE_PATTERN_IDS,nb as REFERENCE_INTEGRITY_RULES,Vn as RELATIONSHIP_FIELD_TYPES,Pf as RLS_PREDICATE_OVER_BUDGET,Mf as RLS_PREDICATE_UNENFORCEABLE,Ff as RLS_PREDICATE_UNKNOWN_FIELD,If as RLS_PREDICATE_UNKNOWN_USER_VARIABLE,Nf as RLS_PREDICATE_UNPARSEABLE,P_ as RUNTIME_AJV_OPTIONS,ba as SEAL_MARKERS,Dc as SEARCHABLE_FIELD_UNKNOWN,kc as SEARCHABLE_FIELD_UNPROVISIONED,Oc as SEARCHABLE_FIELD_UNSEARCHABLE,qd as SECURITY_ANCHOR_HIGH_PRIVILEGE,Yd as SECURITY_BOOK_AUDIENCE_UNKNOWN_SET,rf as SECURITY_CBP_AMBIGUOUS_RELATION,nf as SECURITY_CBP_NO_RELATION,tf as SECURITY_DELEGATION_MISSING_REASON,Gd as SECURITY_EXTERNAL_WIDER,$d as SECURITY_FLS_UNKNOWN_FIELD,Qd as SECURITY_FLS_UNQUALIFIED_KEY,ef as SECURITY_GRANT_EXPIRED_AT_AUTHORING,Zd as SECURITY_MASTER_DETAIL_UNGRANTED,Wd as SECURITY_OWD_ALIAS,Ud as SECURITY_OWD_UNSET,Xd as SECURITY_PRIVATE_NO_READSCOPE,Jd as SECURITY_ROLE_WORD,Kd as SECURITY_WILDCARD_VAMA,Ld as SEED_INSERT_MODE_DUPLICATES_ON_REPLAY,zd as SEED_VALUE_OUTSIDE_STATE_MACHINE,$l as SEMANTIC_ROLE_FIELD_UNKNOWN,eu as SEMANTIC_ROLE_FIELD_UNPROVISIONED,Gp as SHARING_RULE_OBJECT_CONTROLLED_BY_PARENT,Wp as SHARING_RULE_OBJECT_NOT_SHAREABLE,Up as SHARING_RULE_RUNTIME_VARIABLE_CONDITION,Hp as SHARING_RULE_UNLOWERABLE_CONDITION,Ph as SORT_FIELD_UNKNOWN,Ih as SORT_FIELD_UNPROVISIONED,Fh as SORT_FIELD_UNSORTABLE,ha as STARTUP_OPEN_VOCABULARY_VERDICT,_a as STARTUP_SOURCE_UNPARSEABLE,ga as STARTUP_VERDICT_ASSERTIVE_WORDING,Ea as STARTUP_VERDICT_HINT,sc as STYLE_CLASSNAME_TAILWIND,oc as STYLE_NODE_MISSING_ID,cc as STYLE_RESPONSIVE_NO_BASE,lc as STYLE_UNKNOWN_CSS_PROPERTY,uc as STYLE_UNKNOWN_TOKEN,gr as TABLE_COUNT_ONLY,ql as TITLE_FORMAT_RETIRED,Jl as TITLE_UNRESOLVABLE,qv as TRANSLATION_OPTION_KEY_UNKNOWN,gy as TRANSLATION_SECTION_NAME_MISSING,Kv as TRANSLATION_TARGET_UNKNOWN,MS as UNIQUE_DOUBLE_DECLARATION,PS as UNIQUE_LEGACY_ORGANIZATION_COMPOSITE,NS as UNIQUE_UNSCOPED_DECLARED_INDEX,M_ as VALIDATION_RULE_REGEX_UNCOMPILABLE,N_ as VALIDATION_RULE_SCHEMA_UNCOMPILABLE,q_ as VALIDATION_RULE_SCHEMA_UNKNOWN_FORMAT,tc as VIEW_CONTAINER_SHAPE,cS as VIEW_KEY_COLLISION,uS as VIEW_REF_FORM_TARGET_KIND,lS as VIEW_REF_FORM_TARGET_MISSING,dS as VIEW_REF_NAV_VIEW_MISSING,xu as VISIBILITY_BARE_IDENTIFIER,Cu as VISIBILITY_PREDICATE_OVER_BUDGET,Su as VISIBILITY_PREDICATE_SYNTAX,wu as VISIBILITY_PREDICATE_UNKNOWN_FUNCTION,bu as VISIBILITY_ROOT_MISLAYERED,cr as WIDGET_DATASET_UNKNOWN,lr as WIDGET_DIMENSION_UNKNOWN,wr as WIDGET_FILTER_FIELD_NOT_INCLUDED,Cr as WIDGET_FILTER_FIELD_UNKNOWN,vr as WIDGET_LEGACY_ANALYTICS_SHAPE,yr as WIDGET_LEGACY_ANALYTICS_UNRENDERABLE,hr as WIDGET_MEASURES_MISSING,ur as WIDGET_MEASURE_UNKNOWN,Tr as WIDGET_SORTBY_UNSELECTED,SC as auditPageExpressionEnvelopes,Ux as authorWarnedProperties,YS as authoringRulesFor,iv as buildAccessMatrix,sC as buildRuntimeWriteSnapshots,Kc as checkSectionGroupRefs,zh as checkSortDeclaration,Ni as classifyFlowTemplateToken,Yn as describeFieldPathVerdict,da as describeParseFailure,ov as diffAccessMatrix,hs as extractHookBodyWriteSet,ms as extractHookBodyWrites,ra as fieldRuleRootIssue,La as findStartupRegistryVerdicts,xi as findUnguardedNullableOperands,Wc as indexObjectFieldGroups,qn as indexObjectGraph,hx as isCredentialShapedLiteral,Bc as isSourceAuthoredPage,Xn as isUnjudgeable,Jn as joinablePrefixes,sS as lintAutonumberFormats,HS as lintDataModel,Ax as lintFlowCredentialLiterals,cx as lintFlowPatterns,VS as lintLegacyOrganizationComposites,Zx as lintLivenessProperties,BS as lintUniqueDeclarations,zS as lintUnscopedDeclaredIndexes,_S as lintViewRefs,$n as listNames,$S as narrowObjectsToPackageClosure,Zn as nearestName,nv as nearestRegisteredFormat,Ci as nullGuardMessage,CC as renderBareExpressionFindings,T as resolveFieldPath,XS as runAuthoringRules,gC as runRuntimeAuthoringRules,rC as runtimeAuthoringRulesFor,iC as runtimeGatedTypes,Gc as sectionGroupRefs,ZS as splitBySeverity,aC as stackKeyForType,E as suggestName,Ws as validateActionBodyWrites,Sg as validateActionDispatchContract,Dg as validateActionLocations,mg as validateActionNameRefs,Gy as validateAiAgentAuthoring,Oy as validateAiSurfaceAffinity,Ly as validateAiToolReferences,Id as validateApprovalApprovers,gd as validateCapabilityReferences,g_ as validateChartBindings,e_ as validateComponentProps,i_ as validateComponentTypes,lm as validateDashboardActionRefs,fm as validateDashboardWidgetOptions,Zr as validateDatasetMeasureAggregates,w_ as validateDatasetReferences,mh as validateEmptyCombinators,Wv as validateFieldConsumers,xm as validateFilterTokens,uo as validateFlowApiTriggerSecret,Em as validateFlowFilterTokens,$y as validateFlowNodeWrites,Vo as validateFlowTemplatePaths,lo as validateFlowTriggerReadiness,fu as validateFormLayout,Ga as validateFunctionalCompleteness,gs as validateHookBodyWrites,Cc as validateJsxPages,Qh as validateListViewFieldRefs,Va as validateListViewMode,Ya as validateManagedApiMethods,k_ as validateMappingTargetFields,uv as validateNavAccess,Nh as validateNavObjectServability,Oh as validateNavTargetRefs,ug as validateObjectFieldRefs,xh as validateObjectReferences,jf as validateOrgAxisRedLines,al as validatePageFieldBindings,Kl as validatePageSourceStyling,Gg as validatePageVisualizationBindings,fd as validatePredicatePathRefs,th as validatePresetComparands,Ul as validateReactPageProps,Ec as validateReactPages,ec as validateReadonlyActionWrites,Xo as validateReadonlyFlowWrites,ks as validateReadonlyHookWrites,Yl as validateRecordTitle,rb as validateReferenceIntegrity,xc as validateResponsiveStyles,nS as validateRetiredPermissionResidue,Vp as validateRlsPredicateEnforceability,K_ as validateRuleCompilability,rv as validateRuleSchemaFormats,Fc as validateSearchableFields,xf as validateSecurityPosture,Sf as validateSecurityRoleWord,Rd as validateSeedReplaySafety,Hd as validateSeedStateMachine,tu as validateSemanticRoles,tm as validateSharingRuleEnforceability,Bh as validateSortableFields,la as validateStackExpressions,wy as validateTranslatableSections,cy as validateTranslationReferences,ac as validateViewContainers,Wu as validateVisibilityPredicates,zr as validateWidgetBindings,sr as walkFilterFieldKeys,Vc as walkPageComponents};