@objectstack/console 17.6.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 (277) hide show
  1. package/CHANGELOG.md +428 -0
  2. package/dist/.objectstack-injection.json +2 -2
  3. package/dist/.objectui-sha +1 -1
  4. package/dist/assets/{ActionResultDialog-4kHDGnT3.js → ActionResultDialog-ChYnuROr.js} +3 -3
  5. package/dist/assets/{AiPendingActionsPage-JjOddm0h.js → AiPendingActionsPage-Dh3-i4BB.js} +1 -1
  6. package/dist/assets/{ApiConsolePage-BgS26lbp.js → ApiConsolePage-CKYEqlMs.js} +1 -1
  7. package/dist/assets/{AppDocsIndex-BDoH5ECM.js → AppDocsIndex-B5Tky2xg.js} +1 -1
  8. package/dist/assets/{AppManagementPage-CCgKmNTj.js → AppManagementPage-ZwyvnHpM.js} +1 -1
  9. package/dist/assets/ApprovalsInboxPage-DD4fe0Em.js +1 -0
  10. package/dist/assets/AuditLogPage-Sed6iMqP.js +1 -0
  11. package/dist/assets/BookPage-DYjUsQIc.js +1 -0
  12. package/dist/assets/{ComponentNavView-B5g9c6fx.js → ComponentNavView-DrlxM4SY.js} +1 -1
  13. package/dist/assets/CreateViewDialog-Cp72x_O7.js +1 -0
  14. package/dist/assets/{DashboardView-BOcovpPd.js → DashboardView-juicRxcP.js} +1 -1
  15. package/dist/assets/DocPage-CxJaQ-pC.js +1 -0
  16. package/dist/assets/{DocsIndex-DwW2QsYY.js → DocsIndex-LALVtIVR.js} +1 -1
  17. package/dist/assets/{DocsLayout-D63StSgd.js → DocsLayout-BAwlJQQf.js} +1 -1
  18. package/dist/assets/{DocsSlug-CP9fcabi.js → DocsSlug-CkF1E-Zs.js} +1 -1
  19. package/dist/assets/ExpressionProvider-Dr0e99r1.js +1 -0
  20. package/dist/assets/FlowRunsPage-R3W3t2s4.js +1 -0
  21. package/dist/assets/{IntegrationsPage-DvG0x0Nb.js → IntegrationsPage-DIuFLEbF.js} +2 -2
  22. package/dist/assets/InterfaceListPage-BfoCldGu.js +1 -0
  23. package/dist/assets/{MarketplaceInstalledPage-B7KETQG2.js → MarketplaceInstalledPage-DyjhcUNB.js} +1 -1
  24. package/dist/assets/MarketplacePackagePage-BbO27Pgs.js +4 -0
  25. package/dist/assets/MarketplacePage-DO2_b64U.js +1 -0
  26. package/dist/assets/{MetadataInspector-EP0I3-Kq.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-D3uCTR-8.js → PublicFormsPage-D3AT2EH9.js} +1 -1
  31. package/dist/assets/RecordDetailView-B3XBEgk2.js +3 -0
  32. package/dist/assets/{RecordFormPage-kiJI-ieF.js → RecordFormPage-CcoZfUJ3.js} +1 -1
  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-DP1mrzEN.js → SettingsHub-CPP9FDe8.js} +1 -1
  39. package/dist/assets/{SettingsView-u7mc6pcc.js → SettingsView-CrHAROu9.js} +1 -1
  40. package/dist/assets/{SkeletonDetail-DIwlbHTr.js → SkeletonDetail-CP-35B8x.js} +1 -1
  41. package/dist/assets/{af-DPUgkQl0.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-B-6GTIRU.js → ar-DG8TAFtm.js} +1 -1
  45. package/dist/assets/{ar-DZ-wEl298ti.js → ar-DZ-BtSien-d.js} +1 -1
  46. package/dist/assets/{ar-EG-YBT90_S0.js → ar-EG-DpXC0zoY.js} +1 -1
  47. package/dist/assets/{ar-MA-3uT-EYh6.js → ar-MA-D1qVJLyE.js} +1 -1
  48. package/dist/assets/{ar-SA-SiQsjhhc.js → ar-SA-BIYKNgv8.js} +1 -1
  49. package/dist/assets/{ar-TN-CfzXjKzS.js → ar-TN-mUR5Mq3s.js} +1 -1
  50. package/dist/assets/{az-BqAfcNza.js → az-B7IqwHGK.js} +1 -1
  51. package/dist/assets/{be-CQgWXa9_.js → be-CnZyPaSX.js} +1 -1
  52. package/dist/assets/{be-tarask-BmNg0Sir.js → be-tarask--uMMCC7l.js} +1 -1
  53. package/dist/assets/{bg-D3evgRuS.js → bg-CZwuirtY.js} +1 -1
  54. package/dist/assets/{bn-uItkARwm.js → bn-BbOX0r-z.js} +1 -1
  55. package/dist/assets/{bs-DueReOpO.js → bs-B5W75cYR.js} +1 -1
  56. package/dist/assets/{ca-Cr3AHktR.js → ca-Be69LdIM.js} +1 -1
  57. package/dist/assets/{ckb-CTi5BET7.js → ckb-B-nKM1Vn.js} +1 -1
  58. package/dist/assets/{createDerive-CjN1i5vn.js → createDerive-CynsXU-B.js} +1 -1
  59. package/dist/assets/{cs-43mFX9jr.js → cs-qHngxH7l.js} +1 -1
  60. package/dist/assets/{cy-BBSkg3F8.js → cy-DscO2Pgf.js} +1 -1
  61. package/dist/assets/{da-C5oA5qcs.js → da-vibkaLMF.js} +1 -1
  62. package/dist/assets/data-adapter-BDsrq0TX.js +2 -0
  63. package/dist/assets/{de-AT-CApxwJzu.js → de-AT--JneEuBw.js} +1 -1
  64. package/dist/assets/{de-CPtbLlAf.js → de-BCT78XYW.js} +1 -1
  65. package/dist/assets/default-inspector-registry-Dktr6x_q.js +1 -0
  66. package/dist/assets/dist-yh3dYtHt.js +14 -0
  67. package/dist/assets/drillUrlFilters-N0RngQg6.js +1 -0
  68. package/dist/assets/{el-Dto2xBQU.js → el-Cl0y9T2b.js} +1 -1
  69. package/dist/assets/en-AU-By42tTB7.js +1 -0
  70. package/dist/assets/{en-CA-DKuJPN1U.js → en-CA-BqEEoj-Y.js} +1 -1
  71. package/dist/assets/en-GB-Cx8B9nkB.js +1 -0
  72. package/dist/assets/en-IE-CX9nv6uO.js +1 -0
  73. package/dist/assets/en-IN-ByGSBHa4.js +1 -0
  74. package/dist/assets/en-NZ-BPMwa2ZN.js +1 -0
  75. package/dist/assets/en-ZA-lj_N4R6c.js +1 -0
  76. package/dist/assets/{eo-BL8JXIWd.js → eo-oOXROuhF.js} +1 -1
  77. package/dist/assets/{es-BnoaNxsu.js → es-EudscwjH.js} +1 -1
  78. package/dist/assets/{et-tPYLNenO.js → et-CB-5LLh6.js} +1 -1
  79. package/dist/assets/{eu-CUBG6bT0.js → eu-B4-hcseX.js} +1 -1
  80. package/dist/assets/{fa-IR-Rr2d9xSs.js → fa-IR-CogavcMJ.js} +1 -1
  81. package/dist/assets/{fi-B0NVIZsV.js → fi-CIBE0mYa.js} +1 -1
  82. package/dist/assets/{formatLong-1-gt9bpo.js → formatLong-qqgm7lV1.js} +1 -1
  83. package/dist/assets/{fr-CA-CBDvLXFg.js → fr-CA-BugXMutW.js} +1 -1
  84. package/dist/assets/{fr-BbhHek8e.js → fr-CDReXYWW.js} +1 -1
  85. package/dist/assets/{fr-CH-WPNmwPn7.js → fr-CH-fiTiB6X1.js} +1 -1
  86. package/dist/assets/framework-CAuH4h0L.js +35 -0
  87. package/dist/assets/{fy-DvOBbvEF.js → fy-t_GzIAg_.js} +1 -1
  88. package/dist/assets/{gd-BQPiTPX5.js → gd-CSncIxtN.js} +1 -1
  89. package/dist/assets/getIcon-BDkBRQFw.js +1 -0
  90. package/dist/assets/{gl-BJCXK8uO.js → gl-_138Mj2S.js} +1 -1
  91. package/dist/assets/{gu-CctPRz3V.js → gu-COfH-YUT.js} +1 -1
  92. package/dist/assets/{he-CVFMk6p2.js → he-BXL4lOKY.js} +1 -1
  93. package/dist/assets/{hi-Ba30-RwS.js → hi-kXuYI0TJ.js} +1 -1
  94. package/dist/assets/{highlighted-body-OFNGDK62-BQ57IrBV.js → highlighted-body-OFNGDK62-CK7x7Gzm.js} +1 -1
  95. package/dist/assets/{hr-BZUqTbZs.js → hr-DAOsQWzI.js} +1 -1
  96. package/dist/assets/{ht-BLe05tPx.js → ht-Ch8SKz8p.js} +1 -1
  97. package/dist/assets/{hu-2CQ_Mkww.js → hu-q6W_rWPT.js} +1 -1
  98. package/dist/assets/{hy-CclcPG4H.js → hy-0M8OmwnM.js} +1 -1
  99. package/dist/assets/{i18n-BnUsCaSC.js → i18n-DTfZonAM.js} +3 -3
  100. package/dist/assets/i18n-locale-ar-O6rs-Cir.js +4 -0
  101. package/dist/assets/i18n-locale-de-CMc1jk4a.js +4 -0
  102. package/dist/assets/i18n-locale-en-CbRQO81h.js +4 -0
  103. package/dist/assets/i18n-locale-es-t47nyoCX.js +4 -0
  104. package/dist/assets/i18n-locale-fr-E425EqJM.js +4 -0
  105. package/dist/assets/i18n-locale-ja-y_fk77fz.js +4 -0
  106. package/dist/assets/i18n-locale-ko-CdnY2uCg.js +4 -0
  107. package/dist/assets/i18n-locale-pt-BaUOXS6y.js +4 -0
  108. package/dist/assets/i18n-locale-ru-pFlhX9wg.js +4 -0
  109. package/dist/assets/i18n-locale-zh-Dkj4ROTN.js +4 -0
  110. package/dist/assets/i18n-runtime-CdWyaiOD.js +1 -0
  111. package/dist/assets/{id-6JLB8s-f.js → id-BM_H1_jv.js} +1 -1
  112. package/dist/assets/index-ocmkyCt6.js +19 -0
  113. package/dist/assets/index-v2Ijn9Gr.css +2 -0
  114. package/dist/assets/{infrastructure-Cc34lEqb.js → infrastructure-CSnL6ntj.js} +2 -2
  115. package/dist/assets/integration-7NqwVHuJ.js +1 -0
  116. package/dist/assets/{is-to0CWzm1.js → is-B_7jXZfS.js} +1 -1
  117. package/dist/assets/isSameWeek-D90tBsli.js +1 -0
  118. package/dist/assets/{it-ea0B8Ujp.js → it-CBM0J9cD.js} +1 -1
  119. package/dist/assets/{it-CH-DhdfjP5Z.js → it-CH-BQltCNsR.js} +1 -1
  120. package/dist/assets/{ja-B1bzkgDW.js → ja-DBjnsx21.js} +1 -1
  121. package/dist/assets/{ja-Hira-CMrY5hXO.js → ja-Hira-BZfSmj1i.js} +1 -1
  122. package/dist/assets/{ka-DKSXLnXP.js → ka-HwpuKgUY.js} +1 -1
  123. package/dist/assets/{kk-DHwMv8Dn.js → kk-DLKA9paj.js} +1 -1
  124. package/dist/assets/{km-tpLG1xNr.js → km-BU5kermq.js} +1 -1
  125. package/dist/assets/{kn-MLreVnHA.js → kn-BNFqbCoi.js} +1 -1
  126. package/dist/assets/{ko-CI0DBazn.js → ko-D8n4uMqQ.js} +1 -1
  127. package/dist/assets/{lb-CmL572Xe.js → lb-B1empQ7m.js} +1 -1
  128. package/dist/assets/{lt-DRtUOLdw.js → lt-gMukpK3G.js} +1 -1
  129. package/dist/assets/{lv-COSHgkOP.js → lv-D2O5AnsZ.js} +1 -1
  130. package/dist/assets/{match-BQoOW8Cj.js → match-BTF6WqJh.js} +1 -1
  131. package/dist/assets/{match-B-ergJQb.js → match-Cyum2eeW.js} +1 -1
  132. package/dist/assets/{match-dfBS0YSQ.js → match-ScHH8kYk.js} +1 -1
  133. package/dist/assets/mermaid-GHXKKRXX-D4H6EVJQ.js +1 -0
  134. package/dist/assets/metadata-admin-CEhVmXFv.js +9 -0
  135. package/dist/assets/{mk-B0IH_YL_.js → mk-D-Zl0xVN.js} +1 -1
  136. package/dist/assets/{mn-P-QdQ2n3.js → mn-jJbTslgD.js} +1 -1
  137. package/dist/assets/{ms-CtyEOINy.js → ms-CUuJHLA4.js} +1 -1
  138. package/dist/assets/{mt-DfuZ2HRm.js → mt-yIcbfxKY.js} +1 -1
  139. package/dist/assets/{nb-2Hp-5Tnt.js → nb-D9WNypoj.js} +1 -1
  140. package/dist/assets/{nl-BE-mmxbfNoR.js → nl-BE-B1vKiw2h.js} +1 -1
  141. package/dist/assets/{nl-CZ_nLREz.js → nl-DC7b5e90.js} +1 -1
  142. package/dist/assets/{nn-ccWhYsNa.js → nn-uP4yJ9s0.js} +1 -1
  143. package/dist/assets/{oc-z504BFRV.js → oc-DHTqadJI.js} +1 -1
  144. package/dist/assets/{pl-DeQ7ASt-.js → pl-Bxnnizf5.js} +1 -1
  145. package/dist/assets/plugin-calendar-b7C35ANT.js +1 -0
  146. package/dist/assets/plugin-charts-b-yVtmdI.js +7 -0
  147. package/dist/assets/{plugin-chatbot-Ck47EhDX.js → plugin-chatbot-D1KW_oIO.js} +8 -8
  148. package/dist/assets/plugin-dashboard-DTkPoPEb.js +6 -0
  149. package/dist/assets/plugin-form-UIRm-FpQ.js +1 -0
  150. package/dist/assets/plugin-gantt-9dtc8zzX.js +63 -0
  151. package/dist/assets/plugin-grid-Cp4RKtMJ.js +10 -0
  152. package/dist/assets/plugin-kanban-B2JOPZIJ.js +1 -0
  153. package/dist/assets/plugin-map-CBJcVJYk.js +1 -0
  154. package/dist/assets/{plugin-markdown-BOkHcir_.js → plugin-markdown-CNlDzqP-.js} +1 -1
  155. package/dist/assets/plugin-report-IZzgQb-Q.js +59 -0
  156. package/dist/assets/plugin-timeline-DsmtjcJ3.js +1 -0
  157. package/dist/assets/plugin-tree-DTRPBdhe.js +1 -0
  158. package/dist/assets/plugin-view-D9ixsNDG.js +1 -0
  159. package/dist/assets/plugins-views-CnvkdSJK.js +3 -0
  160. package/dist/assets/{pt-BR-D80_lPYF.js → pt-BR-D416seHT.js} +1 -1
  161. package/dist/assets/{pt-CJJ1RmXd.js → pt-DwHBy9_c.js} +1 -1
  162. package/dist/assets/{ro-EuFb2TCj.js → ro-DDf1X3Np.js} +1 -1
  163. package/dist/assets/{ru-CMaVQScp.js → ru-8eM3mcgK.js} +1 -1
  164. package/dist/assets/{runtime-metadata-persistence-ClOTznqa.js → runtime-metadata-persistence-DX29lQ62.js} +1 -1
  165. package/dist/assets/{se-DsfdKLdF.js → se-D4JvQeRX.js} +1 -1
  166. package/dist/assets/{sk-BNV9omI8.js → sk-DvpgttGI.js} +1 -1
  167. package/dist/assets/{sl-DJS_nINU.js → sl-B3gCZ-_a.js} +1 -1
  168. package/dist/assets/{sq-HEgjcbHe.js → sq-CVaTmL0V.js} +1 -1
  169. package/dist/assets/{sr-CO0CFu4X.js → sr-CnH5Ffyz.js} +1 -1
  170. package/dist/assets/{sr-Latn-eE1Idzey.js → sr-Latn-Dw9w61q6.js} +1 -1
  171. package/dist/assets/src-BUry7633.js +2 -0
  172. package/dist/assets/{src-BU7L2v4J.js → src-DMDT5a27.js} +1 -1
  173. package/dist/assets/src-ZxH3AOCu.js +16 -0
  174. package/dist/assets/{studioEntry-WeMfaSGn.js → studioEntry-DAqcBFtr.js} +1 -1
  175. package/dist/assets/{submitRedirect-C2lfZSHt.js → submitRedirect-iy0oOi7I.js} +1 -1
  176. package/dist/assets/{sv-5uTzgQT3.js → sv-CU7wdxyK.js} +1 -1
  177. package/dist/assets/{ta-BzgdkBZG.js → ta-DPH6q0HR.js} +1 -1
  178. package/dist/assets/{te-Ct_pl7ZJ.js → te-BSaThkGV.js} +1 -1
  179. package/dist/assets/{th-DouAlk0-.js → th-NXP8_Qb8.js} +1 -1
  180. package/dist/assets/{tr-3XNBsI40.js → tr-DDXoH663.js} +1 -1
  181. package/dist/assets/types-zod-ChJ30y25.js +1 -0
  182. package/dist/assets/{ug-B9n24h9G.js → ug-Guus6pPe.js} +1 -1
  183. package/dist/assets/ui-components-D8wcRNrt.js +37 -0
  184. package/dist/assets/ui-layout-BYO3rRIl.js +1 -0
  185. package/dist/assets/{uk-DCAenByf.js → uk-uiy4vsp8.js} +1 -1
  186. package/dist/assets/use-book-data-DFTswcKm.js +1 -0
  187. package/dist/assets/{useActionModal-Blp4rhOk.js → useActionModal-h52Z5Pkl.js} +1 -1
  188. package/dist/assets/useCanAuthorMetadata-TDrVrYGB.js +1 -0
  189. package/dist/assets/useDatasetCatalog-BOd0Ybr1.js +1 -0
  190. package/dist/assets/{useNavTargetLabel-BOJncjIb.js → useNavTargetLabel-D8lRdb6O.js} +1 -1
  191. package/dist/assets/useOpenRecordList-C7oqUD3F.js +1 -0
  192. package/dist/assets/{usePackageL10n-Ci9uVkRZ.js → usePackageL10n-Jl2XiF2F.js} +1 -1
  193. package/dist/assets/{useSettingsLabel-CeMnMWsh.js → useSettingsLabel-CSpBDTdy.js} +1 -1
  194. package/dist/assets/{uz-Cyrl-JSeHEqu-.js → uz-Cyrl-Cmb5bvbf.js} +1 -1
  195. package/dist/assets/{uz-DT3s9bZS.js → uz-DJWxoTz4.js} +1 -1
  196. package/dist/assets/vendor-objectstack-C4eD5dbT.js +139 -0
  197. package/dist/assets/{vi-D2p-h6bY.js → vi-Bb3QoIJC.js} +1 -1
  198. package/dist/assets/{zh-CN-DHOKqAit.js → zh-CN-C-Hts1ZR.js} +1 -1
  199. package/dist/assets/{zh-HK-D4iIPY7I.js → zh-HK-CtBAZ_ZS.js} +1 -1
  200. package/dist/assets/{zh-TW-gORQ_tZh.js → zh-TW-B7DDahD-.js} +1 -1
  201. package/dist/chunk-membership.json +28 -26
  202. package/dist/eager-closure.json +107 -101
  203. package/dist/index.html +4 -4
  204. package/dist/sdui.manifest.json +486 -63
  205. package/package.json +1 -1
  206. package/dist/assets/ApprovalsInboxPage-C6S1vk0X.js +0 -1
  207. package/dist/assets/AuditLogPage-v2dKXMuk.js +0 -1
  208. package/dist/assets/BookPage-DwFMcTSN.js +0 -1
  209. package/dist/assets/CreateViewDialog-D3l-tYHM.js +0 -1
  210. package/dist/assets/DocPage-B6AkH5WI.js +0 -1
  211. package/dist/assets/ExpressionProvider-CrL6jhVq.js +0 -1
  212. package/dist/assets/FlowRunsPage-CxdaiUyk.js +0 -1
  213. package/dist/assets/InterfaceListPage-C4wPYohR.js +0 -1
  214. package/dist/assets/MarketplacePackagePage-CfgKDpNH.js +0 -4
  215. package/dist/assets/MarketplacePage-DNEyU5AE.js +0 -1
  216. package/dist/assets/ObjectDataPage-CykEm9MD.js +0 -1
  217. package/dist/assets/PageView-C6u86tni.js +0 -1
  218. package/dist/assets/ProfilePage-C3SjXMzi.js +0 -1
  219. package/dist/assets/RecordDetailView-DgR_zhP4.js +0 -3
  220. package/dist/assets/ReportDefaultInspector-BIinF0EQ.js +0 -1
  221. package/dist/assets/ReportView-BREO-ADE.js +0 -2
  222. package/dist/assets/RuntimeDraftBar-BCWfd2yS.js +0 -1
  223. package/dist/assets/SchemaForm-C4uMMZ13.js +0 -3
  224. package/dist/assets/SearchResultsPage-C6Hw_Lpn.js +0 -1
  225. package/dist/assets/ai-DPBykF2N.js +0 -3
  226. package/dist/assets/app-shell-eager-leaves-Cf2bM6uT.js +0 -1
  227. package/dist/assets/data-adapter-Cymvlczj.js +0 -1
  228. package/dist/assets/default-inspector-registry-Bs6GBn00.js +0 -1
  229. package/dist/assets/dist-BF-ssUpn.js +0 -14
  230. package/dist/assets/drillUrlFilters-hi-2d3DW.js +0 -1
  231. package/dist/assets/en-AU-FVwCiDJO.js +0 -1
  232. package/dist/assets/en-GB-DQ_y5VbJ.js +0 -1
  233. package/dist/assets/en-IE-DaXOhsZW.js +0 -1
  234. package/dist/assets/en-IN-CnRZnAom.js +0 -1
  235. package/dist/assets/en-NZ-CBZLEToK.js +0 -1
  236. package/dist/assets/en-ZA-BE59v0wZ.js +0 -1
  237. package/dist/assets/framework-DFR4HNtj.js +0 -35
  238. package/dist/assets/getIcon-Cfwf-Egt.js +0 -1
  239. package/dist/assets/i18n-locale-ar-92O_xtDZ.js +0 -4
  240. package/dist/assets/i18n-locale-de-T5ic3yH9.js +0 -4
  241. package/dist/assets/i18n-locale-en-rxr7WJYl.js +0 -4
  242. package/dist/assets/i18n-locale-es-D_WOifJ_.js +0 -4
  243. package/dist/assets/i18n-locale-fr-3cvyjMkp.js +0 -4
  244. package/dist/assets/i18n-locale-ja-DXlIkB8I.js +0 -4
  245. package/dist/assets/i18n-locale-ko-DngRpS45.js +0 -4
  246. package/dist/assets/i18n-locale-pt-BkPaFCqZ.js +0 -4
  247. package/dist/assets/i18n-locale-ru-E5wLh-y6.js +0 -4
  248. package/dist/assets/i18n-locale-zh-BL4_Yand.js +0 -4
  249. package/dist/assets/i18n-runtime-97_bDVjP.js +0 -1
  250. package/dist/assets/index-Cadlh4t_.css +0 -2
  251. package/dist/assets/index-D98sa5GF.js +0 -20
  252. package/dist/assets/integration-CeAF4JFT.js +0 -1
  253. package/dist/assets/isSameWeek-DBXaA1Gd.js +0 -1
  254. package/dist/assets/mermaid-GHXKKRXX-Bb17TtNP.js +0 -1
  255. package/dist/assets/metadata-admin-CABUxbJl.js +0 -9
  256. package/dist/assets/plugin-calendar-Cn5HaZU8.js +0 -1
  257. package/dist/assets/plugin-charts-B6RcFWbo.js +0 -7
  258. package/dist/assets/plugin-dashboard-DjEx8e5Y.js +0 -6
  259. package/dist/assets/plugin-form-CLDvL0up.js +0 -1
  260. package/dist/assets/plugin-gantt-CrVrxVdi.js +0 -63
  261. package/dist/assets/plugin-grid-D2rmQEW_.js +0 -11
  262. package/dist/assets/plugin-kanban-BUNHFfIC.js +0 -1
  263. package/dist/assets/plugin-map-y-7RQQC5.js +0 -1
  264. package/dist/assets/plugin-report-mT3jpna0.js +0 -59
  265. package/dist/assets/plugin-timeline-B1EF83D3.js +0 -1
  266. package/dist/assets/plugin-tree-MTHUt3_S.js +0 -1
  267. package/dist/assets/plugin-view-DHJI-ahf.js +0 -1
  268. package/dist/assets/plugins-views-CfkgqD30.js +0 -3
  269. package/dist/assets/src-BUtIBFDA.js +0 -1
  270. package/dist/assets/src-C0eXlKtx.js +0 -16
  271. package/dist/assets/types-zod-DXpXw10W.js +0 -1
  272. package/dist/assets/ui-components-D6cEVg0T.js +0 -37
  273. package/dist/assets/ui-layout-DgVDuPEM.js +0 -1
  274. package/dist/assets/use-book-data-CwRldFxP.js +0 -1
  275. package/dist/assets/useCanAuthorMetadata-BxCMgFRf.js +0 -1
  276. package/dist/assets/useOpenRecordList-BrwJFojQ.js +0 -1
  277. package/dist/assets/vendor-objectstack-DFqu45yM.js +0 -138
@@ -1,14 +0,0 @@
1
- import{t as e}from"./rolldown-runtime-C0FnF6B9.js";import{$ as t,$i as n,A as r,B as i,Bn as a,C as o,D as s,Dn as c,Dt as l,E as u,Et as d,Fi as f,Fn as p,Ft as m,G as h,Gn as g,Gr as _,Gt as v,H as y,Hr as b,Ii as ee,It as x,Jn as te,Jr as ne,Jt as re,Kn as ie,Kt as ae,L as oe,Li as se,Ln as ce,Mn as le,Mt as ue,N as de,Nn as fe,Nt as pe,O as me,On as he,Ot as ge,Pn as _e,Q as ve,Qi as ye,Qr as be,Qt as xe,R as Se,Ri as Ce,Rn as we,Rt as Te,S as Ee,Tt as De,U as Oe,Un as ke,V as Ae,Vn as je,W as Me,Wi as Ne,X as Pe,Xi as Fe,Xr as Ie,Xt as Le,Yi as Re,Yn as ze,Yr as Be,Yt as Ve,Zi as He,Zr as Ue,_ as We,_n as Ge,_t as Ke,a as qe,an as Je,b as Ye,cn as Xe,cr as Ze,ct as Qe,dn as $e,dr as et,ea as tt,en as nt,et as rt,f as it,ft as at,gn as ot,gt as st,h as ct,ht as lt,i as ut,in as dt,j as ft,jt as pt,k as mt,kn as ht,kr as gt,l as _t,ln as vt,lt as yt,mt as bt,nt as xt,on as St,or as Ct,p as wt,pn as Tt,pt as Et,r as Dt,rn as Ot,sn as kt,st as At,ur as jt,ut as Mt,v as Nt,vn as Pt,vt as Ft,w as It,wi as Lt,wn as S,xn as Rt,xt as zt,y as Bt,yn as Vt,yt as Ht,zn as Ut}from"./vendor-objectstack-DFqu45yM.js";import{r as Wt}from"./contracts-DieHW666.js";var Gt=e(((e,t)=>{t.exports={}}));Pt();var C=Gt(),Kt=/^on[A-Z]/,qt=new Set([`dangerouslySetInnerHTML`,`ref`,`key`]),Jt=`type`;function Yt(e,t={}){return new Qt(e,t).parseDocument()}var Xt=e=>/[A-Za-z]/.test(e),Zt=e=>/[A-Za-z0-9:_-]/.test(e),Qt=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===Jt?(this.error(`forbidden-attr`,`Attribute "${Jt}" 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}):Kt.test(n)||qt.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 $t(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(!Xt(this.peek()))return``;let e=this.pos;for(this.pos++;this.pos<this.src.length&&Zt(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 $t(e){let t=e.trim();try{return JSON.parse(t)}catch{let e=on(t);return e===w?{$expr:t}:e}}var w=Symbol(`not-a-literal`),en=/[ \t\n\r]/,tn=/[A-Za-z_$]/,nn=/[A-Za-z0-9_$]/,rn=/^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/,an={'"':`"`,"\\":`\\`,"/":`/`,b:`\b`,f:`\f`,n:`
2
- `,r:`\r`,t:` `};function on(e){let t=new sn(e),n=t.value();return n===w?w:(t.ws(),t.done()?n:w)}var sn=class{constructor(e){this.src=e,this.pos=0}done(){return this.pos>=this.src.length}ws(){for(;this.pos<this.src.length&&en.test(this.src[this.pos]);)this.pos++}value(){this.ws();let e=this.src[this.pos];return e===void 0?w: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&&nn.test(t)?!1:(this.pos+=e.length,!0)}number(){let e=rn.exec(this.src.slice(this.pos));return e?(this.pos+=e[0].length,Number(e[0])):w}string(e){this.pos++;let t=``;for(;;){let n=this.src[this.pos];if(n===void 0)return w;if(n===e)return this.pos++,t;if(n===`\\`){let n=this.src[this.pos+1];if(n===void 0)return w;if(n===`u`){let e=this.src.slice(this.pos+2,this.pos+6);if(!/^[0-9a-fA-F]{4}$/.test(e))return w;t+=String.fromCharCode(parseInt(e,16)),this.pos+=6;continue}if(n===`'`&&e===`'`){t+=`'`,this.pos+=2;continue}let r=an[n];if(r===void 0)return w;t+=r,this.pos+=2;continue}if(n<` `)return w;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===w)return w;e.push(t),this.ws();let n=this.src[this.pos];if(n===`,`){this.pos++;continue}return n===`]`?(this.pos++,e):w}}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===w||(this.ws(),this.src[this.pos]!==`:`))return w;this.pos++;let n=this.value();if(n===w)return w;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):w}}key(){let e=this.src[this.pos];if(e===`"`||e===`'`)return this.string(e);if(e!==void 0&&tn.test(e)){let e=this.pos;for(this.pos++;this.pos<this.src.length&&nn.test(this.src[this.pos]);)this.pos++;return this.src.slice(e,this.pos)}return w}};function cn(e){return e===void 0?[]:Array.isArray(e)?e:[e]}var ln=new Set([`dashboard`,`dashboard-grid`]),un=[`dateGranularity`,`description`,`limit`,`sortBy`,`sortOrder`,`stageOrder`],dn=new Set(un),fn=e=>typeof e==`object`&&!!e&&!Array.isArray(e),pn=e=>fn(e)&&`$expr`in e;function mn(e){if(!ln.has(e.type))return[];let t=e.widgets;if(!Array.isArray(t))return[];let n=[];return t.forEach((t,r)=>{if(!fn(t)||pn(t)||t.component!==void 0||t.dataset===void 0||t.dataset===null||t.dataset===``)return;let i=t.options;if(!fn(i)||pn(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))dn.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: ${un.join(`, `)}`,tag:e.type})}),n}var hn=`quickAdd`,gn=new Set([`object-kanban`]),_n=e=>typeof e==`object`&&!!e&&!Array.isArray(e),vn=e=>_n(e)&&`$expr`in e;function yn(e,t,n){return t!==`quickAdd`||!gn.has(e)||vn(n)||!n?null:{severity:`warning`,code:`inert-quick-add`,message:`<${e}> prop "${hn}" reaches no control \u2014 the Quick Add button is gated on BOTH "${hn}" and an "onQuickAdd" handler, and this block supplies neither half of the pair: "onQuickAdd" takes a FUNCTION, which no page on this tier can write (this tier parses, never executes) and which this board substitutes none of its own for. Drop the key, or mount KanbanRenderer from "@object-ui/plugin-kanban" in a React host that passes "onQuickAdd".`,tag:e}}var bn=`children`;function xn(e){return e.inputs.some(e=>e.name===bn)}var Sn=new Set([`type`,`id`,`className`,`style`,`visible`,`visibleOn`,`disabled`,`disabledOn`,bn]),Cn=e=>typeof e==`object`&&!!e&&`$expr`in e;function wn(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))continue;let o=yn(e.type,r,a);if(o){n.push(o);continue}let s=t.get(r);if(!s){n.push({severity:`warning`,code:`unknown-prop`,message:`<${e.type}> has no prop "${r}"`,tag:e.type});continue}if(s.binding&&i.push({tag:e.type,input:r,kind:s.binding,value:a}),Cn(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=An(e.type,s,a);if(t)n.push(t);else{let t=kn(e.type,s,a);t&&n.push(t)}}}e.children?.length&&!xn(o)&&n.push({severity:`warning`,code:`not-a-container`,message:`<${e.type}> does not accept children`,tag:e.type}),n.push(...mn(e))}e.children&&e.children.forEach(a)};return e&&a(e),{diagnostics:n,requires:[...r],bindings:i}}var Tn=e=>(e.enum??[]).map(e=>typeof e==`object`?e.value:e);function En(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 Tn(t).includes(n);default:return!0}}function Dn(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(Tn(t))}`;default:return`a string`}}function On(e){return Array.isArray(e)?e.map((e,t)=>[String(t),e]):typeof e==`object`&&e?Object.entries(e):null}function kn(e,t,n){let r=cn(t.of);if(r.length===0)return null;let i=On(n);if(i===null)return null;let a=i.filter(([,e])=>!r.some(n=>En(n,t,e)));if(a.length===0)return null;let o=r.map(e=>Dn(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 An(e,t,n){let r=cn(t.type);return r.length===0||r.some(e=>En(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(Tn(t))}`,tag:e}:{severity:r.includes(`enum`)?`error`:`warning`,code:`type-mismatch`,message:`<${e}> prop "${t.name}" expected ${r.map(e=>Dn(e,t)).join(` or `)}`,tag:e}}function jn(e,t){let n=Yt(e,{allowedTags:new Set(Object.keys(t.components))}),r=wn(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 Mn=new Set([...Te,...Object.values(Oe)]);function Nn(e){return g(e).names}function Pn(e){return new Map(Object.entries(Vt(e)))}function Fn(e){return new Set(ze(e))}function In(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 Ln(e){let t=new Map;for(let n of In(e)){let e=typeof n.name==`string`&&n.name.length>0?n.name:void 0;if(!e)continue;let r=Fn(n);r.size>0&&t.set(e,r)}return t}function Rn(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 zn(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 Bn=new Set([`lookup`,`master_detail`,`user`,`tree`]);function Vn(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function T(e){return Array.isArray(e)?e.filter(Vn):Vn(e)?Object.entries(e).map(([e,t])=>({name:e,...Vn(t)?t:{}})):[]}function Hn(e){let t=e?.packages;if(t===void 0)return[];if(Array.isArray(t))return t.filter(Vn);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 Un(e){return typeof e==`string`&&e.length>0?e:void 0}function Wn(e){return{type:typeof e.type==`string`?e.type:void 0,reference:Ut(e),multiple:e.multiple===!0||void 0}}function Gn(e){let t=e.fields;if(!t||typeof t!=`object`)return null;let n=new Set,r=new Map;for(let e of T(t)){let t=Un(e.name);t&&(n.add(t),r.set(t,Wn(e)))}if(n.size===0)return null;let i=Pn(e),a=new Map;for(let t of Nn(e))a.set(t,Wn(i.get(t)??{}));return{names:n,fields:r,injected:a}}function Kn(e){let t=new Map;if(!e||typeof e!=`object`)return t;for(let n of T(e.objects)){let e=Un(n.name);e&&t.set(e,Gn(n))}return t}function E(e,t,n){let r=Un(t),i=Un(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||!Bn.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 qn(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 Jn(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}".${D(e.segment,e.candidates)}`,detail:`Fields on "${e.object}": ${Qn(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 ${[...Bn].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}".${D(e.field,e.candidates)}`,detail:`Fields on "${e.object}": ${Qn(e.candidates)}.`}}}function Yn(e){return!e||e.kind===`unknowable`||e.kind===`hop-untargeted`}function Xn(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=Zn(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 D(e,t){let n=Xn(e,t);return n?` Did you mean "${n}"?`:``}function Zn(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 Qn(e){let t=[...e].sort();return t.length>0?t.join(`, `):`(none)`}var $n=new Set([`filter`,`filters`,`runtimeFilter`,`relatedListFilter`,`filterBy`,`lookupFilters`]);function er(e,t){return typeof e==`string`&&e.length>0?e:t}function tr(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)=>tr(e,`${t}[${a}]`,n,r,i));return}for(let[a,o]of Object.entries(e)){let e=`${t}.${a}`;if($n.has(a)){r({value:o,path:e,where:n});continue}tr(o,e,n,r,i)}}}function nr(e,t,n){if(e&&typeof e==`object`)for(let{key:r,kind:i}of t)T(e[r]).forEach((e,t)=>{let a=er(e.name??e.id,`#${t}`);if(i===`dashboard`){(Array.isArray(e.widgets)?e.widgets:[]).forEach((e,i)=>{let o=er(e.id??e.title,`#${i}`);tr(e,`${r}[${t}].widgets[${i}]`,`dashboard "${a}" \xB7 widget "${o}"`,n,new Set)});let{widgets:i,...o}=e;tr(o,`${r}[${t}]`,`dashboard "${a}"`,n,new Set);return}tr(e,`${r}[${t}]`,`${i} "${a}"`,n,new Set)})}var rr=32;function ir(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&!(e instanceof Date)}function ar(e,t,n,r,i){if(!(i>rr))for(let[a,o]of Object.entries(e)){let e=`${t}.${a}`;if(a===`$and`||a===`$or`){Array.isArray(o)&&o.forEach((t,a)=>{ir(t)&&ar(t,`${e}[${a}]`,n,r,i+1)});continue}if(a===`$not`){ir(o)&&ar(o,e,n,r,i+1);continue}if(a.startsWith(`$`))continue;let s=n?`${n}.${a}`:a;if(ir(o)&&!Object.keys(o).some(e=>e.startsWith(`$`))&&Object.keys(o).length>0){ar(o,e,s,r,i+1);continue}r({field:s,path:e})}}function or(e,t,n,r=0){if(!(r>rr)){if(Array.isArray(e)){if(typeof e[0]==`string`&&typeof e[1]==`string`&&![`and`,`or`].includes(e[0].toLowerCase())&&nt.has(e[1].toLowerCase())){n({field:e[0],path:`${t}[0]`});return}e.forEach((e,i)=>{typeof e!=`string`&&or(e,`${t}[${i}]`,n,r+1)});return}if(ir(e)){if(typeof e.field==`string`&&typeof e.operator==`string`){n({field:e.field,path:`${t}.field`});return}ar(e,t,``,n,r)}}}var sr=`widget-dataset-unknown`,cr=`widget-dimension-unknown`,lr=`widget-measure-unknown`,ur=`chart-field-unknown`,dr=`chart-config-missing`,fr=`chart-measures-missing`,pr=`chart-dimensions-missing`,mr=`widget-measures-missing`,hr=`table-count-only`,gr=`measure-aggregate-incoherent`,_r=`widget-legacy-analytics-shape`,vr=`widget-legacy-analytics-unrenderable`,yr=`dashboard-filter-field-unknown`,br=`dashboard-filter-field-unprovisioned`,xr=`dashboard-filter-field-not-included`,Sr=`widget-filter-field-unknown`,Cr=`widget-filter-field-not-included`,wr=`widget-sortby-unselected`,Tr=[`categoryField`,`valueField`,`xAxisField`,`yAxisFields`,`aggregate`,`aggregation`,`rowField`,`columnField`];function Er(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}var Dr=new Set([`combo`]),Or=new Set([`metric`,`kpi`,`gauge`,`solid-gauge`,`bullet`]),kr=new Set([`table`,`pivot`]),Ar=new Set(jt.options.filter(e=>!Or.has(e)&&!kr.has(e)));function jr(e){return typeof e==`string`&&Ar.has(e)}var Mr=new Set(jt.options.filter(e=>!Ar.has(e)));function Nr(e){return typeof e==`string`&&Mr.has(e)}function O(e){let t=[...e];return t.length>0?t.join(`, `):`(none)`}var Pr=`dateRange`,Fr=`created_at`;function Ir(e){let t=new Map,n=e.dateRange;if(n&&typeof n==`object`){let e=n.field,r=typeof e==`string`&&e?e:Fr;t.set(Pr,{name:Pr,field:r})}for(let n of T(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 Lr(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 Rr(e){let t=[],n=new Map;for(let t of T(e.datasets))typeof t.name==`string`&&n.set(t.name,t);let r=new Map;for(let t of T(e.objects)){if(typeof t.name!=`string`)continue;let e=new Map;for(let n of T(t.fields))typeof n.name==`string`&&typeof n.type==`string`&&e.set(n.name,n.type);r.set(t.name,e)}let i=Ln(e),a=Kn(e),o=T(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=T(n.measures);for(let r=0;r<a.length;r++){let o=a[r],s=typeof o.field==`string`?o.field:void 0,l=typeof o.aggregate==`string`?o.aggregate:void 0;if(!s||!l)continue;let u=i.get(s);u&&c(l,u)&&t.push({severity:`warning`,rule:gr,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 ${l} to ${u} 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: ['${gr}'] on the measure.`})}}let s=T(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=Ir(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=Tr.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:_r,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: ['${_r}'] if intentional.`}:{severity:`error`,rule:vr,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:sr,message:`dataset "${h}" does not resolve to a declared dataset.`,hint:`Declared datasets: ${O(n.keys())}.${D(h,n.keys())} Define the dataset with defineDataset() or fix the reference (ADR-0021).`}),!h){p({severity:`error`,rule:sr,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: ${O(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=qn(g.include);for(let r of l){let o=Lr(s,r);if(!o)continue;let c=o.field,l=E(a,e,c);if(Yn(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(`.`)?Jn(l,c,`the effective field`):void 0;if(n){p({severity:`error`,rule:yr,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:yr,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 }.${D(c,t.names)} Object fields: ${O(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>' }.${D(c,t.names)} Object fields: ${O(t.names)}.`});continue}let d=c.lastIndexOf(`.`);if(d>=0){let t=c.slice(0,d);if(!n.has(t)){p({severity:`error`,rule:xr,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:br,message:`${u}${Rn(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:`${zn(f,m)} A widget can also opt out with filterBindings: { ${r.name}: false }. Suppress with suppressWarnings: ['${br}'] 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=qn(g.include);or(s.filter,`${d}.filter`,({field:n,path:r})=>{let i=E(a,e,n);if(Yn(i)||!i)return;let o=Jn(i,n,`filter key`);if(o){p({severity:`error`,rule:Sr,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:Cr,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 T(g.dimensions))typeof e.name==`string`&&_.add(e.name);let v=new Map;for(let e of T(g.measures))typeof e.name==`string`&&v.set(e.name,e);let y=Er(s.dimensions);for(let e=0;e<y.length;e++)_.has(y[e])||p({severity:`error`,rule:cr,message:`dimensions[${e}] "${y[e]}" is not a dimension of dataset "${h}" (declared dimensions: ${O(_)}).`,hint:`Widgets select dataset dimensions BY NAME.${D(y[e],_)} Add the dimension to the dataset or fix the reference.`});let b=Er(s.values);for(let e=0;e<b.length;e++)v.has(b[e])||p({severity:`error`,rule:lr,message:`values[${e}] "${b[e]}" is not a measure of dataset "${h}" (declared measures: ${O(v.keys())}).`,hint:`Widgets select dataset measures BY NAME, not by base column.${D(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:wr,path:`${d}.options.sortBy`,message:e?`options.sortBy "${x}" is declared by dataset "${h}" but is not selected by this widget (selects: ${O(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: ${O(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.${D(x,t)}`:`Point options.sortBy at one of this widget's selected names (${O(t)}).${D(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`&&Dr.has(s.type),te){let e=new Set(b.filter(e=>v.has(e))),t=`Suppress with suppressWarnings: ['${ur}'] 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:ur,message:`chartConfig.xAxis.field "${n.field}" does not resolve to a dimension of dataset "${h}" (declared dimensions: ${O(_)}) \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 (${O(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.${D(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 (${O(b)})`:`chartConfig.${n} "${r}" does not resolve to a measure of dataset "${h}" (declared measures: ${O(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 (${O(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.${D(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:ur,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(jr(s.type))p({severity:`warning`,rule:fr,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: ${O(v.keys())}).`+(y.length===0?` This widget selects no \`dimensions\` either; a chart family needs one to plot against (see ${pr}).`:``)+` If the widget is deliberately still being authored, suppress with: suppressWarnings: ['${fr}']`});else if(Nr(s.type)){let e=Or.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:mr,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: ${O(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: ['${mr}']`})}}else y.length===0&&jr(s.type)&&p({severity:`warning`,rule:pr,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: ${O(_)}) \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: ['${pr}']`});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:hr,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: ['${hr}']`})}}return t}var zr=`measure-aggregate-field-type-refused`,Br=e=>!!e&&typeof e==`object`&&!Array.isArray(e),Vr=e=>typeof e==`string`&&e.length>0?e:void 0,Hr=new Map(Object.entries(pt).map(([e,t])=>[e,t]));function Ur(e){let t=[];for(let[n]of Hr)Rt(n,e)&&t.push(n);return t}function Wr(e){let t=[];if(!Br(e))return t;let n=T(e.datasets);if(n.length===0)return t;let r=Kn(e);return n.forEach((e,n)=>{let i=Vr(e.object);if(!i||!r.has(i)||!r.get(i))return;let a=Vr(e.name)??`#${n}`;T(e.measures).forEach((e,o)=>{let s=Vr(e.aggregate),c=Vr(e.field);if(!s||!c)return;let l=Hr.get(s);if(!l)return;let u=E(r,i,c);if(!u||Yn(u)||u.kind!==`ok`)return;let d=u.meta?.type;if(!d||Rt(s,d))return;let f=Vr(e.name)??`#${o}`,p=u.object===i?`object "${i}"`:`object "${u.object}" (reached through this dataset's join chain)`;t.push({severity:`error`,rule:zr,where:`dataset "${a}" \u203A measure "${f}"`,path:`datasets[${n}].measures[${o}].aggregate`,message:`measure "${f}" applies aggregate "${s}" to field "${c}", which ${p} 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 \`${d}\` type accepts: ${Ur(d).join(`, `)}. \`count\` / \`count_distinct\` accept every type because they read no arithmetic off the value; 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 Gr=[`iteratorVariable`,`indexVariable`,`errorVariable`,`outputVariable`],Kr=`assignment`,qr=[`variable`,`name`,`key`];function Jr(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 qr){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 Yr(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 T(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 Gr){let t=r[e];typeof t==`string`&&t&&n.add(t)}if(t.type===Kr)for(let e of Jr(r))e&&n.add(e)}return n}var Xr=64;function Zr(e){let t=[];for(let n=0;n<Xr;n++){let n=at(e,t);if(n===null||t.includes(n))break;t.push(n)}return t}function Qr(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?[]:Zr(e).filter(e=>r.has(e))}function $r(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 ei=`Guard it with '!= null' — 'has(x)' does NOT do that: a declared field holding null is still PRESENT, so has(x) is true.`,ti=new Set([`<`,`<=`,`>`,`>=`,`+`,`-`,`*`,`/`,`%`]),ni=[`record`,`previous`];function ri(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function ii(e){return ri(e)&&e.op===`value`&&e.args===null}function ai(e,t){if(!ri(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`||!ri(r)||r.op!==`id`)return null;let a=r.args;return typeof a!=`string`||!t.includes(a)?null:{operand:`${a}.${i}`,field:i}}function oi(e){let t=e.args;if(ri(t))return[t];if(!Array.isArray(t))return[];let n=[];for(let e of t)if(ri(e))n.push(e);else if(Array.isArray(e))for(let t of e)ri(t)&&n.push(t);return n}function si(e){if(e.op!==`call`)return null;let t=e.args;return!Array.isArray(t)||typeof t[0]!=`string`?null:t[0]}function ci(e){let t=e.args;return!Array.isArray(t)||!Array.isArray(t[1])?[]:t[1]}function li(e,t){return new Set([...e,...t])}function ui(e,t){let n=new Set;for(let r of e)t.has(r)&&n.add(r);return n}function di(e,t){if(!ri(e))return new Set;switch(e.op){case`!=`:{let[n,r]=e.args??[];if(ii(r)){let e=ai(n,t);return e?new Set([e.operand]):new Set}if(ii(n)){let e=ai(r,t);return e?new Set([e.operand]):new Set}return new Set}case`&&`:{let[n,r]=e.args;return li(di(n,t),di(r,t))}case`||`:{let[n,r]=e.args;return ui(di(n,t),di(r,t))}case`!_`:return fi(e.args,t);case`?:`:{let[,n,r]=e.args;return ui(di(n,t),di(r,t))}default:return new Set}}function fi(e,t){if(!ri(e))return new Set;switch(e.op){case`==`:{let[n,r]=e.args??[];if(ii(r)){let e=ai(n,t);return e?new Set([e.operand]):new Set}if(ii(n)){let e=ai(r,t);return e?new Set([e.operand]):new Set}return new Set}case`||`:{let[n,r]=e.args;return li(fi(n,t),fi(r,t))}case`&&`:{let[n,r]=e.args;return ui(fi(n,t),fi(r,t))}case`!_`:return di(e.args,t);case`call`:{if(si(e)!==`isBlank`)return new Set;let[n]=ci(e),r=ai(n,t);return r?new Set([r.operand]):new Set}default:return new Set}}function pi(e,t,n){if(ri(e)){if(si(e)===`has`)for(let r of ci(e)){let e=ai(r,t);e&&n.add(e.operand)}for(let r of oi(e))pi(r,t,n)}}function mi(e,t){if(typeof e!=`string`||!e.trim()||t.nullableFields.size===0)return[];let n=t.roots??ni,r=Ke(e);if(!r)return[];let i=new Set;pi(r,n,i);let a=[],o=new Set,s=(e,r,s)=>{let c=ai(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(!ri(e))return;let r=e.op;if(r===`&&`){let[r,i]=e.args;c(r,t),c(i,li(t,di(r,n)));return}if(r===`||`){let[r,i]=e.args;c(r,t),c(i,li(t,fi(r,n)));return}if(r===`?:`){let[r,i,a]=e.args;c(r,t),c(i,li(t,di(r,n))),c(a,li(t,fi(r,n)));return}if(r!==`call`||si(e)!==`has`){if(ti.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 oi(e))c(n,t)}};return c(r,new Set),a}var hi={"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 gi(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 ${hi[r]}. The predicate compares a value that is null. ${ei}`}var _i=/^(NOW|TODAY)\s*\(\s*\)\s*(?:([+\-])\s*(\S+))?$/,vi=/^[A-Za-z_$][\w$]*(?:\.(?:[A-Za-z_$][\w$]*|\d+))*$/,yi=/^[\w\s+\-*/%().,?:<>=!&|"'$]+$/,bi=/([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)/g,xi=/^\s*\(/,Si=new Set([`true`,`false`,`null`,`undefined`]),Ci=[`NOW`,`TODAY`],wi=[`round`,`floor`,`ceil`,`abs`,`min`,`max`],Ti=new Set(wi);function Ei(e){let t=e.trim();if(!t)return{kind:`unresolvable-shape`};let n=_i.exec(t);if(n)return{kind:`date-function`,name:n[1]};if(t.startsWith(`$User.`))return{kind:`user-context`};if(vi.test(t))return{kind:`variable-path`,head:t.split(`.`)[0]};if(!yi.test(t))return{kind:`unresolvable-shape`};for(let e of t.matchAll(bi)){let n=e[0];if(Si.has(n))continue;let r=t.slice((e.index??0)+n.length);if(xi.test(r)&&!Ti.has(n))return{kind:`unknown-function`,name:n}}return{kind:`unresolvable-shape`}}var Di=/\{([^{}]+)\}/g,Oi=/[+\-*/%<>=!&|?]/,ki=RegExp(`\\b(?:${wi.join(`|`)})\\s*\\(`);function Ai(e){Di.lastIndex=0;for(let t=Di.exec(e);t!==null;t=Di.exec(e)){let e=t[1].trim();if(Ei(e).kind===`unresolvable-shape`&&yi.test(e)&&(Oi.test(e)||ki.test(e)))return t[0]}}function ji(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 Mi(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=T(r).map(e=>e.name).filter(e=>typeof e==`string`):r&&typeof r==`object`&&(i=Object.keys(r)),t.set(e,[...new Set([...i,...Nn(n)])])}return t}var Ni=[`record`,`previous`];function Pi(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function Fi(e){let t=new Map,n=Ke(e);if(!n)return t;let r=[n];for(;r.length>0;){let e=r.pop();if(!Pi(e))continue;if((e.op===`.`||e.op===`.?`)&&Array.isArray(e.args)&&e.args.length>=2){let[n,r]=e.args;typeof r==`string`&&Pi(n)&&n.op===`id`&&typeof n.args==`string`&&Ni.includes(n.args)&&(t.has(r)||t.set(r,`${n.args}.${r}`))}let n=e.args;if(Pi(n))r.push(n);else if(Array.isArray(n)){for(let e of n)if(Pi(e))r.push(e);else if(Array.isArray(e))for(let t of e)Pi(t)&&r.push(t)}}return t}function Ii(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 Li(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 Ri(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 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=new Set;for(let[e,t]of Li(n))Ri(t)&&r.add(e);t.set(e,r)}return t}function Bi(e){let t=yt(e);return t.ok&&t.roots.includes(`parent`)}function Vi(e){let t=0;for(let[,n]of Li(e)){if(n.type!==`master_detail`)continue;let e=we({reference:n.reference},`validate-expressions masterDetailCount`);e!==void 0&&e.trim()!==``&&(t+=1)}return t}function Hi(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 Ui(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(...Ui(r,`${i} ${t}`))}return n}var Wi=[`record`,`previous`,`parent`],Gi=[`app`],Ki=[...At,...Gi],qi=[`current_user`,`user`,`ctx`,`os`],Ji=`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`,Yi={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:Ji};function Xi(e,t){let n=yt(t);if(!n.ok)return null;let r=Ki.filter(e=>!Wi.includes(e)&&n.roots.includes(e));if(r.length===0)return null;let i=qi.find(e=>r.includes(e))??r[0],a=qi.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>`.":Gi.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 ${Yi[e]??Ji}. `+a}}function Zi(e,t){return t.some(t=>e.startsWith(`bare reference \`${t}\``))}var Qi={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 $i(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. ${Qi[e]}. ${c}`}function ea(e){let t=[];for(let[,n]of Li(e)){if(n.type!==`master_detail`)continue;let e=we({reference:n.reference},`validate-expressions singleMasterOf`);e!==void 0&&e.trim()!==``&&t.push(e.trim())}return t.length===1?t[0]:void 0}function ta(e){let t=typeof e==`string`?e:e.source;if(typeof t!=`string`)return;let n=de.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 na(e){let t=[],n=T(e.objects),r=Mi(n),i=Ii(n),a=zi(n),c=new Map;for(let e of n){let t=typeof e.name==`string`?e.name:void 0;if(!t)continue;let n=Fn(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=Hi(n);if(a)for(let[n,o]of Fi(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,o=`fail-closed`)=>{if(!i)return;let s=a.get(i);if(!s||s.size===0)return;let c=Hi(r);if(c)for(let r of mi(c,{nullableFields:s}))t.push({where:e,message:gi(n,i,r,o),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=zt(`predicate`,n,a?{objectName:a,fields:u,fieldTypes:d,scope:o,traversalHydration:c}:{scope:o});for(let n of f.errors)s&&Zi(n.message,Gi)||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=Hi(t);if(!n)return null;let r=Xi(e,n);return r?{...r,source:n}:null},p=(e,n,r,i)=>{let a=Hi(r);if(a)for(let{root:r,types:o,owner:s}of i){let i=Qe(a,r)?.traversals;for(let[c,l]of i??[]){let i=o[c];typeof i==`string`&&ae.has(i)&&t.push({where:e,message:$i(n,r,c,i,[...l].sort(),s),source:a,severity:`error`})}}},m=(e,n)=>{let r=s(n);if(r)return t.push({where:e,message:r.message,source:r.source,severity:`error`}),{refused:!0};let i=zt(`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=Hi(n)??``,i=We.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=zt(`value`,n);for(let n of a.errors)t.push({where:e,message:`${Bt} ${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 T(e.flows)){let e=typeof n.name==`string`?n.name:`(unnamed flow)`,i=T(n.nodes),a=T(n.edges),s=i.find(e=>e.type===`start`)?.config??{},c=typeof s.objectName==`string`?s.objectName:void 0,l=o({...n,nodes:i,edges:a}),u=Yr(n,l),f=(e,n)=>{if(!c)return;let i=Hi(n);if(i)for(let n of Qr(i,u,r.get(c)??[]))t.push({where:e,message:$r(n,c),source:i,severity:`warning`})},p=(e,n)=>{if(n==null)return{refused:!1};let r=ft(n);if(r)return t.push({where:e,message:r.message,source:r.source,severity:`error`}),{refused:!0};let i=ta(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 T(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=It(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 me(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 mt(a,n)){if(typeof i.value!=`string`)continue;let n=Ai(i.value);n!==void 0&&t.push({where:`${r} \xB7 node '${e.id}' (${a}) ${i.entry.label} at config.${i.path}`,message:ji(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 T(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 T(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 Ui(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=Vi(e),m=n?i.get(n):void 0,h=c===1?ea(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 T(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=Hi(i);c!==1&&a&&Bi(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=zt(`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 T(e.actions))_(`stack`,t);for(let e of n){let t=typeof e.name==`string`?e.name:void 0;for(let n of T(e.actions))_(`object '${t}'`,n,t)}for(let t of T(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 T(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 ra(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 ia(e){let t=e.count>1?`; ${e.count} syntax errors in total`:``;return`line ${e.line}, column ${e.column}: ${e.message}${t}`}var aa=`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.`,oa=null;function sa(){if(oa)return oa;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{oa=(0,C.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 oa}var ca=`startup-open-vocabulary-verdict`,la=`startup-verdict-assertive-wording`,ua=`startup-source-unparseable`,da=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`]]),fa=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`]]),pa=[`seal`],ma=new Set([`warn`,`error`,`fatal`]),ha=new Set([`warn`,`error`,`fatal`,`info`,`debug`,`trace`,`log`]),ga=new Set([`insert`,`insertOne`,`update`,`updateOne`,`upsert`,`save`,`saveMetaItem`]),_a=[`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`],va=[`not yet`,`yet been registered`,`so far`,`as of`,`may still`,`might still`,`still be registered`,`has started`,`have started`],ya='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 ba(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 xa(e,t,n){t.forEachChild(t=>{ba(e,t)||e.isClassDeclaration(t)||e.isClassExpression(t)||(n(t),xa(e,t,n))})}function Sa(e,t,n){t.forEachChild(t=>{n(t),Sa(e,t,n)})}function Ca(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 wa(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(!ha.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 Ta(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),Sa(e,t,r),n.join(` `).toLowerCase()}function Ea(e,t){let n=!1,r=t=>{if(!n&&e.isIdentifier(t)){let e=t.text.toLowerCase();pa.some(t=>e.includes(t))&&(n=!0)}};return r(t),Sa(e,t,r),n}function Da(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 Oa(e,t){let n=new Map;return Sa(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 ka(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?fa.has(n.name.text)&&r.push({phase:n.name.text,body:n.body}):e.isPropertyDeclaration(n)&&e.isIdentifier(n.name)&&fa.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`)&&ba(e,n.initializer)&&(a=!0),fa.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 Sa(e,t,t=>{e.isClassDeclaration(t)||e.isClassExpression(t)?r(t):e.isObjectLiteralExpression(t)&&i(t)}),n}function Aa(e,t={}){if(!e||!e.trim())return[];let n=!1;for(let t of da.keys())if(e.includes(t)){n=!0;break}if(!n)return[];let r=sa(),i=t.file??`source`,{sourceFile:a,failure:o}=ra(r,i,e,{target:r.ScriptTarget.Latest,setParentNodes:!0,scriptKind:r.ScriptKind.TS}),s=[];o&&s.push({severity:`warning`,rule:ua,where:i,path:`${i}:${o.line}`,message:`source did not parse (${ia(o)}), so this rule read a partially recovered tree \u2014 a startup verdict in the unread part is not reported.`,hint:aa});let c=Da(r,a),l=Oa(r,a),u=e=>a.getLineAndCharacterOfPosition(e.getStart(a)).line+1;for(let e of ka(r,a))for(let{phase:t,body:n}of e.phases){let a=[],o=new Set,d=(e,t)=>{a.push(e),!(t>=2)&&xa(r,e,e=>{let n=Ca(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)xa(r,e,e=>{let t=Ca(r,e);t&&da.has(t)&&f.push({probe:t,node:e})});if(!f.length||a.some(e=>Ea(r,e)))continue;let p=[];for(let e of a)xa(r,e,e=>{let t=wa(r,e);if(t&&ma.has(t)){p.push({kind:`announced`,detail:`${t} log`,line:u(e),node:e});return}let n=Ca(r,e);if(n&&ga.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`?``:`()`}`,_=da.get(m.probe),v=fa.get(t);s.push({severity:`warning`,rule:ca,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:ya});for(let e of p){if(e.kind!==`announced`)continue;let t=Ta(r,e.node);if(!t||va.some(e=>t.includes(e)))continue;let n=_a.find(e=>t.includes(e));n&&s.push({severity:`warning`,rule:la,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:ya})}}return s}var ja=`list-view-filters-in-views-mode`;function Ma(e,t,n,r){if(!e||typeof e!=`object`)return;let i=e;i.quickFilters!=null&&r.push({severity:`error`,rule:ja,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:ja,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 Na(e,t,n,r){if(e&&typeof e==`object`)for(let[i,a]of Object.entries(e))Ma(a,`${t} \u203A listViews.${i}`,`${n}.listViews.${i}`,r)}function Pa(e){let t=[];return T(e.objects).forEach((e,n)=>{let r=typeof e.name==`string`?`object "${e.name}"`:`objects[${n}]`;Na(e.listViews,r,`objects[${n}]`,t)}),T(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}]`;Ma(e.list,`${i} \u203A list`,`views[${n}].list`,t),Na(e.listViews,i,`views[${n}]`,t)}),t}var Fa=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Ia(e){return Array.isArray(e)?e.flatMap((e,t)=>Fa(e)?[{name:String(e.name??t),def:e,key:`[${t}]`}]:[]):Fa(e)?Object.entries(e).flatMap(([e,t])=>Fa(t)?[{name:e,def:{name:e,...t},key:`.${e}`}]:[]):[]}function La(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 Ra(e){let n=[];if(!Fa(e))return n;for(let[t,r]of Ia(e.objects).entries())for(let e of Ia(r.def.fields))La(n,ve(e.def),`object "${r.name}" \u203A fields.${e.name}`,`objects[${t}].fields${e.key}`);let r=new Map(Ia(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=>Fa(e.data)?i(e.data.object):void 0,s=(e,t)=>a(o(e)??i(t.objectName)??i(t.object));for(let[r,i]of Ia(e.views).entries()){let e=i.def.object?`view container "${i.name}"`:`view container [${r}]`;Fa(i.def.list)&&La(n,t(i.def.list,s(i.def.list,i.def)),`${e} \u203A list`,`views[${r}].list`);for(let a of Ia(i.def.listViews))La(n,t(a.def,s(a.def,i.def)),`${e} \u203A listViews.${a.name}`,`views[${r}].listViews${a.key}`)}for(let[r,i]of Ia(e.objects).entries()){let e=`object "${i.name}"`;Fa(i.def.list)&&La(n,t(i.def.list,a(o(i.def.list)??i.name)),`${e} \u203A list`,`objects[${r}].list`);for(let s of Ia(i.def.listViews))La(n,t(s.def,a(o(s.def)??i.name)),`${e} \u203A listViews.${s.name}`,`objects[${r}].listViews${s.key}`)}for(let t of Ia(e.webhooks))La(n,rt(t.def),`webhook "${t.name}"`,`webhooks${t.key}`);return n}var za=`object/managed-api-method-unaffordable`,Ba=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Va(e){return Array.isArray(e)?e.flatMap((e,t)=>Ba(e)?[{name:String(e.name??t),def:e,key:`[${t}]`}]:[]):Ba(e)?Object.entries(e).flatMap(([e,t])=>Ba(t)?[{name:e,def:{name:e,...t},key:`.${e}`}]:[]):[]}function Ha(e){let t=[];if(!Ba(e))return t;for(let[n,r]of Va(e.objects).entries()){let e=kt(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:za,where:`object "${r.name}"`,path:`objects[${n}].enable.apiMethods`,message:`\`managedBy: '${String(r.def.managedBy)}'\` object "${r.name}" `+ot(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 Ua=`flow-trigger-unknown-object`,Wa=`flow-draft-status-ambiguous`,Ga=`flow-trigger-unknown-event`,Ka=`flow-time-relative-descriptor-invalid`,qa=`flow-time-relative-descriptor-unroutable`,Ja=`flow-trigger-unroutable`,Ya=/^record-(?:before|after)-(?:create|insert|update|delete|write)$/;function Xa(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 Za(e){if(typeof e==`string`)return`'${e}'`;let t=JSON.stringify(e);return t===void 0?`a ${typeof e}`:t}function Qa(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 $a(e){let t=[],n=T(e.flows);if(n.length===0)return t;let i=new Set(T(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=Qa(e),s=o?.node.config??{},c=typeof s.triggerType==`string`?s.triggerType:void 0,l=!!c&&c.startsWith(`record-`),u=Array.isArray(s.triggerType)&&s.triggerType.some(e=>typeof e==`string`&&e.startsWith(`record-`)),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:Ua,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:Ua,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=Nt.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:Ka,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&&!Ya.test((c??``).trim())&&t.push({severity:`error`,rule:Ga,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:Ga,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:qa,where:`flow "${a}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.timeRelative`,message:`has config.timeRelative = ${Xa(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:Ja,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 ${Za(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:Wa,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 eo(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function to(e){return typeof e==`string`&&e.length>0?e:void 0}var no=new Map([...ct].map(([e,t])=>[e,t.map(e=>e.key)])),ro=16;function io(e,t){return to(e.label)??to(e.id)??`#${t}`}var ao=[];function oo(e){let t=to(e);return(t?no.get(t):void 0)??ao}function so(e,t){if(!eo(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 co(e,t){let n=[];if(!eo(e))return n;let r=(e,t,i,a)=>{!Array.isArray(e)||a>ro||e.forEach((e,o)=>{if(!eo(e))return;let s=`${t}[${o}]`,c=oo(e.type);n.push({node:e,path:s,localConfig:so(e.config,c),regionTrail:i,depth:a});let l=to(e.type),u=c.length>0?c:void 0;if(!u||!eo(e.config))return;let d=e.config,f=`${l} "${io(e,o)}"`;for(let e of u){let t=d[e];if(e===`branches`){if(!Array.isArray(t))continue;t.forEach((e,t)=>{if(!eo(e))return;let n=to(e.name)??`#${t}`;r(e.nodes,`${s}.config.branches[${t}].nodes`,lo(i,`${f} \u203A branch ${n}`),a+1)});continue}eo(t)&&r(t.nodes,`${s}.config.${e}.nodes`,lo(i,`${f} \u203A ${e}`),a+1)}})};return r(e.nodes,`${t}.nodes`,``,0),n}function lo(e,t){return e?`${e} \u203A ${t}`:t}var uo=`flow-template-unknown-field`,fo=`flow-template-lookup-traversal`,po=`flow-template-field-unprovisioned`,mo=new Set([...Mn,`name`,`owner`,`record_type`]),ho=new Set([`lookup`,`master_detail`,`user`,`tree`]),go=new Set([`get_record`,`update_record`,`delete_record`]);function _o(e){let t=new Map;for(let n of T(e.fields))typeof n.name==`string`&&t.set(n.name,typeof n.type==`string`?n.type:``);return t}function vo(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 yo(e,t){if(typeof e==`string`){e.includes(`{`)&&t.push(e);return}if(Array.isArray(e)){for(let n of e)yo(n,t);return}if(e&&typeof e==`object`)for(let n of Object.values(e))yo(n,t)}var bo=[`config`,`notify`,`update_record`,`create_record`,`http`,`script`,`screen`,`wait`,`approval`,`connector_action`,`subflow`,`decision`,`start`];function xo(e,t){let n=[],r=[];for(let i of bo){if(!(i in e))continue;let a=e[i];if(t&&a&&typeof a==`object`&&!Array.isArray(a)){let{filter:e,...t}=a,i=[];yo(e,i);for(let e of i)n.push({text:e,inFilter:!0});let o=[];yo(t,o);for(let e of o)r.push({text:e,inFilter:!1});continue}let o=[];yo(a,o);for(let e of o)r.push({text:e,inFilter:!1})}return[...n,...r]}function So(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 Co(e){let t=T(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 wo(e){let t=(T(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 To=new Set,Eo=new Set([`record`,`previous`]),Do=/^[A-Za-z_$][\w$]*$/;function Oo(e){if(typeof e!=`string`)return;let t=e.trim();if(!t)return;let n=/^\{([^{}]+)\}$/.exec(t);return(n?n[1]:t).trim()}function ko(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=Oo(e),s=i&&Do.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)||Eo.has(e)||e.startsWith(`$`)||t.has(e)||c.set(e,r);return c}function Ao(e){let t=[],n=T(e.flows);if(n.length===0)return t;let r=new Map;for(let t of T(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=_o(t),i.set(e,n)),n};return n.forEach((e,n)=>{let i=typeof e.name==`string`?e.name:`#${n}`,o=T(e.nodes).find(e=>e.type===`start`)?.config??{},s=new Map;if(So(e,o)){let t=Co(e),n=t?r.get(t):void 0;t&&n&&s.set(`record`,{objectName:t,fieldTypes:a(t,n),isTrigger:!0,unprovisionedAnchors:Fn(n),expand:wo(e)})}let c=co(e,`flows[${n}]`),l=s.get(`record`),u=l?new Set([...l.fieldTypes.keys(),...mo]):To;for(let[e,t]of ko(c,u)){let n=r.get(t);n&&s.set(e,{objectName:t,fieldTypes:a(t,n),isTrigger:!1,unprovisionedAnchors:To,expand:To})}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=go.has(u),f=xo(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 vo(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)||mo.has(d);if(e.unprovisionedAnchors.has(d)&&(h.has(d)||(h.add(d),t.push({severity:`warning`,rule:po,where:l,path:n,message:(r?`${u} filter references `:`template references `)+`'{${c}}', and ${Rn(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:zn(o,d)}))),!g){if(p.has(c))continue;p.add(c),t.push({severity:r?`error`:`warning`,rule:uo,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(ho.has(a)&&!e.expand.has(d)){if(m.has(c))continue;m.add(c),t.push({severity:r?`error`:`warning`,rule:fo,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 jo=`flow-update-readonly-field`,Mo=`flow-update-readonly-when-field`,No=`create_record`,Po=new Set([`update_record`,No]);function Fo(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 Io=new Set([`engine-owned`,`append-only`,`better-auth`]);function Lo(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`&&Io.has(n.managedBy)||e.startsWith(`sys_`))&&t.add(e)}return t}function Ro(e){let t=e.objectName??e.object;if(!(typeof t!=`string`||t.includes(`{`)))return t||void 0}function zo(e){let t=[],n=T(e.flows);if(n.length===0)return t;let r=T(e.objects),i=Fo(r),a=Lo(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}`;co(e,`flows[${n}]`).forEach(({node:e,path:n,regionTrail:c},l)=>{let u=e?.type;if(typeof u!=`string`||!Po.has(u))return;let d=u===No,f=e.config??{},p=Ro(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=io(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:jo,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:Mo,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 Bo=null;function Vo(){if(Bo)return Bo;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{Bo=(0,C.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 Bo}var Ho=`hook-body-write-unknown-field`,Uo=`hook-body-source-unparseable`,Wo=`hook-body-write-unprovisioned-anchor`,Go=[{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`}]}}],Ko=[`input-property-assign`,`input-object-assign`,`api-crud-literal`],qo=[{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"}],Jo=new Set(Ko),Yo=new Map([[`insert`,0],[`update`,0],[`updateById`,1]]),Xo=new Set([`id`,`options`,`ast`,`data`]),Zo=new Set([...Mn,`_id`,`name`,`space`,`owner`,`record_type`]);function Qo(){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 $o=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function es(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 ts(e){let t=new Map;for(let n of T(e.objects)){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=new Set;for(let e of T(n.fields))typeof e.name==`string`&&e.name&&r.add(e.name);t.set(e,r)}return t}function ns(e,t){let n=e.get(t);if(n&&n.size!==0)return n}function rs(e){return is(e).writes}function is(e){if(!/\bctx\b/.test(e)&&!/\bObject\b/.test(e))return{writes:[],ctxRecordEscapes:!1};let t=Vo(),{sourceFile:n,failure:r}=ra(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&&!Xo.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))Xo.has(e)||i.push({patternId:`input-object-assign`,field:e});if(t.isPropertyAccessExpression(n)&&t.isIdentifier(n.name)){let r=Yo.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 as(e,t){let n=[],r=T(e.hooks);if(r.length===0)return n;let i=null,a=null;return r.forEach((r,o)=>{let s=r.body;if(!$o(s)||s.language!==`js`)return;let c=s.source;if(typeof c!=`string`||c.trim()===``)return;let l=is(c),u=typeof r.name==`string`&&r.name?r.name:`#${o}`,d=es(r,o,t);l.parseFailure&&n.push({severity:`warning`,rule:Uo,where:`hook "${u}" \u203A body`,path:d.path,message:`L2 body did not parse (${ia(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:aa});let f=l.writes.filter(e=>Jo.has(e.patternId));if(f.length===0)return;i??=ts(e),a??=Ln(e);let p=(Array.isArray(r.object)?r.object:[r.object]).filter(e=>typeof e==`string`&&e.trim()!==``),m=p.map(e=>ns(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(Zo.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:Wo,where:g,path:_,message:`body writes '${e.field}' to its input, and ${Rn(r,e.field)} \u2014 `+Qo()+d.messageSuffix,hint:zn(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:Ho,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:ss(e.field,os(m))})}else{let r=ns(i,e.object);if(!r||r.has(e.field))continue;if(Zo.has(e.field)){if(!a.get(e.object)?.has(e.field))continue;v.add(t),n.push({severity:`warning`,rule:Wo,where:g,path:_,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', and ${Rn(e.object,e.field)} \u2014 ${Qo()}`+d.messageSuffix,hint:zn(e.object,e.field)});continue}v.add(t),n.push({severity:`warning`,rule:Ho,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:ss(e.field,[...r])})}}}}),n}function os(e){let t=new Set;for(let n of e)for(let e of n??[])t.add(e);return[...t]}function ss(e,t){let n=Se(oe(e,[...t,...Zo]));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 cs=`hook-api-update-readonly-field`,ls=`hook-api-update-readonly-when-field`,us=[`api-crud-literal`],ds=[{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)`}],fs=new Set(us),ps=new Set([`update`,`updateById`,`insert`]),ms=new Set([`update`,`updateById`]),hs=new Set([`update`]),gs=`id`;function _s(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function vs(e,t){let n=[],r=T(e.hooks);if(r.length===0)return n;let i=null,a=null;return r.forEach((r,o)=>{let s=r.body;if(!_s(s)||s.language!==`js`)return;let c=s.source;if(typeof c!=`string`||c.trim()===``||r.runAs===`system`)return;let l=is(c);if(l.parseFailure)return;let u=l.writes.filter(e=>fs.has(e.patternId)&&typeof e.object==`string`&&e.method!==void 0&&ps.has(e.method));if(u.length===0)return;i??=Fo(T(e.objects)),a??=Lo(T(e.objects));let d=`hook "${typeof r.name==`string`&&r.name?r.name:`#${o}`}" > body`,f=es(r,o,t),p=f.path,m=new Set;for(let e of u){let t=e.object,r=e.method;if(e.field===gs&&hs.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=!ms.has(r);u&&a.has(t)||(s.readonly?(m.add(c),n.push({severity:`error`,rule:cs,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:ls,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 ys=`action-body-write-unknown-field`,bs=`action-record-write-discarded`,xs=`action-body-source-unparseable`,Ss=`action-body-write-unprovisioned-anchor`,Cs=[`api-crud-literal`],ws=[`record-property-assign`],Ts=[{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`}],Es=Go.filter(e=>Cs.includes(e.id)),Ds=Go.filter(e=>ws.includes(e.id)),Os=new Set(Cs),ks=new Set(ws),As=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function js(e,t){return typeof e.object==`string`&&e.object?e.object:typeof e.objectName==`string`&&e.objectName?e.objectName:t}function Ms(e){let t=[],n=new Set,r=(e,r,i)=>{T(e).forEach((e,a)=>{if((typeof e.type==`string`?e.type:`script`)!==`script`)return;let o=e.body;if(!As(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=`${js(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`),T(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 Ns(e){let t=[];if(!As(e))return t;let n=Ms(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}=is(a.source),c=n.filter(e=>Os.has(e.patternId)),l=n.filter(e=>ks.has(e.patternId)),u=`action "${a.name}" \u203A body`;if(s&&t.push({severity:`warning`,rule:xs,where:u,path:a.path,message:`L2 body did not parse (${ia(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:aa}),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:bs,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??=ts(e),i??=Ln(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=ns(r,e.object);if(o&&!o.has(e.field)){if(Zo.has(e.field)){if(!i.get(e.object)?.has(e.field))continue;d.add(n),t.push({severity:`warning`,rule:Ss,where:u,path:a.path,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', and ${Rn(e.object,e.field)} \u2014 ${Qo()}`,hint:zn(e.object,e.field)});continue}d.add(n),t.push({severity:`warning`,rule:ys,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:Ps(e.field,[...o])})}}}return t}function Ps(e,t){let n=Se(oe(e,[...t,...Zo]));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 Fs=`action-api-update-readonly-when-field`,Is=[`api-crud-literal`],Ls=[{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`}],Rs=new Set(Is),zs=new Set([`update`,`updateById`]),Bs=new Set([`update`]),Vs=`id`,Hs=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Us(e){let t=[];if(!Hs(e))return t;let n=Ms(e);if(n.length===0)return t;let r=null;for(let i of n){if(!/\bapi\b/.test(i.source))continue;let n=is(i.source);if(n.parseFailure)continue;let a=n.writes.filter(e=>Rs.has(e.patternId)&&typeof e.object==`string`&&e.method!==void 0&&zs.has(e.method));if(a.length===0)continue;r??=Fo(T(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===Vs&&Bs.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:Fs,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 Ws=`view-container-shape`,Gs=[`list`,`form`,`listViews`,`formViews`];function Ks(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 qs(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 Js(e){let t=[];if(!e||typeof e!=`object`)return t;let n=e.viewItems;n!=null&&Ks(n).length>0&&t.push({severity:`error`,rule:Ws,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 Ks(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:Ws,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(qs(e)>0)continue;let i=typeof e.name==`string`?` ("${e.name}")`:``,a=!Gs.some(t=>t in e)&&[`type`,`columns`,`data`,`filter`,`sort`].some(t=>t in e);t.push({severity:`error`,rule:Ws,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 Ys=`style-node-missing-id`,Xs=`style-classname-tailwind`,Zs=`style-responsive-no-base`,Qs=`style-unknown-css-property`,$s=`style-unknown-token`,ec=[`large`,`medium`,`small`,`xsmall`],tc=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(`.`)),nc=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(`.`)),rc=/var\(\s*--([a-zA-Z0-9-]+)\s*[,)]/g,ic=/^(sm|md|lg|xl|2xl|hover|focus|active|disabled|dark|group-hover|peer-[a-z]+|first|last|odd|even):/,ac=/^-?(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)$/,oc=/^(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 sc(e){return e.split(/\s+/).some(e=>e?!!(ic.test(e)||/\[[^\]]+\]/.test(e)||ac.test(e)||oc.test(e)):!1)}function cc(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 lc(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`&&ec.some(e=>s[e]);if(c&&!i&&r.push({severity:`error`,rule:Ys,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&&ec.slice(1).some(e=>s[e])&&r.push({severity:`warning`,rule:Zs,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()&&sc(e.className)&&r.push({severity:`warning`,rule:Xs,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 ec){let t=s[e];if(t&&typeof t==`object`){for(let[i,a]of Object.entries(t))if(!i.startsWith(`--`)&&!nc.has(i)&&r.push({severity:`warning`,rule:Qs,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(rc.lastIndex=0;t=rc.exec(a);){let a=t[1];!tc.has(a)&&!a.startsWith(`tw-`)&&r.push({severity:`warning`,rule:$s,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=cc(e);for(let e=0;e<l.length;e++)lc(l[e],t,`${n}.children[${e}]`,r)}function uc(e){let t=[],n=T(e.pages);for(let e=0;e<n.length;e++){let r=n[e],i=typeof r.name==`string`?r.name:`pages[${e}]`,a=T(r.regions);for(let n=0;n<a.length;n++){let r=T(a[n].components);for(let a=0;a<r.length;a++)lc(r[a],i,`pages[${e}].regions[${n}].components[${a}]`,t)}}return t}function dc(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function k(e,t){if(Array.isArray(e)){let n=[];for(let r=0;r<e.length;r++)dc(e[r])&&n.push({rec:e[r],path:`${t}[${r}]`});return n}return dc(e)?Object.entries(e).filter(([,e])=>dc(e)).map(([e,n])=>({rec:{name:e,...n},path:`${t}.${e}`})):[]}function fc(e,t={}){let n=[];for(let{rec:r,path:i}of k(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?jn(a,t.manifest):Yt(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 pc=null;function mc(){if(pc)return pc;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{pc=(0,C.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 pc}function hc(e){let t=[];for(let{rec:n,path:r}of k(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=mc();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 gc=`searchable-field-unknown`,_c=`searchable-field-unsearchable`,vc=`searchable-field-unprovisioned`;function A(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function yc(e){return typeof e==`string`&&e.length>0?e:void 0}function bc(e){let t=e.fields;if(!t||typeof t!=`object`)return null;let n=new Set,r={};for(let e of T(t)){let t=yc(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:yc(e.nameField)??yc(e.displayNameField)}}function xc(e){let t=e.fields,n=(e.searchableFields??[]).filter(t=>!e.names.has(t)&&Mn.has(t));if(n.length>0){t={...t};for(let e of n)t[e]={}}let{allowed:r,source:i}=ie({fields:t,searchableFields:e.searchableFields,displayField:e.displayField});return{allowed:new Set(r),source:i,declaredList:r}}function Sc(e){let t=new Map;if(!A(e))return t;for(let n of T(e.objects)){let e=yc(n.name);e&&t.set(e,bc(n))}return t}function Cc(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`?xc(l):void 0;for(let n=0;n<e.length;n++){let s=e[n],p=yc(s);if(!p)continue;if(!u.has(p)&&!Mn.has(p)){let e=p.includes(`.`);c.push({severity:`error`,rule:gc,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?``:D(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:vc,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" resolves on object "${t}", but ${Rn(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:zn(t,p)}),le(l.fields[p])){let e=l.fields[p]?.type;c.push({severity:`error`,rule:_c,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:_c,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 h=m?.type===`lookup`||m?.type===`master_detail`,g;if(Le.has(p))g=`a system/audit column, which the auto-default set never includes`;else if(m?.hidden)g=`hidden`;else if(typeof m?.type==`string`)g=`of type '${m.type}', which 'search' cannot scan`;else continue;c.push({severity:`error`,rule:_c,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" on object "${t}" is ${g}. With no 'searchableFields' declared on the object, 'search' scans its text-like columns (${[...Ve,...re].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:(h?`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 wc(e){let t=[];if(!A(e))return t;let n=T(e.objects),r=Sc(e),i=Ln(e),a=(e,n,a,o,s,c)=>{t.push(...Cc(e,n,r,a,o,s,c,i))};for(let e=0;e<n.length;e++){let t=n[e];if(!A(t))continue;let r=yc(t.name),i=r?`object "${r}"`:`objects[${e}]`;if(a(t.searchableFields,r,i,`objects[${e}].searchableFields`,`searchableFields`,`canonical`),A(t.listViews))for(let[n,o]of Object.entries(t.listViews))A(o)&&a(o.searchableFields,Tc(o)??r,`${i} \u203A listViews.${n}`,`objects[${e}].listViews.${n}.searchableFields`,`list-view searchableFields`,`narrowing`)}let o=T(e.views);for(let e=0;e<o.length;e++){let t=o[e];if(!A(t))continue;let n=yc(t.name)??yc(t.objectName)??`#${e}`,r=yc(t.objectName)??yc(t.object);if(t.viewKind===`list`&&!A(t.config)&&a(t.searchableFields,Tc(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}].searchableFields`,`list-view searchableFields`,`narrowing`),t.viewKind===`list`&&A(t.config)&&a(t.config.searchableFields,Tc(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config.searchableFields`,`list-view searchableFields`,`narrowing`),A(t.list)&&a(t.list.searchableFields,Tc(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list.searchableFields`,`list-view searchableFields`,`narrowing`),A(t.listViews))for(let[i,o]of Object.entries(t.listViews))A(o)&&a(o.searchableFields,Tc(o)??r,`view "${n}" \u203A listViews.${i}`,`views[${e}].listViews.${i}.searchableFields`,`list-view searchableFields`,`narrowing`)}return t}function Tc(e){let t=e.data;return A(t)?yc(t.object):void 0}function Ec(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Dc(e){return typeof e==`string`&&e.length>0?e:void 0}var Oc=new Set([`html`,`react`,`jsx`]);function kc(e){let t=Dc(e.kind);return t!==void 0&&Oc.has(t)}function Ac(e,t){let n=[];if(!Ec(e)||kc(e))return n;let r=Dc(e.object),i=new Set,a=(e,t,r)=>{if(!Ec(e)||i.has(e))return;let o=Ec(e.properties)?e.properties:void 0,s=Dc((Ec(e.dataSource)?e.dataSource:void 0)?.object)??Dc(o?.object)??r;if(n.push({component:e,path:t,objectName:s}),o){i.add(e);try{if(Array.isArray(o.items))for(let e=0;e<o.items.length;e++){let n=o.items[e];if(Ec(n)&&Array.isArray(n.children))for(let r=0;r<n.children.length;r++)a(n.children[r],`${t}.properties.items[${e}].children[${r}]`,s)}if(Array.isArray(o.children))for(let e=0;e<o.children.length;e++)a(o.children[e],`${t}.properties.children[${e}]`,s);for(let e of[`body`,`footer`]){let n=o[e];if(Array.isArray(n))for(let r=0;r<n.length;r++)a(n[r],`${t}.properties.${e}[${r}]`,s)}}finally{i.delete(e)}}},o=Array.isArray(e.regions)?e.regions:[];for(let e=0;e<o.length;e++){let n=o[e];if(Ec(n)&&Array.isArray(n.components))for(let i=0;i<n.components.length;i++)a(n.components[i],`${t}.regions[${e}].components[${i}]`,r)}let s=Ec(e.slots)?e.slots:void 0;if(s)for(let[e,n]of Object.entries(s)){let i=Array.isArray(n)?n:[n],o=Array.isArray(n);for(let n=0;n<i.length;n++)a(i[n],`${t}.slots.${e}${o?`[${n}]`:``}`,r)}return n}function jc(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Mc(e){return typeof e==`string`&&e.length>0?e:void 0}function Nc(e){let t=new Map;if(!jc(e))return t;for(let n of T(e.objects)){let e=Mc(n.name);if(!e)continue;let r=new Set;for(let e of T(n.fieldGroups)){let t=Mc(e.key)??Mc(e.name);t&&r.add(t)}t.set(e,r)}return t}function Pc(e,t,n=`.`){if(!Array.isArray(e))return[];let r=[];for(let i=0;i<e.length;i++){let a=e[i];if(!jc(a))continue;let o=Mc(a.group);o&&r.push({key:o,path:`${t}[${i}]${n}group`})}return r}function Fc(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 Ic=`page-field-unknown`,Lc=`page-field-unprovisioned`,Rc=`page-section-group-unknown`;function j(e){return typeof e==`string`&&e.length>0?e:void 0}function zc(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function M(e,t){let n=[],r=(e,t)=>{let r=j(e);if(r){n.push({name:r,path:t});return}if(!zc(e))return;let i=j(e.field)??j(e.name);i&&n.push({name:i,path:`${t}.${j(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 Bc(e,t){if(typeof e==`string`){let n=e.trim().split(/\s+/)[0];return n?[{name:n,path:t}]:[]}return M(e,t)}var Vc={"record:highlights":{props:[`fields`]},"record:details":{props:[`fields`,`hideFields`],nestedSections:[`sections`]},"record:path":{props:[`statusField`]},"element:number":{props:[`field`]},"element:record_picker":{props:[`labelField`]}},Hc=`record:related_list`;function Uc(e,t,n,r=`.`){let i=Vc[e];if(!i)return null;let a=[];for(let e of i.props??[])a.push(...M(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];zc(o)&&a.push(...M(o.fields,`${n}${r}${e}[${t}].fields`))}}return a}function Wc(e,t,n,r=`.`){let i=Vc[e];if(!i)return null;let a=[];for(let e of i.nestedSections??[])a.push(...Pc(t[e],`${n}${r}${e}`,r));return a}function Gc(e,t,n=`.`){let r=zc(e.add)?e.add:void 0,i=r&&zc(r.picker)?r.picker:void 0,a=e=>`${t}${n}${e}`;return{relatedObject:j(e.objectName),related:[...M(e.columns,a(`columns`)),...Bc(e.sort,a(`sort`)),...M(e.filter,a(`filter`)),...M(e.relationshipField,a(`relationshipField`)),...r?M(r.linkField,a(`add.linkField`)):[]],parent:M(e.relationshipValueField,a(`relationshipValueField`)),pickerObject:i?j(i.object):void 0,picker:i?[...M(i.valueField,a(`add.picker.valueField`)),...M(i.labelField,a(`add.picker.labelField`))]:[]}}function Kc(e){let t=new Map;if(!zc(e))return t;for(let n of T(e.objects)){let e=j(n.name);if(!e)continue;let r=new Set;for(let e of T(n.fields)){let t=j(e.name);t&&r.add(t)}t.set(e,r)}return t}function qc(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)||Mn.has(n.name)){c?.has(n.name)&&o.push({severity:`warning`,rule:Lc,where:r,path:n.path,message:`field "${n.name}" resolves on object "${t}", but ${Rn(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:zn(t,n.name)});continue}o.push({severity:i===`queried`?`error`:`warning`,rule:Ic,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 Jc(e){let t=[];if(!e||typeof e!=`object`)return t;let n=Kc(e),r=Ln(e),i=Nc(e),a=T(e.pages);for(let e=0;e<a.length;e++){let o=a[e];if(!o||typeof o!=`object`)continue;let s=j(o.name)??`#${e}`,c=(e,i,a)=>{t.push(...qc(e,i,n,a,`skipped`,r))};for(let{component:n,path:r,objectName:a}of Ac(o,`pages[${e}]`)){let e=j(n.type),o=zc(n.properties)?n.properties:void 0;if(!e||!o)continue;let l=`page "${s}" \xB7 ${e}`,u=`${r}.properties`;if(e===Hc){let e=Gc(o,u);c(e.related,e.relatedObject,l),c(e.parent,a,l),c(e.picker,e.pickerObject,l);continue}let d=Uc(e,o,u);d&&(c(d,a,l),t.push(...Fc(Wc(e,o,u)??[],a,i,l,Rc)))}let l=zc(o.interfaceConfig)?o.interfaceConfig:void 0;if(l){let t=j(l.source)??j(o.object),n=`pages[${e}].interfaceConfig`,r=[...M(l.columns,`${n}.columns`),...Bc(l.sort,`${n}.sort`),...M(l.filterBy,`${n}.filterBy`)],i=zc(l.userFilters)?l.userFilters:void 0;i&&r.push(...M(i.fields,`${n}.userFilters.fields`)),c(r,t,`page "${s}" \xB7 interfaceConfig`)}}return t}var Yc=e=>!!e&&typeof e==`object`&&!Array.isArray(e),Xc=(e,t)=>{let n=e;for(let e of t){if(!Yc(n)&&!Array.isArray(n))return;n=n[e]}return n},Zc=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 Qc(e,t,n=0){let r=n===0?Xc(t,e.path):void 0,i=n>0||e.code===`custom`||e.message.includes(`received `)?``:r===void 0?` (nothing is set there)`:` (received ${Zc(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 `:``}${Qc(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 $c=null;function el(){if($c)return $c;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{$c=(0,C.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 $c}var tl=new Map(ne.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(Ie[e.tag]??{})),requiredDescriptions:new Map(e.interactions.filter(e=>e.required).map(e=>[e.name,e.description]))}]));function nl(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 rl(e,t){if(t.has(e))return null;let n=null,r=3;for(let i of t){let t=nl(e,i);t<r&&(r=t,n=i)}return r<=2?n:null}var N=Symbol(`not-static`);function il(e,t,n){if(!n)return N;if(e.isParenthesizedExpression(n))return il(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=il(e,t,i);if(n===N)return N;r.push(n)}return r}if(e.isObjectLiteralExpression(n)){let r={};for(let i of n.properties){if(!e.isPropertyAssignment(i))return N;let n=e.isIdentifier(i.name)||e.isStringLiteral(i.name)?i.name.text:null;if(n===null)return N;let a=il(e,t,i.initializer);if(a===N)return N;r[n]=a}return r}return N}function al(e,t,n){let r=n.initializer;return r?e.isStringLiteral(r)?r.text:e.isJsxExpression(r)?il(e,t,r.expression):N:!0}function ol(e,t,n){let r=n.initializer;if(!r||!e.isJsxExpression(r))return N;let i=n=>n?e.isParenthesizedExpression(n)?i(n.expression):e.isArrayLiteralExpression(n)?n.elements.map(e=>i(e)):il(e,t,n):N;return i(r.expression)}var sl=`react-page-source-unparseable`,cl=`react-prop-deprecated`,ll=`react-prop-retired`,ul=`react-chart-field-unknown`,dl=`react-chart-field-unprovisioned`,fl=`react-chart-aggregate-invalid`,pl=`react-chart-axis-unknown`,ml=`react-chart-drilldown-invalid`;function hl(e,t){if(e===void 0||e===N)return;if(!P(e)){t(`error`,ml,`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=Ze.safeParse(e);if(!n.success)for(let e of n.error.issues)t(`error`,ml,`${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 gl(e,t){if(e===void 0||e===N)return;if(!P(e)){t(`error`,fl,`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`,fl,`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=Ct.safeParse(e);if(!r.success)for(let i of r.error.issues)n&&i.path[0]===`groupBy`||t(`error`,fl,`${i.path.length?`aggregate.${i.path.join(`.`)}`:`aggregate`}: ${Qc(i,e)}`,`The aggregate is declared by ChartAggregateSchema (@objectstack/spec/ui) — the rejection above carries the fix.`)}var P=e=>!!e&&typeof e==`object`&&!Array.isArray(e),F=e=>typeof e==`string`&&e.length>0?e:void 0;function _l(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(hl(i.get(`drillDown`),s),i.has(`data`))return;let c=i.get(`aggregate`);if(gl(c,s),c===void 0||c===N||!P(c))return;let l=F(c.function),u=F(c.field),d=c.groupBy,f=F(d)??(P(d)?F(d.field):void 0),p=F(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)||Mn.has(t)){e?.has(t)&&s(`warning`,dl,`aggregate.${n} "${t}" resolves on object "${p}", but ${Rn(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.`,zn(p,t));return}s(`error`,ul,`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=Lt({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`,pl,`"${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=F(i.get(`xAxisKey`))??F(v)??(P(v)?F(v.field):void 0),b=i.has(`xAxisKey`)?`xAxisKey`:`xAxis.field`;_(y,b);let ee=i.get(`yAxis`),x=Array.isArray(ee)?ee:ee===void 0?[]:[ee];for(let e of x)_(F(e)??(P(e)?F(e.field):void 0),`yAxis[].field`);let te=i.get(`series`);if(Array.isArray(te))for(let e of te){if(!P(e))continue;let t=F(e.dataKey);_(t??F(e.name),t?`series[].dataKey`:`series[].name`)}y&&h.category&&y!==h.category&&y===h.value&&s(`error`,pl,`${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 vl={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`]}},yl=` › `,bl=new Map(ne.map(e=>[e.tag,e.schemaType])),xl=new Set(Object.values(vl).flatMap(e=>e.filterArrays??[]));function Sl(e){let t={};for(let[n,r]of e)r!==N&&(t[n]=r);return t}function Cl(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(!P(a))continue;let o=e=>`${t}[${i}].${e}`;n.push({objectName:F(a.childObject),refs:[...M(a.columns,o(`columns`)),...M(a.relationshipField,o(`relationshipField`)),...M(a.amountField,o(`amountField`))]}),r.push(...M(a.totalField,o(`totalField`)))}return{child:n,parent:r}}function wl(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++)wl(e[r],`${t}[${r}]`,n);return}if(Array.isArray(r)){for(let r=0;r<e.length;r++)wl(e[r],`${t}[${r}]`,n);return}typeof r==`string`&&r.length>0&&e.length>=2&&typeof e[1]==`string`&&nt.has(e[1].toLowerCase())&&n.push({name:r,path:`${t}[0]`})}function Tl(e,t,n){let r=[],i=[],a=e=>{let n=t.get(e);return n===N?void 0:n},o=e=>`${n}${yl}${e}`;for(let t of e.fields??[])r.push(...M(a(t),o(t)));for(let t of e.sorts??[])r.push(...Bc(a(t),o(t)));for(let t of e.nestedFields??[]){let e=a(t);P(e)&&r.push(...M(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];P(i)&&r.push(...M(i.fields,o(`${t}[${n}].fields`)))}}for(let t of e.keyedByField??[]){let e=a(t);if(P(e))for(let n of Object.keys(e))r.push({name:n,path:o(`${t}.${n}`)})}for(let n of e.filterArrays??[])wl(t.get(n),o(n),i);return{own:r,queried:i}}function El(e,t){if(e!==`ListView`)return F(t.get(`objectName`));let n=t.get(`data`);return P(n)&&n.provider===`object`?F(n.object):void 0}function Dl(e,t,n,r,i,a){let o=El(e,t),s=[],c=vl[e];if(c){let{own:e,queried:l}=Tl(c,t,i);s.push(...qc(e,o,n,r,`skipped`,a)),s.push(...qc(l,o,n,r,`queried`,a))}if(e===`ObjectForm`){let e=t.get(`subforms`),c=Cl(e===N?void 0:e,`${i}${yl}subforms`);for(let e of c.child)s.push(...qc(e.refs,e.objectName,n,r,`skipped`,a));s.push(...qc(c.parent,o,n,r,`skipped`,a))}let l=e===`Block`?F(t.get(`type`)):bl.get(e);return l&&Vc[l]&&s.push(...qc(Uc(l,Sl(t),i,yl)??[],o,n,r,`skipped`,a)),s}var Ol=`react-block-needs-record-context`,kl="author the page as `type:'record'` — a record page mounts the record context these blocks render from.";function Al(e,t,n,r){return{severity:`error`,rule:Ol,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: ${Be[t]??kl}`}}function jl(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 Ml(e){let t=[],n=Kc(e),r=Ln(e),i=Sc(e);for(let{rec:a,path:o}of k(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=el(),{sourceFile:l,failure:u}=ra(c,`page.tsx`,e,{target:c.ScriptTarget.Latest,setParentNodes:!0,scriptKind:c.ScriptKind.TSX});u&&t.push({severity:`warning`,rule:sl,where:`page "${s}"`,path:`${o}.source`,message:`kind:'react' source did not parse (${ia(u)}), so the component-contract checks read a partially recovered tree and may have missed real problems.`,hint:aa});let d=jl(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=Ue.get(a);if(m&&!d.has(a)){t.push(Al(a,m,u,p)),c.forEachChild(e,f);return}let h=tl.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,xl.has(e)?ol(c,l,t):al(c,l,t))}}if(a===`Block`){let n=F(d.get(`type`));if(n&&se(n)){t.push(Al(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:ll,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:cl,where:u,path:p,message:`<${a}> prop "${e}" is the deprecated spelling of the metadata-tier "${r.replacedBy}" and is removed after the deprecation window (#11284).`,hint:r.note});let i=rl(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&&_l({values:d,where:u,path:p},n,t,r),a===`ListView`&&!o&&t.push(...Cc(d.get(`searchableFields`),El(a,d),i,u,`${p} \u203A searchableFields`,`searchableFields`,`narrowing`,r)),o||t.push(...Dl(a,d,n,u,p,r))}}c.forEachChild(e,f)};f(l)}return t}var Nl=`page-source-className-tailwind`,Pl=/\bclassName\s*=\s*["'{]/g;function Fl(e){let t=[];for(let{rec:n,path:r}of k(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);Pl.lastIndex=0;let o=0;for(;Pl.exec(i)!==null;)o++;o!==0&&t.push({severity:`warning`,rule:Nl,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 Il=`title-format-retired`,Ll=`title-unresolvable`;function Rl(e){let t=[],n=T(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:Il,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.`}),_e(r).status===`none`&&t.push({severity:`warning`,rule:Ll,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 zl=`field-group-undeclared`,Bl=`field-group-empty`,Vl=`field-group-shadowed`,Hl=`semantic-role-field-unknown`,Ul=`semantic-role-field-unprovisioned`;function Wl(e){let t=[],n=T(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),...Nn(r)]),l=Fn(r),u=(e,t)=>({severity:`warning`,rule:Ul,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:zl,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:Bl,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:Hl,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:Vl,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 Gl(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Kl(e){return typeof e==`string`&&e.length>0?e:void 0}function ql(e){return Kl(e.objectName)??Kl(e.object)??(Gl(e.data)?Kl(e.data.object):void 0)}function Jl(e,t){if(!Gl(e))return[];let n=[{view:e,path:t,surface:``,kind:`self`}];Gl(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(!Gl(i))continue;let a=r===`listViews`?`listView`:`formView`;for(let[e,o]of Object.entries(i))Gl(o)&&n.push({view:o,path:`${t}.${r}.${e}`,surface:`${r}.${e}`,kind:a})}return n}function Yl(e,t){return Jl(e,t).filter(e=>e.kind!==`listView`)}var Xl=`form-field-unknown`,Zl=`form-section-group-unknown`;function Ql(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function $l(e){return typeof e==`string`&&e.length>0?e:void 0}function eu(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 tu(e){let t=[],n=new Map;for(let t of T(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=Nc(e);for(let{rec:i,path:a}of k(e.views,`views`)){let e=$l(i.name)??$l(i.object)??a,o=ql(i),s=Ql(i.list)?ql(i.list)??o:void 0;for(let c of Yl(i,a)){let i=ql(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(...Fc(Pc(o,`${c.path}.${n}`),i,r,l,Zl));for(let r=0;r<o.length;r++){let s=o[r],u=Ql(s)&&Array.isArray(s.fields)?s.fields:[];for(let o=0;o<u.length;o++){let s=u[o],d=eu(s),f=`${c.path}.${n}[${r}].fields[${o}]`;d&&a&&!a.has(d)&&t.push({severity:`warning`,rule:Xl,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 nu(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}var ru=new Set([`==`,`!=`]),iu=new Set([`all`,`exists`,`exists_one`,`map`,`filter`]);function au(e){return nu(e)&&e.op===`id`&&typeof e.args==`string`?e.args:null}function ou(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(!nu(e))return;let a=e.args;if(e.op===`rcall`&&Array.isArray(a)&&typeof a[0]==`string`&&iu.has(a[0])){r(a[1],i),r(a[2],!1);return}if(typeof e.op==`string`&&ru.has(e.op)&&Array.isArray(a)&&a.length===2){let e=i?au(a[1]):null;if(r(a[0],i),e!==null){t.add(e);return}r(a[1],i);return}let o=au(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 su(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function cu(e){let t=e.data;if(su(t)&&t.provider===`schema`)return typeof t.schemaId==`string`?t.schemaId:void 0}var lu=`visibility-root-mislayered`,uu=`visibility-bare-identifier`,du=`visibility-predicate-syntax`,fu=`visibility-predicate-over-budget`,pu=`visibility-predicate-unknown-function`,mu=`visibleWhen`;function hu(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`&&typeof e.source==`string`)return e.source}function gu(e,t){return RegExp(`(^|[^.\\w$])${t}\\.\\w`).test(e)}function _u(e){return e.replace(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g,e=>` `.repeat(e.length))}var vu=[{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 yu(e){let t=e.replace(/\s+/g,` `).trim();return t.length>120?`${t.slice(0,117)}...`:t}function bu(e){if(!e.trim())return null;let t=Ft(e);if(t.ok||t.kind===`empty`)return null;if(t.kind===`bounds`)return{kind:`bounds`,overrun:t.overrun};let n=yt(e),r=n.ok?`the expression could not be parsed`:n.error.split(`
6
- `)[0].trim(),i=_u(e);return{kind:`syntax`,detail:r,token:vu.find(e=>e.re.test(i))??null}}function xu(e){return e.limit&&e.limitValue!==null?`the \`${e.limit}\` budget (platform limit ${e.limitValue})`:`one of the platform's parse budgets`}var Su=[`current_user`,`page`];function Cu(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function wu(e,t){if(Array.isArray(e)){for(let n of e)wu(n,t);return}if(!Cu(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`)&&Cu(r)&&r.op===`id`&&typeof r.args==`string`&&t.add(r.args)}wu(n,t)}var Tu=`true`;function Eu(e,t,n){if(Array.isArray(e)){for(let r of e)if(!Eu(r,t,n))return!1;return!0}if(!Cu(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<Tu.length||!t.slice(a,o).startsWith(`has`)?!1:(n.push([a,o]),!0)}return Eu(r,t,n)}function Du(e,t){let n=[];if(!Eu(t,e,n)||n.length===0)return e;let r=e;for(let[e,t]of n)r=r.slice(0,e)+Tu.padEnd(t-e,` `)+r.slice(t);return r}function Ou(e,t){let n=Ke(e);if(!n)return null;let r=new Set;wu(n,r);let i=t?ou(n):[];return at(Du(e,n),[...Su,...r,...i])}var ku={runtime:`record`,metadata:`data`},Au={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 ju(e,t,n,r,i,a=!1){let o=hu(e[mu]??e.visibleOn??e.visibility),s=Au[r];o&&gu(o,s.forbiddenRoot)&&i.push({severity:`warning`,rule:lu,where:t,path:n,message:s.message,hint:s.hint});let c=o?bu(o):null;if(o&&c?.kind===`bounds`){let e=xu(c.overrun),a=ku[r];i.push({severity:`error`,rule:fu,where:t,path:n,message:`visibility predicate is syntactically valid CEL but overruns ${e} (${c.overrun.summary}) (predicate: \`${yu(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:du,where:t,path:n,message:`visibility predicate is not valid CEL \u2014 ${c.detail} (predicate: \`${yu(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?Et(o):null;if(o&&l&&i.push({severity:`error`,rule:pu,where:t,path:n,message:`visibility predicate calls \`${l.name}\`, which the platform's CEL environment does not register \u2014 ${l.detail} (predicate: \`${yu(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=Ou(o,a);if(e){let a=ku[r];i.push({severity:`error`,rule:uu,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 Mu(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Nu(e,t={}){let n=t.layer??`runtime`,r=[];for(let{rec:t,path:i}of k(e.views,`views`)){let e=typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:i;for(let a of Yl(t,i)){let t=a.surface?`view "${e}" \xB7 ${a.surface}`:`view "${e}"`,i=cu(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}]`;ju(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];Mu(n)&&ju(n,t,`${l}.fields[${e}]`,s,r,o)}}}}}for(let{rec:t,path:i}of k(e.pages,`pages`)){let e=`page "${(typeof t.name==`string`?t.name:void 0)??i}"`;for(let a of Ac(t,i))ju(a.component,e,a.path,n,r)}return r}var Pu=`predicate-path-unresolved`,Fu=`predicate-path-unrooted`,Iu=`predicate-rhs-path-shaped`,Lu=[`visibleWhen`,`visibleOn`],I=`data`;function Ru(e){if(!e||typeof e!=`object`&&typeof e!=`function`)return;let t=e;return t.def??t._def}function zu(e,t=0){if(!e||t>25)return e;let n=Ru(e);if(!n)return e;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`readonly`:case`catch`:case`nonoptional`:return zu(n.innerType,t+1);case`lazy`:return zu(n.getter(),t+1);case`pipe`:{let e=zu(n.in,t+1);return Ru(e)?.type===`transform`?zu(n.out,t+1):e}default:return e}}function Bu(e){return Array.isArray(e?.options)?e.options:[]}function Vu(e,t=0){if(t>25)return null;let n=zu(e),r=Ru(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 Bu(r)){let r=Vu(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=Vu(r.left,t+1),n=Vu(r.right,t+1);return!e&&!n?null:[...new Set([...e??[],...n??[]])]}return null}function Hu(e,t,n=0){if(n>25)return;let r=zu(e),i=Ru(r);if(i?.type===`object`)return(i.shape??r.shape??{})[t];if(i?.type===`union`||i?.type===`discriminated_union`)for(let e of Bu(i)){let r=Hu(e,t,n+1);if(r!==void 0)return r}if(i?.type===`intersection`)return Hu(i.left,t,n+1)??Hu(i.right,t,n+1)}function Uu(e,t){let n=Hu(e,t);if(n===void 0)return;let r=zu(n);for(let e=0;e<25;e++){let e=Ru(r);if(e?.type===`array`)r=zu(e.element);else if(e?.type===`record`)r=zu(e.valueType);else return r}return r}function Wu(e,t){let n=zu(e),r=Ru(n);if(r?.type===`record`)return{kind:`declared`,next:r.valueType};let i=Vu(n);return i===null?{kind:`opaque`}:i.includes(t)?{kind:`declared`,next:Hu(n,t)}:{kind:`undeclared`,declared:i}}function Gu(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function Ku(e){if(!Gu(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=Ku(e.args[0]);return t?[...t,e.args[1]]:null}return null}function qu(e,t){if(Array.isArray(e)){for(let n of e)qu(n,t);return}if(Gu(e)){if(e.op===`.`){let n=Ku(e);if(n&&n[0]===I&&n.length>1){t.push(n.slice(1));return}}qu(e.args,t)}}var Ju=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/;function Yu(e,t){if(Array.isArray(e)){for(let n of e)Yu(n,t);return}if(!Gu(e))return;let n=e.args;if(e.op===`rcall`&&Array.isArray(n)&&typeof n[0]==`string`&&iu.has(n[0])){Yu(n[1],t);return}typeof e.op==`string`&&ru.has(e.op)&&Array.isArray(n)&&n.length===2&&t.push({op:e.op,right:n[1]}),Yu(n,t)}function Xu(e,t,n){if(Array.isArray(e)){for(let r of e)Xu(r,t,n);return}if(!Gu(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`)&&Gu(t)&&t.op===`id`&&typeof t.args==`string`&&n.add(t.args),e.op===`rcall`&&typeof r[0]==`string`&&iu.has(r[0])){let e=r[2];if(Array.isArray(e)&&e.length>=2){let t=e[0];Gu(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}Xu(r,t,n)}function Zu(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`&&typeof e.source==`string`)return e.source}function Qu(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function $u(e,t,n,r,i){let a=Ke(e);if(!a)return;let o=[];qu(a,o);for(let e of o){let a=t,o=[];for(let t of e){let e=Wu(a,t);if(e.kind===`opaque`)break;if(e.kind===`undeclared`){let a=[I,...o,t].join(`.`),s=o.length?`${I}.${o.join(`.`)}`:I;i.push({severity:`error`,rule:Pu,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:`${ye(He(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=Vu(t),c=ou(a);if(s){let e=new Set,t=new Set;Xu(a,e,t);for(let a of e)t.has(a)||c.has(a)||!s.includes(a)||i.push({severity:`error`,rule:Fu,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 \`${I}\` 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 \`${I}.${a}\` instead of \`${a}\`. A metadata-editing form binds the row under edit as \`${I}\` at every depth \u2014 inside a repeater \`${I}\` is the ROW, but it is still spelled \`${I}\` (there is no implicit row scope).`})}let l=[];Yu(a,l);for(let{op:e,right:t}of l){let a=Ku(t);if(!a)continue;let o=a.join(`.`);if(!Ju.test(o))continue;let s=a.length>1;i.push({severity:s?`error`:`warning`,rule:Iu,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 \`${I}.\` 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 \`${I}.${o}\`, move it to the LEFT and put a literal on the right, e.g. \`${I}.${o} == 'yes'\`. \u26D4 Do NOT simply add the root in place: \`${e} ${I}.${o}\` is a path on the RIGHT, which this surface parses as the literal string "${I}.${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 ed(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(!Qu(s))continue;let c=`${r}[${o}]`;for(let e of Lu){let r=Zu(s[e]);if(r!==void 0&&r.trim()){$u(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:Uu(t,s.field);ed(s.fields,e,n,`${c}.fields`,i,a+1)}}}function td(e,t={}){let n=t.resolveSchema??(e=>xt(e)),r=[];for(let{rec:t,path:i}of k(e.views,`views`)){let e=typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:i;for(let a of Yl(t,i)){let t=cu(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(!Qu(s))continue;let c=`${a.path}.${e}[${n}]`;for(let e of Lu){let t=Zu(s[e]);if(t!==void 0&&t.trim()){$u(t,i,o,`${c}.${e}`,r);break}}ed(s.fields,i,o,`${c}.fields`,r,0)}}}}return r}var nd=`capability-reference-unknown`;function rd(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function id(e){if(Array.isArray(e))return rd(e).map(e=>({cap:e}));if(e&&typeof e==`object`){let t=[];for(let[n,r]of Object.entries(e))for(let e of rd(r))t.push({cap:e,key:n});return t}return[]}function ad(e){let t=[];if(!e||typeof e!=`object`)return t;let n=new Set(d);for(let t of T(e.capabilities))typeof t.name==`string`&&t.name.length>0&&n.add(t.name);for(let t of T(e.permissions))for(let e of rd(t.systemPermissions))n.add(e);for(let t of T(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:nd,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=T(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 id(t.requiredPermissions))r(e,`object "${n}"`,`${a}.requiredPermissions${i?`.${i}`:``}`);let o=T(t.fields);for(let e of o){let t=typeof e.name==`string`?e.name:`(field)`;for(let i of rd(e.requiredPermissions))r(i,`field "${n}.${t}"`,`${a}.fields.${t}.requiredPermissions`)}for(let[e,i]of T(t.actions).entries()){let t=typeof i.name==`string`?i.name:`(action ${e})`;for(let o of rd(i.requiredPermissions))r(o,`action "${n}.${t}"`,`${a}.actions[${e}].requiredPermissions`)}}for(let[t,n]of T(e.actions).entries()){let e=typeof n.name==`string`?n.name:`(action ${t})`;for(let i of rd(n.requiredPermissions))r(i,`action "${e}"`,`actions[${t}].requiredPermissions`)}let a=T(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 rd(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 od=`approval-approver-not-membership-tier`,sd=`approval-approver-type-deprecated`,cd=`approval-approver-type-unknown`,ld=`approval-approver-type-unsupported`,ud=`approval-escalation-reassign-no-target`,dd=`approval-approvers-may-resolve-empty`,fd=`approval-expression-invalid`,pd=`approval-expression-no-empty-policy`,md=`approval-decision-outputs-reserved`,hd=`approval-approver-cross-org-unsupported`,gd=new Set([`current`,`trigger`,`vars`]),_d=new Set([`decision`,`requestId`]),vd=new Set([`position`,`team`,`department`]),yd=`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.`,bd=`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.`,xd=new Set(Ne),Sd=Ne.join(`/`),Cd={business_unit:`department`,bu:`department`};function wd(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 Td(e){let t=[];if(!e||typeof e!=`object`)return t;let n=T(e.flows),r=new Set(_t.options),i=wd(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=co(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})`,l=n.config??{},d=Array.isArray(l.approvers)?l.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=Cd[i];t.push({severity:`warning`,rule:cd,where:f,path:`${s}.type`,message:`approver type '${i}' is not an ApproverType (${_t.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=Ee(i);if(c===`expression`){let e=o.trim();if(!e)t.push({severity:`error`,rule:fd,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=yt(e);if(!n.ok)t.push({severity:`error`,rule:fd,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=>!gd.has(e));if(e.length){let n=e.includes(`record`)||e.includes(`previous`);t.push({severity:`error`,rule:fd,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:fd,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&&!xd.has(o.toLowerCase()))t.push({severity:`warning`,rule:od,where:f,path:`${s}.value`,message:`approver { type: '${i}', value: '${o}' } resolves against the better-auth org-membership tier (sys_member.role: ${Sd}) \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 (${Sd}) \u2014 the vocabulary is closed (ADR-0108), so a business role is always a position.`});else if(i in it){let e=Ee(i);t.push({severity:`warning`,rule:sd,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 qe[c]?.source===`unsupported`&&t.push({severity:`warning`,rule:ld,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()!==``&&_t.options.includes(c)&&!Ye(c)&&t.push({severity:`error`,rule:hd,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=>vd.has(Ee(String(e.type))))){let e=l.lockRecord!==!1;t.push({severity:`info`,rule:dd,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=>Ee(String(e.type))===`manager`)){let e=l.lockRecord!==!1;t.push({severity:`info`,rule:dd,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:`${yd} ${bd} 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`&&Ee(String(e.type??``))===`expression`)&&l.onEmptyApprovers==null&&t.push({severity:`info`,rule:pd,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=u(l.decisionOutputs).map(e=>e.key).filter(e=>_d.has(e));m.length&&t.push({severity:`error`,rule:md,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=l.escalation??null;h&&typeof h==`object`&&h.action===`reassign`&&(typeof h.escalateTo==`string`&&h.escalateTo.trim()||t.push({severity:`warning`,rule:ud,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 Ed=`seed-insert-mode-duplicates-on-replay`;function Dd(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:Ed,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 Od=`seed-value-outside-state-machine`;function kd(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 Ad(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 jd(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=kd(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:Od,where:`seed "${r}" (${Ad(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 Md=`security-owd-unset`,Nd=`security-owd-alias`,Pd=`security-external-wider-than-internal`,Fd=`security-wildcard-vama`,Id=`security-anchor-high-privilege`,Ld=`security-role-word`,Rd=`security-book-audience-unknown-set`,zd=`security-private-no-readscope`,Bd=`security-master-detail-ungranted`,Vd=`security-fls-unqualified-key`,Hd=`security-fls-unknown-field`,Ud=`security-grant-expired-at-authoring`,Wd=`security-delegation-missing-reason`,Gd=`security-controlled-by-parent-no-relation`,Kd=`security-controlled-by-parent-ambiguous-relation`,qd=[`private`,`public_read`,`public_read_write`,`controlled_by_parent`],Jd={read:`public_read`,read_write:`public_read_write`,full:`public_read_write`},Yd={public:`public_read_write`},Xd={...Jd,...Yd},Zd={private:0,public_read:1,public_read_write:2};function Qd(e){return e.sharingModel}function $d(e){return Jd[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 ef(e){return e.isSystem===!0||String(e.name??``).startsWith(`sys_`)}function tf(e){return typeof e==`string`&&e.toLowerCase().split(/[^a-z0-9]+/).some(e=>e===`role`||e===`roles`)}function nf(e){return typeof e==`string`&&/\brole(s)?\b/i.test(e)}function rf(e){return we({reference:e.reference},`validate-security-posture refOf`)}function af(e){for(let t of T(e.fields))if(t.type===`master_detail`)return{name:String(t.name??`?`),parent:rf(t)}}var of=[{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 sf(e){let t=T(e.fields);for(let{label:e,pred:n}of of){let r=t.filter(e=>n(e)&&rf(e));if(r.length>0)return{tier:e,candidates:r.map(e=>({field:String(e.name??`?`),type:String(e.type),master:rf(e)}))}}}function cf(e){return sf(e)?.candidates[0]}function lf(e){return e.allowRead===!0||e.allowCreate===!0||e.allowEdit===!0||e.allowDelete===!0||e.viewAllRecords===!0||e.modifyAllRecords===!0}function uf(e,t){let n=[];if(!e||typeof e!=`object`)return n;let r=T(e.objects),i=T(e.permissions),a=T(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=Qd(t),s=t.externalSharingModel;ef(t)||(o==null?n.push({severity:`error`,rule:Md,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`&&Xd[o]?n.push({severity:`error`,rule:Nd,where:`object "${i}"`,path:`${a}.sharingModel`,message:`sharingModel '${o}' ${$d(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: '${Xd[o]}'.`}):typeof o==`string`&&!qd.includes(o)&&n.push({severity:`error`,rule:Nd,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: ${qd.join(`, `)}.`})),o===`controlled_by_parent`&&!cf(t)&&n.push({severity:`error`,rule:Gd,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`?sf(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:Kd,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`&&(Xd[s]?n.push({severity:`error`,rule:Nd,where:`object "${i}"`,path:`${a}.externalSharingModel`,message:`externalSharingModel '${s}' ${$d(s)}.`,hint:`Replace with the canonical value: externalSharingModel: '${Xd[s]}'.`}):typeof o==`string`&&s in Zd&&o in Zd&&Zd[s]>Zd[o]&&n.push({severity:`error`,rule:Pd,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=Kn(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:{},u=t.fields&&typeof t.fields==`object`?t.fields:{};for(let e of Object.keys(u))e.includes(`.`)||n.push({severity:`error`,rule:Vd,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(u)){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:Hd,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 d=c[`*`];if(d&&(d.viewAllRecords===!0||d.modifyAllRecords===!0)&&n.push({severity:`error`,rule:Fd,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=l(t,`everyone`,o);e&&n.push({severity:`error`,rule:Id,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 T(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:Rd,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 u=new Set(r.filter(e=>e&&typeof e==`object`&&!ef(e)).filter(e=>{let t=Qd(e);return t==null||t===`private`}).map(e=>String(e.name??``)));if(u.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(!u.has(t))continue;let a=i??{};a.allowRead===!0&&a.readScope==null&&a.viewAllRecords!==!0&&n.push({severity:`info`,rule:zd,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=>lf(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!==`*`&&lf(r??{})&&e.add(t)}for(let t=0;t<r.length;t++){let i=r[t];if(!i||typeof i!=`object`||ef(i))continue;let a=typeof i.name==`string`?i.name:``;if(!a||e.has(a))continue;let o=af(i);if(!o)continue;let s=o.parent?` \u2192 "${o.parent}"`:``;n.push({severity:`warning`,rule:Bd,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 d=new Set([`sys_user_position`,`sys_user_permission_set`]),f=new Set([`sys_user_position`]),p=t?.nowMs??Date.now();for(let[t,r]of T(e.data).entries()){let e=typeof r.object==`string`?r.object:``;if(!d.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<=p)&&n.push({severity:`error`,rule:Ud,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(f.has(e)&&c!=null&&c!==``){let e=a.reason;(typeof e!=`string`||e.trim().length===0)&&n.push({severity:`error`,rule:Wd,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 df(e){let t=[];if(!e||typeof e!=`object`)return t;let n=T(e.objects),r=T(e.permissions),i=(e,n,r,i,a,o=`name`)=>{tf(n)?t.push({severity:`error`,rule:Ld,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').`}):nf(r)&&t.push({severity:`error`,rule:Ld,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`||ef(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 T(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 T(t.actions).entries())i(`action`,a.name,a.label,`action "${r}.${String(a.name??`?`)}"`,`objects[${e}].actions[${n}].name`);for(let[n,a]of T(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 T(e.positions).entries())i(`position`,n.name,n.label,`position "${String(n.name??t)}"`,`positions[${t}].name`);for(let[t,n]of T(e.apps).entries())i(`app`,n.name,n.label,`app "${String(n.name??t)}"`,`apps[${t}].name`);for(let[t,n]of T(e.books).entries())i(`book`,n.name,n.label,`book "${String(n.name??t)}"`,`books[${t}].name`);return t}var ff=`org-axis-permission-inheritance`,pf=`org-axis-cross-org-bu-grant`,mf=`parent_organization_id`,hf=new Set([`business_unit`,`unit_and_subordinates`]);function gf(e){return typeof e==`string`?e:``}function _f(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 vf(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 yf=`Remove the ${mf} 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 bf(e){let t=[],n=e??{};T(n.permissions).forEach((e,n)=>{T(e.rowLevelSecurity).forEach((r,i)=>{for(let a of[`using`,`check`])gf(r[a]).includes(mf)&&t.push({severity:`error`,rule:ff,where:`permission set "${gf(e.name)||n}" policy "${gf(r.name)||i}"`,path:`permissions[${n}].rowLevelSecurity[${i}].${a}`,message:`RLS ${a} reads \`${mf}\`, which builds a permission hierarchy along the organization axis. ADR-0105 D6 forbids it: the org tree is a REPORTING dimension only.`,hint:yf})})}),T(n.sharingRules).forEach((e,n)=>{let r=[{key:`condition`,text:_f(e.condition)},{key:`sharedWith`,text:JSON.stringify(e.sharedWith??``)??``}];for(let i of r)i.text.includes(mf)&&t.push({severity:`error`,rule:ff,where:`sharing rule "${gf(e.name)||n}"`,path:`sharingRules[${n}].${i.key}`,message:`Sharing rule ${i.key} reads \`${mf}\`, granting access by walking the organization tree. ADR-0105 D6 forbids permission inheritance along the org axis.`,hint:yf})});let r=new Set(T(n.objects).filter(e=>vf(e)).map(e=>gf(e.name)).filter(Boolean));return T(n.sharingRules).forEach((e,n)=>{let i=gf(e.object);if(!i||!r.has(i))return;let a=e.sharedWith,o=gf(a?.type);if(!hf.has(o))return;let s=o===`unit_and_subordinates`?`a business unit AND every descendant unit`:`a business unit`;t.push({severity:`error`,rule:pf,where:`sharing rule "${gf(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 xf=`rls-predicate-unenforceable`,Sf=`rls-predicate-unparseable`,Cf=`rls-predicate-over-budget`,wf=`rls-predicate-unknown-field`,Tf=`rls-predicate-unknown-user-variable`;function Ef(e){return typeof e==`string`?e:``}var Df="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 Of(e){let t=Ft(e);return!t.ok&&t.kind===`bounds`?t.overrun:null}function kf(e){return e.length>200?`${e.slice(0,197)}...`:e}var Af=" 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.",jf=" 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.",Mf='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). ',Nf='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 Pf(e,t=Mf){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."+Af: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."+jf}var Ff=new Set(Wt),If=[`__objectstack_lint_probe__`],Lf=`__objectstack_lint_probe__`,Rf={id:`userId`,organization_id:`tenantId`};function zf(e){let t=Rf[e]??e,n=Pe.shape[t];return n?n.safeParse(If).success?If:Lf:If}function Bf(e){let t=/variable "([^"]+)"/.exec(e);return t?t[1]:null}function Vf(){let e={};for(let t of Ff)e[t]=zf(t);return e}function Hf(e,t){return Mt(e,{variables:{current_user:t}})}function Uf(e,t,n){let r={...t};Wf(r,n,Lf);let i=Hf(e,r);return i.ok?!0:i.reason===`unresolved-variable`&&Bf(i.detail)!==n}function Wf(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 Gf(e){let t=e.split(`.`);return t.length===2&&t[0]===`current_user`&&Ff.has(t[1])}function Kf(e){let t=Vf(),n=[],r=(e=null)=>({filter:null,unresolvedScalars:n,probe:t,refusal:e});for(let i=0;i<32;i++){let i=Hf(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=Bf(i.detail);if(!a||!a.startsWith(`current_user.`)||Gf(a))return r();Uf(e,t,a)?(n.push(a),Wf(t,a,Lf)):Wf(t,a,If)}return r()}function qf(e,t){if(Array.isArray(e)){for(let n of e)qf(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):qf(r,t)}function Jf(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),qf(i,t))}};return n(e),t}var Yf=`${Lf}swap`;function Xf(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 Zf(e,t){let n=[];for(let e of Ff){let r=Array.isArray(t[e]),i=r?Yf:[Yf];n.push({variable:`current_user.${e}`,holds:r?`list`:`one value`,context:{...t,[e]:i},marker:i})}let r=Object.assign([Yf],t);n.push({variable:`current_user`,holds:`context object`,context:r,marker:r}),n.push({variable:`current_user`,holds:`context object`,context:Yf,marker:Yf});for(let t of n){let n=Mt(e,{variables:{current_user:t.context}});if(!n.ok)continue;let r=Xf(n.filter,(e,n)=>n===t.marker);if(r.length>0)return{variable:t.variable,holds:t.holds,sites:r}}return null}function Qf(e){return[...Ff].filter(t=>Array.isArray(zf(t))===(e===`list`)).sort()}var $f=new Map([[`$startsWith`,`startsWith`],[`$endsWith`,`endsWith`],[`$contains`,`contains`]]);function ep(e,t){let n=`record.${t.field}`,r=e.variable,i=$f.get(t.op),a=Qf(`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: `+Qf(`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: `+Qf(`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 tp={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."},np={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 rp(e,t,n){if(!Object.values(t).every(e=>typeof e==`string`||Array.isArray(e)))return null;try{return Ot(e,void 0,n),fe(e,void 0,n),null}catch(e){return e?.code===`INVALID_FILTER`?e instanceof Error?e.message:String(e):null}}var ip=new Map([[`$gt`,`>`],[`$gte`,`>=`],[`$lt`,`<`],[`$lte`,`<=`]]);function ap(e){return typeof e==`string`?JSON.stringify(e):String(e)}function op(e){let t=[];for(let n of Xf(e,(e,t)=>e===`$in`&&Array.isArray(t)&&t.includes(null)||ip.has(e)&&t===null)){let e=`record.${n.field}`;if(n.op===`$in`){let r=n.operand,i=`${e} in [${r.map(ap).join(`, `)}]`,a=r.filter(e=>e!==null);t.push(a.length===0?`replace \`${i}\` with \`${e} == null\``:`replace \`${i}\` with \`(${e} in [${a.map(ap).join(`, `)}] || ${e} == null)\` to keep matching a missing value, or drop the member: \`${e} in [${a.map(ap).join(`, `)}]\``)}else t.push(`replace \`${e} ${ip.get(n.op)} null\` with \`${e} != null\` (has a value) or \`${e} == null\` (has none), or compare against a real bound`)}return t}function sp(e){let t=e.indexOf(`. `);return t===-1?e:e.slice(0,t)}var cp='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. ',lp=new Map([[`$eq`,`==`],[`$ne`,`!=`],...ip]);function up(e){let t=e?.type;return t?xe.has(t)?`\`type: '${t}'\``:he({type:t,multiple:e.multiple===!0})?e.multiple===!0?`\`type: '${t}'\`, \`multiple: true\``:`\`type: '${t}'\``:null:null}function dp(e,t,n){let r=new Map,i=Xf(n,(e,t)=>lp.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=E(e,t,r),i=n?.kind===`ok`?up(n.meta):null;i&&a.push(`\`${r}\` is declared ${i}`)}if(a.length===0)continue;let o=`record.${n.field} ${lp.get(n.op)} record.${i}`;r.set(o,{written:o,columns:a})}return[...r.values()]}function fp(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 pp={numeric:`a number`,text:`text`,boolean:`a boolean`,date:`a date`,datetime:`a datetime`,time:`a time of day`},mp={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`},hp=m.map(e=>{let t=x.filter(t=>t.verdict.kind===`class`&&t.verdict.class===e).flatMap(e=>[...e.types]);return`${pp[e]} only with ${pp[e]} (${t.map(e=>`\`${e}\``).join(`, `)})`}).join(`; `);function gp(e,t,n){let r=E(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 _p(e,t){let n=`\`${e.name}\` is declared \`type: '${e.type}'\``;return t.kind===`class`?`${n}, compared as ${pp[t.class]}`:t.reason===`list-or-object`?n:`${n}, ${mp[t.reason]}`}function vp(e,t,n){let r=new Map,i=Xf(n,(e,t)=>lp.has(e)&&!!t&&typeof t==`object`&&!Array.isArray(t)&&typeof t.$field==`string`);for(let n of i){let i=n.operand.$field,a=gp(e,t,n.field),o=gp(e,t,i);if(!a||!o||up(a.meta)||up(o.meta))continue;let s=$e(a,o),c;if(s.verdict===`cross-class`)c=[_p(a,{kind:`class`,class:s.left}),_p(o,{kind:`class`,class:s.right})];else if(s.verdict===`no-class`)c=[...s.left.kind===`no-class`?[_p(a,s.left)]:[],...s.right.kind===`no-class`&&o.name!==a.name?[_p(o,s.right)]:[]];else continue;let l=`record.${n.field} ${lp.get(n.op)} record.${i}`;r.set(l,{written:l,columns:c})}return[...r.values()]}function yp(e){return e.map(e=>`\`${e.written}\`, where ${e.columns.join(` and `)}`).join(`; `)}var bp=`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 xp(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 Sp=`Compare a field only with a field of the same comparison class: ${hp}. 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 Cp(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."+Af: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."+jf}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."+Af: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."+jf+` ⚠️ 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 wp=new Set([`select`,`all`]);function Tp(e){let t={},n=!1;for(let[r,i]of Object.entries(e))Ff.has(r)?t[r]=i:(t[r]=[],n=!0);return{probe:t,rebound:n}}function Ep(e,t,n,r,i){let{probe:a,rebound:o}=Tp(i);if(!Object.values(a).every(e=>typeof e==`string`||Array.isArray(e)))return null;let s=r;if(o){let e=Hf(n,a);if(!e.ok)return null;s=e.filter}let c=e(t,s,{operation:`find`});return c.ok?null:c}var Dp=`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 Op(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 (${Qn(Ff)}). 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. "+Df}function kp(e,t,n,r,i,a,o){let s=[],c=Ht(t),{filter:l,unresolvedScalars:u,probe:d,refusal:f}=Kf(c);for(let o of Jf(l)){let c=E(e,a,o);if(Yn(c)||!c)continue;let l=Jn(c,o,`RLS ${n} predicate field`);l&&s.push({severity:`error`,rule:wf,where:r,path:i,message:`RLS ${n} \`${kf(t)}\` lowers correctly but does not name a real column: ${l.message} `+Cp(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:Tf,where:r,path:i,message:`RLS ${n} \`${kf(t)}\` reads \`${e}\`, which nothing pre-resolves. The kernel-resolved \`current_user\` keys are exactly ${Qn(Ff)}, 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. `+Cp(n,`variable`),hint:`Use one of the pre-resolved context values (${Qn(Ff)})${D(a,Ff)} \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:Zf(c,d);f!==null&&p&&s.push({severity:`error`,rule:xf,where:r,path:i,message:`RLS ${n} \`${kf(t)}\` passes the shape check, but the compiler refuses it for the value \`${p.variable}\` holds on every request (${f}). ${tp[p.holds](p.variable)} `+Pf(n,Nf),hint:`${np[p.holds]} In this predicate: ${p.sites.map(e=>ep(p,e)).join(`; `)}.`});let m=l?rp(l,d,n):null;if(l&&m!==null){let e=op(l);s.push({severity:`error`,rule:xf,where:r,path:i,message:`RLS ${n} \`${kf(t)}\` lowers, but to a comparand the platform's shared filter check refuses (${sp(m)}), ${Pf(n,cp)}`,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. `+Df})}let h=l?dp(e,a,l):[];h.length>0&&s.push({severity:`error`,rule:xf,where:r,path:i,message:`RLS ${n} \`${kf(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: `+fp(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?vp(e,a,l):[];g.length>0&&s.push({severity:`error`,rule:xf,where:r,path:i,message:`RLS ${n} \`${kf(t)}\` lowers, but compares two fields that share no comparison class: ${yp(g)}. ${bp}: ${xp(n)}`,hint:`${Sp} 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?Ep(o,a,c,l,d):null;return _&&s.push({severity:`error`,rule:xf,where:r,path:i,message:`RLS ${n} \`${kf(t)}\` lowers, but the engine refuses to run the lowered filter on "${a}" (${_.code} / ${_.status}): ${_.message} ${Dp}`,hint:Op(_.code)}),s}function Ap(e,t={}){let n=[],r=e??{},i=Kn(r);return T(r.permissions).forEach((e,r)=>{T(e.rowLevelSecurity).forEach((a,o)=>{for(let s of[`using`,`check`]){let c=Ef(a[s]);if(!c.trim())continue;let l=Ef(e.name)||String(r),u=Ef(a.name)||String(o),d=Ef(a.object),f=`permission set "${l}" policy "${u}"`+(d?` on object "${d}"`:``),p=`permissions[${r}].rowLevelSecurity[${o}].${s}`;if(lt(c)){let e=s===`using`&&d&&wp.has(Ef(a.operation))?t.judgeFilter:void 0;n.push(...kp(i,c,s,f,p,d,e));continue}let m=Ht(c),h=bt(m),g=h.ok?``:h.detail,_=!h.ok&&h.reason===`parse-error`,v=_?Of(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:Cf,where:y,path:b,message:`RLS ${s} \`${kf(c)}\` is syntactically valid, lowerable CEL but overruns the platform parse bound ${e}${t}${r} (${v.summary}), `+Pf(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:Sf,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}), `+Pf(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:xf,where:y,path:b,message:`RLS ${s} \`${c}\` is outside the pushdown subset the runtime can compile (${g}), `+Pf(s),hint:`Rewrite the predicate inside the lowerable subset. `+Df+" 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 jp=`sharing-rule-unlowerable-condition`,Mp=`sharing-rule-runtime-variable-condition`,Np=`sharing-rule-object-not-shareable`,Pp=`sharing-rule-object-controlled-by-parent`;function Fp(e){return typeof e==`string`?e:``}function Ip(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 Lp(e){let t=Ip(e);return typeof t==`string`?t:Fp(t?.source)}var Rp="The lowerable subset is: `==` `!=` `>` `<` `>=` `<=`, `in`, `&&` `||` `!`, `== null` / `!= null`, and the string methods `startsWith` / `endsWith` / `contains` — over SINGLE-column `record.<field>` paths (ADR-0058 D2).";function zp(e,t,n,r){let i=dp(e,t,n);return i.length===0?null:{severity:`error`,rule:jp,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 Bp(e,t,n,r){let i=vp(e,t,n);return i.length===0?null:{severity:`error`,rule:jp,where:r.where,path:r.path,message:`Sharing-rule condition \`${r.source}\` lowers, but compares two fields that share no comparison class: ${yp(i)}. ${bp}: 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:`${Sp} 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 Vp(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||Fp(e.name).startsWith(`sys_`))?`public`:`private`}function Hp(e){for(let t of T(e.fields))if(t.type===`master_detail`){let e=we({reference:t.reference},`validate-sharing-rule-enforceability masterOf`);if(e)return e}}function Up(e,t,n){let r=Fp(e.object);if(!r)return[];let i=n.get(r);if(!i)return[];let a=Fp(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=Hp(i);return[{severity:`error`,rule:Pp,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 Vp(i)===`public`?[{severity:`error`,rule:Np,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 Wp(e){let t=[],n=e??{},r=new Map;for(let e of T(n.objects)){let t=Fp(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=Kn({objects:[t]}),i.set(e,n)),n};return T(n.sharingRules).forEach((e,n)=>{Up(e,n,r).forEach(e=>t.push(e));let i=Ip(e.condition);if(i===null)return;let o=Fp(e.name)||String(n),s=Fp(e.object),c=`sharing rule "${o}"${s?` on object "${s}"`:``}`,l=`sharingRules[${n}].condition`,u=Lp(e.condition),d=Mt(i,{variables:{}});if(d.ok){let e=s?a(s):null,n=e?zp(e,s,d.filter,{where:c,path:l,source:u}):null;n&&t.push(n);let r=e?Bp(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:Mp,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:jp,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. `+Rp+" 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 Gp=`dashboard-action-target-undefined`,Kp=`dashboard-action-route-unresolved`;function L(e){return typeof e==`string`&&e.length>0?e:void 0}var qp={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 Jp(e){return L(e.name)??L(e.id)??L(e.object)??L(e.list?.data&&e.list.data.object)??L(e.form?.data&&e.form.data.object)}function Yp(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 T(e)){if(!r||typeof r!=`object`)continue;let e=n(r);e&&t.add(e)}};c(e.actions,t,e=>L(e.name)),c(e.apps,n,e=>L(e.name));for(let n of T(e.objects)){if(!n||typeof n!=`object`)continue;let e=L(n.name);e&&r.add(e),c(n.actions,t,e=>L(e.name))}c(e.reports,i,e=>L(e.name)),c(e.dashboards,a,e=>L(e.name)),c(e.pages,o,e=>L(e.name)),c(e.views,s,Jp);for(let e of r)s.add(e);return{actions:t,apps:n,objects:r,reports:i,dashboards:a,pages:o,views:s}}function Xp(e,t,n){return e===`modal`?n.pages.has(t):n.actions.has(t)}function Zp(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=qp[n[e]];if(!i)continue;let a=n[e+1];t[i].has(a)||r.push({collection:n[e],name:a})}return r}function Qp(e){let t=[];if(!e||typeof e!=`object`)return t;let n=T(e.dashboards);if(n.length===0)return t;let r=Yp(e),i=(e,n,i)=>{let a=L(e.actionUrl);if(!a||a.includes("${"))return;let o=L(e.actionType)??`url`;if(o===`script`||o===`modal`){if(Xp(o,a,r))return;t.push({severity:`error`,rule:Gp,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=Zp(a,r);for(let r of e)t.push({severity:`warning`,rule:Kp,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=L(t.name)??`(dashboard ${e})`,a=`dashboards[${e}]`,o=T(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 "${L(t.label)??L(t.actionUrl)??`#${e}`}"`,`${a}.header.actions[${e}].actionUrl`)}}return t}var $p=`filter-token-unknown`,em=pe.join(`}, {`),tm=[{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`}],nm=`record`;function rm(e){let t=e.type===void 0?nm:e.type;return t===nm?{recordInContext:!0,surface:`a record page`}:{recordInContext:!1,surface:`a page of type ${JSON.stringify(t)}`}}function im(e,t){let n=e.name??e.id;return typeof n==`string`&&n.length>0?n:`#${t}`}function am(e,t,n,r,i){return{severity:`error`,rule:$p,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 om(e,t,n,r,i,a){if(e!=null){if(typeof e==`string`){let a=vt(e);if(a?.kind===`record-context`&&!r.recordInContext)i.push(am(e,a.token,t,n,r));else if(a?.kind===`unknown`){let r=a.suggestion;i.push({severity:`error`,rule:$p,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&&ht(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 {${em}}; time-based values use date macros such as {today} or {30_days_ago}.`:`Resolvable placeholders are the context tokens {${em}} 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)=>om(e,`${t}[${o}]`,n,r,i,a));return}for(let[o,s]of Object.entries(e))om(s,`${t}.${o}`,n,r,i,a)}}}function sm(e){if(!e||typeof e!=`object`)return[];let t=[],n=e=>({value:n,path:r,where:i})=>{om(n,r,i,e,t,new Set)};for(let t of tm){if(t.kind===`page`){T(e[t.key]).forEach((e,r)=>{tr(e,`${t.key}[${r}]`,`${t.kind} "${im(e,r)}"`,n(rm(e)))});continue}nr(e,[t],n({recordInContext:!1,surface:t.noun}))}return t}var cm=`flow-filter-token-unknown`,lm=[{key:`flows`,kind:`flow`}];function um(e){if(Ci.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=wi.includes(t)?t:st(t,wi),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 ${wi.join(`, `)} \u2014 and, for a token the evaluator does not resolve, the filter placeholders ({current_user_id}, {today}, {30_days_ago}).${r}`}function dm(e,t,n,r,i){if(e!=null){if(typeof e==`string`){let i=vt(e);if(i?.kind!==`unknown`)return;let a=Ei(i.token);if(a.kind!==`unknown-function`)return;r.push({severity:`error`,rule:cm,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:um(a.name)});return}if(typeof e==`object`&&!i.has(e)){if(i.add(e),Array.isArray(e)){e.forEach((e,a)=>dm(e,`${t}[${a}]`,n,r,i));return}for(let[a,o]of Object.entries(e))dm(o,`${t}.${a}`,n,r,i)}}}function fm(e){if(!e||typeof e!=`object`)return[];let t=[];return nr(e,lm,({value:e,path:n,where:r})=>{dm(e,n,r,t,new Set)}),t}var pm=`filter-preset-comparand`,mm=[{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`}],hm=new Set([`$gt`,`$gte`,`$lt`,`$lte`]),gm=new Set([`>`,`>=`,`<`,`<=`]),_m=new Set([`greater_than`,`greater_than_or_equal`,`less_than`,`less_than_or_equal`,`before`,`after`]),vm=new Set([`$eq`,`$ne`]),ym=new Set([`$in`,`$nin`]),bm=new Set([`=`,`!=`]),xm=new Set([`in`,`nin`]),Sm=new Set([`equals`,`not_equals`]),Cm=new Set([`in`,`not_in`]),wm=new Set([`date`,`datetime`]),Tm=32;function Em(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&!(e instanceof Date)}function Dm(e){return typeof e==`string`&&e.length>0?e:void 0}function Om(e){let t=Dm(e);return t&&!t.includes(`{`)?t:void 0}function R(e,t,n,r){return{severity:`error`,rule:pm,where:e,path:t,message:dt(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 km=()=>!1;function Am(e,t){return t?n=>{let r=E(e,t,n);if(!r||r.kind!==`ok`)return!1;let i=r.meta?.type;return typeof i==`string`&&wm.has(i)}:km}function jm(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 Mm(e,t){let n=jm(t);if(!n||n.length<3)return null;let[r,i,...a]=n;if(typeof r!=`string`||typeof i!=`number`)return null;let o=T(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)||Em(c)?c[e]:void 0,Em(c))s.push({key:l,node:c});else if(!Array.isArray(c))break;return{collection:r,chain:s,filterKey:a[a.length-1]}}var Nm=`publicPicker`,Pm=`lookupFilters`,Fm=`interfaceConfig`;function Im(e,t,n,r){let i=Mm(e,t);if(i){if(i.filterKey===Pm){let e=i.chain[i.chain.length-1].node;return Object.prototype.hasOwnProperty.call(e,Pm)?Om(e.reference):void 0}return Lm(i.collection,i.chain,i.chain.length-1,n,r)}}function Lm(e,t,n,r,i){for(let a=n;a>=0;a--){let{key:n,node:o}=t[a],s=n===Nm?Dm(t[a-1]?.node.field):void 0;if(s){let n=Om(o.object);if(n)return n;let c=Lm(e,t,a-2,r,i);if(!c)return;let l=E(i,c,s);return l?.kind===`ok`?Dm(l.meta?.reference):void 0}if(e===`pages`&&a===1&&n===Fm){let e=Om(o.source);if(e)return e}let c=Om(o.object)??Om(o.objectName);if(c)return c;let l=Dm(o.dataset);if(l){let e=r.get(l);return e?Om(e.object):void 0}if(Em(o.data)){let e=o.data.provider;if(e!==void 0&&e!==`object`)return;let t=Om(o.data.object);if(t)return t}if(Em(o.config)){let e=Om(o.config.objectName)??Om(o.config.object);if(e)return e}if(Em(o.dataSource)){let e=Om(o.dataSource.object);if(e)return e}if(Em(o.properties)){let e=Om(o.properties.object)??Om(o.properties.objectName);if(e)return e}}if(e===`objects`)return Dm(t[0].node.name)}function Rm(e,t,n,r,i,a,o){if(!(i>Tm))for(let[s,c]of Object.entries(e)){let e=`${t}.${s}`;if(s===`$and`||s===`$or`){Array.isArray(c)&&c.forEach((t,s)=>{Em(t)&&Rm(t,`${e}[${s}]`,n,r,i+1,a,o)});continue}if(s===`$not`){Em(c)&&Rm(c,e,n,r,i+1,a,o);continue}if(s.startsWith(`$`))continue;let l=o?`${o}.${s}`:s;if(!Em(c)){S(c)&&a(l)&&r.push(R(n,e,c,`$eq`));continue}if(!Object.keys(c).some(e=>e.startsWith(`$`))){Rm(c,e,n,r,i+1,a,l);continue}for(let[t,i]of Object.entries(c)){if(hm.has(t)&&S(i)){r.push(R(n,`${e}.${t}`,i,t));continue}if(t===`$between`&&Array.isArray(i)){i.forEach((i,a)=>{S(i)&&r.push(R(n,`${e}.${t}[${a}]`,i,t))});continue}if(vm.has(t)&&S(i)&&a(l)){r.push(R(n,`${e}.${t}`,i,t));continue}ym.has(t)&&Array.isArray(i)&&a(l)&&i.forEach((i,a)=>{S(i)&&r.push(R(n,`${e}.${t}[${a}]`,i,t))})}}}function zm(e,t,n,r,i){let a=Ce(e.operator);if(typeof a!=`string`)return;let o=e.value;if(_m.has(a)&&S(o)){r.push(R(n,`${t}.value`,o,a));return}if(a===`between`&&Array.isArray(o)){o.forEach((e,i)=>{S(e)&&r.push(R(n,`${t}.value[${i}]`,e,a))});return}let s=Dm(e.field);if(s&&i(s)){if(Sm.has(a)&&S(o)){r.push(R(n,`${t}.value`,o,a));return}Cm.has(a)&&Array.isArray(o)&&o.forEach((e,i)=>{S(e)&&r.push(R(n,`${t}.value[${i}]`,e,a))})}}function Bm(e,t,n,r,i){let a=e[1];if(typeof a!=`string`)return;let o=St(a),s=e[2];if(gm.has(o)&&S(s)){r.push(R(n,`${t}[2]`,s,a));return}if(o===`between`&&Array.isArray(s)){s.forEach((e,i)=>{S(e)&&r.push(R(n,`${t}[2][${i}]`,e,a))});return}let c=Dm(e[0]);if(c&&i(c)){if(bm.has(o)&&S(s)){r.push(R(n,`${t}[2]`,s,a));return}xm.has(o)&&Array.isArray(s)&&s.forEach((e,i)=>{S(e)&&r.push(R(n,`${t}[2][${i}]`,e,a))})}}function Vm(e,t,n,r,i,a){if(!(i>Tm)){if(Array.isArray(e)){if(typeof e[0]==`string`&&typeof e[1]==`string`&&![`and`,`or`].includes(e[0].toLowerCase())&&nt.has(e[1].toLowerCase())){Bm(e,t,n,r,a);return}e.forEach((e,o)=>{typeof e!=`string`&&Vm(e,`${t}[${o}]`,n,r,i+1,a)});return}if(Em(e)){if(typeof e.field==`string`&&typeof e.operator==`string`){zm(e,t,n,r,a);return}Rm(e,t,n,r,i,a,``)}}}function Hm(e){if(!e||typeof e!=`object`)return[];let t=[],n=Kn(e),r=new Map;for(let t of T(e.datasets)){let e=Dm(t.name);e&&r.set(e,t)}return nr(e,mm,({value:i,path:a,where:o})=>{let s=Am(n,Im(e,a,r,n));Vm(i,a,o,t,0,s)}),t}var Um=`filter-empty-combinator`,Wm=`filter-empty-node`,Gm=[{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 Km(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var qm={$and:ce({$and:[]}),$or:ce({$or:[]}),$not:ce({$not:{}}),node:ce({}),orWithEmptyBranch:ce({$or:[{status:`open`},{}]})};function Jm(e){return e===`true`?`matches EVERY row`:e===`false`?`matches NO row`:`carries a real predicate`}var Ym="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.",Xm='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 Zm(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 ${Jm(qm.$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 ${Jm(qm.$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 ${Jm(qm.$not)} \u2014 the opposite of the "no filter" an empty operand looks like.`,a=e===`$and`?`${Xm} To express a constraint, put the conditions in the array. ${Ym}`:e===`$or`?`If you meant "no filter", this is its OPPOSITE: emptying the array does not relax the filter, it closes it. ${Xm} If you meant to offer alternatives, put the branches in the array. ${Ym}`:`Put the condition you are negating inside \`$not\` (\`{ $not: { status: 'closed' } }\`). ${Xm} ${Ym}`;n.out.push({severity:`error`,rule:Um,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 Qm(e,t,n){if(e===`root`){n.out.push({severity:`error`,rule:Wm,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 ${Jm(qm.node)}, exactly as if the key were absent \u2014 so a filter is declared and enforces nothing.`,hint:`${Xm} If you meant to constrain something, write the condition into the node. ${Ym}`});return}if(e===`or-branch`){n.out.push({severity:`error`,rule:Wm,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' }, {}] }\` ${Jm(qm.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:Wm,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 $m(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){Zm(r,`${t}.${r}`,n);continue}i.forEach((e,i)=>{eh(e,`${t}.${r}[${i}]`,r===`$and`?`and-branch`:`or-branch`,n)});continue}if(r===`$not`){if(!Km(i))continue;if(Object.keys(i).length===0){Zm(`$not`,`${t}.$not`,n);continue}$m(i,`${t}.$not`,n);continue}}}function eh(e,t,n,r){if(Km(e)){if(Object.keys(e).length===0){Qm(n,t,r);return}$m(e,t,r)}}function th(e){if(!e||typeof e!=`object`)return[];let t=[];return nr(e,Gm,({value:e,path:n,where:r})=>{eh(e,n,`root`,{where:r,out:t})}),t}var nh=[...i],rh=new Set([`lookup`,`master_detail`,`user`]),ih=`object-reference-unknown`,ah=`object-reference-unregistered-platform`;function z(e){return typeof e==`string`&&e.length>0?e:void 0}function oh(e){if(e.includes("${"))return!0;let t=e.indexOf(`{`);return t!==-1&&e.indexOf(`}`,t+2)!==-1}function sh(e){let t=[];for(let n of Hn(e)){let e=n.manifest;if(e&&typeof e==`object`&&!Array.isArray(e))for(let n of T(e.objects)){let e=z(n.name);e&&t.push(e)}}return t}function ch(e){let t=[];if(!e||typeof e!=`object`)return t;let n=T(e.objects),r=new Set;for(let e of n){let t=z(e.name);t&&r.add(t)}let i=new Set(r);for(let t of sh(e))i.add(t);let a=(e,n,r,a,o)=>{let s=z(e);if(s&&!oh(s)&&!i.has(s)&&!h(s)){if(Me(s)){t.push({severity:`warning`,rule:ah,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.`+D(s,nh),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:ih,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.`+D(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=z(t.name)??`#${e}`,i=T(t.fields);for(let t=0;t<i.length;t++){let n=i[t],o=z(n.type);if(!o||!rh.has(o))continue;let s=z(n.name)??`#${t}`;a(Ut(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=z(e.manifest?.namespace),s=T(e.views);for(let e=0;e<s.length;e++){let t=s[e],n=z(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 ${z(t.name)?`"${z(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=T(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 "${z(i.name)??z(i.field)??`#${e}`}"`;a(we({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(z(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=T(e.actions);for(let e=0;e<l.length;e++){let t=l[e];t&&typeof t==`object`&&c(t,`actions[${e}]`,`action "${z(t.name)??`#${e}`}"`)}for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`)continue;let r=z(t.name)??`#${e}`,i=T(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 "${z(n.name)??`#${t}`}"`)}}let u=T(e.dashboards);for(let e=0;e<u.length;e++){let t=u[e];if(!t||typeof t!=`object`)continue;let n=z(t.name)??`#${e}`,r=T(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(z(o.object),`dashboard "${n}" \xB7 filter "${z(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 d=T(e.datasets);for(let e=0;e<d.length;e++){let t=d[e];t&&typeof t==`object`&&a(z(t.object),`dataset "${z(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 f=T(e.apps);for(let e=0;e<f.length;e++){let t=f[e];if(!t||typeof t!=`object`)continue;let n=z(t.name)??`#${e}`,r=(e,t)=>{let i=T(e);for(let e=0;e<i.length;e++){let o=i[e];if(!o||typeof o!=`object`)continue;let s=z(o.id)??`#${e}`,c=`app "${n}" \xB7 nav "${s}"`,l=`${t}[${e}]`;a(z(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&&z(o.objectName)&&a(z(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=T(t.areas);for(let t=0;t<i.length;t++)r(i[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var lh=`nav-target-unresolved`,uh=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function dh(e){return typeof e==`string`&&e.length>0?e:void 0}var fh=e=>e.includes("${")||e.includes(`{`),ph=[[`page`,`pageName`,`pages`,`page`],[`report`,`reportName`,`reports`,`report`],[`dashboard`,`dashboardName`,`dashboards`,`dashboard`]];function mh(e){let t=new Set;for(let n of T(e)){let e=dh(n.name);e&&t.add(e)}return t}function hh(e){let t=[];if(!uh(e))return t;let n=T(e.apps);if(n.length===0)return t;let r=new Map;for(let[,,t]of ph)r.set(t,mh(e[t]));for(let[e,i]of n.entries()){let n=dh(i.name)??`#${e}`,a=(e,i)=>{if(Array.isArray(e))for(let[o,s]of e.entries()){if(!uh(s))continue;let e=s,c=`${i}[${o}]`;for(let[i,a,s,l]of ph){if(e.type!==i)continue;let u=dh(e[a]);if(!u||fh(u))continue;let d=r.get(s);if(d.has(u))continue;let f=d.size===0;t.push({severity:`warning`,rule:lh,where:`app "${n}" \xB7 nav "${dh(e.id)??dh(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 T(i.areas).entries())a(n.items,`apps[${e}].areas[${t}].items`),a(n.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var gh=`nav-object-unservable`,_h=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function vh(e){return typeof e==`string`&&e.length>0?e:void 0}var yh=e=>e.includes("${")||e.includes(`{`);function bh(e){let t=[];if(!_h(e))return t;let n=T(e.apps);if(n.length===0)return t;let r=new Map,i=T(e.objects);for(let[e,t]of i.entries()){let n=vh(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=vh(i.name)??`#${e}`,a=(e,i)=>{if(Array.isArray(e))for(let[o,s]of e.entries()){if(!_h(s))continue;let e=s,c=`${i}[${o}]`;if(e.type===`object`){let i=vh(e.objectName),a=i&&!yh(i)?r.get(i):void 0;if(i&&a&&!Je(a.enable,`list`)){let r=_h(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:gh,where:`app "${n}" \xB7 nav "${vh(e.id)??vh(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 T(i.areas).entries())a(n.items,`apps[${e}].areas[${t}].items`),a(n.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var xh=`sort-field-unknown`,Sh=`sort-field-unsortable`,Ch=`sort-field-unprovisioned`;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 Th(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(!B(i))continue;let a=wh(i.field);a&&n.push({field:a.trim(),at:`[${r}]`})}return n}return[]}function Eh(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 Th(e)){let e=n.field,o=e.split(`.`)[0];if(Mn.has(o)){!e.includes(`.`)&&u?.has(o)&&s.push({severity:`warning`,rule:Ch,where:r,path:`${i}${n.at}`,message:`${a} orders by "${e}", which resolves on object "${t}", but ${Rn(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:zn(t,e)});continue}if(!l.has(o)){let c=e.includes(`.`);s.push({severity:`error`,rule:xh,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?``:D(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(le(d)){let o=d?.type;s.push({severity:`error`,rule:Sh,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 Dh(e){let t=[];if(!B(e))return t;let n=Array.isArray(e.objects)?e.objects:B(e.objects)?Object.entries(e.objects).map(([e,t])=>({name:e,...t})):[],r=Sc(e),i=Ln(e),a=(e,n,a,o,s)=>{t.push(...Eh(e,n,r,a,o,s,i))};for(let e=0;e<n.length;e++){let t=n[e];if(!B(t))continue;let r=wh(t.name),i=r?`object "${r}"`:`objects[${e}]`;if(B(t.listViews))for(let[n,o]of Object.entries(t.listViews))B(o)&&a(o.sort,Oh(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(!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)&&a(t.sort,Oh(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}].sort`,`list-view sort`),t.viewKind===`list`&&B(t.config)&&a(t.config.sort,Oh(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config.sort`,`list-view sort`),B(t.list)&&a(t.list.sort,Oh(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list.sort`,`list-view sort`),B(t.listViews))for(let[i,o]of Object.entries(t.listViews))B(o)&&a(o.sort,Oh(o)??r,`view "${n}" \u203A listViews.${i}`,`views[${e}].listViews.${i}.sort`,`list-view sort`)}return t}function Oh(e){let t=e.data;return B(t)?wh(t.object):void 0}var kh=`list-view-field-unknown`,Ah=`list-view-field-dotted`;function V(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function jh(e){return typeof e==`string`&&e.length>0?e:void 0}function Mh(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}var Nh={"":{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`}}},Ph={"":{columns:`projection`,filterableFields:`filter`},userFilters:{fields:`filter`}};function Fh(e,t){return Ph[e]?.[t]}var Ih=[{block:`summary`,key:`field`,severity:`error`},{block:`prefix`,key:`field`,severity:`warning`}],Lh=`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 Rh(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=Xe(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 zh(e){let t=[];if(!V(e))return t;let n=Kn(e);if(n.size===0)return t;let r=(e,r,i,a,o,s,c=void 0)=>{let l=jh(e);if(!l)return;let u=l.split(`.`)[0];if(!u)return;let d=E(n,r,u);if(Yn(d)||!d)return;let f=Jn(d,u,s),p=u!==l;if(!f){if(!p||!c)return;let e=Rh(c,l,u,r,d.kind===`ok`?d.meta:void 0,s);if(!e)return;t.push({severity:`error`,rule:Ah,where:a,path:o,message:e.message,hint:e.hint});return}t.push({severity:i,rule:kh,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)`:``)+` ${Lh}`,hint:`Name a field that exists on "${r}", or drop the entry. ${f.detail}`})},i=(e,t,i,a)=>{if(!V(e))return;let o=e.data;if(V(o)){let e=jh(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(Nh)){let o=t===``?e:e[t];if(!V(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=Fh(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=Fh(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(V(n)&&(r(n.field,s,i,l,`${u}.field`,`${e}[${o}].field`,a),t===``&&e===`columns`))for(let t of Ih){let i=n[t.block];V(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&&or(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(!V(e))return;let i=jh(e.name)??`#${r}`;c(e.filter,`${t}[${r}] "${i}" \u203A filter`,`${n}[${r}].filter`)})};l(e.tabs,`${i} \u203A tabs`,`${a}.tabs`),V(e.userFilters)&&l(e.userFilters.tabs,`${i} \u203A userFilters.tabs`,`${a}.userFilters.tabs`)},a=e=>{let t=e.data;return V(t)?jh(t.object):void 0},o=Mh(e.objects);for(let e=0;e<o.length;e++){let t=o[e];if(!V(t))continue;let n=jh(t.name),r=n?`object "${n}"`:`objects[${e}]`;if(V(t.listViews))for(let[o,s]of Object.entries(t.listViews))V(s)&&i(s,a(s)??n,`${r} \u203A listViews.${o}`,`objects[${e}].listViews.${o}`)}let s=Mh(e.views);for(let e=0;e<s.length;e++){let t=s[e];if(!V(t))continue;let n=jh(t.name)??jh(t.objectName)??`#${e}`,r=jh(t.objectName)??jh(t.object);if(t.viewKind===`list`&&!V(t.config)&&i(t,a(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}]`),t.viewKind===`list`&&V(t.config)&&i(t.config,a(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config`),V(t.list)&&i(t.list,a(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list`),V(t.listViews))for(let[o,s]of Object.entries(t.listViews))V(s)&&i(s,a(s)??r,`view "${n}" \u203A listViews.${o}`,`views[${e}].listViews.${o}`)}return t}var Bh=`object-field-ref-unknown`;function Vh(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Hh(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}var Uh=[{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.`}],Wh={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."},Gh=new Set([`lookup`,`master_detail`,`user`]);function Kh(e){return typeof e==`string`&&e.length>0?e:void 0}function qh(e){let t=Kh(e);return t?{name:t,suffix:``}:void 0}function Jh(e,t){let n=Vh(e)?Kh(e[t]):void 0;return n?{name:n,suffix:`.${t}`}:void 0}var Yh=[{key:`relatedListColumns`,address:`owner`,verbatim:!1,read:qh,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=>qh(e)??Jh(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=>Jh(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=>qh(e)??Jh(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=>qh(e)??Jh(e,`param`)??Jh(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 Xh(e,t,n,r){if(!r||!n.includes(`.`))return E(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 Zh(e){let t=[];if(!Vh(e))return t;let n=Kn(e);if(n.size===0)return t;let r=e=>{let r=Xh(n,e.against,e.name,e.verbatim);if(Yn(r)||!r)return!1;let i=Jn(r,e.name,e.subject);return i?(t.push({severity:`error`,rule:Bh,where:e.where,path:e.path,message:`${i.message} ${e.consequence}`,hint:`${e.prescription} ${i.detail}`}),!0):!1},i=Hh(e.objects);for(let e=0;e<i.length;e++){let t=i[e];if(!Vh(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 Uh){let n=e.block===``?t:t[e.block];if(!Vh(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)=>{Vh(e)&&Array.isArray(e.fields)&&e.fields.forEach((e,n)=>{let i=Kh(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:Wh.consequence,prescription:Wh.prescription})})});for(let e of T(t.fields)){let t=Kh(e.name);if(!t)continue;let n=o.fields.get(t),i=n?.type&&Gh.has(n.type)?n.reference:void 0,l=new Set;for(let n of Yh){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 Qh=`action-name-undefined`;function H(e){return typeof e==`string`&&e.length>0?e:void 0}function $h(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function eg(e){let t=new Set;for(let n of T(e.actions)){let e=H(n?.name);e&&t.add(e)}for(let n of T(e.objects))if(n&&typeof n==`object`)for(let e of T(n.actions)){let n=H(e?.name);n&&t.add(n)}return t}function tg(e){let t=[];if(!e||typeof e!=`object`)return t;let n=eg(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:Qh,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}`+D(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=$h(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=H(o.name);c&&r(c,`${t} \xB7 ${n} \xB7 bulkActionDefs[${e}]`,`${a}.bulkActionDefs[${e}].name`,`Aggregate bulk action`,i)}},o=T(e.views);for(let e=0;e<o.length;e++){let t=o[e];if(!t||typeof t!=`object`)continue;let n=`view "${H(t.name)??H(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=T(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 "${H(t.name)??`#${e}`}"`;for(let[t,i]of Object.entries(n))a(i,r,`listViews.${t}`,`objects[${e}].listViews.${t}`)}let c=T(e.pages);for(let e=0;e<c.length;e++){let t=c[e];if(!t||typeof t!=`object`)continue;let n=H(t.name)??`#${e}`;for(let{component:i,path:a}of Ac(t,`pages[${e}]`)){let e=i.properties;if(!e||typeof e!=`object`)continue;let t=H(i.type),o=`page "${n}" \xB7 component "${t??`?`}"`,s=$h(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)?H(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=H(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=T(e.apps);for(let e=0;e<l.length;e++){let t=l[e];if(!t||typeof t!=`object`)continue;let n=H(t.name)??`#${e}`,i=(e,t)=>{let a=T(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=H(c?.actionName);o.type===`action`&&l&&r(l,`app "${n}" \xB7 nav "${H(o.id)??`#${e}`}"`,`${s}.actionDef.actionName`,`Navigation action item`);let u=H(o.runAction);o.type===`object`&&u&&r(u,`app "${n}" \xB7 nav "${H(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=T(t.areas);for(let t=0;t<a.length;t++)i(a[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var ng=`action-dispatch-contract-mismatch`,rg=[`perRecord`,`aggregate`];function ig(e){return typeof e==`string`&&e.length>0?e:void 0}function ag(e){return rg.find(t=>t===e)}var og={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`"},sg={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 cg(e){let t=new Map,n=e=>{if(!e||typeof e!=`object`)return;let n=e,r=ig(n.name);if(!r)return;let i=ag(n.execution)??`none`;t.has(r)||t.set(r,new Set),t.get(r).add(i)};for(let t of T(e.actions))n(t);for(let t of T(e.objects))if(t&&typeof t==`object`)for(let e of T(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 lg(e){let t=[];if(!e||typeof e!=`object`)return t;let n=cg(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:ng,where:i,path:a,message:`Action "${e}" declares ${og[s]}, but ${o} wires it as ${og[r]}. The two contracts deliver opposite input to the same body: ${sg[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=ig(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=ig(t.name);n&&r(n,`aggregate`,`${o} \xB7 bulkActionDefs[${e}]`,`${i}.bulkActionDefs[${e}]`,o)}},a=T(e.views);for(let e=0;e<a.length;e++){let t=a[e];if(!t||typeof t!=`object`)continue;let n=`view "${ig(t.name)??ig(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=T(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 "${ig(t.name)??`#${e}`}"`;for(let[t,a]of Object.entries(n))i(a,r,`listViews.${t}`,`objects[${e}].listViews.${t}`)}return t}var ug=`action-no-placement`;function dg(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,n=e=>{if(!e||typeof e!=`object`)return;let n=e;for(let e of[`rowActions`,`bulkActions`])for(let r of fg(n[e]))t.add(r);for(let e of T(n.bulkActionDefs)){let n=dg(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 T(e.views))t&&typeof t==`object`&&(n(t.list),r(t.listViews));for(let t of T(e.objects))t&&typeof t==`object`&&r(t.listViews);return t}function mg(e){let t=[];if(!e||typeof e!=`object`)return t;let n=pg(e),r=(e,r)=>{if(!e||typeof e!=`object`||`locations`in e)return;let i=dg(e.name);i&&(n.has(i)||t.push({severity:`warning`,rule:ug,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=T(e.actions);for(let e=0;e<i.length;e++)r(i[e],`actions[${e}]`);let a=T(e.objects);for(let e=0;e<a.length;e++){let t=a[e];if(!t||typeof t!=`object`)continue;let n=T(t.actions);for(let t=0;t<n.length;t++)r(n[t],`objects[${e}].actions[${t}]`)}return t}var hg=`page/visualization-without-binding`,gg=[{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`]}],_g=`grid`,vg=new Map(gg.map(e=>[e.visualization,e])),yg=/start|begin|kickoff/i,bg=/end|due|finish|deadline|close/i;function U(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function xg(e){return typeof e==`string`&&e.length>0?e:void 0}function Sg(e){let t=e.fields;if(!U(t)&&!Array.isArray(t))return;let n=0,r=[];for(let e of T(t)){let t=xg(e.name);t&&(n++,!(e.hidden===!0||e.system===!0||Mn.has(t))&&r.push({name:t,type:xg(e.type)}))}return n===0?void 0:r}function Cg(e,t){return e.find(t)?.name}function wg(e,t){let n=Cg(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 Cg(e,e=>r.test(e.name))}function Tg(e,t){let n=e=>!!e.type&&t.includes(e.type),r=Cg(e,e=>n(e)&&yg.test(e.name))??Cg(e,n);if(!r)return;let i=Cg(e,e=>n(e)&&e.name!==r&&bg.test(e.name))??Cg(e,e=>n(e)&&e.name!==r);if(i)return`${r} + ${i}`}function Eg(e,t){return t.visualization===`gantt`?Tg(e,t.types):wg(e,t)}function Dg(e,t,n){let r=new Map,i=(e,t)=>{U(t)&&!r.has(e)&&r.set(e,t)},a=U(t?.listViews)?t.listViews:U(t?.list_views)?t.list_views:void 0;if(a)for(let[e,t]of Object.entries(a))i(e,t);t&&U(t.list)&&i(`list`,t.list);for(let t of T(e.views)){let e=xg(t.objectName)??xg(t.object),r=t=>(U(t.data)?xg(t.data.object):void 0)??e;if(U(t.listViews))for(let[e,a]of Object.entries(t.listViews))U(a)&&r(a)===n&&i(e,a);U(t.list)&&r(t.list)===n&&i(`list`,t.list)}return r}function Og(e){return Array.isArray(e.columns)&&e.columns.length>0}function kg(e,t,n){let r=[e.get(`${t}.${n}`),e.get(n),...n==="default"||n===`list`?[e.get(`list`)]:[]].filter(U);return r.find(Og)??r[0]}function Ag(e,t){let n=U(e.options)?e.options:void 0;return t.viewBlocks.some(t=>U(e[t])||!!n&&U(n[t]))}function jg(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 Mg(e){let t=[];if(!U(e))return t;let n=new Map;for(let t of T(e.objects)){let e=xg(t.name);e&&!n.has(e)&&n.set(e,t)}let r=T(e.pages);for(let i=0;i<r.length;i++){let a=r[i];if(a.type!==`list`)continue;let o=U(a.interfaceConfig)?a.interfaceConfig:void 0;if(!o)continue;let s=(U(o.appearance)?o.appearance:void 0)?.allowedVisualizations;if(!Array.isArray(s)||s.length===0)continue;let c=xg(o.source)??xg(a.object);if(!c)continue;let l=n.get(c);if(!l)continue;let u=Sg(l);if(!u)continue;let d=xg(o.sourceView),f;if(d&&(f=kg(Dg(e,l,c),c,d),!f))continue;let p=xg(a.name)??`#${i}`,m=`page "${p}" \xB7 interfaceConfig.appearance`;for(let e=0;e<s.length;e++){let n=xg(s[e]);if(!n||n===_g)continue;let r=vg.get(n);if(!r||f&&Ag(f,r)||Eg(u,r))continue;let a=e===0;t.push({severity:a?`error`:`warning`,rule:hg,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 ${jg(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 (${jg(r)}), or drop '${n}' from \`appearance.allowedVisualizations\`.`})}}return t}var Ng=`component-props-unknown-key`,Pg=`component-props-invalid`;function Fg(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Ig(e){return typeof e==`string`&&e.length>0?e:void 0}var Lg=et,Rg=`object`;function zg(e,t){return e.path.length!==1||e.path[0]!==Rg||Ig((Fg(t.dataSource)?t.dataSource:void 0)?.object)===void 0?!1:(Fg(t.properties)?t.properties:void 0)?.[Rg]===void 0}function Bg(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 Vg(e){let t=[];if(!Fg(e))return t;let n=T(e.pages);for(let e=0;e<n.length;e++){let r=n[e];if(!Fg(r))continue;let i=Ig(r.name)??`#${e}`;for(let{component:n,path:a}of Ac(r,`pages[${e}]`)){let e=Ig(n.type);if(!e)continue;let r=Lg[e];if(!r)continue;let o=Fg(n.properties)?n.properties:void 0;if(!o)continue;let s=`page "${i}" \xB7 ${e}`,c=`${a}.properties`;for(let n of tt(r,o,e,c))t.push({severity:`warning`,rule:Ng,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(zg(r,n))continue;let i=r.path.length?`${c}.${r.path.join(`.`)}`:c,a=Bg(r);if(a){for(let n of a.keys??[])t.push({severity:`warning`,rule:Ng,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:Ng,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:Pg,where:s,path:i,message:`${i.slice(c.length+1)||`properties`}: ${Qc(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 Hg=`component-type-unknown`;function Ug(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Wg(e){return typeof e==`string`&&e.length>0?e:void 0}function Gg(e){let t=[];if(!Ug(e))return t;let n=T(e.pages);for(let e=0;e<n.length;e++){let r=n[e];if(!Ug(r))continue;let i=Wg(r.name)??`#${e}`;for(let{component:n,path:a}of Ac(r,`pages[${e}]`)){let e=Wg(n.type);if(!e)continue;let r=be.get(e);if(r!==void 0){t.push({severity:`error`,rule:Hg,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(!f(e)||ee(e))continue;let o=oe(e,gt),s=Se(o);t.push({severity:`error`,rule:Hg,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 Kg=`chart-dimension-unknown`,qg=`chart-measure-unknown`,Jg=`chart-dataset-unknown`,Yg=`chart-axis-not-selected`;function W(e){return typeof e==`string`&&e.length>0?e:void 0}function Xg(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function Zg(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Qg(e){let t=[...e].sort();return t.length?t.join(`, `):`(none)`}function $g(e){let t=new Map;for(let n of T(e.datasets)){let e=W(n.name);if(!e)continue;let r=new Set;for(let e of T(n.dimensions)){let t=W(e.name);t&&r.add(t)}let i=new Set;for(let e of T(n.measures)){let t=W(e.name);t&&i.add(t)}t.set(e,{dimensions:r,measures:i})}return t}var e_={"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."},t_={"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`."},n_={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 r_(e){let t=[];if(!e||typeof e!=`object`)return t;let n=$g(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:Jg,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: ${Qg(n.keys())}.${D(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:Kg,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: ${Qg(e.dimensions)}.${D(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:qg,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.`:e_[o]),hint:`Dataset measures: ${Qg(e.measures)}.${D(i,e.measures)} `+(o===`query`?`Declare the measure on the dataset, or bind an existing one.`:`${t_[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:Yg,where:r.where,path:a,message:`"${i}" is a declared measure of "${n}" but is not in this chart's selected values (${Qg(s)}) \u2014 ${n_[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=T(e.reports);for(let e=0;e<o.length;e++){let t=o[e];if(!Zg(t))continue;let n=W(t.name)??`#${e}`,a=(e,t,n,a)=>{let o=W(e.dataset),s=r(o,t,n);if(!s||!o||(i(s,o,{dimensions:[{names:Xg(e.rows),path:`${n}.rows`},{names:Xg(e.columns),path:`${n}.columns`}],values:{names:Xg(e.values),path:`${n}.values`},where:t,path:n}),!a))return;let c=e.chart;if(!Zg(c))return;let l=W(c.xAxis),u=W(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:T(c.series).map((e,t)=>({name:W(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];Zg(r)&&a(r,`report "${n}" \xB7 block "${W(r.name)??`#${t}`}"`,`reports[${e}].blocks[${t}]`,!1)}}let s=(e,t,n)=>{if(!Zg(e))return;let r=e.chart;Zg(r)&&a({dataset:W(r.dataset),dimensions:[{names:Xg(r.dimensions),path:`${n}.chart.dimensions`}],values:{names:Xg(r.values),path:`${n}.chart.values`},where:t,path:`${n}.chart`})},c=T(e.views);for(let e=0;e<c.length;e++){let t=c[e];if(!Zg(t))continue;let n=W(t.name)??W(t.objectName)??`#${e}`;if(s(t.list,`view "${n}" \xB7 list chart`,`views[${e}].list`),Zg(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=T(e.objects);for(let e=0;e<l.length;e++){let t=l[e];if(!Zg(t)||!Zg(t.listViews))continue;let n=W(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=T(e.pages);for(let e=0;e<u.length;e++){let t=u[e];if(!Zg(t))continue;let n=W(t.name)??`#${e}`;for(let{component:r,path:i}of Ac(t,`pages[${e}]`)){let e=Zg(r.properties)?r.properties:void 0;if(!e||!W(e.dataset))continue;let t=T(e.yAxis).map((e,t)=>({name:W(e.field),path:`${i}.properties.yAxis[${t}].field`})).filter(e=>!!e.name),o=T(e.series).map((e,t)=>({name:W(e.name),path:`${i}.properties.series[${t}].name`,kind:`page-series`})).filter(e=>!!e.name);a({dataset:W(e.dataset),dimensions:[{names:Xg(e.dimensions),path:`${i}.properties.dimensions`}],values:{names:Xg(e.values),path:`${i}.properties.values`},axes:t,series:o,where:`page "${n}" \xB7 ${W(r.type)??`chart`}`,path:`${i}.properties`})}}return t}var i_=`dataset-include-unknown`,a_=`dataset-field-unknown`,o_=`dataset-field-not-included`,s_=`dataset-filter-field-unknown`;function c_(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function l_(e){return typeof e==`string`&&e.length>0?e:void 0}var u_=`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 d_(e){let t=[];if(!c_(e))return t;let n=T(e.datasets);if(n.length===0)return t;let r=Kn(e);return n.forEach((e,n)=>{let i=`dataset "${l_(e.name)??`#${n}`}"`,a=`datasets[${n}]`,o=l_(e.object);if(!o||!r.has(o)||!r.get(o))return;let s=qn(e.include);(Array.isArray(e.include)?e.include:[]).forEach((e,n)=>{if(typeof e!=`string`||!e)return;let s=`${a}.include[${n}]`,c=E(r,o,e);if(Yn(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&&Bn.has(r))return;t.push({severity:`error`,rule:i_,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=Jn(c,e,`include[${n}]`);u&&t.push({severity:`error`,rule:i_,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=l_(e);if(!u)return;let d=E(r,o,u);if(Yn(d)||!d)return;let f=Jn(d,u,a);if(f){t.push({severity:`error`,rule:c,where:n,path:i,message:`${f.message} ${u_}`,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:o_,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. ${u_}`,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)`}.`})};T(e.dimensions).forEach((e,t)=>{let n=l_(e.name)??`#${t}`;c(e.field,`${i} \u203A dimension "${n}"`,`${a}.dimensions[${t}].field`,`dimension field`,a_,`Bind the dimension to a field on "${o}", or to a \`relationship[.relationship].field\` path whose prefix is declared in \`include\`.`)}),T(e.measures).forEach((e,t)=>{let n=l_(e.name)??`#${t}`;c(e.field,`${i} \u203A measure "${n}"`,`${a}.measures[${t}].field`,`measure field`,a_,`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&&or(e,n,({field:e,path:n})=>{c(e,t,n,`filter key`,s_,`Filter on a field that exists on "${o}" (or on a declared \`include\` path).`)})};l(e.filter,`${i} \u203A filter`,`${a}.filter`),T(e.measures).forEach((e,t)=>{let n=l_(e.name)??`#${t}`;l(e.filter,`${i} \u203A measure "${n}" \u203A filter`,`${a}.measures[${t}].filter`)})}),t}var f_=`mapping-target-field-unknown`;function p_(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function m_(e){return typeof e==`string`&&e.length>0?e:void 0}function h_(e){let t=new Map,n=e=>{for(let n of T(e)){let e=m_(n.extend);if(!e)continue;let r=T(n.fields);r.length!==0&&t.set(e,[...t.get(e)??[],...r])}};n(e.objectExtensions);for(let t of Hn(e))p_(t.manifest)&&n(t.manifest.objectExtensions);return t}function g_(e){let t=[];if(!p_(e))return t;let n=T(e.mappings);if(n.length===0)return t;let r=new Map;for(let t of T(e.objects)){let e=m_(t.name);e&&r.set(e,t)}let i=h_(e);for(let e=0;e<n.length;e++){let a=n[e],o=m_(a.targetObject);if(!o)continue;let s=r.get(o);if(!s)continue;let c=i.get(o),l=c?{...s,fields:[...T(s.fields),...c]}:s,u=te(a.fieldMapping,l);if(u.length===0)continue;let d=Ge(l),f=d?.names??new Set,p=d&&d.parts.size>0?[...d.parts].map(([e,t])=>`${e}: ${t.join(`, `)}`).join(`; `):``,m=m_(a.name)??`#${e}`,h=`mapping "${m}" \xB7 object "${o}"`;for(let n of u){if(n.reason===`collides`){let r=n.target.indexOf(`.`);t.push({severity:`error`,rule:f_,where:h,path:`mappings[${e}].${n.path}`,message:`Import mapping "${m}" writes the compound field "${n.target.slice(0,r)}" of object "${o}" 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 (${p}).`});continue}t.push({severity:`error`,rule:f_,where:h,path:`mappings[${e}].${n.path}`,message:`Import mapping "${m}" writes target "${n.target}", which names no field of object "${o}". 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?__(n.head,n.target,o):D(n.target,f)),hint:`Point the target at a field "${o}" declares, or at a column the platform provisions on it`+(p?`, or at a declared part of a compound field as field.part (${p})`:``)+`. Addressable names: ${Qn(f)}.`})}}return t}function __(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(`, `)}.`+D(n,e.parts)}return e.type&&ae.has(e.type)?` ${v_(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.`:` ${v_(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 v_(e){return e.length>0?e[0].toUpperCase()+e.slice(1):e}var y_=`validation-rule-regex-uncompilable`,b_=`validation-rule-json-schema-uncompilable`,x_={allErrors:!0,strict:!1},S_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),C_=null,w_=null;function T_(){if(C_)return C_;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`,t;try{t=(0,C.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=S_(t)&&`default`in t?t.default:t;return C_=n,n}function E_(){if(w_)return w_;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`,t;try{t=(0,C.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=S_(t)&&`default`in t?t.default:t;return w_=n,n}function D_(){let e=new(T_())(x_);return E_()(e),e}function O_(){let e=Object.keys(D_().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 k_(e){return e instanceof Error?e.message:String(e)}var A_=16;function j_(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>=A_)return s;for(let t of[`then`,`otherwise`]){let n=e[t];S_(n)&&s.push(...j_(n,a,`${o}.${t}`,r+1))}return s}function M_(e){let t=[];if(!S_(e))return t;for(let n of T(e.objects)){let e=typeof n.name==`string`?n.name:`(unnamed object)`,r=n.validations;for(let n of T(r))for(let{rule:r,label:i,path:a}of j_(n,``,``))t.push({rule:r,objectName:e,label:i,where:`object '${e}' \xB7 validation ${i}`,basePath:`objects.${e}.validations.${a}`})}return t}function N_(e){let t=[];for(let{rule:n,objectName:r,label:i,where:a,basePath:o}of M_(e)){if(n.type===`format`&&typeof n.regex==`string`&&n.regex!==``)try{new RegExp(n.regex)}catch(e){t.push({severity:`error`,rule:y_,where:a,path:`${o}.regex`,message:`\`format\` validation ${i} on object '${r}' declares a \`regex\` that does not compile: ${k_(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`&&S_(n.schema))try{D_().compile(n.schema)}catch(e){t.push({severity:`error`,rule:b_,where:a,path:`${o}.schema`,message:`\`json_schema\` validation ${i} on object '${r}' declares a \`schema\` ajv cannot compile: ${k_(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 P_=`validation-rule-json-schema-unknown-format`,F_=e=>!!e&&typeof e==`object`&&!Array.isArray(e),I_=[`additionalItems`,`additionalProperties`,`contains`,`propertyNames`,`if`,`then`,`else`,`not`,`unevaluatedItems`,`unevaluatedProperties`],L_=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],R_=[`properties`,`patternProperties`,`$defs`,`definitions`,`dependentSchemas`],z_=32,B_=e=>e.replace(/~/g,`~0`).replace(/\//g,`~1`);function V_(e,t,n,r){if(!F_(e)||(typeof e.format==`string`&&n.push({pointer:`${t}/format`,name:e.format}),r>=32))return;for(let i of I_)i in e&&V_(e[i],`${t}/${B_(i)}`,n,r+1);for(let i of L_){let a=e[i];Array.isArray(a)&&a.forEach((e,a)=>{V_(e,`${t}/${B_(i)}/${a}`,n,r+1)})}for(let i of R_){let a=e[i];if(F_(a))for(let[e,o]of Object.entries(a))V_(o,`${t}/${B_(i)}/${B_(e)}`,n,r+1)}let i=e.items;Array.isArray(i)?i.forEach((e,i)=>V_(e,`${t}/items/${i}`,n,r+1)):F_(i)&&V_(i,`${t}/items`,n,r+1);let a=e.dependencies;if(F_(a))for(let[e,i]of Object.entries(a))F_(i)&&V_(i,`${t}/dependencies/${B_(e)}`,n,r+1)}function H_(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 U_(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=H_(r,e);t<a&&(a=t,i=e)}return a<=n?i:null}function W_(e){let t=[],n=[];for(let{rule:t,objectName:r,label:i,where:a,basePath:o}of M_(e)){if(t.type!==`json_schema`||!F_(t.schema))continue;let e=[];V_(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=O_(),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=U_(e.name,r),l=`#${e.pointer}`;t.push({severity:`error`,rule:P_,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 G_(e){let t=[];if(!e||typeof e!=`object`)return{version:1,entries:t};let n=new Map;for(let t of T(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 T(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:ge(o,`allowCreate`),read:ge(o,`allowRead`),edit:ge(o,`allowEdit`),delete:ge(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 K_=[[`create`,`create`],[`read`,`read`],[`edit`,`edit`],[`delete`,`delete`],[`viewAllRecords`,`View All Data`],[`modifyAllRecords`,`Modify All Data`]];function q_(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=K_.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 K_)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 J_=`nav-object-ungranted`;function Y_(e){return typeof e==`string`&&e.length>0?e:void 0}function X_(e){let t=[],n=T(e.apps);for(let e=0;e<n.length;e++){let r=n[e];if(!r||typeof r!=`object`)continue;let i=Y_(r.name)??`#${e}`,a=(e,n)=>{let r=T(e);for(let e=0;e<r.length;e++){let o=r[e];if(!o||typeof o!=`object`)continue;let s=`${n}[${e}]`,c=Y_(o.objectName);o.type===`object`&&c&&t.push({objectName:c,where:`app "${i}" \xB7 nav "${Y_(o.id)??`#${e}`}"`,path:`${s}.objectName`}),Array.isArray(o.children)&&a(o.children,`${s}.children`)}};a(r.navigation,`apps[${e}].navigation`);let o=T(r.areas);for(let t=0;t<o.length;t++)a(o[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}function Z_(e){let t=[];if(!e||typeof e!=`object`||T(e.permissions).length===0)return t;let n=X_(e);if(n.length===0)return t;let r=new Set;for(let t of T(e.objects)){let e=Y_(t.name);e&&r.add(e)}let i=new Set;for(let t of G_(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)||h(n)||r.has(n)&&(i.has(n)||(a.add(n),t.push({severity:`warning`,rule:J_,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 Q_=`field-no-consumers`;function $_(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function ev(e){return typeof e==`string`&&e.length>0?e:void 0}var tv=[`objects`,`views`,`pages`,`apps`,`flows`,`dashboards`,`reports`,`datasets`,`actions`,`hooks`,`jobs`,`emailTemplates`,`agents`,`tools`,`skills`,`apis`,`webhooks`,`sharingRules`,`analyticsCubes`],nv=[`translations`,`data`,`mappings`,`permissions`],rv=new Set([`externalId`,`upsertKey`]),iv=new Set([`views`,`pages`,`apps`]),av=new Set([`label`,`pluralLabel`,`description`,`message`,`successMessage`,`errorMessage`,`title`,`placeholder`,`helpText`,`emptyText`,`tooltip`,`subtitle`]),ov=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(`.`)),sv=new Set([`highlightFields`,`searchableFields`,`indexes`,`columns`,`sections`,`groups`,`hideFields`,`hiddenFields`,`fieldOrder`,`visibleFields`,`labelField`,`displayField`,`descriptionField`,`tooltipFields`,`fieldGroups`,`recordTypes`,`listViews`]),cv=new Set([`filter`,`filters`,`runtimeFilter`,`relatedListFilter`,`where`,`criteria`,`defaultFilter`,`conditions`]),lv=new Set([`fields`,`values`,`set`,`record`,`data`,`input`,`defaults`,`records`]),uv=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(`.`)),dv=[/\.([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],fv=new Set([`source`,`expression`,`formula`,`condition`,`criteria`,`when`,`visibleWhen`,`readonlyWhen`,`requiredWhen`,`where`,`predicate`,`script`,`body`,`handler`,`code`]),pv=/\b([A-Za-z_][A-Za-z0-9_]*)\b/g,mv=2e5,hv=class{constructor(){this.fieldsByObject=new Map,this.objectsByField=new Map,this.datasetObject=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 gv(e,t,n){return nv.includes(e)?t.some(e=>rv.has(e))?`behaviour`:`carrier`:av.has(n)?`carrier`:t.some(e=>ov.has(e))?`behaviour`:iv.has(e)||t.some(e=>sv.has(e))?`display`:`behaviour`}function _v(e,t,n,r,i,a,o){if(t.length===0||t.length>mv||uv.has(o))return;let s=[],c=t.trim();e.objectsByField.has(c)&&s.push({token:c,at:0});let l=fv.has(o)?[...dv,pv]:dv;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=av.has(o);for(let{token:t,at:c}of s){let s=d.some(([e,t])=>c>=e&&c<t),l=f&&!s?`carrier`:gv(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 vv(e,t,n){let r=t=>e.isObject(t)?t:void 0,i=(e,t)=>$_(e)?r(e[t]):void 0,a=$_(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=>$_(e)?i(e.config,`objectName`)??i(e.config,`object`):void 0).find(e=>e!==void 0):void 0)??n}function yv(e,t,n,r,i,a,o){if(t==null)return;if(typeof t==`function`){_v(e,Function.prototype.toString.call(t),n,r,i,a,o);return}if(typeof t==`string`){_v(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++)yv(e,t[s],n,r,`${i}[${s}]`,a,o);return}let s=t,c=vv(e,s,n);for(let[t,n]of Object.entries(s)){let s=`${i}.${t}`,l=[...a,t];if(e.objectsByField.has(t)&&(cv.has(o)||lv.has(o))){if(e.declares(c,t)){let n=lv.has(o)?`carrier`:gv(r,l,o);e.record(c,t,{root:r,path:s,kind:n})}else e.unresolved+=1}yv(e,n,e.isObject(t)?t:c,r,s,l,t)}}var bv=new Set([`name`,`label`,`type`,`reference`]);function xv(e,t,n,r,i){for(let[i,a]of Object.entries(t))i!==`fields`&&i!==`name`&&yv(e,a,n,`objects`,`${r}.${i}`,[i],i);for(let{rec:r,path:a}of k(t.fields,i)){let t=Ut(r),i=ev(r.displayField);t&&i&&e.declares(t,i)&&e.record(t,i,{root:`objects`,path:`${a}.displayField`,kind:`display`});for(let[t,i]of Object.entries(r))bv.has(t)||t===`displayField`||yv(e,i,n,`objects`,`${a}.${t}`,[t],t)}}function Sv(e){let t={};for(let{rec:n}of e){let e=ev(n.name);e&&(t[e]=n)}return t}function Cv(e,t){return{nameField:ev(e.nameField),displayNameField:ev(e.displayNameField),fields:Sv(t)}}function wv(e,t,n,r){let i=Tt({fieldGroups:t.fieldGroups,fields:Sv(r)});if(i===null)return;let a=new Map;for(let{rec:e,path:t}of r){let n=ev(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 Tv(e){return e.join(`, `)}function Ev(e){let t=[];if(!$_(e)||!tv.some(t=>t!==`objects`&&T(e[t]).length>0))return t;let n=new hv,r=[],i=k(e.objects,`objects`);for(let{rec:e,path:t}of i){let i=ev(e.name);if(!i||!e.fields||typeof e.fields!=`object`)continue;let a=k(e.fields,`${t}.fields`),o=Nn(e),s=ke(Cv(e,a));wv(n,e,i,a);for(let{rec:e,path:t}of a){let a=ev(e.name);if(!a)continue;n.declare(i,a);let c=o.has(a)||a===s||e.type===`master_detail`;r.push({object:i,field:a,path:t,exempt:c})}}if(r.length===0)return t;for(let t of T(e.datasets)){let e=ev(t.name),r=ev(t.object);e&&r&&n.datasetObject.set(e,r)}for(let{rec:e,path:t}of i){let r=ev(e.name);r&&n.fieldsByObject.has(r)&&xv(n,e,r,t,`${t}.fields`)}for(let t of[...tv,...nv])t!==`objects`&&yv(n,e[t],void 0,t,t,[],t);let a=[...tv,...nv];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: ${Tv(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:Q_,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, 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 or a flow that only WRITES it 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: ${tv.join(`, `)} (consumers) \xB7 ${nv.join(`, `)} (carriers); test fixtures are never scanned.`,object:e,field:i,verdict:l,carriers:c,rootsScanned:a})}return t}var Dv=`screen`,Ov=`translation-target-unknown`,kv=`translation-option-key-unknown`,Av=`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 jv(e,t){let n=K(e.name);n&&t.add(n),G(e.then)&&jv(e.then,t),G(e.otherwise)&&jv(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}"?`:D(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 Mv=new Set([...Mn,`_id`,`name`,`space`]);function Nv(){return{fields:new Map,views:new Set,actions:new Map,sections:new Set,validations:new Set,tabs:new Set}}function Pv(e,t){let n=ql(e),r=e=>ql(e)??n,i=(e,n)=>{e&&n&&t(e).views.add(n)},a=(e,n)=>{if(n)for(let r of T(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,Iv(o,e)),i(n??o,K(e.name));let s=Lv(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 Fv(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 T(r.tabs)){let n=K(e.name);n&&t(i).tabs.add(n)}}function Iv(e,t){if(!e||!G(t.list))return;let n=Re(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 Lv(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=Re(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 Rv(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 zv(e){let t=new Map,n=e=>{for(let n of T(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 Hn(e)){let e=t.manifest;G(e)&&n(e.navigationContributions)}return t}function Bv(e){let t=new Map,n=e=>{for(let n of T(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 Hn(e)){let e=t.manifest;G(e)&&n(e.objectExtensions)}return t}function Vv(e,t){let n=[];for(let r of Hn(e)){let e=r.manifest;G(e)&&n.push(...T(e[t]))}return n}function Hv(e){let t=new Map,n=e=>{let n=t.get(e);return n||(n=Nv(),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 T(e.fields)){let e=K(n.name);e&&(t||!i.fields.has(e))&&i.fields.set(e,n)}for(let n of T(e.actions)){let e=K(n.name);e&&(t||!i.actions.has(e))&&i.actions.set(e,n)}for(let t of T(e.views))Pv({...t,object:K(t.object)??r},n);Pv({object:r,listViews:e.listViews},n);for(let t of T(e.fieldGroups)){let e=K(t.key)??K(t.name);e&&i.sections.add(e)}for(let t of T(e.validations))jv(t,i.validations)};for(let t of T(e.objects))r(t,{ownDeclaration:!0});for(let t of Vv(e,`objects`))r(t,{ownDeclaration:!1});let i=Bv(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 T(e.fields)){let e=K(t.name);e&&(r.fields.has(e)||r.fields.set(e,t))}for(let t of T(e.validations))jv(t,r.validations)}}for(let t of[...T(e.views),...Vv(e,`views`)])Pv(t,n);let o=e=>{Fv(e,n);for(let t of Ac(e,``)){if(!t.objectName)continue;let e=G(t.component.properties)?t.component.properties:void 0;if(e)for(let r of T(e.sections)){let e=K(r.name);e&&n(t.objectName).sections.add(e)}}};for(let t of T(e.pages))o(t);for(let t of Vv(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 T(e.actions))l(t,{ownDeclaration:!0});for(let t of Vv(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=zv(e),d=new Map,f=(e,t)=>{for(let n of T(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 T(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 T(e.apps))p(t);for(let t of Vv(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 T(e.widgets)){let e=K(t.id)??K(t.name);e&&r.add(e)}let i=new Set,a=[...T(G(e.header)?e.header.actions:void 0),...T(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 T(e.dashboards))g(t,{ownDeclaration:!0});for(let t of Vv(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 co(e,``)){let e=K(t.id);if(!e)continue;let n=K(t.type);if(n!==Dv){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 T(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 T(e.flows))v(t,{ownDeclaration:!0});for(let t of Vv(e,`flows`))v(t,{ownDeclaration:!1});return{objects:t,extended:a,apps:d,contributedOnlyApps:m,dashboards:h,flows:_,globalActions:s,actionOwners:c}}function Uv(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`translations[${e}].${t}`:`translations[${e}]["${t}"]`}function Wv(e){let t=[];if(!G(e))return t;let n=Array.isArray(e.translations)?e.translations:[];if(n.length===0)return t;let r=Hv(e),i=(e,n,r,i)=>{t.push({severity:Av,rule:Ov,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=Uv(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(h(e)||r.extended.has(e))continue;i(`${s} \xB7 object "${e}"`,o,Me(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(Mv.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)&&Gv(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}Kv(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}Kv(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 Gv(e,t){let n=Object.keys(Y(t.optionMap));if(n.length===0)return;let r=Rv(t.field);if(!r){e.push({severity:`warning`,rule:kv,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:kv,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 Kv(e,t){let n=Object.keys(Y(G(t.rawAction)?t.rawAction.params:void 0));if(n.length===0)return;let r=new Set;for(let e of T(t.action.params)){let t=K(e.name)??K(e.field);t&&r.add(t)}for(let i of n)r.has(i)||e.push({severity:Av,rule:Ov,where:`${t.where} \xB7 param "${i}"`,path:`${t.path}.params.${i}`,message:`Translations are keyed to parameter "${i}", which ${t.subject} does not declare. The parameter's label and help text render untranslated in the action dialog.`+q(i,r),hint:"Match the key to a declared param `name`, or drop it."+(r.size>0?` Declared params: ${J(r)}.`:``)})}var qv=`translation-section-name-missing`;function Jv(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Yv(e){return typeof e==`string`&&e.length>0?e:void 0}function Xv(e){let t=Yv(e.name);return t?`view "${t}"`:``}function Zv(...e){return e.filter(e=>e.length>0).join(` · `)}function Qv(e,t,n,r){let i=ql(e),a=Jv(e.list)?ql(e.list)??i:void 0;for(let o of Jl(e,t))r.push({path:`${o.path}.sections`,surface:Zv(n,o.surface),objectName:ql(o.view)??i??a,sections:o.view.sections})}function $v(e){let t=new Set,n=Array.isArray(e.translations)?e.translations:[];for(let e of n)if(Jv(e)){for(let n of Object.values(e))if(Jv(n)&&Jv(n.objects))for(let[e,r]of Object.entries(n.objects))Jv(r)&&t.add(e)}return t}function ey(e){let t=e.toLowerCase().replace(/&/g,` and `).replace(/[^a-z0-9]+/g,`_`).replace(/^_+|_+$/g,``);return t.length>0?t:void 0}function ty(e){let t=[];if(!Jv(e))return t;let n=$v(e);if(n.size===0)return t;let r=[];for(let{rec:t,path:n}of k(e.objects,`objects`)){let e=Yv(t.name);if(e){for(let{rec:i,path:a}of k(t.views,`${n}.views`))Qv({...i,object:Yv(i.object)??e},a,Xv(i),r);Jv(t.listViews)&&Qv({object:e,listViews:t.listViews},n,``,r)}}for(let{rec:t,path:n}of k(e.views,`views`))Qv(t,n,Xv(t),r);for(let{rec:t,path:n}of k(e.pages,`pages`)){let e=Yv(t.name),i=e?`page "${e}"`:``;for(let e of Ac(t,n)){if(!e.objectName)continue;let t=Jv(e.component.properties)?e.component.properties:void 0;if(!t)continue;let n=Yv(e.component.type)??`component`;r.push({path:`${e.path}.properties.sections`,surface:Zv(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(!Jv(i)||Yv(i.name))continue;let a=Yv(i.label);if(!a)continue;let o=ey(a);t.push({severity:`warning`,rule:qv,where:Zv(`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 ny=`ai-skill-surface-mismatch`;function ry(e){return typeof e==`string`&&e.length>0?e:void 0}function iy(e){return typeof e==`string`&&e.length>0?e:`ask`}function ay(e){let t=[];if(!e||typeof e!=`object`)return t;let n=new Map;for(let t of T(e.skills)){let e=ry(t.name);e&&n.set(e,t)}let r=T(e.agents);for(let e=0;e<r.length;e++){let i=r[e],a=ry(i.name)??`#${e}`,o=iy(i.surface),s=Array.isArray(i.skills)?i.skills:[];for(let r=0;r<s.length;r++){let i=ry(s[r]);if(!i)continue;let c=n.get(i);if(!c)continue;let l=iy(c.surface);l!==`both`&&l!==o&&t.push({severity:`error`,rule:ny,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 oy=`ai-skill-tool-unresolved`;function sy(e){return typeof e==`string`&&e.length>0?e:void 0}function cy(e,t){for(let n of y)if(t.has(`${n}${e}`))return` Did you mean "${n}${e}"?`;return D(e,t)}var ly=new Set([`script`,`api`,`flow`]),uy=`update`;function dy(e){let t=e.ai;if(!t||typeof t!=`object`)return!1;let n=t;if(n.exposed!==!0||!sy(n.description))return!1;if(e.operation===uy)return!0;let r=sy(e.type);return!r||!ly.has(r)?!1:r===`script`?!!(e.target||e.body):!!e.target}function fy(e){let t=new Set(Ae);for(let n of T(e.tools)){let e=sy(n.name);e&&t.add(e)}let n=e=>{for(let n of T(e)){let e=sy(n.name);e&&dy(n)&&t.add(`action_${e}`)}};n(e.actions);for(let t of T(e.objects))n(t.actions);return t}function py(e){let t=new Set,n=e=>{for(let n of T(e)){let e=sy(n.name);e&&!dy(n)&&t.add(e)}};n(e.actions);for(let t of T(e.objects))n(t.actions);return t}function my(e){let t=[];if(!e||typeof e!=`object`)return t;let n=fy(e),r=py(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=T(e.skills);for(let e=0;e<a.length;e++){let o=a[e],s=sy(o.name)??`#${e}`,c=Array.isArray(o.tools)?o.tools:[];for(let a=0;a<c.length;a++){let o=sy(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:oy,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.`+cy(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: ${y.join(`, `)}.`})}}return t}var hy=`agent-authoring-withdrawn`,gy=`default-agent-outside-roster`,_y=`default-agent-legacy-alias`;function vy(e){return typeof e==`string`&&e.length>0?e:void 0}var yy=[`ask`,`build`],by=new Map([[`data_chat`,`ask`],[`metadata_assistant`,`build`]]),xy=new Set([...yy,...by.keys()]);function Sy(e){let t=[];if(!e||typeof e!=`object`)return t;let n=T(e.agents);for(let e=0;e<n.length;e++){let r=n[e],i=vy(r.name)??`#${e}`,a=xy.has(i),o=Array.isArray(r.skills)?r.skills.length:0;t.push({severity:`warning`,rule:hy,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=yy.join(`, `),i=T(e.apps);for(let e=0;e<i.length;e++){let n=i[e],a=vy(n.defaultAgent);if(!a||yy.includes(a))continue;let o=vy(n.name)??`#${e}`,s=by.get(a);if(s){t.push({severity:`warning`,rule:_y,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:gy,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 Cy=`flow-node-write-unknown-field`,wy=`flow-node-write-unprovisioned-anchor`,Ty=[`update_record`,`create_record`],Ey=[],Dy=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Oy(e){let t=e.objectName??e.object;if(!(typeof t!=`string`||t.includes(`{`)))return t||void 0}var ky=new Set(Ty);function Ay(e){let t=[];if(!Dy(e))return t;let n=T(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}`;co(n,`flows[${a}]`).forEach(({node:n,path:a,regionTrail:s},c)=>{if(typeof n.type!=`string`||!ky.has(n.type))return;let l=Dy(n.config)?n.config:void 0;if(!l)return;let u=l.fields;if(!Dy(u))return;let d=Object.keys(u);if(d.length===0)return;let f=Oy(l);if(!f)return;r??=ts(e),i??=Ln(e);let p=ns(r,f);if(!p)return;let m=io(n,c),h=s?`${s} \u203A node "${m}"`:`node "${m}"`;for(let e of d)if(!p.has(e)){if(Zo.has(e)){if(!i.get(f)?.has(e))continue;t.push({severity:`warning`,rule:wy,where:`flow "${o}" \u203A ${h}`,path:`${a}.config.fields.${e}`,message:`${n.type} writes '${e}', and ${Rn(f,e)} \u2014 `+Qo(),hint:zn(f,e)});continue}e.includes(`.`)||t.push({severity:`error`,rule:Cy,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:jy(e,[...p])})}})}),t}function jy(e,t){let n=Se(oe(e,[...t,...Zo]));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 My=[`flow`],Ny=[{name:`validateObjectReferences`,runtimeTypes:[`flow`,`dataset`],run:ch},{name:`validateSearchableFields`,runtimeTypes:[`flow`,`view`,`object`],run:wc},{name:`validateSortableFields`,runtimeTypes:[`flow`,`view`],run:Dh},{name:`validateListViewFieldRefs`,runtimeTypes:[`flow`,`view`,`object`],run:zh},{name:`validateObjectFieldRefs`,runtimeTypes:[`flow`,`object`],run:Zh},{name:`validateActionNameRefs`,run:tg},{name:`validateActionDispatchContract`,run:lg},{name:`validatePageFieldBindings`,run:Jc},{name:`validatePageVisualizationBindings`,run:Mg},{name:`validateChartBindings`,runtimeTypes:[`flow`,`report`],run:r_},{name:`validateDatasetReferences`,runtimeTypes:[`flow`,`dataset`],run:d_},{name:`validateMappingTargetFields`,run:g_},{name:`validateNavAccess`,run:Z_},{name:`validateNavTargetRefs`,run:hh},{name:`validateNavObjectServability`,run:bh},{name:`validateTranslationReferences`,run:Wv},{name:`validateTranslatableSections`,run:ty},{name:`validateFlowTemplatePaths`,run:Ao},{name:`validateAiSurfaceAffinity`,run:ay},{name:`validateAiToolReferences`,run:my},{name:`validateAiAgentAuthoring`,run:Sy},{name:`validateHookBodyWrites`,run:(e,t)=>as(e,t)},{name:`validateActionBodyWrites`,run:Ns},{name:`validateFlowNodeWrites`,run:Ay},{name:`validateReadonlyFlowWrites`,run:zo},{name:`validateReadonlyHookWrites`,run:(e,t)=>vs(e,t)},{name:`validateReadonlyActionWrites`,run:Us},{name:`validateReactPageProps`,run:Ml}];function Py(e,t){let n=[],r=t?.runtimeWriteType;for(let i of Ny)(r===void 0||(i.runtimeTypes??My).includes(r))&&n.push(...i.run(e,t));return n}function Fy(e){return typeof e==`string`?e:e&&typeof e==`object`&&typeof e.source==`string`?e.source:``}var Iy=`daysFromNow|daysAgo|today|now|date|datetime`,Ly=RegExp(`\\b(?:${Iy})\\s*\\(`),Ry=RegExp(`(?:(?:${Iy})\\s*\\([^)]*\\)\\s*(?:==|!=))|(?:(?:==|!=)\\s*(?:${Iy})\\s*\\()`),zy=`flow-time-relative-antipattern`,By=`flow-date-equality-filter`,Vy=`flow-phantom-aggregation`,Hy=`flow-double-brace-interpolation`,Uy=`flow-bare-dollar-reference`,Wy=`flow-approval-revise-dead-end`,Gy=`flow-approval-revise-unmarked-backedge`,Ky=`flow-approval-revise-disabled`,qy=`flow-approval-revise-target-not-service-owned`,Jy=`flow-runas-unscoped`,Yy=`flow-error-label-not-fault`,Xy=`flow-branch-label-unmatched`,Zy=`flow-decision-unconditional-branch`,Qy=`flow-default-edge-with-condition`,$y=`flow-multiple-default-edges`,eb=`flow-inert-node-condition`,tb=`flow-decision-mode-invalid`,nb=`flow-decision-inclusive-overlap`,rb=`flow-multi-write-unfiltered`,ib=`flow-loop-body-uncontained`,ab=`flow-try-catch-without-catch`,ob=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`]),sb=new Set([`get_record`,`create_record`,`update_record`,`delete_record`]),cb=new Set([`get_record`,`create_record`,`update_record`,`delete_record`,`http`,`notify`,`connector_action`,`script`,`subflow`,`map`,Dt]),lb=`try_catch`,ub=`loop`,db="`runAs:'user'` (the default when none is declared)";function fb(e,t){for(let n of o({nodes:e,edges:t}))for(let e of T(n.nodes))if(sb.has(typeof e.type==`string`?e.type:``))return{node:e,scope:n.scope};return null}var pb=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)"}]]),mb=new Set([`error`,`fault`,`failure`,`failed`,`catch`,`on_error`,`onerror`,`on error`]),hb=new Set([`decision`,`approval`,`screen`,`try_catch`]);function gb(e,t){return e.type===`schedule`||typeof t.triggerType==`string`&&t.triggerType===`schedule`||t.schedule!=null}function _b(e,t){return gb(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 yb(e){if(e&&typeof e==`object`&&e.dialect===`cel`){let t=e.source;if(typeof t==`string`&&Ly.test(t))return t}return null}var bb=new Set([`$gte`,`$gt`,`$lte`,`$lt`,`$ne`]);function xb(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)xb(e,t,n);continue}let e=yb(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(!bb.has(e)){if(e===`$eq`){let e=yb(t);if(e){a={op:`$eq`,src:e};break}}else if(e===`$in`&&Array.isArray(t)){for(let e of t){let t=yb(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:By})}}var Sb=/\{\{\s*[\w$][\w$.\s]*\}\}/,Cb=/(?:^|[^{])\$[A-Za-z_]\w*\.[A-Za-z_]/,wb=new Set([`condition`,`expression`,`conditions`]);function Tb(e,t,n){if(!(t&&wb.has(t))){if(typeof e==`string`){n.push(e);return}if(Array.isArray(e)){for(let r of e)Tb(r,t,n);return}if(e&&typeof e==`object`)for(let[t,r]of Object.entries(e))Tb(r,t,n)}}function Eb(e){return typeof e.label==`string`?e.label.trim().toLowerCase():``}function Db(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(!mb.has(n)||t.type===`fault`||t.condition)continue;let a=typeof t.source==`string`?t.source:``;hb.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:Yy})}}function Ob(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:Qy,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:$y})}for(let n of t){let t=typeof n.type==`string`?n.type:``;if(!ob.has(t))continue;let i=n.config??{};i.condition!=null&&Fy(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:eb})}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(Eb).filter(Boolean)),l=wt.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:tb,severity:`error`});if(o.mode===`inclusive`){let n=a.filter(e=>e.condition&&Fy(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:nb})}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:Xy,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:Zy});continue}let p=a.filter(e=>!e.condition&&e.isDefault!==!0&&!s.has(Eb(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:Zy})}}function kb(e){return e==null?!0:typeof e!=`object`||Array.isArray(e)?!1:ce(e)===`true`}function Ab(e){return e==null?"no `filter` key":Object.keys(e).length===0?"an EMPTY `filter`":`a \`filter\` that REDUCES TO TRUE (\`${jb(e)}\`)`}function jb(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 Mb(e,t,n){for(let r of t){let t=typeof r.type==`string`?r.type:``,i=pb.get(t);if(!i)continue;let a=r.config??{};if(a.multi!==!0||!kb(a.filter))continue;let o=typeof a.objectName==`string`&&a.objectName?a.objectName:`(unnamed object)`,s=Ab(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:rb})}}function Nb(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&&Eb(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 '${ut}' 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: '${ut}'\` (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:qy})}(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:Ky});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 '${ut}' node whose resubmit edge returns to '${i}' marked \`type: 'back'\` (ADR-0044). See examples/app-showcase showcase_budget_approval.`,rule:Wy}):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:Gy})}}var Pb="`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",Fb="A `catch` region cannot be empty: its `nodes` is `.min(1)`, so `catch: {}` and `catch: { nodes: [] }` are both refused by the parse.";function Ib(e){if(!e||typeof e!=`object`||Array.isArray(e))return;let t=e.nodes;return Array.isArray(t)?t:void 0}function Lb(e,t,n){for(let r of t){if(r.type!==ub)continue;let t=Ib((r.config??{}).body);if(!t)continue;let i=typeof r.id==`string`&&r.id?r.id:`(unnamed loop)`,a=(t,r,o)=>{if(!(o>ro))for(let s of t){if(!s||typeof s!=`object`)continue;let t=typeof s.type==`string`?s.type:``;if(t===lb||t===ub)continue;let c=typeof s.id==`string`&&s.id?s.id:`(unnamed node)`;if(cb.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 } } ] } }\`. ${Fb} The minimal handler is ${Pb}. 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:ib});continue}let l=no.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=Ib(e);i&&a(i,`${r} \u2192 ${t} '${c}' branch ${n}`,o+1)});continue}let i=Ib(n);i&&a(i,`${r} \u2192 ${t} '${c}' ${e}`,o+1)}}};a(t,`loop '${i}' body`,0)}}function Rb(e,t,n){for(let r of t){if(r.type!==lb)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}' (${lb})`,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: ${Pb}. ${Fb} 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:ab})}}function zb(e){let t=[];for(let n of T(e.flows)){let e=typeof n.name==`string`?n.name:`(unnamed flow)`,r=T(n.nodes),i=T(n.edges),a=r.find(e=>e.type===`start`)?.config??{};if((typeof a.triggerType==`string`?a.triggerType:``).startsWith(`record-`)){let n=Fy(a.condition).trim();n&&Ry.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:zy})}let s=typeof n.runAs==`string`?n.runAs:`user`,c=_b(n,a);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 ${db}, 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:Jy,severity:`error`})}}for(let n of o({nodes:r,edges:i})){let r=n.scope?`flow '${e}' \xB7 ${n.scope}`:`flow '${e}'`,i=T(n.nodes),a=T(n.edges);for(let e of i){let n=`${r} \xB7 node '${e.id}' (${e.type})`,i=e.config??{};i.filter&&xb(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:Vy});let a=[];Tb(so(e.config,oo(e.type)),void 0,a);for(let e of a)Sb.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:Hy}),Cb.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:Uy})}Nb(r,i,a,t),Db(r,i,a,t),Ob(r,i,a,t),Mb(r,i,t),Lb(r,i,t),Rb(r,i,t)}}return t}var Bb=`liveness-dead-property`,Vb=`liveness-experimental-property`,Hb=`liveness-planned-property`,Ub=`liveness-live-elsewhere-property`,Wb=`liveness-ledger-unreadable`;function Gb(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Kb(){try{let e=(0,C.createRequire)(import.meta.url).resolve(`@objectstack/spec/package.json`),t=(0,C.join)((0,C.dirname)(e),`liveness`);return(0,C.existsSync)(t)?t:null}catch{return null}}function qb(e,t){let n=new Map,r=(0,C.join)(e,`${t}.json`);if(!(0,C.existsSync)(r))return{map:n,fault:`missing`};let i;try{i=JSON.parse((0,C.readFileSync)(r,`utf8`))}catch{return{map:n,fault:`unreadable`}}if(!Gb(i)||!Gb(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))Jb(i)&&n.set(`${e}.${r}`,i);Jb(t)&&n.set(e,t)}return{map:n}}function Jb(e){return e?e.authorWarn===!0||e.status===`experimental`:!1}function Yb(e){return e==null?!1:typeof e!=`boolean`||e===!0}function Xb(e){if(e.status===`experimental`)return{kind:`is experimental — declared but NOT enforced at runtime`,rule:Vb,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:Hb,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:Bb,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:Ub,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 Zb(e){let t=Kb();return t?new Set(qb(t,e).map.keys()):new Set}function Qb(e,t,n,r,i){for(let[a,o]of r){let r=a.includes(`.`)?$b(t,a):[t[a]];for(let t of r instanceof Array?r:[r]){if(!Yb(t))continue;let{kind:r,rule:s,defaultHint:c}=Xb(o),l=o.authorHint??o.note??c;i.push({where:n,message:`sets \`${a}\` but this ${e} property ${r}.`,hint:l,rule:s});break}}}function $b(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 ex=[{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 tx(e,t){let n=[],r=t(`object`),i=t(`field`);for(let t of T(e.objects)){if(!Gb(t))continue;let e=typeof t.name==`string`?t.name:`(unnamed object)`;if(r.size>0&&Qb(`object`,t,`object '${e}'`,r,n),i.size>0)for(let r of T(t.fields))Gb(r)&&Qb(`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=T(e.translations);for(let e=0;e<t.length;e++){let r=t[e];if(Gb(r))for(let[t,i]of Object.entries(r))Gb(i)&&Qb(`translation`,i,`translation bundle #${e} \xB7 locale '${t}'`,a,n)}}for(let{type:r,key:i}of ex){let a=t(r);if(a.size!==0)for(let t of T(e[i]))Gb(t)&&Qb(r,t,`${r} '${typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:`(unnamed ${r})`}'`,a,n)}return n}var nx={missing:`no ledger file was found for it`,unreadable:`its ledger file does not parse as a ledger`};function rx(e){return[...e].map(([e,t])=>({where:`liveness ledger '${e}'`,message:`every author warning for \`${e}\` metadata is switched off: ${nx[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:Wb}))}function ix(e,t){let n=new Map,r=new Map,i=tx(t,t=>{let i=n.get(t);if(i)return i;let{map:a,fault:o}=qb(e,t);return n.set(t,a),o&&r.set(t,o),a});return[...rx(r),...i]}function ax(e){let t=Kb();return t?ix(t,e):[]}var ox=`permission-retired-lifecycle-residue`,sx=[[`allowRestore`,!1],[`allowPurge`,!1]],cx=/^\[REMOVED\]\s*/;function lx(e){let t=De.shape?.[e]?.description;if(typeof t!=`string`||t.length===0)return null;let n=t.replace(cx,``).trim();return n.length>0?n:null}function ux(e){let t=[],n=T(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 sx){if(!Object.prototype.hasOwnProperty.call(i,r)||i[r]!==o)continue;let s=lx(r);s!==null&&t.push({rule:ox,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 dx=`autonumber-references-unknown-field`,fx=`autonumber-references-optional-field`,px=`autonumber-references-self`,mx=`autonumber-unrecognized-token`;function hx(e){let t=[];for(let n of T(e.objects)){let e=typeof n.name==`string`?n.name:`(unnamed object)`,r=T(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)`,o=je(n),s=p(o),c=a(s),l=`object '${e}' \xB7 field '${r}' (autonumber "${o}")`;for(let e of s){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:l,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:mx,severity:`warning`})}}for(let n of c){if(n===r){t.push({where:l,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:px,severity:`error`});continue}let a=i.get(n);a?a.required||t.push({where:l,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:fx,severity:`warning`}):t.push({where:l,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:dx,severity:`error`})}}}return t}var gx=`view-key-collision`,_x=`view-ref-form-target-missing`,vx=`view-ref-form-target-kind`,yx=`view-ref-nav-view-missing`,bx=e=>e.includes("${")||e.includes(`{`);function xx(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 Sx=(e,t)=>e.startsWith(`${t}.`)?e.slice(t.length+1):e;function Cx(e){return{list:e.list,form:e.form,listViews:e.listViews,formViews:e.formViews}}function wx(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 Tx(e){let t=[],r=new Map,i=(e,t)=>{let n=r.get(e);n||r.set(e,n=new Set),n.add(t)},a=new Map,o=new Map,s=(e,t,n)=>{let r=n===`list`?a:o,i=r.get(e);i||r.set(e,i=new Set),i.add(t)},c=e=>{for(let t of[e.object,e.objectName,e.data?.object,e.list?.data?.object])if(typeof t==`string`&&t)return t},l=[];for(let t of T(e.views)){if(t.viewKind){let e=t.viewKind===`form`?`form`:`list`;if(typeof t.name==`string`){i(t.name,e);let n=c(t);n&&s(n,t.name,e)}continue}if(!n(t))continue;let e=wx(t);e&&l.push({object:e,container:t})}for(let t of T(e.objects)){let e=typeof t.name==`string`?t.name:void 0;e&&(t.list||t.form||t.listViews||t.formViews)&&l.push({object:e,container:Cx(t)})}for(let{object:e,container:n}of l){let{items:r,collisions:a}=Fe(e,n);for(let t of r)i(t.name,t.viewKind),s(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:gx,severity:`warning`})}let u=new Set,d=(e,n)=>{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(u.has(o))return;u.add(o);let s=n?`action '${a}' on object '${n}'`:`action '${a}'`,c=r.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:_x,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:vx,severity:`error`})}};for(let t of T(e.objects)){let e=typeof t.name==`string`?t.name:void 0;for(let n of T(t.actions))d(n,e)}for(let t of T(e.actions))d(t);let f=new Set,p=(e,n)=>{let r=typeof e.objectName==`string`?e.objectName:void 0,i=typeof e.viewName==`string`?e.viewName:void 0;if(!r||!i||bx(i)||typeof e.recordId==`string`&&e.recordId||e.requiresObject)return;let s=a.get(r);if(!s||s.size===0||xx(i,s,r))return;let c=typeof e.id==`string`&&e.id||typeof e.label==`string`&&e.label||`(unnamed)`,l=JSON.stringify([n,c,r,i]);if(f.has(l))return;f.add(l);let u=[...s].map(e=>Sx(e,r)),d=o.get(r),p=!!d&&xx(i,d,r);t.push({where:`app '${n}' \xB7 nav '${c}'`,message:`Navigation entry opens view '${i}' 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}': ${Qn(u)}.`,hint:`Correct the name, declare '${i}' 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.`:``)+D(i,u),rule:yx,severity:`error`})},m=(e,t)=>{if(Array.isArray(e))for(let n of e){if(!n||typeof n!=`object`||Array.isArray(n))continue;let e=n;p(e,t),Array.isArray(e.children)&&m(e.children,t)}};for(let[t,n]of T(e.apps).entries()){let e=typeof n.name==`string`&&n.name?n.name:`#${t}`;m(n.navigation,e);for(let t of T(n.areas))m(t.items,e),m(t.navigation,e)}return t}function Ex(e){return`object "${e?.name}"`}function Dx(e,t,n,r){let i=(typeof t?.name==`string`&&t.name.trim()?`'${t.name.trim()}'`:``)||(r.length>0?`[${r.join(`, `)}]`:`#${n}`);return`${Ex(e)} \xB7 index ${i}`}function Ox(e,t){return`${Ex(e)} \xB7 field '${t}'`}var kx=new Set([`lookup`,`master_detail`]),Ax=new Set([`number`,`currency`,`integer`,`decimal`,`percent`,`float`,`double`]),jx=new Set([`select`,`multiselect`,`radio`,`enum`]);function Mx(e){return v.has(e)||ue.has(e)}var Nx=[`name`,`title`,`subject`,`label`,`full_name`,`display_name`,`code`],Px=/_(line|lines|line_item|line_items|item|items|detail|details|entry|entries)$/,Fx=[`comment`,`attachment`,`note`,`log`,`audit`,`activity`,`activities`,`history`,`event`,`reaction`,`like`,`mention`,`notification`,`message`];function Ix(e){return Px.test(e)}function Lx(e){let t=e.toLowerCase();return Fx.some(e=>t===e||t.endsWith(`_${e}`)||t.endsWith(`_${e}s`))}function Rx(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 zx(e){return we({reference:e?.reference},`data-model-rules refOf`)}var Bx=`unique/double-declaration`,Vx=`unique/unscoped-declared-index`,Hx=`unique/legacy-organization-composite`;function Ux(e){let t=e?.tenancy?.tenantField;return typeof t==`string`&&t.trim()?t.trim():`organization_id`}function Wx(e){return e===!0||e===`global`||e===`organization`}function Gx(e){return e===`global`?`global`:`organization`}function Kx(e){return e===`organization`?`organization`:`global`}function qx(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:Vx,where:Dx(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 Jx(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(!Wx(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 Rx(r.fields)){if(!Wx(i?.unique))continue;let o=a.get(e);if(!o)continue;let s=Gx(i.unique),c=Kx(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:Bx,where:Ox(r,e),message:f,path:`objects[${n}]`,fix:p})}}return t}function Yx(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=Ux(r),a=Array.isArray(r.indexes)?r.indexes:[];for(let e=0;e<a.length;e++){let o=a[e];if(!Wx(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:Hx,where:Dx(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 Xx(e){let t=[...qx(e),...Jx(e),...Yx(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 Rx(t.fields)){if(!kx.has(n?.type))continue;let i=zx(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=Rx(a.fields),c=!!a.nameField||s.some(e=>Nx.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(jx.has(s)&&(Array.isArray(r.options)&&r.options.length>0||r.optionsFrom||r.dataSource||zx(r)||t.push({severity:`warning`,rule:`field/select-missing-options`,message:`${s} field "${a.name}.${e}" has no options`,path:`${i}.options`})),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?Rx(r.fields).find(e=>e.name===l):void 0)?.def?.type;typeof o==`string`&&!Mx(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(!kx.has(s))continue;let c=zx(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'`}),Ix(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`&&Ix(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&&Lx(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||zx(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=Rx(e.fields).find(e=>Ax.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 Zx=[`validate`,`build`,`lint`],Qx=[`cli`,`runtime-publish`],X=Zx,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.`,$x=`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.`,eS=`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).`,tS=`expression-invalid`,nS=[{name:`validateStackExpressions`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-expressions.ts`,surfaces:Q,runtimeTypes:[`flow`,`action`,`hook`],run:e=>na(e).map(e=>({severity:e.severity??`error`,rule:tS,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=>Pa(e)},{name:`validateFunctionalCompleteness`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-functional-completeness.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>Ra(e)},{name:`validateManagedApiMethods`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-managed-api-methods.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>Ha(e)},{name:`validateViewContainers`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-view-containers.ts`,surfaces:Z,surfaceReason:$,run:e=>Js(e)},{name:`validateWidgetBindings`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-widget-bindings.ts`,surfaces:Q,runtimeTypes:[`dashboard`],run:e=>Rr(e)},{name:`validateDatasetMeasureAggregates`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-dataset-measure-aggregates.ts`,surfaces:Q,runtimeTypes:[`dataset`],run:e=>Wr(e)},{name:`validateDashboardActionRefs`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-dashboard-action-refs.ts`,surfaces:Z,surfaceReason:$,run:e=>Qp(e)},{name:`validateFilterTokens`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-filter-tokens.ts`,surfaces:Z,surfaceReason:$,run:e=>sm(e)},{name:`validateFlowFilterTokens`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-flow-filter-tokens.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>fm(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=>Hm(e)},{name:`validateEmptyCombinators`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-empty-combinators.ts`,surfaces:Q,runtimeTypes:[`flow`,`report`],run:e=>th(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)=>Py(e,t)},{name:`validateComponentProps`,tier:`advisory`,input:`normalized`,commands:X,source:`packages/lint/src/validate-component-props.ts`,surfaces:Z,surfaceReason:$,run:e=>Vg(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=>Gg(e)},{name:`validateResponsiveStyles`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-responsive-styles.ts`,surfaces:Z,surfaceReason:$,run:e=>uc(e)},{name:`validateJsxPages`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-jsx-pages.ts`,surfaces:Z,surfaceReason:$x,run:(e,t)=>fc(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:$x,run:e=>hc(e)},{name:`validatePageSourceStyling`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-page-source-styling.ts`,surfaces:Z,surfaceReason:$,run:e=>Fl(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=>ad(e)},{name:`validateFlowTriggerReadiness`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-flow-trigger-readiness.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>$a(e)},{name:`validateApprovalApprovers`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-approval-approvers.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>Td(e)},{name:`validateRecordTitle`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-record-title.ts`,surfaces:Z,surfaceReason:eS,run:e=>Rl(e)},{name:`validateFieldConsumers`,tier:`advisory`,input:`normalized`,commands:X,source:`packages/lint/src/validate-field-consumers.ts`,surfaces:Z,surfaceReason:$,run:e=>Ev(e)},{name:`validateSemanticRoles`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-semantic-roles.ts`,surfaces:Z,surfaceReason:eS,run:e=>Wl(e)},{name:`validateFormLayout`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-form-layout.ts`,surfaces:Z,surfaceReason:$,run:e=>tu(e)},{name:`validateActionLocations`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-action-locations.ts`,surfaces:Z,surfaceReason:$,run:e=>mg(e)},{name:`validateSeedReplaySafety`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-seed-replay-safety.ts`,surfaces:Z,surfaceReason:$,run:e=>Dd(e)},{name:`validateSeedStateMachine`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-seed-state-machine.ts`,surfaces:Z,surfaceReason:$,run:e=>jd(e)},{name:`validateVisibilityPredicates`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-visibility-predicates.ts`,surfaces:Q,runtimeTypes:[`view`],run:e=>Nu(e)},{name:`validatePredicatePathRefs`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-predicate-path-refs.ts`,surfaces:Q,runtimeTypes:[`view`],run:e=>td(e)},{name:`lintFlowPatterns`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/lint-flow-patterns.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>zb(e).map(e=>({severity:e.severity??`warning`,rule:e.rule,where:e.where,path:e.where,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=>ax(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=>ux(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=>hx(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=>Tx(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:eS,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=>qx(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:eS,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=>Jx(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:eS,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=>Yx(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=>uf(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=>df(e)},{name:`validateOrgAxisRedLines`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-org-axis-red-lines.ts`,surfaces:Z,surfaceReason:$,run:e=>bf(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=>Wp(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)=>Ap(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=>N_(e)},{name:`validateRuleSchemaFormats`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-rule-schema-formats.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>W_(e)}];function rS(e){return nS.filter(t=>t.commands.includes(e))}function iS(e,t){let n=[],r={sduiManifest:t.sduiManifest,loweredHookRefs:t.loweredHookRefs,judgeFilter:t.judgeFilter};for(let i of rS(e)){let e=i.input===`normalized`?t.normalized:t.parsed??t.normalized;n.push(...i.run(e,r))}return n}function aS(e){return{errors:e.filter(e=>e.severity===`error`),advisories:e.filter(e=>e.severity!==`error`)}}var oS={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 sS(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[cS];return typeof t!=`string`||t===``||t===lS||n.has(t)?!0:ef(e)})}var cS=`_packageId`,lS=`sys_metadata`,uS=Object.keys({objects:!0,permissions:!0,books:!0,datasets:!0});function dS(e){return nS.filter(t=>t.surfaces.includes(`runtime-publish`)&&(t.runtimeTypes??[]).includes(e))}function fS(){let e=new Set;for(let t of nS)if(t.surfaces.includes(`runtime-publish`))for(let n of t.runtimeTypes??[])e.add(n);return[...e].sort()}function pS(e){return oS[e]??null}var mS=e=>`${e.rule}\0${e.where}\0${e.path}\0${e.message}`;function hS(e){let t=pS(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 uS){let a=e.context?.[n]??[],o=n===`objects`?sS(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 gS(e,t){let n=new Set(t);return e.filter(e=>n.has(e))}function _S(e){if(e.length===0)return/(?!)/;let t=e.map(e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)).join(`|`);return RegExp(`^(${t})\\[(\\d+)\\](.*)$`)}var vS=gS(uS,new Set(Object.values(oS))),yS=/^[A-Za-z_][A-Za-z0-9_]*$/,bS=_S(vS);function xS(e,t){let n=bS.exec(e);if(!n)return e;let[,r,i,a]=n;if(!vS.includes(r))return e;let o=t[r]?.[Number(i)],s=o&&typeof o==`object`?o.name:void 0;return typeof s!=`string`||!yS.test(s)?e:`${r}.${s}${a}`}function SS(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 CS(e){let t=dS(e.type),n={errors:[],advisories:[],rulesRun:[]};if(t.length===0)return n;let r=hS({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},a=new Set(SS(t,r.baseline,i).map(mS)),o=SS(t,r.candidate,i).filter(e=>!a.has(mS(e))).map(e=>{let t=xS(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 wS=e=>!!e&&typeof e==`object`&&!Array.isArray(e),TS=e=>wS(e)&&typeof e.dialect==`string`,ES=et;function DS(e){return e?e.issues.map(e=>`${e.path.map(String).join(`.`)||`(root)`}: ${e.message}`).join(` | `):`(no issues reported)`}function OS(e,t,n,r,i,a,o=new Set){if(typeof e==`string`){TS(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++)OS(e[s],t[s],`${n}[${s}]`,r,i,a,o);return}if(!wS(e)||!wS(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])=>TS(e)&&e.source===c);if(n){a.push({page:r,path:e,authored:c,normalizedTo:n[0],door:i});continue}}OS(c,l,e,r,i,a,o)}}finally{o.delete(e)}}}function kS(e,t){let n={findings:[],componentParseErrors:[],unmappedTypes:[],unreadableProps:[],componentCount:0};if(!wS(e))return n.pageParseError=`not an object`,n;let r=[],i=_.safeParse(e);i.success?OS(e,i.data,``,t,`PageSchema`,r):n.pageParseError=DS(i.error);let a=Ac(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=b.safeParse(e);s.success?OS(e,s.data,a,t,`PageComponentSchema`,r):n.componentParseErrors.push({path:a,type:o,issues:DS(s.error)});let c=ES[o];if(!c){n.unmappedTypes.push({path:a,type:o});continue}if(!wS(e.properties))continue;let l=c.safeParse(e.properties);l.success?OS(e.properties,l.data,`${a}.properties`,t,`ComponentPropsMap`,r):n.unreadableProps.push({path:a,type:o,issues:DS(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 AS(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{Fs as ACTION_API_UPDATE_READONLY_WHEN_FIELD,xs as ACTION_BODY_SOURCE_UNPARSEABLE,Ts as ACTION_BODY_WRITE_EXCLUSIONS,Es as ACTION_BODY_WRITE_PATTERNS,Cs as ACTION_BODY_WRITE_PATTERN_IDS,ys as ACTION_BODY_WRITE_UNKNOWN_FIELD,Ss as ACTION_BODY_WRITE_UNPROVISIONED_ANCHOR,ng as ACTION_DISPATCH_CONTRACT_MISMATCH,Qh as ACTION_NAME_UNDEFINED,ug as ACTION_NO_PLACEMENT,bs as ACTION_RECORD_WRITE_DISCARDED,Ds as ACTION_RECORD_WRITE_PATTERNS,ws as ACTION_RECORD_WRITE_PATTERN_IDS,hy as AGENT_AUTHORING_WITHDRAWN,ny as AI_SKILL_SURFACE_MISMATCH,oy as AI_SKILL_TOOL_UNRESOLVED,dd as APPROVAL_APPROVERS_MAY_RESOLVE_EMPTY,hd as APPROVAL_APPROVER_CROSS_ORG_UNSUPPORTED,od as APPROVAL_APPROVER_NOT_MEMBERSHIP_TIER,sd as APPROVAL_APPROVER_TYPE_DEPRECATED,cd as APPROVAL_APPROVER_TYPE_UNKNOWN,ld as APPROVAL_APPROVER_TYPE_UNSUPPORTED,md as APPROVAL_DECISION_OUTPUTS_RESERVED,ud as APPROVAL_ESCALATION_REASSIGN_NO_TARGET,fd as APPROVAL_EXPRESSION_INVALID,pd as APPROVAL_EXPRESSION_NO_EMPTY_POLICY,Zx as AUTHORING_COMMANDS,nS as AUTHORING_RULES,Qx as AUTHORING_SURFACES,mx as AUTONUMBER_LITERAL_TOKEN,fx as AUTONUMBER_OPTIONAL_FIELD,px as AUTONUMBER_SELF_REFERENCE,dx as AUTONUMBER_UNKNOWN_FIELD,nd as CAPABILITY_REFERENCE_UNKNOWN,Yg as CHART_AXIS_NOT_SELECTED,dr as CHART_CONFIG_MISSING,Jg as CHART_DATASET_UNKNOWN,pr as CHART_DIMENSIONS_MISSING,Kg as CHART_DIMENSION_UNKNOWN,ur as CHART_FIELD_UNKNOWN,fr as CHART_MEASURES_MISSING,qg as CHART_MEASURE_UNKNOWN,Pg as COMPONENT_PROPS_INVALID,Ng as COMPONENT_PROPS_UNKNOWN_KEY,Hg as COMPONENT_TYPE_UNKNOWN,Kp as DASHBOARD_ACTION_ROUTE_UNRESOLVED,Gp as DASHBOARD_ACTION_TARGET_UNDEFINED,xr as DASHBOARD_FILTER_FIELD_NOT_INCLUDED,yr as DASHBOARD_FILTER_FIELD_UNKNOWN,br as DASHBOARD_FILTER_FIELD_UNPROVISIONED,o_ as DATASET_FIELD_NOT_INCLUDED,a_ as DATASET_FIELD_UNKNOWN,s_ as DATASET_FILTER_FIELD_UNKNOWN,i_ as DATASET_INCLUDE_UNKNOWN,_y as DEFAULT_AGENT_LEGACY_ALIAS,gy as DEFAULT_AGENT_OUTSIDE_ROSTER,tS as EXPRESSION_INVALID,nv as FIELD_CARRIER_ROOTS,tv as FIELD_CONSUMER_ROOTS,Bl as FIELD_GROUP_EMPTY,Vl as FIELD_GROUP_SHADOWED,zl as FIELD_GROUP_UNDECLARED,Q_ as FIELD_NO_CONSUMERS,Wi as FIELD_RULE_BOUND_ROOTS,Um as FILTER_EMPTY_COMBINATOR,Wm as FILTER_EMPTY_NODE,pm as FILTER_PRESET_COMPARAND,$p as FILTER_TOKEN_UNKNOWN,Wy as FLOW_APPROVAL_REVISE_DEAD_END,Ky as FLOW_APPROVAL_REVISE_DISABLED,qy as FLOW_APPROVAL_REVISE_TARGET_NOT_SERVICE_OWNED,Gy as FLOW_APPROVAL_REVISE_UNMARKED_BACKEDGE,Uy as FLOW_BARE_DOLLAR_REF,Xy as FLOW_BRANCH_LABEL_UNMATCHED,By as FLOW_DATE_EQUALITY_FILTER,nb as FLOW_DECISION_INCLUSIVE_OVERLAP,tb as FLOW_DECISION_MODE_INVALID,Zy as FLOW_DECISION_UNCONDITIONAL_BRANCH,Qy as FLOW_DEFAULT_EDGE_WITH_CONDITION,Hy as FLOW_DOUBLE_BRACE_INTERP,Wa as FLOW_DRAFT_STATUS_AMBIGUOUS,Yy as FLOW_ERROR_LABEL_NOT_FAULT,cm as FLOW_FILTER_TOKEN_UNKNOWN,eb as FLOW_INERT_NODE_CONDITION,ib as FLOW_LOOP_BODY_UNCONTAINED,$y as FLOW_MULTIPLE_DEFAULT_EDGES,rb as FLOW_MULTI_WRITE_UNFILTERED,Cy as FLOW_NODE_WRITE_UNKNOWN_FIELD,wy as FLOW_NODE_WRITE_UNPROVISIONED_ANCHOR,Vy as FLOW_PHANTOM_AGGREGATION,Jy as FLOW_RUNAS_UNSCOPED,Ci as FLOW_TEMPLATE_DATE_FUNCTIONS,po as FLOW_TEMPLATE_FIELD_UNPROVISIONED,fo as FLOW_TEMPLATE_LOOKUP_TRAVERSAL,uo as FLOW_TEMPLATE_UNKNOWN_FIELD,wi as FLOW_TEMPLATE_VALUE_FUNCTIONS,zy as FLOW_TIME_RELATIVE_ANTIPATTERN,Ka as FLOW_TIME_RELATIVE_DESCRIPTOR_INVALID,qa as FLOW_TIME_RELATIVE_DESCRIPTOR_UNROUTABLE,Ga as FLOW_TRIGGER_UNKNOWN_EVENT,Ua as FLOW_TRIGGER_UNKNOWN_OBJECT,Ja as FLOW_TRIGGER_UNROUTABLE,ab as FLOW_TRY_CATCH_WITHOUT_CATCH,jo as FLOW_UPDATE_READONLY_FIELD,Mo as FLOW_UPDATE_READONLY_WHEN_FIELD,Ty as FLOW_WRITE_NODE_TYPES,Ey as FLOW_WRITE_NODE_TYPES_DEFERRED,Xl as FORM_FIELD_UNKNOWN,Zl as FORM_SECTION_GROUP_UNKNOWN,cs as HOOK_API_UPDATE_READONLY_FIELD,ls as HOOK_API_UPDATE_READONLY_WHEN_FIELD,Uo as HOOK_BODY_SOURCE_UNPARSEABLE,qo as HOOK_BODY_WRITE_EXCLUSIONS,Go as HOOK_BODY_WRITE_PATTERNS,Ko as HOOK_BODY_WRITE_PATTERN_IDS,Ho as HOOK_BODY_WRITE_UNKNOWN_FIELD,Wo as HOOK_BODY_WRITE_UNPROVISIONED_ANCHOR,Ah as LIST_VIEW_FIELD_DOTTED,kh as LIST_VIEW_FIELD_UNKNOWN,ja as LIST_VIEW_FILTERS_IN_VIEWS_MODE,Bb as LIVENESS_DEAD_PROPERTY,Vb as LIVENESS_EXPERIMENTAL_PROPERTY,Wb as LIVENESS_LEDGER_UNREADABLE,Ub as LIVENESS_LIVE_ELSEWHERE_PROPERTY,Hb as LIVENESS_PLANNED_PROPERTY,za as MANAGED_API_METHOD_UNAFFORDABLE,f_ as MAPPING_TARGET_FIELD_UNKNOWN,z_ as MAX_SCHEMA_WALK_DEPTH,zr as MEASURE_AGGREGATE_FIELD_TYPE_REFUSED,gr as MEASURE_AGGREGATE_INCOHERENT,J_ as NAV_OBJECT_UNGRANTED,gh as NAV_OBJECT_UNSERVABLE,lh as NAV_TARGET_UNRESOLVED,ei as NULL_GUARD_HINT,gg as OBJECTUI_DERIVATION_PREDICATES,Bh as OBJECT_FIELD_REF_UNKNOWN,ih as OBJECT_REFERENCE_UNKNOWN,ah as OBJECT_REFERENCE_UNREGISTERED_PLATFORM,da as OPEN_VOCABULARY_PROBES,pf as ORG_AXIS_CROSS_ORG_BU_GRANT,ff as ORG_AXIS_PERMISSION_INHERITANCE,Ic as PAGE_FIELD_UNKNOWN,Lc as PAGE_FIELD_UNPROVISIONED,Rc as PAGE_SECTION_GROUP_UNKNOWN,Nl as PAGE_SOURCE_CLASSNAME,hg as PAGE_VISUALIZATION_WITHOUT_BINDING,aa as PARSE_FAILURE_HINT,ox as PERMISSION_RETIRED_LIFECYCLE_RESIDUE,Pu as PREDICATE_PATH_UNRESOLVED,Fu as PREDICATE_PATH_UNROOTED,Iu as PREDICATE_RHS_PATH_SHAPED,fa as PRE_SEAL_PHASES,Ol as REACT_BLOCK_NEEDS_RECORD_CONTEXT,fl as REACT_CHART_AGGREGATE_INVALID,pl as REACT_CHART_AXIS_UNKNOWN,ml as REACT_CHART_DRILLDOWN_INVALID,ul as REACT_CHART_FIELD_UNKNOWN,dl as REACT_CHART_FIELD_UNPROVISIONED,sl as REACT_PAGE_SOURCE_UNPARSEABLE,cl as REACT_PROP_DEPRECATED,ll as REACT_PROP_RETIRED,Ls as READONLY_ACTION_WRITE_EXCLUSIONS,Is as READONLY_ACTION_WRITE_PATTERN_IDS,ds as READONLY_HOOK_WRITE_EXCLUSIONS,us as READONLY_HOOK_WRITE_PATTERN_IDS,Ny as REFERENCE_INTEGRITY_RULES,Bn as RELATIONSHIP_FIELD_TYPES,Cf as RLS_PREDICATE_OVER_BUDGET,xf as RLS_PREDICATE_UNENFORCEABLE,wf as RLS_PREDICATE_UNKNOWN_FIELD,Tf as RLS_PREDICATE_UNKNOWN_USER_VARIABLE,Sf as RLS_PREDICATE_UNPARSEABLE,x_ as RUNTIME_AJV_OPTIONS,pa as SEAL_MARKERS,gc as SEARCHABLE_FIELD_UNKNOWN,vc as SEARCHABLE_FIELD_UNPROVISIONED,_c as SEARCHABLE_FIELD_UNSEARCHABLE,Id as SECURITY_ANCHOR_HIGH_PRIVILEGE,Rd as SECURITY_BOOK_AUDIENCE_UNKNOWN_SET,Kd as SECURITY_CBP_AMBIGUOUS_RELATION,Gd as SECURITY_CBP_NO_RELATION,Wd as SECURITY_DELEGATION_MISSING_REASON,Pd as SECURITY_EXTERNAL_WIDER,Hd as SECURITY_FLS_UNKNOWN_FIELD,Vd as SECURITY_FLS_UNQUALIFIED_KEY,Ud as SECURITY_GRANT_EXPIRED_AT_AUTHORING,Bd as SECURITY_MASTER_DETAIL_UNGRANTED,Nd as SECURITY_OWD_ALIAS,Md as SECURITY_OWD_UNSET,zd as SECURITY_PRIVATE_NO_READSCOPE,Ld as SECURITY_ROLE_WORD,Fd as SECURITY_WILDCARD_VAMA,Ed as SEED_INSERT_MODE_DUPLICATES_ON_REPLAY,Od as SEED_VALUE_OUTSIDE_STATE_MACHINE,Hl as SEMANTIC_ROLE_FIELD_UNKNOWN,Ul as SEMANTIC_ROLE_FIELD_UNPROVISIONED,Pp as SHARING_RULE_OBJECT_CONTROLLED_BY_PARENT,Np as SHARING_RULE_OBJECT_NOT_SHAREABLE,Mp as SHARING_RULE_RUNTIME_VARIABLE_CONDITION,jp as SHARING_RULE_UNLOWERABLE_CONDITION,xh as SORT_FIELD_UNKNOWN,Ch as SORT_FIELD_UNPROVISIONED,Sh as SORT_FIELD_UNSORTABLE,ca as STARTUP_OPEN_VOCABULARY_VERDICT,ua as STARTUP_SOURCE_UNPARSEABLE,la as STARTUP_VERDICT_ASSERTIVE_WORDING,ya as STARTUP_VERDICT_HINT,Xs as STYLE_CLASSNAME_TAILWIND,Ys as STYLE_NODE_MISSING_ID,Zs as STYLE_RESPONSIVE_NO_BASE,Qs as STYLE_UNKNOWN_CSS_PROPERTY,$s as STYLE_UNKNOWN_TOKEN,hr as TABLE_COUNT_ONLY,Il as TITLE_FORMAT_RETIRED,Ll as TITLE_UNRESOLVABLE,kv as TRANSLATION_OPTION_KEY_UNKNOWN,qv as TRANSLATION_SECTION_NAME_MISSING,Ov as TRANSLATION_TARGET_UNKNOWN,Bx as UNIQUE_DOUBLE_DECLARATION,Hx as UNIQUE_LEGACY_ORGANIZATION_COMPOSITE,Vx as UNIQUE_UNSCOPED_DECLARED_INDEX,y_ as VALIDATION_RULE_REGEX_UNCOMPILABLE,b_ as VALIDATION_RULE_SCHEMA_UNCOMPILABLE,P_ as VALIDATION_RULE_SCHEMA_UNKNOWN_FORMAT,Ws as VIEW_CONTAINER_SHAPE,gx as VIEW_KEY_COLLISION,vx as VIEW_REF_FORM_TARGET_KIND,_x as VIEW_REF_FORM_TARGET_MISSING,yx as VIEW_REF_NAV_VIEW_MISSING,uu as VISIBILITY_BARE_IDENTIFIER,fu as VISIBILITY_PREDICATE_OVER_BUDGET,du as VISIBILITY_PREDICATE_SYNTAX,pu as VISIBILITY_PREDICATE_UNKNOWN_FUNCTION,lu as VISIBILITY_ROOT_MISLAYERED,sr as WIDGET_DATASET_UNKNOWN,cr as WIDGET_DIMENSION_UNKNOWN,Cr as WIDGET_FILTER_FIELD_NOT_INCLUDED,Sr as WIDGET_FILTER_FIELD_UNKNOWN,_r as WIDGET_LEGACY_ANALYTICS_SHAPE,vr as WIDGET_LEGACY_ANALYTICS_UNRENDERABLE,mr as WIDGET_MEASURES_MISSING,lr as WIDGET_MEASURE_UNKNOWN,wr as WIDGET_SORTBY_UNSELECTED,kS as auditPageExpressionEnvelopes,Zb as authorWarnedProperties,rS as authoringRulesFor,G_ as buildAccessMatrix,hS as buildRuntimeWriteSnapshots,Fc as checkSectionGroupRefs,Eh as checkSortDeclaration,Ei as classifyFlowTemplateToken,Jn as describeFieldPathVerdict,ia as describeParseFailure,q_ as diffAccessMatrix,is as extractHookBodyWriteSet,rs as extractHookBodyWrites,Xi as fieldRuleRootIssue,Aa as findStartupRegistryVerdicts,mi as findUnguardedNullableOperands,Nc as indexObjectFieldGroups,Kn as indexObjectGraph,kc as isSourceAuthoredPage,Yn as isUnjudgeable,qn as joinablePrefixes,hx as lintAutonumberFormats,Xx as lintDataModel,zb as lintFlowPatterns,Yx as lintLegacyOrganizationComposites,ax as lintLivenessProperties,Jx as lintUniqueDeclarations,qx as lintUnscopedDeclaredIndexes,Tx as lintViewRefs,Qn as listNames,sS as narrowObjectsToPackageClosure,Xn as nearestName,U_ as nearestRegisteredFormat,gi as nullGuardMessage,AS as renderBareExpressionFindings,E as resolveFieldPath,iS as runAuthoringRules,CS as runRuntimeAuthoringRules,dS as runtimeAuthoringRulesFor,fS as runtimeGatedTypes,Pc as sectionGroupRefs,aS as splitBySeverity,pS as stackKeyForType,D as suggestName,Ns as validateActionBodyWrites,lg as validateActionDispatchContract,mg as validateActionLocations,tg as validateActionNameRefs,Sy as validateAiAgentAuthoring,ay as validateAiSurfaceAffinity,my as validateAiToolReferences,Td as validateApprovalApprovers,ad as validateCapabilityReferences,r_ as validateChartBindings,Vg as validateComponentProps,Gg as validateComponentTypes,Qp as validateDashboardActionRefs,Wr as validateDatasetMeasureAggregates,d_ as validateDatasetReferences,th as validateEmptyCombinators,Ev as validateFieldConsumers,sm as validateFilterTokens,fm as validateFlowFilterTokens,Ay as validateFlowNodeWrites,Ao as validateFlowTemplatePaths,$a as validateFlowTriggerReadiness,tu as validateFormLayout,Ra as validateFunctionalCompleteness,as as validateHookBodyWrites,fc as validateJsxPages,zh as validateListViewFieldRefs,Pa as validateListViewMode,Ha as validateManagedApiMethods,g_ as validateMappingTargetFields,Z_ as validateNavAccess,bh as validateNavObjectServability,hh as validateNavTargetRefs,Zh as validateObjectFieldRefs,ch as validateObjectReferences,bf as validateOrgAxisRedLines,Jc as validatePageFieldBindings,Fl as validatePageSourceStyling,Mg as validatePageVisualizationBindings,td as validatePredicatePathRefs,Hm as validatePresetComparands,Ml as validateReactPageProps,hc as validateReactPages,Us as validateReadonlyActionWrites,zo as validateReadonlyFlowWrites,vs as validateReadonlyHookWrites,Rl as validateRecordTitle,Py as validateReferenceIntegrity,uc as validateResponsiveStyles,ux as validateRetiredPermissionResidue,Ap as validateRlsPredicateEnforceability,N_ as validateRuleCompilability,W_ as validateRuleSchemaFormats,wc as validateSearchableFields,uf as validateSecurityPosture,df as validateSecurityRoleWord,Dd as validateSeedReplaySafety,jd as validateSeedStateMachine,Wl as validateSemanticRoles,Wp as validateSharingRuleEnforceability,Dh as validateSortableFields,na as validateStackExpressions,ty as validateTranslatableSections,Wv as validateTranslationReferences,Js as validateViewContainers,Nu as validateVisibilityPredicates,Rr as validateWidgetBindings,or as walkFilterFieldKeys,Ac as walkPageComponents};