@lunora/studio 1.0.0-alpha.36 → 1.0.0-alpha.361

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 (475) hide show
  1. package/LICENSE.md +6 -0
  2. package/README.md +4 -4
  3. package/dist/index.d.mts +1621 -0
  4. package/dist/index.d.ts +1013 -809
  5. package/dist/index.mjs +1 -0
  6. package/dist/mount.d.mts +23 -0
  7. package/dist/mount.d.ts +13 -11
  8. package/dist/mount.mjs +1 -0
  9. package/dist/packem_chunks/AdvisorHealthPanel.mjs +1 -0
  10. package/dist/packem_chunks/ApiTab.mjs +1 -0
  11. package/dist/packem_chunks/AuditPanel.mjs +1 -0
  12. package/dist/packem_chunks/DeploymentHealthPanel.mjs +1 -0
  13. package/dist/packem_chunks/ExportImportPanel.mjs +8 -0
  14. package/dist/packem_chunks/FileBrowser.mjs +4 -0
  15. package/dist/packem_chunks/FunctionRunner.mjs +1 -0
  16. package/dist/packem_chunks/FunctionStatsPanel.mjs +1 -0
  17. package/dist/packem_chunks/HealthPanel.mjs +1 -0
  18. package/dist/packem_chunks/InsightsPanel.mjs +1 -0
  19. package/dist/packem_chunks/LogsPanel.mjs +1 -0
  20. package/dist/packem_chunks/MailPanel.mjs +2 -0
  21. package/dist/packem_chunks/MetricsPanel.mjs +1 -0
  22. package/dist/packem_chunks/NotificationsPanel.mjs +1 -0
  23. package/dist/packem_chunks/PitrPanel.mjs +1 -0
  24. package/dist/packem_chunks/SchemaViewer.mjs +1 -0
  25. package/dist/packem_chunks/SecurityAdvisorPanel.mjs +1 -0
  26. package/dist/packem_chunks/SettingsPanel.mjs +1 -0
  27. package/dist/packem_chunks/SqlEditorPanel.mjs +10 -0
  28. package/dist/packem_chunks/TableEditor.mjs +1 -0
  29. package/dist/packem_chunks/agents-panel.mjs +1 -0
  30. package/dist/packem_chunks/ai-usage-panel.mjs +1 -0
  31. package/dist/packem_chunks/analytics-panel.mjs +1 -0
  32. package/dist/packem_chunks/architecture-panel.mjs +1 -0
  33. package/dist/packem_chunks/auth-audit-panel.mjs +1 -0
  34. package/dist/packem_chunks/auth-config-panel.mjs +1 -0
  35. package/dist/packem_chunks/auth-sessions-panel.mjs +1 -0
  36. package/dist/packem_chunks/containers-panel.mjs +1 -0
  37. package/dist/packem_chunks/dashboards-panel.mjs +1 -0
  38. package/dist/packem_chunks/evals-panel.mjs +1 -0
  39. package/dist/packem_chunks/fanout-panel.mjs +1 -0
  40. package/dist/packem_chunks/flags-panel.mjs +1 -0
  41. package/dist/packem_chunks/issues-panel.mjs +1 -0
  42. package/dist/packem_chunks/kv-browser.mjs +1 -0
  43. package/dist/packem_chunks/log-drains-panel.mjs +4 -0
  44. package/dist/packem_chunks/migrations-route.mjs +1 -0
  45. package/dist/packem_chunks/organizations-panel.mjs +1 -0
  46. package/dist/packem_chunks/payments-panel.mjs +1 -0
  47. package/dist/packem_chunks/permissions-panel.mjs +1 -0
  48. package/dist/packem_chunks/privacy-requests-panel.mjs +1 -0
  49. package/dist/packem_chunks/queues-panel.mjs +1 -0
  50. package/dist/packem_chunks/reactors-panel.mjs +1 -0
  51. package/dist/packem_chunks/rls-panel.mjs +1 -0
  52. package/dist/packem_chunks/schedule-panel.mjs +1 -0
  53. package/dist/packem_chunks/storage-rules-panel.mjs +1 -0
  54. package/dist/packem_chunks/subscriptions-panel.mjs +1 -0
  55. package/dist/packem_chunks/sync-client-panel.mjs +1 -0
  56. package/dist/packem_chunks/theme-indicator.mjs +1 -0
  57. package/dist/packem_chunks/traces-panel.mjs +1 -0
  58. package/dist/packem_chunks/users-panel.mjs +1 -0
  59. package/dist/packem_chunks/vector-browser.mjs +1 -0
  60. package/dist/packem_chunks/workflows-panel.mjs +1 -0
  61. package/dist/packem_shared/ADMIN_FUNCTIONS-4aGsMs95.mjs +1 -0
  62. package/dist/packem_shared/ApiDocsPanel-DD2Uns6b.mjs +2 -0
  63. package/dist/packem_shared/ApiReferencePanel-CQxU1Ocx.mjs +1 -0
  64. package/dist/packem_shared/CommandPalette-BZCHLpst.mjs +1 -0
  65. package/dist/packem_shared/ConfirmButton-CIXYF6Mg.mjs +1 -0
  66. package/dist/packem_shared/ConnectionBadge-BfcoN-VE.mjs +1 -0
  67. package/dist/packem_shared/DEFAULT_AUTO_REFRESH_MS-Py5Yx7rP.mjs +1 -0
  68. package/dist/packem_shared/DEFAULT_INSIGHT_THRESHOLDS-D5YMT0gM.mjs +1 -0
  69. package/dist/packem_shared/DEFAULT_LOCALE-BQ3jRT74.mjs +1 -0
  70. package/dist/packem_shared/DataBrowser-CVRWnNWu.mjs +4 -0
  71. package/dist/packem_shared/DataFilters--ocFTVT2.mjs +1 -0
  72. package/dist/packem_shared/ErrorBoundary-BWNF98VF.mjs +1 -0
  73. package/dist/packem_shared/GlobalDataBrowser-DC47T6Zl.mjs +1 -0
  74. package/dist/packem_shared/HomePanel-D12HxHQo.mjs +1 -0
  75. package/dist/packem_shared/MigrationsPanel-DMkxSXNl.mjs +1 -0
  76. package/dist/packem_shared/OpenRpcReferencePanel-BFDG91tn.mjs +1 -0
  77. package/dist/packem_shared/STUDIO_ROOT_CLASS-C6MccdVk.mjs +1 -0
  78. package/dist/packem_shared/ScheduledJobs-QCTRdugp.mjs +1 -0
  79. package/dist/packem_shared/ShardInput-CoySruKZ.mjs +1 -0
  80. package/dist/packem_shared/Studio-MA8kKZLu.mjs +1 -0
  81. package/dist/packem_shared/StudioApp-isdWpF9P.mjs +1 -0
  82. package/dist/packem_shared/StudioI18nProvider-CGXCPnQn.mjs +1 -0
  83. package/dist/packem_shared/advisor-view-tBumWci_.mjs +1 -0
  84. package/dist/packem_shared/aggregateMetrics-DKFJc-o5.mjs +1 -0
  85. package/dist/packem_shared/alert-PB5W11MM.mjs +1 -0
  86. package/dist/packem_shared/app.d-D425h1XO.d.mts +352 -0
  87. package/dist/packem_shared/app.d-D425h1XO.d.ts +352 -0
  88. package/dist/packem_shared/auth-pager-DW77WeZw.mjs +1 -0
  89. package/dist/packem_shared/badge-r_5B4LHP.mjs +1 -0
  90. package/dist/packem_shared/bar-chart-BCsEIQoQ.mjs +6 -0
  91. package/dist/packem_shared/browser-storage-BH1MxLZs.mjs +1 -0
  92. package/dist/packem_shared/button-q0UYSmrn.mjs +1 -0
  93. package/dist/packem_shared/card-By2O8ULa.mjs +1 -0
  94. package/dist/packem_shared/cf-links-CBJ5SywP.mjs +1 -0
  95. package/dist/packem_shared/checkbox-CnS9cyCz.mjs +1 -0
  96. package/dist/packem_shared/control-button-BOZ5K-FC.mjs +1 -0
  97. package/dist/packem_shared/data-grid-B5m1OosL.mjs +1 -0
  98. package/dist/packem_shared/data-view-params-C-_G-biH.mjs +1 -0
  99. package/dist/packem_shared/diagram-export-panel-Vdt-DZnO.mjs +2 -0
  100. package/dist/packem_shared/dropdown-menu-jLZenfWH.mjs +2 -0
  101. package/dist/packem_shared/empty-state-D7jEML_T.mjs +1 -0
  102. package/dist/packem_shared/error-alert-C0R39DO1.mjs +1 -0
  103. package/dist/packem_shared/grid-features-Drvfswwy.mjs +6 -0
  104. package/dist/packem_shared/grid-pagination-DY2erU65.mjs +1 -0
  105. package/dist/packem_shared/home-panel-CDVTuTF8.mjs +3 -0
  106. package/dist/packem_shared/input-CXhxesPC.mjs +1 -0
  107. package/dist/packem_shared/internal-hIuTpSbx.mjs +2 -0
  108. package/dist/packem_shared/label-DKFzyHq6.mjs +1 -0
  109. package/dist/packem_shared/live-status-D1GasNsH.mjs +1 -0
  110. package/dist/packem_shared/log-fields-BolUoZ9g.mjs +1 -0
  111. package/dist/packem_shared/log-line-BH0iWiBv.mjs +1 -0
  112. package/dist/packem_shared/metrics-format-1sNGG47R.mjs +1 -0
  113. package/dist/packem_shared/modal-shell-CDztwLnv.mjs +1 -0
  114. package/dist/packem_shared/operation-console-provider-DoloEvon.mjs +1 -0
  115. package/dist/packem_shared/recording-client-DAipTA_n.mjs +1 -0
  116. package/dist/packem_shared/reference-view-DENugPcj.mjs +13 -0
  117. package/dist/packem_shared/schema-diagram-CtVPhOGj.mjs +2 -0
  118. package/dist/packem_shared/scroll-area-CXCQH7VT.mjs +2 -0
  119. package/dist/packem_shared/select-DPyS18Vy.mjs +2 -0
  120. package/dist/packem_shared/shard-history-CaO3C4KQ.mjs +1 -0
  121. package/dist/packem_shared/shortcuts-B9gDaXmw.mjs +1 -0
  122. package/dist/packem_shared/skeleton-DX1gfixl.mjs +1 -0
  123. package/dist/packem_shared/sparkline-B_sPPO_8.mjs +1 -0
  124. package/dist/packem_shared/sql-result-table-DCwooMGW.mjs +1 -0
  125. package/dist/packem_shared/stat-card-BAv73QtB.mjs +1 -0
  126. package/dist/packem_shared/storage-tier-C2mKwYRj.mjs +1 -0
  127. package/dist/packem_shared/studio-UhUrPz5J.mjs +2 -0
  128. package/dist/packem_shared/table-D0SBiDu-.mjs +2 -0
  129. package/dist/packem_shared/table-list-sidebar-CNadcIgG.mjs +1 -0
  130. package/dist/packem_shared/textarea--40GKAyz.mjs +1 -0
  131. package/dist/packem_shared/trace-handoff-BV3EWqy_.mjs +1 -0
  132. package/dist/packem_shared/use-admin-query-CaOm4JS3.mjs +1 -0
  133. package/dist/packem_shared/use-admin-spec-CK7mk3Ui.mjs +1 -0
  134. package/dist/packem_shared/use-async-submit-D0r7-m2J.mjs +1 -0
  135. package/dist/packem_shared/use-auth-config-CG7VvAvQ.mjs +1 -0
  136. package/dist/packem_shared/use-mirrored-ref-CVDf2z1M.mjs +1 -0
  137. package/dist/packem_shared/use-open-trace-BJKMJjeS.mjs +1 -0
  138. package/dist/packem_shared/use-shard-key-BsP3o5wT.mjs +1 -0
  139. package/dist/packem_shared/use-sql-assistant-rZPs3LC3.mjs +1 -0
  140. package/dist/packem_shared/use-studio-client-DCA50tF2.mjs +1 -0
  141. package/dist/packem_shared/useDebounced-DVeQ5-oW.mjs +1 -0
  142. package/dist/packem_shared/utils-bhneXptQ.mjs +1 -0
  143. package/dist/packem_shared/virtual-rect-D_j7aLxX.mjs +1 -0
  144. package/dist/standalone/chunk-2AH4ABE5.js +1 -0
  145. package/dist/standalone/chunk-2G57ENH5.js +1 -0
  146. package/dist/standalone/chunk-3FS22LNI.js +4 -0
  147. package/dist/standalone/chunk-3GXPALXG.js +1 -0
  148. package/dist/standalone/chunk-3GYLOE4V.js +1 -0
  149. package/dist/standalone/chunk-3PAYDWHN.js +8 -0
  150. package/dist/standalone/chunk-473JK2PQ.js +1 -0
  151. package/dist/standalone/chunk-4C4THJUD.js +1 -0
  152. package/dist/standalone/chunk-4DAKKAK7.js +1 -0
  153. package/dist/standalone/chunk-4M57OYFX.js +1 -0
  154. package/dist/standalone/chunk-4SQBAPY6.js +1 -0
  155. package/dist/standalone/chunk-5DNGK3NT.js +1 -0
  156. package/dist/standalone/chunk-5GIQ6C5N.js +1 -0
  157. package/dist/standalone/chunk-5R2YO7HF.js +4 -0
  158. package/dist/standalone/chunk-5WJG7FMH.js +1 -0
  159. package/dist/standalone/chunk-63KDHS3H.js +1 -0
  160. package/dist/standalone/chunk-6B6ARRMI.js +1 -0
  161. package/dist/standalone/chunk-6LMO2D54.js +1 -0
  162. package/dist/standalone/chunk-6M7FLLMT.js +1 -0
  163. package/dist/standalone/chunk-6QEXGYWH.js +1 -0
  164. package/dist/standalone/chunk-6UTZXEW3.js +1 -0
  165. package/dist/standalone/chunk-6VAY6L4J.js +1 -0
  166. package/dist/standalone/chunk-7PADVGQX.js +1 -0
  167. package/dist/standalone/chunk-7RGYCU6F.js +1 -0
  168. package/dist/standalone/chunk-7UM5ROG6.js +1 -0
  169. package/dist/standalone/chunk-7ZIYHKLX.js +5 -0
  170. package/dist/standalone/chunk-A566HCBX.js +1 -0
  171. package/dist/standalone/chunk-A5JISKHE.js +1 -0
  172. package/dist/standalone/chunk-ADNRFCMZ.js +1 -0
  173. package/dist/standalone/chunk-AP4PC2M4.js +1 -0
  174. package/dist/standalone/chunk-BFE2DRP6.js +33 -0
  175. package/dist/standalone/chunk-BPEB4KFE.js +1 -0
  176. package/dist/standalone/chunk-BVX45MU5.js +7 -0
  177. package/dist/standalone/chunk-BYOGQ2IV.js +3 -0
  178. package/dist/standalone/chunk-C6GN7ZXJ.js +1 -0
  179. package/dist/standalone/chunk-CL2VZNDI.js +1 -0
  180. package/dist/standalone/chunk-CNA3TVUK.js +1 -0
  181. package/dist/standalone/chunk-CZ6HBDIL.js +1 -0
  182. package/dist/standalone/chunk-D6S7MXW4.js +1 -0
  183. package/dist/standalone/chunk-DBVJ5VLI.js +1 -0
  184. package/dist/standalone/chunk-DX55P3KZ.js +1 -0
  185. package/dist/standalone/chunk-E26OT26O.js +1 -0
  186. package/dist/standalone/chunk-FCAXVYAX.js +1 -0
  187. package/dist/standalone/chunk-FXPAJDES.js +1 -0
  188. package/dist/standalone/chunk-H7HZ42JY.js +1 -0
  189. package/dist/standalone/chunk-HHRYM6UW.js +1 -0
  190. package/dist/standalone/chunk-HPRF5LMA.js +1 -0
  191. package/dist/standalone/chunk-IB22LETR.js +1 -0
  192. package/dist/standalone/chunk-IBJVVHV5.js +1 -0
  193. package/dist/standalone/chunk-IENQRRQT.js +1 -0
  194. package/dist/standalone/chunk-IH2CJZF2.js +1 -0
  195. package/dist/standalone/chunk-IQ4TTHQT.js +1 -0
  196. package/dist/standalone/chunk-ITH5LRWM.js +1 -0
  197. package/dist/standalone/chunk-J6VFG6M5.js +1 -0
  198. package/dist/standalone/chunk-JSDKOE4U.js +1 -0
  199. package/dist/standalone/chunk-JTGGWF7R.js +1 -0
  200. package/dist/standalone/chunk-JZD7ZN3F.js +1 -0
  201. package/dist/standalone/chunk-K3CWB3AM.js +1 -0
  202. package/dist/standalone/chunk-KNFB3FGW.js +1 -0
  203. package/dist/standalone/chunk-KNXWDE4N.js +1 -0
  204. package/dist/standalone/chunk-KRPXOSBL.js +1 -0
  205. package/dist/standalone/chunk-KRY7BYHT.js +1 -0
  206. package/dist/standalone/chunk-KYAG2YMF.js +1 -0
  207. package/dist/standalone/chunk-KZCEJFZF.js +1 -0
  208. package/dist/standalone/chunk-KZILJQX3.js +8 -0
  209. package/dist/standalone/chunk-LEYUH5TS.js +1 -0
  210. package/dist/standalone/chunk-LFM672WN.js +1 -0
  211. package/dist/standalone/chunk-LIGOLZND.js +1 -0
  212. package/dist/standalone/chunk-LPU6YTSU.js +1 -0
  213. package/dist/standalone/chunk-LUHXNZI4.js +2 -0
  214. package/dist/standalone/chunk-MWJC3S62.js +1 -0
  215. package/dist/standalone/chunk-NGVP66OH.js +1 -0
  216. package/dist/standalone/chunk-NP2AQOLE.js +1 -0
  217. package/dist/standalone/chunk-NVKLYDOH.js +1 -0
  218. package/dist/standalone/chunk-O2NMPIV2.js +59 -0
  219. package/dist/standalone/chunk-O2X2XYCM.js +1 -0
  220. package/dist/standalone/chunk-O3MDWYXF.js +1 -0
  221. package/dist/standalone/chunk-ONG4JEZD.js +1 -0
  222. package/dist/standalone/chunk-ONWGX5Y4.js +6 -0
  223. package/dist/standalone/chunk-OS26JXYA.js +1 -0
  224. package/dist/standalone/chunk-OXFKZ4BM.js +1 -0
  225. package/dist/standalone/chunk-PGTEGUAB.js +1 -0
  226. package/dist/standalone/chunk-PQH2LSJX.js +1 -0
  227. package/dist/standalone/chunk-PTBUWRBY.js +1 -0
  228. package/dist/standalone/chunk-Q6HA3L2H.js +1 -0
  229. package/dist/standalone/chunk-QGV5ARD2.js +1 -0
  230. package/dist/standalone/chunk-QWRK4ESB.js +1 -0
  231. package/dist/standalone/chunk-R36QXQZX.js +1 -0
  232. package/dist/standalone/chunk-RL2ITK2N.js +1 -0
  233. package/dist/standalone/chunk-RTJO3AR4.js +1 -0
  234. package/dist/standalone/chunk-SFY646MC.js +1 -0
  235. package/dist/standalone/chunk-SLIDAWNX.js +1 -0
  236. package/dist/standalone/chunk-SU5DTRGK.js +3 -0
  237. package/dist/standalone/{chunk-BJGBHGK3.js → chunk-SYGCASPT.js} +1 -1
  238. package/dist/standalone/chunk-T5UMHPAB.js +1 -0
  239. package/dist/standalone/chunk-T6HV2FQP.js +2 -0
  240. package/dist/standalone/chunk-T7ZKNNGX.js +1 -0
  241. package/dist/standalone/chunk-TCYPNSTV.js +1 -0
  242. package/dist/standalone/chunk-TDVDZ7XQ.js +1 -0
  243. package/dist/standalone/chunk-TQM6XHBA.js +1 -0
  244. package/dist/standalone/chunk-TRMWBRRU.js +1 -0
  245. package/dist/standalone/chunk-TW7KJSMR.js +15 -0
  246. package/dist/standalone/chunk-TYD3V4NB.js +1 -0
  247. package/dist/standalone/chunk-TZKLK52W.js +1 -0
  248. package/dist/standalone/chunk-U4RXQSQ7.js +1 -0
  249. package/dist/standalone/chunk-UNZ2UBVL.js +1 -0
  250. package/dist/standalone/chunk-UYEZR3BI.js +1 -0
  251. package/dist/standalone/chunk-VEWQWS3J.js +1 -0
  252. package/dist/standalone/chunk-VJRNOSRY.js +1 -0
  253. package/dist/standalone/chunk-W2BCSK5S.js +1 -0
  254. package/dist/standalone/chunk-W7MRISE3.js +1 -0
  255. package/dist/standalone/chunk-WM72PRE3.js +1 -0
  256. package/dist/standalone/chunk-WS36BO4R.js +1 -0
  257. package/dist/standalone/chunk-X4WHMCOZ.js +1 -0
  258. package/dist/standalone/chunk-X74GEPSG.js +1 -0
  259. package/dist/standalone/chunk-XIRKBJPD.js +14 -0
  260. package/dist/standalone/chunk-XKPD4SFN.js +1 -0
  261. package/dist/standalone/chunk-XMSNLMWU.js +1 -0
  262. package/dist/standalone/chunk-XOPFDWXX.js +1 -0
  263. package/dist/standalone/chunk-XQLOVFPP.js +1 -0
  264. package/dist/standalone/chunk-XSHYZPGF.js +1 -0
  265. package/dist/standalone/chunk-XST3UEHU.js +1 -0
  266. package/dist/standalone/chunk-XYR5NST4.js +1 -0
  267. package/dist/standalone/chunk-Y74LIFSL.js +1 -0
  268. package/dist/standalone/chunk-YHTHRYP5.js +1 -0
  269. package/dist/standalone/chunk-YMEKCV27.js +1 -0
  270. package/dist/standalone/chunk-Z5EV64KS.js +1 -0
  271. package/dist/standalone/chunk-ZBON5T5A.js +1 -0
  272. package/dist/standalone/chunk-ZGSL4DPP.js +1 -0
  273. package/dist/standalone/chunk-ZOQTXWPK.js +1 -0
  274. package/dist/standalone/chunk-ZTOREMGH.js +1 -0
  275. package/dist/standalone/chunk-ZZ5GICTF.js +1 -0
  276. package/dist/standalone/studio.js +9 -214
  277. package/dist/styles.css +2 -2
  278. package/package.json +26 -22
  279. package/dist/index.js +0 -41
  280. package/dist/mount.js +0 -27
  281. package/dist/packem_chunks/ApiTab.js +0 -251
  282. package/dist/packem_chunks/AuditPanel.js +0 -200
  283. package/dist/packem_chunks/ExportImportPanel.js +0 -198
  284. package/dist/packem_chunks/FileBrowser.js +0 -2932
  285. package/dist/packem_chunks/FunctionRunner.js +0 -343
  286. package/dist/packem_chunks/FunctionStatsPanel.js +0 -377
  287. package/dist/packem_chunks/HealthPanel.js +0 -648
  288. package/dist/packem_chunks/InsightsPanel.js +0 -462
  289. package/dist/packem_chunks/LogsPanel.js +0 -827
  290. package/dist/packem_chunks/MailPanel.js +0 -353
  291. package/dist/packem_chunks/MetricsPanel.js +0 -1344
  292. package/dist/packem_chunks/MigrationsPanel.js +0 -239
  293. package/dist/packem_chunks/PitrPanel.js +0 -252
  294. package/dist/packem_chunks/SchemaViewer.js +0 -2513
  295. package/dist/packem_chunks/SecurityAdvisorPanel.js +0 -95
  296. package/dist/packem_chunks/SettingsPanel.js +0 -391
  297. package/dist/packem_chunks/SqlEditorPanel.js +0 -2323
  298. package/dist/packem_chunks/TableEditor.js +0 -313
  299. package/dist/packem_chunks/analytics-panel.js +0 -261
  300. package/dist/packem_chunks/auth-config-panel.js +0 -179
  301. package/dist/packem_chunks/auth-sessions-panel.js +0 -175
  302. package/dist/packem_chunks/containers-panel.js +0 -247
  303. package/dist/packem_chunks/dashboards-panel.js +0 -780
  304. package/dist/packem_chunks/fanout-panel.js +0 -482
  305. package/dist/packem_chunks/flags-panel.js +0 -176
  306. package/dist/packem_chunks/kv-browser.js +0 -1896
  307. package/dist/packem_chunks/log-drains-panel.js +0 -273
  308. package/dist/packem_chunks/organizations-panel.js +0 -670
  309. package/dist/packem_chunks/payments-panel.js +0 -186
  310. package/dist/packem_chunks/permissions-panel.js +0 -805
  311. package/dist/packem_chunks/queues-panel.js +0 -1052
  312. package/dist/packem_chunks/rls-panel.js +0 -315
  313. package/dist/packem_chunks/schedule-panel.js +0 -831
  314. package/dist/packem_chunks/sparkline.js +0 -79
  315. package/dist/packem_chunks/storage-rules-panel.js +0 -140
  316. package/dist/packem_chunks/subscriptions-panel.js +0 -238
  317. package/dist/packem_chunks/users-panel.js +0 -1265
  318. package/dist/packem_chunks/vector-browser.js +0 -281
  319. package/dist/packem_chunks/workflows-panel.js +0 -562
  320. package/dist/packem_shared/ADMIN_FUNCTIONS-BHHJi3Gb.js +0 -52
  321. package/dist/packem_shared/ApiDocsPanel-D4CJf2ad.js +0 -842
  322. package/dist/packem_shared/ApiReferencePanel-Co_wpRF2.js +0 -230
  323. package/dist/packem_shared/CommandPalette-BUPpbpMc.js +0 -373
  324. package/dist/packem_shared/ConfirmButton-C2eVi2Qv.js +0 -59
  325. package/dist/packem_shared/ConnectionBadge-B2DDM2Tn.js +0 -111
  326. package/dist/packem_shared/DEFAULT_AUTO_REFRESH_MS-Vxwaxx51.js +0 -50
  327. package/dist/packem_shared/DEFAULT_INSIGHT_THRESHOLDS-DjF0h-gA.js +0 -89
  328. package/dist/packem_shared/DEFAULT_LOCALE-CiX4W7Kr.js +0 -27
  329. package/dist/packem_shared/DataBrowser-BeVNxSVm.js +0 -4493
  330. package/dist/packem_shared/DataFilters-FNquMaiu.js +0 -249
  331. package/dist/packem_shared/ErrorBoundary-BzAApI7J.js +0 -66
  332. package/dist/packem_shared/GlobalDataBrowser-ErfvIs1S.js +0 -289
  333. package/dist/packem_shared/HomePanel-D9MQk8I7.js +0 -14
  334. package/dist/packem_shared/OpenRpcReferencePanel-DLWzrIx9.js +0 -192
  335. package/dist/packem_shared/STUDIO_ROOT_CLASS-D12gX2dV.js +0 -3
  336. package/dist/packem_shared/ScheduledJobs-ClaNpZsg.js +0 -262
  337. package/dist/packem_shared/ShardInput-gx_DZXXn.js +0 -107
  338. package/dist/packem_shared/Studio-C48P1K5W.js +0 -16
  339. package/dist/packem_shared/StudioApp-Cqh-SYm2.js +0 -657
  340. package/dist/packem_shared/StudioI18nProvider-B-tDCZIi.js +0 -48
  341. package/dist/packem_shared/advisor-view-D3-U4kRR.js +0 -159
  342. package/dist/packem_shared/aggregateMetrics-D4nUHEKU.js +0 -108
  343. package/dist/packem_shared/alert-CdAET2K_.js +0 -68
  344. package/dist/packem_shared/app.d-CNLRTrWw.d.ts +0 -300
  345. package/dist/packem_shared/badge-B2PKA1-5.js +0 -49
  346. package/dist/packem_shared/bar-chart-DSwcWIRy.js +0 -3246
  347. package/dist/packem_shared/browser-storage-tLOxkIHd.js +0 -185
  348. package/dist/packem_shared/button-BhsN2uZH.js +0 -49
  349. package/dist/packem_shared/card-DURq3ElK.js +0 -175
  350. package/dist/packem_shared/cf-links-BZfRdxSE.js +0 -8
  351. package/dist/packem_shared/checkbox-UNkzAxl-.js +0 -63
  352. package/dist/packem_shared/data-grid-Jz8FqQ2C.js +0 -183
  353. package/dist/packem_shared/data-view-params-Cd6yRVbv.js +0 -96
  354. package/dist/packem_shared/dropdown-menu-WY4B_eJO.js +0 -280
  355. package/dist/packem_shared/empty-state-DY_oe0k6.js +0 -98
  356. package/dist/packem_shared/error-alert-BBT6D22d.js +0 -114
  357. package/dist/packem_shared/grid-features-CUr8Z1_O.js +0 -745
  358. package/dist/packem_shared/home-panel-CoGxi-oj.js +0 -1639
  359. package/dist/packem_shared/input-XH4r1Pt1.js +0 -53
  360. package/dist/packem_shared/internal-DTsYVn-g.js +0 -97
  361. package/dist/packem_shared/label-D8ykjn5J.js +0 -46
  362. package/dist/packem_shared/live-status-FZ0psC1z.js +0 -44
  363. package/dist/packem_shared/modal-shell-hyaJvIJ6.js +0 -100
  364. package/dist/packem_shared/reference-view-CSKyUyPl.js +0 -2141
  365. package/dist/packem_shared/scroll-area-DLhcy-ml.js +0 -93
  366. package/dist/packem_shared/select-UkNYCT3s.js +0 -273
  367. package/dist/packem_shared/shard-history-DyebH1R5.js +0 -38
  368. package/dist/packem_shared/skeleton-CGhL0p20.js +0 -45
  369. package/dist/packem_shared/sparkline-BnA1kC9X.js +0 -93
  370. package/dist/packem_shared/storage-tier-CL98eOvn.js +0 -85
  371. package/dist/packem_shared/studio-CPHA_-3I.js +0 -4015
  372. package/dist/packem_shared/table-DsCa9Qp9.js +0 -246
  373. package/dist/packem_shared/table-list-sidebar-B5psdSV1.js +0 -832
  374. package/dist/packem_shared/textarea-D3gaCU_-.js +0 -46
  375. package/dist/packem_shared/use-admin-query-BHPKmPuj.js +0 -106
  376. package/dist/packem_shared/use-auth-capabilities-C-VH0oJJ.js +0 -32
  377. package/dist/packem_shared/useDebounced-Dxncpg6z.js +0 -32
  378. package/dist/packem_shared/utils-B05Dmz_H.js +0 -8
  379. package/dist/packem_shared/virtual-rect-CVMUskSm.js +0 -10
  380. package/dist/standalone/chunk-22W5VKZ6.js +0 -1
  381. package/dist/standalone/chunk-2GGMGPEP.js +0 -1
  382. package/dist/standalone/chunk-2K47A3P6.js +0 -1
  383. package/dist/standalone/chunk-2NGUNNGW.js +0 -1
  384. package/dist/standalone/chunk-2THHW7BC.js +0 -1
  385. package/dist/standalone/chunk-3CJW6NWG.js +0 -4
  386. package/dist/standalone/chunk-3OA7PECS.js +0 -6
  387. package/dist/standalone/chunk-46K3NKPA.js +0 -1
  388. package/dist/standalone/chunk-4QHKBC77.js +0 -1
  389. package/dist/standalone/chunk-5OH3VPZF.js +0 -1
  390. package/dist/standalone/chunk-5OIBXYZM.js +0 -1
  391. package/dist/standalone/chunk-6GFEVKJP.js +0 -1
  392. package/dist/standalone/chunk-6WRZP62V.js +0 -1
  393. package/dist/standalone/chunk-764T6X6X.js +0 -1
  394. package/dist/standalone/chunk-7SLSB2TS.js +0 -4
  395. package/dist/standalone/chunk-7TJJXVSE.js +0 -1
  396. package/dist/standalone/chunk-7VF3IAAW.js +0 -2
  397. package/dist/standalone/chunk-AHILM3ZP.js +0 -1
  398. package/dist/standalone/chunk-AJIUI7DD.js +0 -1
  399. package/dist/standalone/chunk-ATYUMPDM.js +0 -1
  400. package/dist/standalone/chunk-BACPICH6.js +0 -1
  401. package/dist/standalone/chunk-BI35RXKQ.js +0 -1
  402. package/dist/standalone/chunk-BOXSWNXZ.js +0 -1
  403. package/dist/standalone/chunk-BQUQS7QN.js +0 -1
  404. package/dist/standalone/chunk-CKSHCYGC.js +0 -2
  405. package/dist/standalone/chunk-DC72CQY4.js +0 -76
  406. package/dist/standalone/chunk-DORBUITF.js +0 -1
  407. package/dist/standalone/chunk-DVC6YWVP.js +0 -1
  408. package/dist/standalone/chunk-DVKPRFIJ.js +0 -1
  409. package/dist/standalone/chunk-DWDILV2E.js +0 -1
  410. package/dist/standalone/chunk-DWTBY343.js +0 -1
  411. package/dist/standalone/chunk-EUIHTPKI.js +0 -1
  412. package/dist/standalone/chunk-FCSPAJW4.js +0 -1
  413. package/dist/standalone/chunk-GMSGZDDH.js +0 -13
  414. package/dist/standalone/chunk-GTM65MVX.js +0 -1
  415. package/dist/standalone/chunk-HV7G6DFP.js +0 -5
  416. package/dist/standalone/chunk-ILCTSAOB.js +0 -1
  417. package/dist/standalone/chunk-IOFMK4D7.js +0 -1
  418. package/dist/standalone/chunk-J6J54MBP.js +0 -1
  419. package/dist/standalone/chunk-JE2YOAB7.js +0 -4
  420. package/dist/standalone/chunk-JSEXCW5Q.js +0 -1
  421. package/dist/standalone/chunk-K3GNLVYK.js +0 -1
  422. package/dist/standalone/chunk-KEGAWN6Y.js +0 -1
  423. package/dist/standalone/chunk-KJJ3WM6H.js +0 -4
  424. package/dist/standalone/chunk-KZ6INM5M.js +0 -1
  425. package/dist/standalone/chunk-LAK5VSPI.js +0 -1
  426. package/dist/standalone/chunk-LD2R263D.js +0 -1
  427. package/dist/standalone/chunk-LI43EKM6.js +0 -1
  428. package/dist/standalone/chunk-M55U7NHO.js +0 -1
  429. package/dist/standalone/chunk-MPTM7ZU3.js +0 -3
  430. package/dist/standalone/chunk-MPYFGAOW.js +0 -1
  431. package/dist/standalone/chunk-NKJDGOM3.js +0 -1
  432. package/dist/standalone/chunk-O3NAGRTR.js +0 -1
  433. package/dist/standalone/chunk-OCHNCAXJ.js +0 -1
  434. package/dist/standalone/chunk-OIZ4CHPN.js +0 -8
  435. package/dist/standalone/chunk-OY3GVYS7.js +0 -4
  436. package/dist/standalone/chunk-PACH5AHG.js +0 -1
  437. package/dist/standalone/chunk-PN5NCZDX.js +0 -1
  438. package/dist/standalone/chunk-PVZI3CXP.js +0 -19
  439. package/dist/standalone/chunk-PZ7HD5T2.js +0 -1
  440. package/dist/standalone/chunk-Q52CHOSY.js +0 -1
  441. package/dist/standalone/chunk-QAFAJBAW.js +0 -1
  442. package/dist/standalone/chunk-QBAT52GB.js +0 -1
  443. package/dist/standalone/chunk-QLM6FYZW.js +0 -2
  444. package/dist/standalone/chunk-RRAFQ5G2.js +0 -1
  445. package/dist/standalone/chunk-RRCPZMC2.js +0 -22
  446. package/dist/standalone/chunk-RSEEHNFI.js +0 -1
  447. package/dist/standalone/chunk-SEU5V7I6.js +0 -1
  448. package/dist/standalone/chunk-SG3ALJJU.js +0 -1
  449. package/dist/standalone/chunk-SLKF2L74.js +0 -1
  450. package/dist/standalone/chunk-TAD43CG5.js +0 -1
  451. package/dist/standalone/chunk-TBMYIZIO.js +0 -1
  452. package/dist/standalone/chunk-TDL7NEWA.js +0 -1
  453. package/dist/standalone/chunk-TO4JQX7W.js +0 -1
  454. package/dist/standalone/chunk-TOJ3TC35.js +0 -1
  455. package/dist/standalone/chunk-TQ36RWOP.js +0 -1
  456. package/dist/standalone/chunk-U4OAQPBT.js +0 -1
  457. package/dist/standalone/chunk-UK64ZSUW.js +0 -1
  458. package/dist/standalone/chunk-VLXV72QE.js +0 -1
  459. package/dist/standalone/chunk-VTGBPW24.js +0 -1
  460. package/dist/standalone/chunk-WI7GWFEG.js +0 -1
  461. package/dist/standalone/chunk-WXPWVBIY.js +0 -1
  462. package/dist/standalone/chunk-X5P2WRYI.js +0 -1
  463. package/dist/standalone/chunk-X7MMBSNW.js +0 -1
  464. package/dist/standalone/chunk-XLQ4BHBD.js +0 -1
  465. package/dist/standalone/chunk-XNJNSCLM.js +0 -1
  466. package/dist/standalone/chunk-XUGSA2NG.js +0 -1
  467. package/dist/standalone/chunk-Y2ZPNDL7.js +0 -4
  468. package/dist/standalone/chunk-YAECF5LW.js +0 -1
  469. package/dist/standalone/chunk-YEVCU7TB.js +0 -13
  470. package/dist/standalone/chunk-ZHVTQ37P.js +0 -1
  471. package/dist/standalone/chunk-ZIGWVHCS.js +0 -1
  472. package/dist/standalone/chunk-ZPP2KOR4.js +0 -1
  473. package/dist/standalone/chunk-ZPUO7FNI.js +0 -1
  474. package/dist/standalone/chunk-ZU4DZ6NK.js +0 -1
  475. package/dist/standalone/chunk-ZYRGPDZB.js +0 -1
package/dist/index.d.ts CHANGED
@@ -1,18 +1,53 @@
1
- import { F as FunctionDescriptor } from "./packem_shared/app.d-CNLRTrWw.js";
2
- export { type a as FunctionKind, type R as RunStatus, b as ScheduledJobs, type c as ScheduledJobsProps, d as Studio, e as StudioApp, type S as StudioAppProps, type f as StudioProps, type g as StudioTab } from "./packem_shared/app.d-CNLRTrWw.js";
1
+ import { F as FunctionDescriptor } from "./packem_shared/app.d-D425h1XO.js";
2
+ export { type a as FunctionKind, type P as PrivacyRequestRow, type b as PrivacyRequestsSource, type R as RunStatus, c as ScheduledJobs, type d as ScheduledJobsProps, e as Studio, f as StudioApp, type S as StudioAppProps, type g as StudioProps } from "./packem_shared/app.d-D425h1XO.js";
3
3
  import { ReactElement, ReactNode, ErrorInfo, Component, ChangeEvent } from 'react';
4
4
  import { CapturedMail } from '@lunora/mail';
5
- export type { CapturedMail } from '@lunora/mail';
5
+ export type {
6
+ /**
7
+ * One captured outbound email as served by `__lunora_admin__:getCapturedMail`.
8
+ * Persisted by `@lunora/mail`'s dev capture transport into the root-shard
9
+ * mailbox and rendered by the studio Mail inbox. `html`/`text` are the rendered
10
+ * bodies; `to`/`cc`/`bcc` are the original recipient lists; `capturedAt` is
11
+ * epoch-ms.
12
+ *
13
+ * Re-exported verbatim from `@lunora/mail`, the canonical owner of the
14
+ * captured-mail wire type (also imported at the top of this file for local use
15
+ * in {@link CapturedMailResult}). This is NOT one of the hand-mirrored
16
+ * `@lunora/do` shapes below — it shares the real source of truth, so a field
17
+ * added in `@lunora/mail` flows here automatically.
18
+ */
19
+ CapturedMail } from '@lunora/mail';
20
+ import { HealthBody } from '@lunora/runtime';
6
21
  import { Messages, I18n } from '@lingui/core';
7
22
  export type { LunoraClient, ScheduleRecord, StorageObject } from '@lunora/client';
8
- /** A navigable destination shown in the palette. */
23
+ export type { LunoraAdminClient } from '@lunora/client/admin';
24
+ import '@lunora/bindings/analytics-sql';
25
+ /**
26
+ * The studio's navigation taxonomy: which pages exist and which domain each one
27
+ * belongs to.
28
+ *
29
+ * Its own module so the label maps (`nav-labels.ts`) can name these types without
30
+ * importing `studio.tsx`, which pulls in every lazy panel behind it.
31
+ */
32
+ /** Identifier for each built-in studio tab. */
33
+ type StudioTab = "agents" | "analytics" | "api" | "architecture" | "audit" | "authAudit" | "authConfig" | "authSessions" | "containers" | "dashboards" | "data" | "deploymentHealth" | "drains" | "export" | "fanout" | "files" | "flags" | "functions" | "health" | "home" | "insights" | "issues" | "kv" | "logs" | "mail" | "metrics" | "migrations" | "notifications" | "organizations" | "payments" | "permissions" | "pitr" | "privacyRequests" | "queues" | "reactors" | "realtime" | "rls" | "schedule" | "schema" | "advisorHealth" | "evals" | "aiUsage" | "security" | "settings" | "sql" | "storageRules" | "traces" | "users" | "vectors" | "workflows";
34
+ /**
35
+ * One palette entry: a navigable destination, or an action to run.
36
+ *
37
+ * `run` exists because not everything the palette should reach is a page. The
38
+ * operation console has no route and no button — the keyboard chord was the only
39
+ * way in, which makes it undiscoverable, and unreachable at all once an operator
40
+ * rebinds the key and forgets what to.
41
+ */
9
42
  interface CommandItem {
10
43
  /** Localised domain label, shown as a muted suffix to disambiguate. */
11
44
  readonly group: string;
12
45
  /** Localised sub-page label, the primary search target. */
13
46
  readonly label: string;
14
- /** Router path to navigate to on select (e.g. `/logs`). */
15
- readonly to: string;
47
+ /** Run on select. Mutually exclusive with `to`. */
48
+ readonly run?: () => void;
49
+ /** Router path to navigate to on select (e.g. `/logs`). Mutually exclusive with `run`. */
50
+ readonly to?: string;
16
51
  }
17
52
  interface CommandPaletteProps {
18
53
  /** Every navigable destination, in rail order. */
@@ -21,17 +56,15 @@ interface CommandPaletteProps {
21
56
  /** Open the command palette from anywhere (e.g. the top-bar Search button). */
22
57
  declare const openCommandPalette: () => void;
23
58
  /**
24
- * Command palette (⌘K / Ctrl-K) — Supabase-style global search. Rendered inside
25
- * the studio shell so its selection can drive the router's `useNavigate`. Opens
26
- * on the keyboard shortcut or the {@link OPEN_EVENT} the top-bar Search button
27
- * dispatches, filters the navigable destinations by a case-insensitive substring
28
- * over their label and domain, and navigates to the chosen one. Built on the
29
- * studio's Base UI dialog primitive — no `cmdk`/extra dependency — with a small
30
- * arrow-key + Enter affordance over the filtered list.
31
- */
32
- declare const CommandPalette: ({
33
- items
34
- }: CommandPaletteProps) => ReactElement;
59
+ * Command palette (⌘K / Ctrl-K) — Supabase-style global search. Rendered inside
60
+ * the studio shell so its selection can drive the router's `useNavigate`. Opens
61
+ * on the keyboard shortcut or the {@link OPEN_EVENT} the top-bar Search button
62
+ * dispatches, filters the navigable destinations by a case-insensitive substring
63
+ * over their label and domain, and navigates to the chosen one. Built on the
64
+ * studio's Base UI dialog primitive — no `cmdk`/extra dependency — with a small
65
+ * arrow-key + Enter affordance over the filtered list.
66
+ */
67
+ declare const CommandPalette: ({ items }: CommandPaletteProps) => ReactElement;
35
68
  interface ConfirmButtonProps {
36
69
  /** Label for the initial trigger (e.g. `Delete`). */
37
70
  readonly children: string;
@@ -45,33 +78,27 @@ interface ConfirmButtonProps {
45
78
  readonly testId: string;
46
79
  }
47
80
  /**
48
- * A destructive-action button that requires a second click to fire. The first
49
- * click swaps the trigger for an inline `Confirm` / `Cancel` pair rather than a
50
- * blocking `window.confirm`, so the guard is testable and non-modal. The
51
- * trigger keeps its `testId` (so existing tests that click it still reach the
52
- * first step); the actual action only runs on the `${testId}-confirm` click.
53
- */
54
- declare const ConfirmButton: ({
55
- children,
56
- confirmLabel,
57
- disabled,
58
- onConfirm,
59
- testId
60
- }: ConfirmButtonProps) => ReactElement;
61
- /**
62
- * Live-socket status indicator. Reflects the client's aggregate WebSocket health
63
- * so an operator can tell a healthy live channel from a silently-dropped socket
64
- * (a panel showing "Live: on" while the socket is down would otherwise look
65
- * identical to one that's simply idle).
66
- */
81
+ * A destructive-action button that requires a second click to fire. The first
82
+ * click swaps the trigger for an inline `Confirm` / `Cancel` pair rather than a
83
+ * blocking `window.confirm`, so the guard is testable and non-modal. The
84
+ * trigger keeps its `testId` (so existing tests that click it still reach the
85
+ * first step); the actual action only runs on the `${testId}-confirm` click.
86
+ */
87
+ declare const ConfirmButton: ({ children, confirmLabel, disabled, onConfirm, testId }: ConfirmButtonProps) => ReactElement;
88
+ /**
89
+ * Live-socket status indicator. Reflects the client's aggregate WebSocket health
90
+ * so an operator can tell a healthy live channel from a silently-dropped socket
91
+ * (a panel showing "Live: on" while the socket is down would otherwise look
92
+ * identical to one that's simply idle).
93
+ */
67
94
  declare const ConnectionBadge: () => ReactElement;
68
95
  interface ErrorBoundaryProps {
69
96
  readonly children: ReactNode;
70
97
  /**
71
- * Localised fallback heading. When omitted, falls back to `${label} failed`
72
- * (or `Something went wrong` with no label). A class component can't use the
73
- * `useT` hook, so localised text is passed in by its parents.
74
- */
98
+ * Localised fallback heading. When omitted, falls back to `${label} failed`
99
+ * (or `Something went wrong` with no label). A class component can't use the
100
+ * `useT` hook, so localised text is passed in by its parents.
101
+ */
75
102
  readonly fallbackTitle?: string;
76
103
  /** Optional label naming the boundary's region, shown in the fallback. */
77
104
  readonly label?: string;
@@ -82,10 +109,10 @@ interface ErrorBoundaryState {
82
109
  readonly error: Error | null;
83
110
  }
84
111
  /**
85
- * Catches render/lifecycle errors in a panel so one throwing component doesn't
86
- * blank the whole studio shell. Shows the error message with a "Try again"
87
- * button that clears the boundary and re-renders its children.
88
- */
112
+ * Catches render/lifecycle errors in a panel so one throwing component doesn't
113
+ * blank the whole studio shell. Shows the error message with a "Try again"
114
+ * button that clears the boundary and re-renders its children.
115
+ */
89
116
  declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
90
117
  static getDerivedStateFromError(error: Error): ErrorBoundaryState;
91
118
  override state: ErrorBoundaryState;
@@ -102,28 +129,47 @@ interface ShardInputProps {
102
129
  readonly value: string;
103
130
  }
104
131
  /**
105
- * Shard-key text field shared by every shard-scoped panel. Backed by a
106
- * `&lt;datalist>` of recently-used shard keys (see {@link loadRecentShards}) so an
107
- * operator can pick a shard they've visited instead of retyping it — the closest
108
- * to a shard picker possible without server-side shard enumeration, which
109
- * Durable Objects don't support. Panels remain responsible for recording a shard
110
- * as used (via `recordShard`) when they actually query it.
111
- */
112
- declare const ShardInput: ({
113
- id,
114
- onChange,
115
- testId,
116
- value
117
- }: ShardInputProps) => ReactElement;
132
+ * Shard-key text field shared by every shard-scoped panel. Backed by a
133
+ * `<datalist>` of recently-used shard keys (see {@link loadRecentShards}) so an
134
+ * operator can pick a shard they've visited instead of retyping it — the closest
135
+ * to a shard picker possible without server-side shard enumeration, which
136
+ * Durable Objects don't support. Panels remain responsible for recording a shard
137
+ * as used (via `recordShard`) when they actually query it.
138
+ */
139
+ declare const ShardInput: ({ id, onChange, testId, value }: ShardInputProps) => ReactElement;
140
+ interface AdvisorHealthPanelProps {
141
+ /** Scopes the `data-testid`s. */
142
+ readonly testId?: string;
143
+ }
144
+ /**
145
+ * The Advisors **Health** tab: one score for the deployment, the coverage split, and
146
+ * every procedure ranked worst-first.
147
+ *
148
+ * Scoring runs client-side over the two admin reads rather than being baked into
149
+ * the worker: `scoreAdvisor` is a pure function, so the panel reuses the exact
150
+ * arithmetic the CLI gate uses — one implementation, no chance of the dashboard
151
+ * and CI disagreeing about the same deployment.
152
+ *
153
+ * Both reads are needed. The advisories are the numerator and the procedures the
154
+ * denominator; without the latter there is no way to tell one failing handler
155
+ * out of two from one out of two hundred.
156
+ */
157
+ declare const AdvisorHealthPanel: ({ testId }: AdvisorHealthPanelProps) => ReactElement;
118
158
  declare const ADMIN_FUNCTION_PREFIX = "__lunora_admin__:";
119
159
  /**
120
- * Fully-qualified reserved paths the studio invokes via the client. The
121
- * `__lunora_admin__:` prefix is spelled out inline rather than interpolated so
122
- * the values stay emittable under `--isolatedDeclarations`. Every path is
123
- * intercepted by `ShardDO` before user dispatch and gated by the server's
124
- * `LUNORA_ADMIN_TOKEN`.
125
- */
160
+ * Fully-qualified reserved paths the studio invokes via the client. The
161
+ * `__lunora_admin__:` prefix is spelled out inline rather than interpolated so
162
+ * the values stay emittable under `--isolatedDeclarations`. Every path is
163
+ * intercepted by `ShardDO` before user dispatch and gated by the server's
164
+ * `LUNORA_ADMIN_TOKEN`.
165
+ */
126
166
  declare const ADMIN_FUNCTIONS: {
167
+ readonly aiAvailable: "__lunora_admin__:aiAvailable";
168
+ readonly aiChartConfig: "__lunora_admin__:aiChartConfig";
169
+ readonly aiGenerateSql: "__lunora_admin__:aiGenerateSql";
170
+ readonly aiTableFilter: "__lunora_admin__:aiTableFilter";
171
+ readonly assignIssue: "__lunora_admin__:assignIssue";
172
+ readonly backRelationCounts: "__lunora_admin__:backRelationCounts";
127
173
  readonly clearCapturedMail: "__lunora_admin__:clearCapturedMail";
128
174
  readonly clearQueueMessages: "__lunora_admin__:clearQueueMessages";
129
175
  readonly clearTable: "__lunora_admin__:clearTable";
@@ -131,56 +177,77 @@ declare const ADMIN_FUNCTIONS: {
131
177
  readonly deleteRows: "__lunora_admin__:deleteRows";
132
178
  readonly describeTable: "__lunora_admin__:describeTable";
133
179
  readonly describeTables: "__lunora_admin__:describeTables";
180
+ readonly explainIssue: "__lunora_admin__:explainIssue";
134
181
  readonly exportShard: "__lunora_admin__:exportShard";
135
182
  readonly facetColumn: "__lunora_admin__:facetColumn";
136
183
  readonly getAdvisories: "__lunora_admin__:getAdvisories";
184
+ readonly getAdvisorProcedures: "__lunora_admin__:getAdvisorProcedures";
137
185
  readonly getAuditLog: "__lunora_admin__:getAuditLog";
186
+ readonly getAuthAuditLog: "__lunora_admin__:getAuthAuditLog";
138
187
  readonly getAuthMetrics: "__lunora_admin__:getAuthMetrics";
139
188
  readonly getCapturedMail: "__lunora_admin__:getCapturedMail";
140
189
  readonly getFanoutMetrics: "__lunora_admin__:getFanoutMetrics";
141
190
  readonly getFunctionStats: "__lunora_admin__:getFunctionStats";
191
+ readonly getIssues: "__lunora_admin__:getIssues";
192
+ readonly lintSql: "__lunora_admin__:lintSql";
142
193
  readonly listFlags: "__lunora_admin__:listFlags";
194
+ readonly listReactors: "__lunora_admin__:listReactors";
195
+ readonly listPushSubscriptions: "__lunora_admin__:listPushSubscriptions";
143
196
  readonly listQueues: "__lunora_admin__:listQueues";
144
197
  readonly listSubscriptions: "__lunora_admin__:listSubscriptions";
145
198
  readonly listTableIndexes: "__lunora_admin__:listTableIndexes";
199
+ readonly listTablesIndexes: "__lunora_admin__:listTablesIndexes";
146
200
  readonly listWorkflows: "__lunora_admin__:listWorkflows";
147
201
  readonly getLogs: "__lunora_admin__:getLogs";
202
+ readonly getMetricHistory: "__lunora_admin__:getMetricHistory";
203
+ readonly getMetricSeries: "__lunora_admin__:getMetricSeries";
148
204
  readonly getMetrics: "__lunora_admin__:getMetrics";
149
205
  readonly getPitrBookmark: "__lunora_admin__:getPitrBookmark";
206
+ readonly getQueryInsights: "__lunora_admin__:getQueryInsights";
150
207
  readonly getQueueMessages: "__lunora_admin__:getQueueMessages";
151
208
  readonly getRequestLog: "__lunora_admin__:getRequestLog";
152
209
  readonly getSecurityAudit: "__lunora_admin__:getSecurityAudit";
153
210
  readonly getSettings: "__lunora_admin__:getSettings";
211
+ readonly getTraces: "__lunora_admin__:getTraces";
154
212
  readonly getWorkflowInstanceStatus: "__lunora_admin__:getWorkflowInstanceStatus";
213
+ readonly ignoreIssue: "__lunora_admin__:ignoreIssue";
155
214
  readonly importShard: "__lunora_admin__:importShard";
156
215
  readonly listTables: "__lunora_admin__:listTables";
157
216
  readonly maskPolicies: "__lunora_admin__:maskPolicies";
158
217
  readonly migrationStatus: "__lunora_admin__:migrationStatus";
218
+ readonly patchRows: "__lunora_admin__:patchRows";
159
219
  readonly pitrRestore: "__lunora_admin__:pitrRestore";
160
220
  readonly readTablePage: "__lunora_admin__:readTablePage";
161
221
  readonly replayQueueMessage: "__lunora_admin__:replayQueueMessage";
222
+ readonly resolveIssue: "__lunora_admin__:resolveIssue";
162
223
  readonly rlsPolicies: "__lunora_admin__:rlsPolicies";
224
+ readonly schemaHistory: "__lunora_admin__:schemaHistory";
225
+ readonly schemaVersion: "__lunora_admin__:schemaVersion";
163
226
  readonly runAs: "__lunora_admin__:runAs";
164
227
  readonly runMigration: "__lunora_admin__:runMigration";
165
228
  readonly runSql: "__lunora_admin__:runSql";
166
229
  readonly sendQueueMessage: "__lunora_admin__:sendQueueMessage";
167
230
  readonly sendTestMail: "__lunora_admin__:sendTestMail";
231
+ readonly sendWorkflowEvent: "__lunora_admin__:sendWorkflowEvent";
232
+ readonly setIssueSeverity: "__lunora_admin__:setIssueSeverity";
168
233
  readonly storageOrphans: "__lunora_admin__:storageOrphans";
169
234
  readonly storageReferences: "__lunora_admin__:storageReferences";
170
235
  readonly storageRules: "__lunora_admin__:storageRules";
171
236
  readonly studioFeatures: "__lunora_admin__:studioFeatures";
172
237
  readonly writeRow: "__lunora_admin__:writeRow";
173
238
  };
174
- /** Comparison a {@link FilterClause} applies, mirroring `@lunora/do`'s `FilterOperator`. `contains` is a substring (LIKE). */
175
- type FilterOperator = "contains" | "eq" | "gt" | "gte" | "lt" | "lte" | "ne";
239
+ /** Comparison a {@link FilterClause} applies, mirroring `@lunora/do`'s `FilterOperator`. `contains` is a substring (LIKE); `has` is membership in a JSON array. */
240
+ type FilterOperator = "contains" | "eq" | "gt" | "gte" | "has" | "lt" | "lte" | "ne";
176
241
  /**
177
- * One structured column filter passed to `readTablePage`, mirroring `@lunora/do`'s
178
- * `FilterClause`. AND-combined with the substring search and the other clauses.
179
- * `value` is sent as-is and bound server-side, so it never injects SQL.
180
- */
242
+ * One structured column filter passed to `readTablePage`, mirroring `@lunora/do`'s
243
+ * `FilterClause`. AND-combined with the substring search and the other clauses.
244
+ * `value` is sent as-is and bound server-side, so it never injects SQL.
245
+ */
181
246
  interface FilterClause {
182
247
  column: string;
183
248
  operator: FilterOperator;
249
+ /** Field names nested under a document `column`, outermost first (`["city"]` addresses `column.city`). */
250
+ path?: string[];
184
251
  value?: unknown;
185
252
  }
186
253
  /** Which single-row mutation a {@link WriteRowArgs} performs. */
@@ -213,7 +280,17 @@ interface CacheStats {
213
280
  }
214
281
  /** Health snapshot returned by `__lunora_admin__:getMetrics` for one shard. */
215
282
  interface ShardMetrics {
216
- cache: CacheStats | null;
283
+ /**
284
+ * Reactive-cache stats. `null` is the shard saying "no cache configured";
285
+ * **absent** is a payload that carries no `cache` key at all — an older shard,
286
+ * or any response shaped before the field existed.
287
+ *
288
+ * Optional on purpose: this arrives as untrusted JSON off the admin wire and
289
+ * `useAdminQuery` casts it straight to this type, so declaring it required
290
+ * made the type lie and let consumers write `cache === null` and then
291
+ * dereference `undefined`. Optional makes the compiler reject that.
292
+ */
293
+ cache?: CacheStats | null;
217
294
  databaseSize: null | number;
218
295
  errors: number;
219
296
  requests: number;
@@ -222,26 +299,26 @@ interface ShardMetrics {
222
299
  uptimeMs: number;
223
300
  }
224
301
  /**
225
- * One full-scan attribution entry on a {@link FunctionCallStat}, mirroring
226
- * `@lunora/do`'s `FunctionScanAttribution`: how many times the function
227
- * full-scanned `table`. The causal evidence behind the "missing index" insight.
228
- */
302
+ * One full-scan attribution entry on a {@link FunctionCallStat}, mirroring
303
+ * `@lunora/do`'s `FunctionScanAttribution`: how many times the function
304
+ * full-scanned `table`. The causal evidence behind the "missing index" insight.
305
+ */
229
306
  interface FunctionScanAttribution {
230
307
  scans: number;
231
308
  table: string;
232
309
  }
233
310
  /**
234
- * Per-function execution counters returned by `__lunora_admin__:getFunctionStats`
235
- * for one shard. Mirrors `@lunora/do`'s `FunctionCallStat`. Counters are
236
- * per-DO-instance and reset on hibernation/restart — a "since this instance
237
- * woke" readout. Durations are handler wall-clock milliseconds.
238
- *
239
- * `scans` / `scannedTables` carry the causal full-scan attribution (PLAN3 1.2).
240
- * They're additive — a worker predating the feature reports `scans: 0` and
241
- * `scannedTables: []`, so the fields are optional on the wire and the consumer
242
- * defaults them. `conflicts` (OCC write-contention count, a subset of `errors`)
243
- * is likewise additive and optional for the same back-compat reason.
244
- */
311
+ * Per-function execution counters returned by `__lunora_admin__:getFunctionStats`
312
+ * for one shard. Mirrors `@lunora/do`'s `FunctionCallStat`. Counters are
313
+ * per-DO-instance and reset on hibernation/restart — a "since this instance
314
+ * woke" readout. Durations are handler wall-clock milliseconds.
315
+ *
316
+ * `scans` / `scannedTables` carry the causal full-scan attribution (PLAN3 1.2).
317
+ * They're additive — a worker predating the feature reports `scans: 0` and
318
+ * `scannedTables: []`, so the fields are optional on the wire and the consumer
319
+ * defaults them. `conflicts` (OCC write-contention count, a subset of `errors`)
320
+ * is likewise additive and optional for the same back-compat reason.
321
+ */
245
322
  interface FunctionCallStat {
246
323
  calls: number;
247
324
  /** OCC write-conflict count — a subset of `errors`; absent on a pre-conflict-tracking worker. */
@@ -264,11 +341,11 @@ interface FunctionStatsResult {
264
341
  sinceMs: number;
265
342
  }
266
343
  /**
267
- * One declared index on a table, mirroring `@lunora/do`'s `TableIndexInfo`.
268
- * `type` is the index kind; `fields` the indexed columns (sort fields for rank,
269
- * text + filter fields for search, source field for vector); `unique` is set
270
- * only for unique secondary indexes.
271
- */
344
+ * One declared index on a table, mirroring `@lunora/do`'s `TableIndexInfo`.
345
+ * `type` is the index kind; `fields` the indexed columns (sort fields for rank,
346
+ * text + filter fields for search, source field for vector); `unique` is set
347
+ * only for unique secondary indexes.
348
+ */
272
349
  interface TableIndexInfo {
273
350
  fields: string[];
274
351
  name: string;
@@ -279,31 +356,43 @@ interface TableIndexInfo {
279
356
  interface TableIndexesResult {
280
357
  indexes: TableIndexInfo[];
281
358
  }
282
- /** Severity of a buffered log entry, mirroring `@lunora/do`'s `LogLevel`. */
283
- type LogLevel = "debug" | "error" | "info" | "warn";
284
359
  /**
285
- * One buffered log line returned by `__lunora_admin__:getLogs`. `functionPath`
286
- * is the RPC that produced it (when known); `timestamp` is epoch-ms. Mirrors
287
- * `@lunora/do`'s `LogEntry`.
288
- */
360
+ * Severity of a buffered log entry, mirroring `@lunora/do`'s `LogLevel` — the
361
+ * full seven-tier `ctx.log` ramp (`trace`→`fatal`). A worker predating the
362
+ * un-folded buffer only ever sends the four console tiers, which are a subset.
363
+ */
364
+ type LogLevel = "debug" | "error" | "fatal" | "info" | "log" | "trace" | "warn";
365
+ /**
366
+ * One buffered log line returned by `__lunora_admin__:getLogs`. `functionPath`
367
+ * is the RPC that produced it (when known); `timestamp` is epoch-ms.
368
+ * `instance`/`exitCode` are populated for container lifecycle entries
369
+ * (`instance` = the per-instance Durable Object id, `exitCode` = the process
370
+ * exit code parsed out of a `stop` event). Mirrors `@lunora/do`'s `LogEntry`.
371
+ */
289
372
  interface LogEntry {
373
+ exitCode?: number;
374
+ /** Structured fields from a `ctx.log.<level>(message, fields)` / `ctx.log.with(fields)` call, when present. */
375
+ fields?: Record<string, unknown>;
290
376
  functionPath?: string;
377
+ instance?: string;
291
378
  level: LogLevel;
292
379
  message: string;
293
380
  timestamp: number;
381
+ /** Trace the line was emitted under; absent outside a dispatch (container lifecycle, hibernation-path errors) and on any worker predating the field. The key the Logs panel's Trace link and the Traces panel's correlated logs both join on. */
382
+ traceId?: string;
294
383
  }
295
384
  /** Payload of a `__lunora_admin__:getLogs` call: the buffered entries, newest first. */
296
385
  interface LogsResult {
297
386
  entries: LogEntry[];
298
387
  }
299
388
  /**
300
- * One recorded admin operation returned by `__lunora_admin__:getAuditLog`,
301
- * mirroring `@lunora/do`'s `AuditEntry`. Unlike the in-memory logs, the audit
302
- * log is durable and survives hibernation/restart. `seq` is a monotonic
303
- * per-shard cursor; `op` the short op name (`writeRow`, `runMigration`,
304
- * `importShard`, `applyCdc`); `table`/`id` are present when the op targets one;
305
- * `detail` carries op-specific context (notably the acting `userId`).
306
- */
389
+ * One recorded admin operation returned by `__lunora_admin__:getAuditLog`,
390
+ * mirroring `@lunora/do`'s `AuditEntry`. Unlike the in-memory logs, the audit
391
+ * log is durable and survives hibernation/restart. `seq` is a monotonic
392
+ * per-shard cursor; `op` the short op name (`writeRow`, `runMigration`,
393
+ * `importShard`, `applyCdc`); `table`/`id` are present when the op targets one;
394
+ * `detail` carries op-specific context (notably the acting `userId`).
395
+ */
307
396
  interface AuditEntry {
308
397
  detail?: Record<string, unknown>;
309
398
  id?: string;
@@ -317,17 +406,17 @@ interface AuditLogResult {
317
406
  entries: AuditEntry[];
318
407
  }
319
408
  /**
320
- * How a deployment binding/var classifies, mirroring `@lunora/do`'s `SettingKind`.
321
- * `var` is a plain Worker var, `secret` a sensitive string (always masked), and
322
- * `binding` a non-string binding object (R2/KV/DO/D1/queue/service).
323
- */
409
+ * How a deployment binding/var classifies, mirroring `@lunora/do`'s `SettingKind`.
410
+ * `var` is a plain Worker var, `secret` a sensitive string (always masked), and
411
+ * `binding` a non-string binding object (R2/KV/DO/D1/queue/service).
412
+ */
324
413
  type SettingKind = "binding" | "secret" | "var";
325
414
  /**
326
- * One row of the read-only deployment-settings view, mirroring `@lunora/do`'s
327
- * `SettingEntry`. `value` is a masked preview for `var`/`secret` strings (never
328
- * the raw secret) and `null` for `binding` entries. The server masks every
329
- * string value, so the studio only ever renders the masked text.
330
- */
415
+ * One row of the read-only deployment-settings view, mirroring `@lunora/do`'s
416
+ * `SettingEntry`. `value` is a masked preview for `var`/`secret` strings (never
417
+ * the raw secret) and `null` for `binding` entries. The server masks every
418
+ * string value, so the studio only ever renders the masked text.
419
+ */
331
420
  interface SettingEntry {
332
421
  /** Coarse runtime class for `binding` entries (`r2`, `kv`, `durable-object`, …). */
333
422
  bindingType?: string;
@@ -336,10 +425,10 @@ interface SettingEntry {
336
425
  value: null | string;
337
426
  }
338
427
  /**
339
- * Best-effort deploy metadata, mirroring `@lunora/do`'s `DeployInfo`. Every
340
- * field is optional: the server reads only what the Worker `env` exposes and
341
- * omits the rest.
342
- */
428
+ * Best-effort deploy metadata, mirroring `@lunora/do`'s `DeployInfo`. Every
429
+ * field is optional: the server reads only what the Worker `env` exposes and
430
+ * omits the rest.
431
+ */
343
432
  interface DeployInfo {
344
433
  deploymentId?: string;
345
434
  environment?: string;
@@ -352,24 +441,24 @@ interface SettingsResult {
352
441
  settings: SettingEntry[];
353
442
  }
354
443
  /**
355
- * Ordering/visual weight of a {@link SecurityFinding}, mirroring `@lunora/do`'s
356
- * `SecurityFindingLevel`. Shares the studio's insight-severity vocabulary so the
357
- * Security and Performance advisors render with one badge palette.
358
- */
444
+ * Ordering/visual weight of a {@link SecurityFinding}, mirroring `@lunora/do`'s
445
+ * `SecurityFindingLevel`. Shares the studio's insight-severity vocabulary so the
446
+ * Security and Performance advisors render with one badge palette.
447
+ */
359
448
  type SecurityFindingLevel = "error" | "info" | "warning";
360
449
  /**
361
- * Which deployment-level security heuristic fired, mirroring `@lunora/do`'s
362
- * `SecurityFindingKind`. The studio maps each kind to a localized title,
363
- * explanation, and remediation hint; the wire payload carries only the kind,
364
- * level, and optional `detail`.
365
- */
450
+ * Which deployment-level security heuristic fired, mirroring `@lunora/do`'s
451
+ * `SecurityFindingKind`. The studio maps each kind to a localized title,
452
+ * explanation, and remediation hint; the wire payload carries only the kind,
453
+ * level, and optional `detail`.
454
+ */
366
455
  type SecurityFindingKind = "admin-token-weak" | "auth-secret-weak" | "cookies-insecure" | "cors-wildcard-credentials" | "csrf-disabled" | "dev-args-unredacted" | "security-headers-disabled" | "ws-gate-open";
367
456
  /**
368
- * One detected security issue from `__lunora_admin__:getSecurityAudit`, mirroring
369
- * `@lunora/do`'s `SecurityFinding`. `detail` carries kind-specific context the
370
- * studio interpolates into the localized copy (e.g. `{ length, min }` for a weak
371
- * admin token); absent when the kind needs none.
372
- */
457
+ * One detected security issue from `__lunora_admin__:getSecurityAudit`, mirroring
458
+ * `@lunora/do`'s `SecurityFinding`. `detail` carries kind-specific context the
459
+ * studio interpolates into the localized copy (e.g. `{ length, min }` for a weak
460
+ * admin token); absent when the kind needs none.
461
+ */
373
462
  interface SecurityFinding {
374
463
  detail?: Record<string, unknown>;
375
464
  kind: SecurityFindingKind;
@@ -391,10 +480,22 @@ interface TablePage {
391
480
  refs?: Record<string, string>;
392
481
  rows: Record<string, unknown>[];
393
482
  /**
394
- * Total rows matching the predicate. Absent when the read passed
395
- * `skipCount: true` — the data browser sources the count from a separate,
396
- * predicate-keyed read so paging never re-runs the COUNT.
397
- */
483
+ * The table's PHYSICAL column names (`id`, `_creationTime`, `__doc__` for a
484
+ * canonical shard table), mirroring `@lunora/do`'s `TablePage.sqlColumns`.
485
+ *
486
+ * `columns` is the DISPLAY list, with every `__doc__` field lifted to a
487
+ * top-level column — names no SQL statement can reference. A surface that
488
+ * feeds columns to something SQL-shaped wants this list, not that one.
489
+ *
490
+ * Optional on the client mirror because a shard running an older `@lunora/do`
491
+ * omits it; a caller must treat its absence as "unknown", never as "none".
492
+ */
493
+ sqlColumns?: string[];
494
+ /**
495
+ * Total rows matching the predicate. Absent when the read passed
496
+ * `skipCount: true` — the data browser sources the count from a separate,
497
+ * predicate-keyed read so paging never re-runs the COUNT.
498
+ */
398
499
  total?: number;
399
500
  }
400
501
  /** Direction a data migration is run in. Mirrors `@lunora/do`. */
@@ -402,9 +503,9 @@ type MigrationDirection = "down" | "up";
402
503
  /** Lifecycle of a data-migration run. Mirrors `@lunora/do`. */
403
504
  type MigrationStatus = "completed" | "failed" | "in_progress";
404
505
  /**
405
- * One persisted migration run-state row, as returned by the
406
- * `__lunora_admin__:migrationStatus` RPC (`{ migrations: MigrationStatusRow[] }`).
407
- */
506
+ * One persisted migration run-state row, as returned by the
507
+ * `__lunora_admin__:migrationStatus` RPC (`{ migrations: MigrationStatusRow[] }`).
508
+ */
408
509
  interface MigrationStatusRow {
409
510
  changed: number;
410
511
  cursor: null | string;
@@ -451,25 +552,27 @@ interface ImportShardResult {
451
552
  conflicts: number;
452
553
  errors: ImportError[];
453
554
  inserted: Record<string, number>;
555
+ /** Existing rows overwritten under `onConflict: "replace"`; absent from a shard built before replace imports. */
556
+ replaced?: number;
454
557
  }
455
558
  /**
456
- * One shard's request total from the worker's `POST /_lunora/admin/shard-traffic`
457
- * endpoint, mirroring `@lunora/runtime`'s `ShardTrafficEntry`. `requests` is the
458
- * shard's lifetime dispatch count (`0` for a shard that failed/timed out);
459
- * `shardKey` is the DO id name (`""` for the root shard). The cross-shard feed
460
- * the `hot_shard` runtime advisor consumes to compute skew.
461
- */
559
+ * One shard's request total from the worker's `POST /_lunora/admin/shard-traffic`
560
+ * endpoint, mirroring `@lunora/runtime`'s `ShardTrafficEntry`. `requests` is the
561
+ * shard's lifetime dispatch count (`0` for a shard that failed/timed out);
562
+ * `shardKey` is the DO id name (`""` for the root shard). The cross-shard feed
563
+ * the `hot_shard` runtime advisor consumes to compute skew.
564
+ */
462
565
  interface ShardTrafficEntry {
463
566
  requests: number;
464
567
  shardKey: string;
465
568
  }
466
569
  /**
467
- * Payload of a `POST /_lunora/admin/shard-traffic` call, mirroring the runtime
468
- * coordinator's shard-traffic fan-out result: one `{ shardKey, requests }` entry
469
- * per live shard plus the ok / failed counts. Fanned out on demand (not on the
470
- * metrics hot path) so the panel can feed `hot_shard` the whole shard set's
471
- * request volumes.
472
- */
570
+ * Payload of a `POST /_lunora/admin/shard-traffic` call, mirroring the runtime
571
+ * coordinator's shard-traffic fan-out result: one `{ shardKey, requests }` entry
572
+ * per live shard plus the ok / failed counts. Fanned out on demand (not on the
573
+ * metrics hot path) so the panel can feed `hot_shard` the whole shard set's
574
+ * request volumes.
575
+ */
473
576
  interface ShardTrafficResult {
474
577
  failed: number;
475
578
  ok: number;
@@ -478,25 +581,26 @@ interface ShardTrafficResult {
478
581
  /** Visual + ordering weight of a detected issue. */
479
582
  type InsightSeverity = "error" | "info" | "warning";
480
583
  /**
481
- * Which heuristic fired. The panel maps each kind to a localized title/detail,
482
- * so the detection stays free of presentation strings (and trivially testable).
483
- *
484
- * `missing-index` is the causal upgrade of `slow-function`: a slow function
485
- * whose latency is explained by a full-table scan. When the scan attribution
486
- * pins the cause, the insight names the scanned table(s) (`tables`) and deep-
487
- * links to the Schema/Indexes tab to add the index, rather than leaving the
488
- * slowness an unattributed symptom.
489
- */
490
- type InsightKind = "high-error-rate" | "high-evictions" | "high-write-contention" | "low-cache-hit-rate" | "missing-index" | "slow-function";
491
- /**
492
- * One detected issue. `value` is the headline number whose meaning depends on
493
- * `kind`: a 0–1 rate for cache-hit / error-rate, a millisecond figure for
494
- * slow-function / missing-index, an entry count for evictions. `fn` is set only
495
- * for per-function insights; `message` carries the last error for
496
- * high-error-rate; `tables` carries the full-scanned tables (busiest first) for
497
- * the causal `missing-index` kind. For `high-write-contention` it is the OCC
498
- * conflict ratio (conflicts / calls).
499
- */
584
+ * Which heuristic fired. The panel maps each kind to a localized title/detail,
585
+ * so the detection stays free of presentation strings (and trivially testable).
586
+ *
587
+ * `missing-index` is the causal upgrade of `slow-function`: a slow function
588
+ * whose latency is explained by a full-table scan. When the scan attribution
589
+ * pins the cause, the insight names the scanned table(s) (`tables`) and deep-
590
+ * links to the Schema/Indexes tab to add the index, rather than leaving the
591
+ * slowness an unattributed symptom.
592
+ */
593
+ type InsightKind = "high-error-rate" | "high-evictions" | "high-write-contention" | "low-cache-hit-rate" | "missing-index" | "slow-function" | "storage-headroom";
594
+ /**
595
+ * One detected issue. `value` is the headline number whose meaning depends on
596
+ * `kind`: a 0–1 rate for cache-hit / error-rate, a millisecond figure for
597
+ * slow-function / missing-index, an entry count for evictions. `fn` is set only
598
+ * for per-function insights; `message` carries the last error for
599
+ * high-error-rate; `tables` carries the full-scanned tables (busiest first) for
600
+ * the causal `missing-index` kind. For `high-write-contention` it is the OCC
601
+ * conflict ratio (conflicts / calls). For `storage-headroom` it is the shard's
602
+ * SQLite size in bytes.
603
+ */
500
604
  interface Insight {
501
605
  fn?: string;
502
606
  kind: InsightKind;
@@ -521,184 +625,180 @@ interface InsightThresholds {
521
625
  minErrorCalls: number;
522
626
  /** Flag functions whose slowest call is at or above this many milliseconds. */
523
627
  slowFunctionMs: number;
628
+ /** Escalate the storage insight to `error` at or above this many bytes. */
629
+ storageCriticalBytes: number;
630
+ /** Flag a shard whose SQLite is at or above this many bytes. */
631
+ storageWarnBytes: number;
524
632
  }
525
633
  declare const DEFAULT_INSIGHT_THRESHOLDS: InsightThresholds;
526
634
  /**
527
- * Derive a prioritised list of issues from the two snapshots the studio
528
- * already pulls — the `getMetrics` health snapshot and the `getFunctionStats`
529
- * per-function table. Pure and side-effect-free: same inputs, same output, so
530
- * the heuristics can be unit-tested without rendering.
531
- *
532
- * Heuristics: low-cache-hit-rate (cache below the threshold once enough samples
533
- * exist — a cold cache isn't a problem); high-evictions (more evictions than
534
- * hits, so the cache is too small or churning on invalidation); missing-index (a
535
- * slow function whose latency is *explained* by a full-table scan — the causal
536
- * upgrade of slow-function, naming the scanned table(s)); slow-function (a
537
- * function whose slowest call crosses the threshold with no scan attribution to
538
- * blame); high-error-rate (a function failing over a meaningful count);
539
- * high-write-contention (a function whose OCC write conflicts make up a
540
- * meaningful share of calls — a sharding candidate).
541
- *
542
- * A slow function with full-scan attribution emits `missing-index` (causal, with
543
- * `tables`) instead of the bare `slow-function`, so the panel can link straight
544
- * to the fix rather than restating the symptom.
545
- */
635
+ * Derive a prioritised list of issues from the two snapshots the studio
636
+ * already pulls — the `getMetrics` health snapshot and the `getFunctionStats`
637
+ * per-function table. Pure and side-effect-free: same inputs, same output, so
638
+ * the heuristics can be unit-tested without rendering.
639
+ *
640
+ * Heuristics: low-cache-hit-rate (cache below the threshold once enough samples
641
+ * exist — a cold cache isn't a problem); high-evictions (more evictions than
642
+ * hits, so the cache is too small or churning on invalidation); missing-index (a
643
+ * slow function whose latency is *explained* by a full-table scan — the causal
644
+ * upgrade of slow-function, naming the scanned table(s)); slow-function (a
645
+ * function whose slowest call crosses the threshold with no scan attribution to
646
+ * blame); high-error-rate (a function failing over a meaningful count);
647
+ * high-write-contention (a function whose OCC write conflicts make up a
648
+ * meaningful share of calls — a sharding candidate); storage-headroom (a shard
649
+ * whose SQLite is closing on the 10 GiB per-DO ceiling).
650
+ *
651
+ * A slow function with full-scan attribution emits `missing-index` (causal, with
652
+ * `tables`) instead of the bare `slow-function`, so the panel can link straight
653
+ * to the fix rather than restating the symptom.
654
+ *
655
+ * `storage-headroom` exists because the runtime's own signal is a one-shot
656
+ * `console.warn` inside the Durable Object — it fires once per DO instance, into
657
+ * a log nobody is tailing at 3am months before the wall. The size is already on
658
+ * the `getMetrics` snapshot the studio pulls, so surfacing it as a finding costs
659
+ * one comparison and puts the warning where someone will actually meet it.
660
+ */
546
661
  declare const deriveInsights: (metrics: ShardMetrics | null, functions: FunctionCallStat[] | null, thresholds?: InsightThresholds) => Insight[];
547
662
  interface InsightsPanelProps {
548
663
  /** Shard key the snapshots target on first load. Defaults to the root shard. */
549
664
  readonly initialShardKey?: string;
550
665
  /**
551
- * Fan the cross-shard traffic feed out for `table`, returning each shard's
552
- * `{ shardKey, requests }` total — the input the `hot_shard` advisor lint
553
- * needs. Defaults to `client.shardTraffic(table)` (the admin-gated
554
- * `POST /_lunora/admin/shard-traffic` fan-out). Best-effort: a rejection
555
- * leaves `hot_shard` dormant rather than blanking the panel. Injectable so
556
- * tests can drive the skew without a worker.
557
- */
666
+ * Fan the cross-shard traffic feed out for `table`, returning each shard's
667
+ * `{ shardKey, requests }` total — the input the `hot_shard` advisor lint
668
+ * needs. Defaults to `client.shardTraffic(table)` (the admin-gated
669
+ * `POST /_lunora/admin/shard-traffic` fan-out). Best-effort: a rejection
670
+ * leaves `hot_shard` dormant rather than blanking the panel. Injectable so
671
+ * tests can drive the skew without a worker.
672
+ */
558
673
  readonly loadShardTraffic?: (table: string) => Promise<ShardTrafficResult>;
559
674
  }
560
675
  /**
561
- * The Performance Advisor — a 1-to-1 of Supabase's Performance Advisor: severity
562
- * tabs over a findings table (via {@link AdvisorView}). It pulls the `getMetrics`
563
- * health snapshot and `getFunctionStats` per-function table for one shard, then
564
- * maps the issues {@link deriveInsights} detects (low cache hit rate, high
565
- * eviction, slow functions, missing indexes, error spikes) into rows. A
566
- * `missing-index` row carries an inline "add the index" jump to the Schema tab.
567
- * Both reads are best-effort — one failing still yields the other's insights.
568
- */
569
- declare const InsightsPanel: ({
570
- initialShardKey,
571
- loadShardTraffic
572
- }: InsightsPanelProps) => ReactElement;
573
- /**
574
- * The Security Advisor — a 1-to-1 of Supabase's Security Advisor: severity tabs
575
- * (Errors / Warnings / Info) over a findings table. It pulls `getSecurityAudit`
576
- * (deployment-wide, so it targets the root shard and needs no shard selector) and
577
- * maps each finding the server derived from the Worker `env` — weak admin token,
578
- * an open WebSocket gate, a dev-mode request log keeping un-redacted args — into a
579
- * row. These are signals only lunora can surface: Cloudflare's dashboard can't
580
- * reason about lunora's admin/WS gates or its log-redaction policy.
581
- */
676
+ * The Performance Advisor — a 1-to-1 of Supabase's Performance Advisor: severity
677
+ * tabs over a findings table (via {@link AdvisorView}). It pulls the `getMetrics`
678
+ * health snapshot and `getFunctionStats` per-function table for one shard, then
679
+ * maps the issues {@link deriveInsights} detects (low cache hit rate, high
680
+ * eviction, slow functions, missing indexes, error spikes, storage headroom)
681
+ * into rows. A `missing-index` row carries an inline "add the index" jump to the
682
+ * Schema tab. Both reads are best-effort — one failing still yields the other's
683
+ * insights.
684
+ */
685
+ declare const InsightsPanel: ({ initialShardKey, loadShardTraffic }: InsightsPanelProps) => ReactElement;
686
+ /**
687
+ * The Security Advisor — a 1-to-1 of Supabase's Security Advisor: severity tabs
688
+ * (Errors / Warnings / Info) over a findings table. It pulls `getSecurityAudit`
689
+ * (deployment-wide, so it targets the root shard and needs no shard selector) and
690
+ * maps each finding the server derived from the Worker `env` — weak admin token,
691
+ * an open WebSocket gate for user subscriptions, a dev-mode request log keeping
692
+ * un-redacted args — into a row. These are signals only lunora can surface: Cloudflare's dashboard can't
693
+ * reason about lunora's admin/WS gates or its log-redaction policy.
694
+ */
582
695
  declare const SecurityAdvisorPanel: () => ReactElement;
583
696
  interface ApiDocsPanelProps {
584
697
  /**
585
- * Registered functions to document. Mirrors the list the Functions tab's
586
- * runner and stats panels receive — a query/mutation/action's `kind` is
587
- * compile-time-only, so it must be named here. When omitted the panel still
588
- * renders (tables come from the admin RPC) and shows an empty functions list.
589
- */
698
+ * Registered functions to document. Mirrors the list the Functions tab's
699
+ * runner and stats panels receive — a query/mutation/action's `kind` is
700
+ * compile-time-only, so it must be named here. When omitted the panel still
701
+ * renders (tables come from the admin RPC) and shows an empty functions list.
702
+ */
590
703
  readonly functions?: FunctionDescriptor[];
591
704
  /** Shard key the table list is read from. Defaults to the root shard. */
592
705
  readonly initialShardKey?: string;
593
706
  }
594
- /** Inputs every function snippet builder closes over — the split path plus its `kind`. */
595
- /**
596
- * Per-resource "how to call this from your app" browser, generated from the
597
- * registered functions and tables the studio already has — no new endpoints.
598
- * The left rail lists functions grouped by file plus a Tables section; the right
599
- * pane shows copy-paste snippets (React / Client / CLI for functions; the typed
600
- * data-model usage for tables).
601
- *
602
- * Args are a placeholder: the real argument shape lives in the codegen'd `api`
603
- * types this browser never loads, the same way Supabase's usage snippets show
604
- * placeholders.
605
- */
606
- declare const ApiDocsPanel: ({
607
- functions,
608
- initialShardKey
609
- }: ApiDocsPanelProps) => ReactElement;
707
+ /**
708
+ * Per-resource "how to call this from your app" browser, generated from the
709
+ * registered functions and tables the studio already has — no new endpoints.
710
+ * The left rail lists functions grouped by file plus a Tables section; the right
711
+ * pane shows copy-paste snippets (React / Client / CLI for functions; the typed
712
+ * data-model usage for tables).
713
+ *
714
+ * Args are a placeholder: the real argument shape lives in the codegen'd `api`
715
+ * types this browser never loads, the same way Supabase's usage snippets show
716
+ * placeholders.
717
+ */
718
+ declare const ApiDocsPanel: ({ functions, initialShardKey }: ApiDocsPanelProps) => ReactElement;
610
719
  interface ApiReferencePanelProps {
611
720
  /**
612
- * Inline OpenAPI document. When supplied the panel renders it directly and
613
- * skips the fetch — used by the mock harness and by hosts that already hold
614
- * the generated spec. When omitted the panel fetches the worker's
615
- * admin-gated `GET /_lunora/admin/openapi` endpoint via the client.
616
- */
721
+ * Inline OpenAPI document. When supplied the panel renders it directly and
722
+ * skips the fetch — used by the mock harness and by hosts that already hold
723
+ * the generated spec. When omitted the panel fetches the worker's
724
+ * admin-gated `GET /_lunora/admin/openapi` endpoint via the client.
725
+ */
617
726
  readonly spec?: unknown;
618
727
  }
619
728
  /**
620
- * In-studio OpenAPI reference: renders the generated OpenAPI 3.1 document with
621
- * the studio-native {@link ReferenceView} — a tag-grouped operation browser,
622
- * schema tables, a live "try it" console, and copy-paste request samples, all
623
- * themed to the studio. The spec comes from an inline
624
- * {@link ApiReferencePanelProps.spec} prop, or — by default — the worker's
625
- * admin-gated `GET /_lunora/admin/openapi` endpoint fetched through the client.
626
- *
627
- * This replaced the embedded Scalar reference (a Vue app in React): Scalar's
628
- * portal/overlay layers repeatedly intercepted clicks and froze the tab, and it
629
- * shipped a multi-megabyte bundle. The native view is overlay-free and reuses
630
- * the studio's own primitives.
631
- */
632
- declare const ApiReferencePanel: ({
633
- spec: inlineSpec
634
- }: ApiReferencePanelProps) => ReactElement;
729
+ * In-studio OpenAPI reference: renders the generated OpenAPI 3.1 document with
730
+ * the studio-native {@link ReferenceView} — a tag-grouped operation browser,
731
+ * schema tables, a live "try it" console, and copy-paste request samples, all
732
+ * themed to the studio. The spec comes from an inline
733
+ * {@link ApiReferencePanelProps.spec} prop, or — by default — the worker's
734
+ * admin-gated `GET /_lunora/admin/openapi` endpoint fetched through the client.
735
+ *
736
+ * This replaced the embedded Scalar reference (a Vue app in React): Scalar's
737
+ * portal/overlay layers repeatedly intercepted clicks and froze the tab, and it
738
+ * shipped a multi-megabyte bundle. The native view is overlay-free and reuses
739
+ * the studio's own primitives.
740
+ */
741
+ declare const ApiReferencePanel: ({ spec: inlineSpec }: ApiReferencePanelProps) => ReactElement;
635
742
  interface ApiTabProps {
636
743
  /** Registered functions documented by the snippets sub-view. Threaded host → studio. */
637
744
  readonly functions?: FunctionDescriptor[];
638
745
  /** Shard key the snippets view reads its table list from. */
639
746
  readonly initialShardKey?: string;
640
747
  /**
641
- * Inline OpenAPI document for the reference sub-view. When omitted the
642
- * reference fetches the worker's `GET /_lunora/admin/openapi` endpoint.
643
- */
748
+ * Inline OpenAPI document for the reference sub-view. When omitted the
749
+ * reference fetches the worker's `GET /_lunora/admin/openapi` endpoint.
750
+ */
644
751
  readonly openApiSpec?: unknown;
645
752
  /**
646
- * Inline OpenRPC document for the reference sub-view's OpenRPC format. When
647
- * omitted the OpenRPC view fetches the worker's `GET /_lunora/admin/openrpc`
648
- * endpoint. OpenRPC is the RPC-native spec (RPC functions only); OpenAPI
649
- * additionally covers `httpRouter()` REST routes.
650
- */
753
+ * Inline OpenRPC document for the reference sub-view's OpenRPC format. When
754
+ * omitted the OpenRPC view fetches the worker's `GET /_lunora/admin/openrpc`
755
+ * endpoint. OpenRPC is the RPC-native spec (RPC functions only); OpenAPI
756
+ * additionally covers `httpRouter()` REST routes.
757
+ */
651
758
  readonly openRpcSpec?: unknown;
652
759
  }
653
760
  /**
654
- * The studio's API tab. Hosts two complementary surfaces behind a segmented
655
- * toggle. The Reference view renders a machine-readable spec — the OpenAPI 3.1
656
- * document or the RPC-native OpenRPC document — through the studio-native
657
- * reference UI (operation browser, schema tables, a live "try it" console, and a
658
- * request-sample rail), with a small format switch between them. The Snippets
659
- * view is the per-function React / Client / CLI copy-paste browser
660
- * (`api-docs-panel`), the lightweight "how do I call this" DX.
661
- *
662
- * Reference is the default; OpenAPI is the default format (the richer,
663
- * spec-driven view that also covers REST). Each format degrades to a clear
664
- * empty state when its spec isn't wired.
665
- */
666
- declare const ApiTab: ({
667
- functions,
668
- initialShardKey,
669
- openApiSpec,
670
- openRpcSpec
671
- }: ApiTabProps) => ReactElement;
761
+ * The studio's API tab. Hosts two complementary surfaces behind a segmented
762
+ * toggle. The Reference view renders a machine-readable spec — the OpenAPI 3.1
763
+ * document or the RPC-native OpenRPC document — through the studio-native
764
+ * reference UI (operation browser, schema tables, a live "try it" console, and a
765
+ * request-sample rail), with a small format switch between them. The Snippets
766
+ * view is the per-function React / Client / CLI copy-paste browser
767
+ * (`api-docs-panel`), the lightweight "how do I call this" DX.
768
+ *
769
+ * Reference is the default; OpenAPI is the default format (the richer,
770
+ * spec-driven view that also covers REST). Each format degrades to a clear
771
+ * empty state when its spec isn't wired.
772
+ */
773
+ declare const ApiTab: ({ functions, initialShardKey, openApiSpec, openRpcSpec }: ApiTabProps) => ReactElement;
672
774
  interface OpenRpcReferencePanelProps {
673
775
  /**
674
- * Inline OpenRPC document. When supplied the panel renders it directly and
675
- * skips the fetch — used by the mock harness and by hosts that already hold
676
- * the generated spec. When omitted the panel fetches the worker's
677
- * admin-gated `GET /_lunora/admin/openrpc` endpoint via the client.
678
- */
776
+ * Inline OpenRPC document. When supplied the panel renders it directly and
777
+ * skips the fetch — used by the mock harness and by hosts that already hold
778
+ * the generated spec. When omitted the panel fetches the worker's
779
+ * admin-gated `GET /_lunora/admin/openrpc` endpoint via the client.
780
+ */
679
781
  readonly spec?: unknown;
680
782
  }
681
783
  /**
682
- * In-studio OpenRPC reference. OpenRPC is the RPC-native spec (a `methods` array
683
- * over the JSON-RPC-shaped `POST /_lunora/rpc` transport), documenting the RPC
684
- * functions only. It is parsed into the shared `ApiModel` and rendered by the
685
- * same studio-native {@link ReferenceView} the OpenAPI panel uses, so both
686
- * formats share one operation browser, schema view, try-it console, and sample
687
- * rail.
688
- *
689
- * The spec comes from an inline {@link OpenRpcReferencePanelProps.spec} prop, or
690
- * — by default — the worker's admin-gated `GET /_lunora/admin/openrpc` endpoint.
691
- */
692
- declare const OpenRpcReferencePanel: ({
693
- spec: inlineSpec
694
- }: OpenRpcReferencePanelProps) => ReactElement;
695
- /**
696
- * A shareable data-browser view: the table, storage tier, shard, structured
697
- * filters, substring search, and sort that together reproduce exactly what the
698
- * grid is showing. This is the unit that is serialized into the URL (so the link
699
- * IS the query) and persisted by name in {@link loadSavedQueries}. Every field is
700
- * optional so a partial/legacy URL still hydrates into a sensible default view.
701
- */
784
+ * In-studio OpenRPC reference. OpenRPC is the RPC-native spec (a `methods` array
785
+ * over the JSON-RPC-shaped `POST /_lunora/rpc` transport), documenting the RPC
786
+ * functions only. It is parsed into the shared `ApiModel` and rendered by the
787
+ * same studio-native {@link ReferenceView} the OpenAPI panel uses, so both
788
+ * formats share one operation browser, schema view, try-it console, and sample
789
+ * rail.
790
+ *
791
+ * The spec comes from an inline {@link OpenRpcReferencePanelProps.spec} prop, or
792
+ * — by default — the worker's admin-gated `GET /_lunora/admin/openrpc` endpoint.
793
+ */
794
+ declare const OpenRpcReferencePanel: ({ spec: inlineSpec }: OpenRpcReferencePanelProps) => ReactElement;
795
+ /**
796
+ * A shareable data-browser view: the table, storage tier, shard, structured
797
+ * filters, substring search, and sort that together reproduce exactly what the
798
+ * grid is showing. This is the unit that is serialized into the URL (so the link
799
+ * IS the query) and persisted by name in {@link loadSavedQueries}. Every field is
800
+ * optional so a partial/legacy URL still hydrates into a sensible default view.
801
+ */
702
802
  interface DataView {
703
803
  /** Structured `column operator value` clauses, AND-combined with the search. */
704
804
  filters?: FilterClause[];
@@ -721,57 +821,64 @@ interface SavedQuery {
721
821
  name: string;
722
822
  view: DataView;
723
823
  }
724
- /** Saved queries, most-recently-saved first. Empty when storage is unavailable or empty. */
725
824
  interface DataBrowserProps {
726
825
  /**
727
- * Allow editing: surfaces insert/edit/delete actions that issue
728
- * `__lunora_admin__:writeRow` ops through the schema-aware writer. Off by
729
- * default — the browser is read-only unless the host opts in.
730
- */
826
+ * Offer "Generate rows" alongside the edit controls. It needs the dev host's
827
+ * seed endpoint, which a deployed studio does not have, so it is its own
828
+ * switch rather than part of `editable`. Off by default.
829
+ */
830
+ readonly canGenerateRows?: boolean;
831
+ /**
832
+ * Allow editing: surfaces insert/edit/delete actions that issue
833
+ * `__lunora_admin__:writeRow` ops through the schema-aware writer. Off by
834
+ * default — the browser is read-only unless the host opts in.
835
+ */
731
836
  readonly editable?: boolean;
732
837
  /**
733
- * Names of the `.global()` (D1-backed) tables. A `v.id` ref cell whose target
734
- * is one of these is followed cross-tier via `onNavigateToGlobal` instead of
735
- * being read from this shard (where it doesn't exist). Supplied by the Table
736
- * editor; defaults to none when the browser is used standalone.
737
- */
838
+ * Names of the `.global()` (D1-backed) tables. A `v.id` ref cell whose target
839
+ * is one of these is followed cross-tier via `onNavigateToGlobal` instead of
840
+ * being read from this shard (where it doesn't exist). Supplied by the Table
841
+ * editor; defaults to none when the browser is used standalone.
842
+ */
738
843
  readonly globalTableNames?: ReadonlySet<string>;
739
844
  /** Structured filters to hydrate from a shared link / saved query. */
740
845
  readonly initialFilters?: FilterClause[];
741
846
  /** Sort to hydrate from a shared link / saved query. */
742
847
  readonly initialOrderBy?: DataView["orderBy"];
848
+ /** Comma-separated pinned columns from the URL; wins over the per-browser default. */
849
+ readonly initialPins?: string;
743
850
  /** Substring search to hydrate from a shared link / saved query. */
744
851
  readonly initialSearch?: string;
745
852
  /** Shard key the browser targets on first load. Defaults to the root shard. */
746
853
  readonly initialShardKey?: string;
747
854
  /**
748
- * Follow a `v.id` ref whose target is a global table — the Table editor switches
749
- * to the global tier and opens that table. When omitted (standalone use), a ref
750
- * to a global table falls through to the in-shard read (and surfaces its error).
751
- */
855
+ * Follow a `v.id` ref whose target is a global table — the Table editor switches
856
+ * to the global tier and opens that table. When omitted (standalone use), a ref
857
+ * to a global table falls through to the in-shard read (and surfaces its error).
858
+ */
752
859
  readonly onNavigateToGlobal?: (table: string, id: string) => void;
753
860
  /**
754
- * Navigate the URL to a table (the Table editor pushes `?table=…`), opening it
755
- * clean; `options.search` pre-fills the search for an FK-cell traversal.
756
- * Omitted in standalone use.
757
- */
861
+ * Navigate the URL to a table (the Table editor pushes `?table=…`), opening it
862
+ * clean; `options.search` pre-fills the search for an FK-cell traversal.
863
+ * Omitted in standalone use.
864
+ */
758
865
  readonly onSelectTable?: (table: string, options?: {
759
866
  search?: string;
760
867
  }) => void;
761
868
  /**
762
- * Called whenever the loaded view (shard / search / filters / sort) changes, so
763
- * the host can mirror it to the URL — making every view a shareable link.
764
- * Omitted in standalone use (view state stays in-component).
765
- */
869
+ * Called whenever the loaded view (shard / search / filters / sort) changes, so
870
+ * the host can mirror it to the URL — making every view a shareable link.
871
+ * Omitted in standalone use (view state stays in-component).
872
+ */
766
873
  readonly onViewChange?: (view: Pick<DataView, "filters" | "orderBy" | "search" | "shard">) => void;
767
874
  /** Rows requested per page. Clamped server-side to `[1, 500]`. */
768
875
  readonly pageSize?: number;
769
876
  /**
770
- * The canned-query toolbar's handlers + saved list. Supplied by the Table editor
771
- * (it owns the router and the `saved-queries` localStorage helper); omitted in
772
- * standalone use, which hides the toolbar entirely. `onSaveQuery` receives the
773
- * name plus the current view to persist.
774
- */
877
+ * The canned-query toolbar's handlers + saved list. Supplied by the Table editor
878
+ * (it owns the router and the `saved-queries` localStorage helper); omitted in
879
+ * standalone use, which hides the toolbar entirely. `onSaveQuery` receives the
880
+ * name plus the current view to persist.
881
+ */
775
882
  readonly queryBar?: {
776
883
  readonly onApplyQuery: (query: SavedQuery) => void;
777
884
  readonly onCopyLink: () => void;
@@ -780,235 +887,304 @@ interface DataBrowserProps {
780
887
  readonly saved: ReadonlyArray<SavedQuery>;
781
888
  };
782
889
  /**
783
- * The schema/source selector rendered at the top of the table-list sidebar —
784
- * the Table editor's `schema public ▾` switch. Supplied when this browser is
785
- * composed into the Table editor; omitted when it's used alone.
786
- */
890
+ * The schema/source selector rendered at the top of the table-list sidebar —
891
+ * the Table editor's `schema public ▾` switch. Supplied when this browser is
892
+ * composed into the Table editor; omitted when it's used alone.
893
+ */
787
894
  readonly schemaSwitch?: ReactNode;
788
895
  /**
789
- * The table named in the URL. Drives the selection — a deep link or browser
790
- * back/forward to a different `?table=…` re-opens that table. Supplied by the
791
- * Table editor; omitted in standalone use (selection stays purely in-component).
792
- */
896
+ * The table named in the URL. Drives the selection — a deep link or browser
897
+ * back/forward to a different `?table=…` re-opens that table. Supplied by the
898
+ * Table editor; omitted in standalone use (selection stays purely in-component).
899
+ */
793
900
  readonly tableParam?: string;
794
901
  }
795
902
  /**
796
- * Read-only data browser for a single shard's SQLite database. Lists the user
797
- * tables (via the `__lunora_admin__:listTables` RPC), then pages through the
798
- * rows of whichever table is selected (`__lunora_admin__:readTablePage`).
799
- *
800
- * Both calls travel over the ordinary `useLunora` client transport; the
801
- * admin RPCs are intercepted inside the Durable Object and are gated by the
802
- * server's `LUNORA_ADMIN_TOKEN`. The host is responsible for configuring the
803
- * client's auth token — this component issues no credentials of its own.
804
- *
805
- * The table view is built on a headless `@tanstack/react-table` model: column
806
- * defs derive from `page.columns`, sorting and (global) filtering run
807
- * page-locally over the loaded rows, and the rendered rows are virtualized with
808
- * `@tanstack/react-virtual` so a large page never inflates the DOM. None of this
809
- * touches the server — pagination still flows through `readTablePage`. All of
810
- * that state lives in {@link useDataBrowser}; this component is just the markup.
811
- */
812
- declare const DataBrowser: ({
813
- editable,
814
- globalTableNames,
815
- initialFilters,
816
- initialOrderBy,
817
- initialSearch,
818
- initialShardKey,
819
- onNavigateToGlobal,
820
- onSelectTable,
821
- onViewChange,
822
- pageSize: initialPageSize,
823
- queryBar,
824
- schemaSwitch,
825
- tableParam
826
- }: DataBrowserProps) => ReactElement;
903
+ * Read-only data browser for a single shard's SQLite database. Lists the user
904
+ * tables (via the `__lunora_admin__:listTables` RPC), then pages through the
905
+ * rows of whichever table is selected (`__lunora_admin__:readTablePage`).
906
+ *
907
+ * Both calls travel over the `LunoraAdminClient` from `useStudioClient`; the
908
+ * admin RPCs are intercepted inside the Durable Object and are gated by the
909
+ * server's `LUNORA_ADMIN_TOKEN`. The host is responsible for configuring the
910
+ * client's auth token — this component issues no credentials of its own.
911
+ *
912
+ * The table view is built on a headless `@tanstack/react-table` model: column
913
+ * defs derive from `page.columns`, sorting and (global) filtering run
914
+ * page-locally over the loaded rows, and the rendered rows are virtualized with
915
+ * `@tanstack/react-virtual` so a large page never inflates the DOM. None of this
916
+ * touches the server — pagination still flows through `readTablePage`. All of
917
+ * that state lives in {@link useDataBrowser}; this component is just the markup.
918
+ */
919
+ declare const DataBrowser: ({ canGenerateRows, editable, globalTableNames, initialFilters, initialOrderBy, initialPins, initialSearch, initialShardKey, onNavigateToGlobal, onSelectTable, onViewChange, pageSize: initialPageSize, queryBar, schemaSwitch, tableParam }: DataBrowserProps) => ReactElement;
827
920
  /** A filter row as edited in the UI — the value is always a string until coerced for the wire. */
828
921
  interface EditableFilter {
829
922
  column: string;
923
+ /**
924
+ * The exact wire value this row carries, when the row did NOT come from the
925
+ * operator typing into the box: a facet-value click, or hydration from a URL
926
+ * / saved query. Present as a one-element tuple so `null` — itself a
927
+ * meaningful filter value — is distinguishable from "no literal".
928
+ *
929
+ * `value` still holds that value's display text (the box has to show
930
+ * something), but {@link toFilterClauses} sends the literal instead of
931
+ * re-deriving a value from the text. Re-deriving is what made a facet
932
+ * disagree with the rows it summarises: a TEXT column faceted as `12345 (2)`
933
+ * round-tripped through {@link coerceFilterValue} as the NUMBER `12345`, and
934
+ * the server compares it against `json_extract(__doc__, …)`, which has no
935
+ * type affinity — so `12345 = '12345'` is false and the grid came back
936
+ * empty under a sidebar still reading "2". A NULL group fared the same way,
937
+ * flattening to `""`.
938
+ *
939
+ * Cleared the moment the operator edits the column or the value, or switches
940
+ * the row to `has`, because from then on the text IS the source of truth and
941
+ * must be coerced like any typed value (`age > 18` has to compare numerically;
942
+ * `has true` has to find a boolean element).
943
+ */
944
+ literal?: [unknown];
830
945
  operator: FilterOperator;
946
+ /**
947
+ * Dot-separated field names nested under `column`, as typed (`city`,
948
+ * `geo.city`). Absent or blank addresses the column itself. {@link toFilterClauses}
949
+ * splits it into the wire `path` segment for segment; an empty segment (`geo.`,
950
+ * `a..b`) goes out as is, and the server refuses it.
951
+ */
952
+ path?: string;
953
+ /**
954
+ * The exact wire `path` this row carries when it was hydrated or suggested
955
+ * rather than typed. The server accepts a field name that itself holds a dot
956
+ * (`["a.b"]`), which the dotted {@link EditableFilter.path} text cannot tell
957
+ * from two segments, so splitting that text back would address a different
958
+ * field. Cleared when the operator edits the path box, since the text is then
959
+ * the source of truth.
960
+ */
961
+ pathSegments?: string[];
831
962
  value: string;
832
963
  }
833
964
  /**
834
- * Convert the UI's string-valued filter rows into wire {@link FilterClause}s:
835
- * drops rows with no column, and coerces a numeric string to a number for the
836
- * comparison operators (so `age > 18` compares numerically, not lexically).
837
- * `contains` always stays a string.
838
- */
965
+ * Convert the UI's string-valued filter rows into wire {@link FilterClause}s:
966
+ * drops rows with no column, and coerces a canonical numeric string to a number for
967
+ * every comparison operator (so `age > 18` compares numerically, not lexically, and
968
+ * an `eq` on a numeric column still matches — see {@link coerceFilterValue} for why a
969
+ * numeric-looking but non-canonical string like a zip code stays text). `contains`
970
+ * always stays a string.
971
+ *
972
+ * A row carrying a {@link EditableFilter.literal} skips coercion entirely and
973
+ * sends that value verbatim: it was produced by a facet or a saved view, not
974
+ * typed, so its type is already known and guessing one from its text can only
975
+ * lose. `contains` is the exception — it is a substring test over text, so it
976
+ * takes the text either way.
977
+ *
978
+ * A row with nothing to test against is dropped too: a `contains ""` matches
979
+ * every row, and an empty range bound (`age > ""`) compares a column against the
980
+ * empty string rather than narrowing it. Such a row is only ever a half-edited
981
+ * one, and sending it would put "Delete N matching" over the whole table. An
982
+ * empty `eq` / `ne` stays — "is (not) the empty string" is a real test, and
983
+ * `eq ""` is what a freshly added row starts as.
984
+ */
839
985
  declare const toFilterClauses: (filters: ReadonlyArray<EditableFilter>) => FilterClause[];
840
986
  /**
841
- * The data browser's filtering controls: the substring search box plus a stack
842
- * of structured `column operator value` rows. All state is owned by the parent
843
- * (the data-browser model); this is the control markup, emitting the full
844
- * filter array up on every edit. Raw strings (no i18n) to match the surrounding
845
- * data-browser controls.
846
- */
847
- declare const DataFilters: ({
848
- columns,
849
- filters,
850
- onFiltersChange,
851
- onSearchChange,
852
- search
853
- }: {
987
+ * The data browser's filtering controls: the substring search box plus a stack
988
+ * of structured `column operator value` rows. All state is owned by the parent
989
+ * (the data-browser model); this is the control markup, emitting the full
990
+ * filter array up on every edit. Raw strings (no i18n) to match the surrounding
991
+ * data-browser controls.
992
+ *
993
+ * ## Why these rows are NOT run through the mask preview
994
+ *
995
+ * Every other read surface in the shard browser honours the "Mask sensitive
996
+ * columns" toggle — grid cells, the transposed and JSON views, the row-detail
997
+ * drawer, all three exports, the facet sidebar — and the `.global()` browser
998
+ * masks its drill-down chips too. This bar deliberately does not, and the
999
+ * question has been raised twice, so here is the enumeration it rests on.
1000
+ *
1001
+ * Two of the ways a value reaches these rows are DATA-DERIVED — the operator did
1002
+ * not type it — and those are the ones that could have leaked.
1003
+ *
1004
+ * A FACET-VALUE CLICK (`facetFilter` in `use-data-browser`) is closed at the
1005
+ * source: `DataFacets` withholds both the toggle and any open section for a
1006
+ * mask-covered column while the preview is on, so this can only reach a covered
1007
+ * column after the operator switched the preview OFF — a deliberate reveal of the
1008
+ * same value, from the same screen.
1009
+ *
1010
+ * HYDRATION FROM THE URL or a saved query (`initialFilters` → `toEditableFilters`)
1011
+ * is the shared-link case, and the one that looks like the `.global()` drill-down
1012
+ * chips — but it is not, because of the invariant below.
1013
+ *
1014
+ * (The AI "describe a filter" affordance sends column names and the prompt, never
1015
+ * a row, so it cannot lift a stored secret into a clause. That is enforced by
1016
+ * `@lunora/do`'s `sql-assistant.test.ts` — "sends the caller's columns and prompt
1017
+ * and nothing else" — rather than asserted here, because a claim about another
1018
+ * package that nothing checks is how a comment goes stale.)
1019
+ *
1020
+ * The invariant that makes both harmless: **a filter clause rendered here is
1021
+ * always simultaneously rendered verbatim in the address bar.** `useDataBrowser`
1022
+ * mirrors the loaded view through `onViewChange`, and `table-editor.tsx` writes
1023
+ * it straight into `?filters=<json>` on every change. So masking a row would
1024
+ * blank a value that is legible, unmasked, three inches above the input — while
1025
+ * making the filter impossible to edit. It would cost usability and buy nothing.
1026
+ *
1027
+ * That is exactly what separates this bar from the `.global()` browser's
1028
+ * drill-down chips, which ARE masked: those are read-only (nothing to edit),
1029
+ * they are fed ONLY by a facet click, and `global-data-browser` keeps them in
1030
+ * local state that never reaches the URL — so masking them genuinely removes a
1031
+ * value from the screen.
1032
+ *
1033
+ * **If either half of that stops being true — a filter row that is not mirrored
1034
+ * to `?filters=`, or a read-only filter display — revisit this.** Both halves are
1035
+ * pinned by `__tests__/features/data/data-browser-mask.test.tsx`'s
1036
+ * "dataBrowser masking — filters" block.
1037
+ */
1038
+ declare const DataFilters: ({ columns, filters, onAskAi, onFiltersChange, onSearchChange, search }: {
854
1039
  columns: ReadonlyArray<string>;
855
1040
  filters: ReadonlyArray<EditableFilter>;
1041
+ /** Ask the model for structured clauses. Omitted when no AI binding is available. */
1042
+ onAskAi?: (prompt: string) => void;
856
1043
  onFiltersChange: (filters: EditableFilter[]) => void;
857
1044
  onSearchChange: (event: ChangeEvent<HTMLInputElement>) => void;
858
1045
  search: string;
859
1046
  }) => ReactElement;
860
1047
  interface GlobalDataBrowserProps {
861
1048
  /**
862
- * Table to open automatically on mount (and whenever it changes). Used by the
863
- * Table editor when a `v.id` reference in a shard row points at a `.global()`
864
- * table: clicking it switches to the global tier and lands here with that table
865
- * pre-selected. Each distinct value is applied once, so the operator can still
866
- * navigate away afterwards.
867
- */
1049
+ * Table to open automatically on mount (and whenever it changes). Used by the
1050
+ * Table editor when a `v.id` reference in a shard row points at a `.global()`
1051
+ * table: clicking it switches to the global tier and lands here with that table
1052
+ * pre-selected. Each distinct value is applied once, so the operator can still
1053
+ * navigate away afterwards.
1054
+ */
868
1055
  readonly initialTable?: string;
869
1056
  /**
870
- * Called whenever the open table changes, so the host can mirror it to the URL
871
- * (the Table editor pushes `?table=…`). Omitted in standalone use.
872
- */
1057
+ * Called whenever the open table changes, so the host can mirror it to the URL
1058
+ * (the Table editor pushes `?table=…`). Omitted in standalone use.
1059
+ */
873
1060
  readonly onSelectTable?: (table: string) => void;
874
1061
  /** Rows requested per page. Clamped server-side to `[1, 500]`. */
875
1062
  readonly pageSize?: number;
876
1063
  /**
877
- * The schema/source selector rendered at the top of the table-list sidebar —
878
- * the Table editor's `schema public ▾` switch. Supplied when this browser is
879
- * composed into the Table editor; omitted when it's used alone.
880
- */
1064
+ * The schema/source selector rendered at the top of the table-list sidebar —
1065
+ * the Table editor's `schema public ▾` switch. Supplied when this browser is
1066
+ * composed into the Table editor; omitted when it's used alone.
1067
+ */
881
1068
  readonly schemaSwitch?: ReactNode;
882
1069
  }
883
1070
  /**
884
- * Read-only browser for `.global()` (D1-backed) tables. Twin of `DataBrowser`,
885
- * but not shard-scoped: it lists tables via `listGlobalTables()` and pages rows
886
- * via `readGlobalTablePage()`. Laid out like Supabase's Table Editor — a left
887
- * table sidebar + a bordered grid with a paginated footer — and gated by the
888
- * server's `LUNORA_ADMIN_TOKEN`.
889
- */
890
- declare const GlobalDataBrowser: ({
891
- initialTable,
892
- onSelectTable,
893
- pageSize: initialPageSize,
894
- schemaSwitch
895
- }?: GlobalDataBrowserProps) => ReactElement;
1071
+ * Read-only browser for `.global()` (D1-backed) tables. Twin of `DataBrowser`,
1072
+ * but not shard-scoped: it lists tables via `listGlobalTables()` and pages rows
1073
+ * via `readGlobalTablePage()`. Laid out like Supabase's Table Editor — a left
1074
+ * table sidebar + a bordered grid with a paginated footer — and gated by the
1075
+ * server's `LUNORA_ADMIN_TOKEN`.
1076
+ */
1077
+ declare const GlobalDataBrowser: ({ initialTable, onSelectTable, pageSize: initialPageSize, schemaSwitch }?: GlobalDataBrowserProps) => ReactElement;
896
1078
  interface TableEditorProps {
1079
+ /** Offer "Generate rows" — only where the host serves the seed endpoint. Forwarded to the shard {@link DataBrowser}. */
1080
+ readonly canGenerateRows?: boolean;
897
1081
  /**
898
- * Allow editing the shard-local tables (insert/edit/delete). Forwarded to the
899
- * shard {@link DataBrowser}; the global D1 browser is always read-only. Off by
900
- * default — see {@link DataBrowser}.
901
- */
1082
+ * Allow editing the shard-local tables (insert/edit/delete). Forwarded to the
1083
+ * shard {@link DataBrowser}; the global D1 browser is always read-only. Off by
1084
+ * default — see {@link DataBrowser}.
1085
+ */
902
1086
  readonly editable?: boolean;
903
1087
  /** Shard key the shard browser targets on first load. Defaults to the root shard. */
904
1088
  readonly initialShardKey?: string;
905
1089
  }
906
1090
  /**
907
- * The Table editor: browses your application's tables across both storage tiers
908
- * from one section. A schema switch in the sidebar header (Supabase's
909
- * `schema public ▾`) toggles between the per-shard SQLite browser
910
- * (`.shardBy(...)`, editable when the host opts in) and the read-only global D1
911
- * browser (`.global()`) — folding what used to be a separate "Global Tables" tab
912
- * into a single editor (`STUDIO-REDESIGN-PLAN.md` §2).
913
- *
914
- * The active tier and open table live in the URL search params (`?schema=global`,
915
- * `?table=…`) rather than component state, so every selection is a real, shareable
916
- * URL and browser back/forward moves between tables and tiers. The browsers push on
917
- * selection and re-open whatever the URL names.
918
- */
919
- declare const TableEditor: ({
920
- editable,
921
- initialShardKey
922
- }: TableEditorProps) => ReactElement;
1091
+ * The Table editor: browses your application's tables across both storage tiers
1092
+ * from one section. A schema switch in the sidebar header (Supabase's
1093
+ * `schema public ▾`) toggles between the per-shard SQLite browser
1094
+ * (`.shardBy(...)`, editable when the host opts in) and the read-only global D1
1095
+ * browser (`.global()`) — folding what used to be a separate "Global Tables" tab
1096
+ * into a single editor (`STUDIO-REDESIGN-PLAN.md` §2).
1097
+ *
1098
+ * The active tier and open table live in the URL search params (`?schema=global`,
1099
+ * `?table=…`) rather than component state, so every selection is a real, shareable
1100
+ * URL and browser back/forward moves between tables and tiers. The browsers push on
1101
+ * selection and re-open whatever the URL names.
1102
+ */
1103
+ declare const TableEditor: ({ canGenerateRows, editable, initialShardKey }: TableEditorProps) => ReactElement;
923
1104
  interface ExportImportPanelProps {
924
1105
  /** Shard key the panel targets. Defaults to the root shard. */
925
1106
  readonly initialShardKey?: string;
926
1107
  }
927
1108
  /**
928
- * Snapshot and restore a single shard's data as NDJSON.
929
- *
930
- * "Export" reads every shard-local row via `__lunora_admin__:exportShard` and
931
- * renders it as NDJSON for download/copy. "Import" parses NDJSON the operator
932
- * pastes in and replays it through `__lunora_admin__:importShard`, reporting
933
- * inserted counts, id conflicts and per-row errors. Globally-scoped (`.global()`)
934
- * tables live in D1 and are intentionally out of scope here.
935
- *
936
- * Both calls travel over the {@link useLunora} client transport and are gated by
937
- * the server's `LUNORA_ADMIN_TOKEN`.
938
- */
939
- declare const ExportImportPanel: ({
940
- initialShardKey
941
- }: ExportImportPanelProps) => ReactElement;
1109
+ * Snapshot and restore a single shard's data as NDJSON.
1110
+ *
1111
+ * "Export" walks the shard's tables one `__lunora_admin__:exportShard` call at a
1112
+ * time (`tables: [name]`), appending each page's NDJSON to a `Blob` the operator
1113
+ * downloads; only the first {@link PREVIEW_LINES} lines are rendered, so a large
1114
+ * shard never lands in one textarea. "Import" reads an NDJSON file, or a CSV file
1115
+ * into the table the operator picks, and replays it through
1116
+ * `__lunora_admin__:importShard` in chunks of {@link IMPORT_CHUNK_ROWS} rows,
1117
+ * reporting progress and then the summed inserted counts, id conflicts and
1118
+ * per-row errors. Globally-scoped (`.global()`) tables live in D1 and are
1119
+ * intentionally out of scope here.
1120
+ *
1121
+ * Both calls travel over the {@link useStudioClient} client transport and are gated by
1122
+ * the server's `LUNORA_ADMIN_TOKEN`.
1123
+ */
1124
+ declare const ExportImportPanel: ({ initialShardKey }: ExportImportPanelProps) => ReactElement;
942
1125
  interface MigrationsPanelProps {
943
1126
  /** Shard key the panel targets. Defaults to the root shard. */
944
1127
  readonly initialShardKey?: string;
945
1128
  }
946
1129
  /**
947
- * Inspect and drive data migrations on a single shard.
948
- *
949
- * Reads the persisted run-state via the `__lunora_admin__:migrationStatus` RPC
950
- * and lets an operator kick off a migration by id (`__lunora_admin__:runMigration`)
951
- * with a direction, an optional batch cap and a dry-run toggle. Both calls
952
- * travel over the ordinary {@link useLunora} client transport and are gated by
953
- * the server's `LUNORA_ADMIN_TOKEN` — this component issues no credentials of
954
- * its own.
955
- */
956
- declare const MigrationsPanel: ({
957
- initialShardKey
958
- }: MigrationsPanelProps) => ReactElement;
1130
+ * Inspect and drive data migrations on a single shard.
1131
+ *
1132
+ * Reads the persisted run-state via the `__lunora_admin__:migrationStatus` RPC
1133
+ * and lets an operator kick off a migration by id (`__lunora_admin__:runMigration`)
1134
+ * with a direction and a dry-run toggle. Both calls
1135
+ * travel over the ordinary {@link useStudioClient} client transport and are gated by
1136
+ * the server's `LUNORA_ADMIN_TOKEN` — this component issues no credentials of
1137
+ * its own.
1138
+ */
1139
+ declare const MigrationsPanel: ({ initialShardKey }: MigrationsPanelProps) => ReactElement;
959
1140
  interface PitrPanelProps {
960
1141
  /** Shard key the PITR ops target. Defaults to the root shard. */
961
1142
  readonly initialShardKey?: string;
962
1143
  }
963
1144
  /**
964
- * Native Durable-Object point-in-time recovery for one shard — the **Time
965
- * Travel** view.
966
- *
967
- * Reads the shard's current bookmark, previews the bookmark nearest a chosen
968
- * time, and (behind a confirm step) restores the shard to a time or an explicit
969
- * bookmark via the `__lunora_admin__:pitrRestore` RPC, surfacing the returned
970
- * undo bookmark so the restore can be reversed. All ops run over the
971
- * {@link useLunora} client and are gated by the server's `LUNORA_ADMIN_TOKEN`.
972
- *
973
- * In-place recovery covers the last 30 days; for older or off-platform recovery
974
- * use the snapshot tier (`lunora backup` / the backup registry item).
975
- */
976
- declare const PitrPanel: ({
977
- initialShardKey
978
- }: PitrPanelProps) => ReactElement;
1145
+ * Native Durable-Object point-in-time recovery for one shard — the **Time
1146
+ * Travel** view.
1147
+ *
1148
+ * Reads the shard's current bookmark, previews the bookmark nearest a chosen
1149
+ * time, and (behind a confirm step) restores the shard to a time or an explicit
1150
+ * bookmark via the `__lunora_admin__:pitrRestore` RPC, surfacing the returned
1151
+ * undo bookmark so the restore can be reversed. All ops run over the
1152
+ * {@link useStudioClient} client and are gated by the server's `LUNORA_ADMIN_TOKEN`.
1153
+ *
1154
+ * In-place recovery covers the last 30 days; for older or off-platform recovery
1155
+ * use the snapshot tier (`lunora backup` / the backup registry item).
1156
+ */
1157
+ declare const PitrPanel: ({ initialShardKey }: PitrPanelProps) => ReactElement;
979
1158
  interface FunctionRunnerProps {
980
1159
  /**
981
- * Functions to expose. When omitted, the runner auto-discovers them via the
982
- * client's `listFunctions()` (the admin-gated `/_lunora/admin/functions`
983
- * endpoint), so it works with no wiring when the worker is built with a
984
- * `functions` registry. Supply the list to override discovery.
985
- */
1160
+ * Functions to expose. When omitted, the runner auto-discovers them via the
1161
+ * client's `listFunctions()` (the admin-gated `/_lunora/admin/functions`
1162
+ * endpoint), so it works with no wiring when the worker is built with a
1163
+ * `functions` registry. Supply the list to override discovery.
1164
+ */
986
1165
  readonly functions?: FunctionDescriptor[];
987
1166
  /**
988
- * Expose the "Run as identity" control — execute the selected function AS a
989
- * chosen authenticated user so an operator can test auth + RLS behavior.
990
- * Security-sensitive: the run is forwarded over the admin-gated
991
- * `__lunora_admin__:runAs` RPC, which forges the per-request identity. The
992
- * host sets this only on a trusted loopback-dev gate (the `Studio` component's
993
- * `runAsIdentity` prop); off by default, the runner always runs with the
994
- * caller's own (admin) identity.
995
- */
1167
+ * Expose the "Run as identity" control — execute the selected function AS a
1168
+ * chosen authenticated user so an operator can test auth + RLS behavior.
1169
+ * Security-sensitive: the run is forwarded over the admin-gated
1170
+ * `__lunora_admin__:runAs` RPC, which forges the per-request identity. The
1171
+ * host sets this only on a trusted loopback-dev gate (the `Studio` component's
1172
+ * `runAsIdentity` prop); off by default, the runner always runs with the
1173
+ * caller's own (admin) identity.
1174
+ */
996
1175
  readonly runAsIdentity?: boolean;
997
1176
  }
998
1177
  /**
999
- * Interactive runner for the registered functions: pick one, edit its JSON
1000
- * arguments, optionally target a shard, then invoke it against the live
1001
- * {@link useLunora} client and inspect the result or error.
1002
- *
1003
- * By default the function list is auto-discovered from the worker's
1004
- * `/_lunora/admin/functions` endpoint; pass an explicit `functions` array to
1005
- * skip discovery (a query/mutation/action's `kind` is compile-time-only, so it
1006
- * must be named).
1007
- */
1008
- declare const FunctionRunner: ({
1009
- functions: functionsProp,
1010
- runAsIdentity
1011
- }?: FunctionRunnerProps) => ReactElement;
1178
+ * Interactive runner for the registered functions: pick one, edit its JSON
1179
+ * arguments, optionally target a shard, then invoke it against the live
1180
+ * {@link useStudioClient} client and inspect the result or error.
1181
+ *
1182
+ * By default the function list is auto-discovered from the worker's
1183
+ * `/_lunora/admin/functions` endpoint; pass an explicit `functions` array to
1184
+ * skip discovery (a query/mutation/action's `kind` is compile-time-only, so it
1185
+ * must be named).
1186
+ */
1187
+ declare const FunctionRunner: ({ functions: functionsProp, runAsIdentity }?: FunctionRunnerProps) => ReactElement;
1012
1188
  interface FunctionStatsPanelProps {
1013
1189
  /** Descriptors from codegen, used to annotate each row with the function's `kind`. */
1014
1190
  readonly functions?: FunctionDescriptor[];
@@ -1016,127 +1192,232 @@ interface FunctionStatsPanelProps {
1016
1192
  readonly initialShardKey?: string;
1017
1193
  }
1018
1194
  /**
1019
- * Per-function execution metrics for one shard: call count, error count/rate,
1020
- * mean and slowest handler latency, last-run time, and the most recent error
1021
- * message. Reads via the `__lunora_admin__:getFunctionStats` RPC through
1022
- * `useAdminQuery`; gated by the server's `LUNORA_ADMIN_TOKEN`.
1023
- *
1024
- * Counters are per-DO-instance and reset on hibernation/restart — this is a
1025
- * "since this instance woke" readout, mirroring the metrics panel. The panel is
1026
- * always live: `useAdminQuery`'s `live` subscription re-pushes on every server
1027
- * write-flush so the table updates as mutations land.
1028
- */
1029
- declare const FunctionStatsPanel: ({
1030
- functions,
1031
- initialShardKey
1032
- }: FunctionStatsPanelProps) => ReactElement;
1195
+ * Per-function execution metrics for one shard: call count, error count/rate,
1196
+ * mean and slowest handler latency, last-run time, and the most recent error
1197
+ * message. Reads via the `__lunora_admin__:getFunctionStats` RPC through
1198
+ * `useAdminQuery`; gated by the server's `LUNORA_ADMIN_TOKEN`.
1199
+ *
1200
+ * Counters are per-DO-instance and reset on hibernation/restart — this is a
1201
+ * "since this instance woke" readout, mirroring the metrics panel. The panel is
1202
+ * always live: `useAdminQuery`'s `live` subscription re-pushes on every server
1203
+ * write-flush so the table updates as mutations land.
1204
+ */
1205
+ declare const FunctionStatsPanel: ({ functions, initialShardKey }: FunctionStatsPanelProps) => ReactElement;
1206
+ /** Which of the two endpoints a probe targets. */
1207
+ type ProbeKind = "live" | "ready";
1208
+ /** The result of one probe fetch — the HTTP status, the parsed body (or `null`), and any transport error. */
1209
+ interface ProbeSnapshot {
1210
+ /** The parsed health body, or `null` when the response wasn't JSON (e.g. an auth-gate rejection). */
1211
+ body: HealthBody | null;
1212
+ /** A transport/gate error message (network failure, or a non-JSON body), else `undefined`. */
1213
+ error?: string;
1214
+ /** Whether the HTTP status was 2xx. */
1215
+ ok: boolean;
1216
+ /** The HTTP status code (`0` when the request never completed). */
1217
+ status: number;
1218
+ }
1219
+ /** Fetch one probe. Injected in tests; the default (see {@link useDefaultProbe}) hits the live deployment. */
1220
+ type DeploymentHealthProbe = (kind: ProbeKind) => Promise<ProbeSnapshot>;
1221
+ interface DeploymentHealthPanelProps {
1222
+ /**
1223
+ * Injectable probe, used by tests to feed a canned response. When omitted the
1224
+ * panel fetches the connected deployment's `/_lunora/health` (and
1225
+ * `/health/ready`) directly — this is a plain HTTP route, not an admin RPC, so
1226
+ * it doesn't ride the `useAdminQuery` machinery. The admin bearer (when the
1227
+ * studio holds one) is attached so an `"admin"`-posture endpoint still answers.
1228
+ */
1229
+ readonly probe?: DeploymentHealthProbe;
1230
+ }
1231
+ /**
1232
+ * Deployment-health panel: renders the live liveness/readiness verdict and the
1233
+ * per-binding/subsystem checks from the deployment's `/_lunora/health` and
1234
+ * `/_lunora/health/ready` endpoints (plan 177). This is the operator's at-a-glance
1235
+ * "are the bindings up?" view — distinct from the app-level SLO panel (error
1236
+ * rate, auth failures, scheduler backlog) that shares the "Health" name.
1237
+ *
1238
+ * The endpoints are plain HTTP routes (not admin RPCs), so the panel fetches them
1239
+ * directly rather than through `useAdminQuery`. The body is deliberately
1240
+ * secret-free — only a check name, an up/down status, whether it's critical, and
1241
+ * a runtime-authored message (present only in the `"admin"` posture) — so nothing
1242
+ * rendered here can leak an env value, connection string, or binding secret.
1243
+ */
1244
+ declare const DeploymentHealthPanel: ({ probe }: DeploymentHealthPanelProps) => ReactElement;
1245
+ /**
1246
+ * The registry of every English source string a call site may pass to `t(...)`.
1247
+ *
1248
+ * English is the source locale, so each id doubles as the rendered text: Lingui
1249
+ * compiles an id verbatim when a catalog has no entry for it. This list is the
1250
+ * single source of known strings — {@link MessageId} is derived from it and
1251
+ * `TFunction` is typed against that union, so `t("Dat")` (or any string absent
1252
+ * here) is a compile error rather than a silently-rendered typo.
1253
+ *
1254
+ * Add a string here the moment a new call site needs it. To translate, create a
1255
+ * sibling catalog (for example `de.ts`) mapping each id to its translation and
1256
+ * register it via `createStudioI18n(locale, { en: enMessages, de: deMessages })`.
1257
+ */
1258
+ declare const MESSAGE_IDS: readonly ["Architecture", "Your modules, and the calls, reads, writes and hand-offs between them, from codegen.", "Module", "Owned tables", "Outside any module", "All modules", "Couldn't load the architecture manifest: {message}", "Architecture unavailable", "Add a lunora/<folder>/module.ts that default-exports defineModule(...) and run lunora codegen to map your modules here. Installed components join the map once you declare one.", "No modules declared", "{count} call sites could not be drawn", "{count} edges shown", "Export failed: {message}", "Not sent to {failed}", "Topic {topic} · {count} subscriptions", "{topic} (topic → {count} subscriptions)", "Component", "Installed component", "Send this link to the invitee. It is shown once and cannot be recovered.", "Only invited addresses can create an account. Nothing is emailed — send the invitee the one-time link yourself.", "Showing the most recent invitations. Query the signUpInvitation table directly to see the rest.", "Sign-up invitations", "Only invited addresses can create an account. Nothing is emailed — send the invitee the sign-up link yourself.", "Email address to invite", "ada@example.com", "Invite", "Your app's sign-up page", "Nobody has been invited yet.", "Email", "Expires", "Invited by", "Accepted", "Expired", "Pending", "Reactors", "Server-side onQueryChange reactors: what has run, what was suppressed, and what is failing.", "Reactor", "State", "Ran", "Suppressed", "Errors", "Watches", "Last dispatch", "No reactors declared", "No reactor is declared in this deployment. Export an onQueryChange(select, handler) from lunora/ to run server-side logic when a query's result changes.", "A reactor runs after a write flush, but only when the result of the query it watches actually changed — a trigger fires on a row write, a reactor fires on a result changing. Suppressed dispatches are the ones where the read re-ran and nothing had moved.", "last dispatch failed", "Live updates unavailable; showing the last reading.", "Agents", "Agent", "Threads", "Timeline", "Messages", "Tokens", "Updated", "Content", "Tool", "Usage", "Approval", "Score your app's advisor findings: a grade, the coverage split, and every procedure ranked worst-first.", "Health score", "Rules fired", "Procedure", "Score", "Kind", "clean", "warned", "failing", "exempt", "sensitive", "no reason given", "Schema & config", "Inspect agent threads, message timelines, tool calls, and token usage.", "Agents run as durable workflows. Each run persists a thread of assistant and tool messages; select a thread to inspect its timeline, tool calls, approvals, and token usage.", "No @lunora/agent tables found in this deployment. Add lunora/agents.ts with defineAgent(...) and merge the agent schema extension to run durable AI agents.", "No agents configured", "No agent has run yet. Start a run with ctx.agents.<name>.run(...) and its thread appears here.", "No agent threads yet", "This thread has no messages yet.", "Showing the latest {count} messages; older ones are not shown.", "Bindings", "KV Namespaces", "R2 Buckets", "Vectorize Indexes", "{count} bindings", "1 binding", "Lunora AI rules aren't installed.", "lets your coding agent use Lunora correctly.", "Dismiss", ", changed", "(no subject)", "(root)", "(none)", "{count} active", "{count} calls", "{count} failed", "{total} total", "No subscriptions yet", "No payments configured", "No @lunora/payment tables found in this deployment. Add `.extend(paymentExtension)` to lunora/schema.ts and wire `payment` on createShardDO() to sync customers and subscriptions.", "Payments", "Plan", "Provider", "Recent webhook events", "Renews", "State", "Subscriptions", "Synced customers, subscriptions, and webhook events.", "{count} messages", "+{count} more", "{count} pending changes", "{count} pasted cells were skipped", "{count} running", "{name} ({rowCount})", "{rangeStart}-{rangeEnd} of {total}", "{rate} ({count} entries)", "{reachable} reachable", "{reachable} reachable, {failed} unreachable", "{status} — processed", "{title} failed", "Actions", "Add a widget to chart a saved SQL query on this browser.", "Add index on {table}", "Add row", "Add widget", "admin token", "Aggregating…", "all", "All shards", "API", "API reference unavailable", "API resources", "API usage snippets", "API view", "Arguments", "Auth", "Auth failures", "Auth failures over time", "Cache hit rate", "Call this {kind} from your app.", "Cancel", "Cancel job?", "Cc", "changed", "Chart widgets backed by saved read-only SQL queries.", "Lunora surfaces slow functions, error spikes, and cache problems here.", "Clear", "Clear inbox", "Columns unavailable", "CLI", "Client", "collecting samples…", "Combined cache hit rate", "Commit", "Committing…", "Breadcrumb", "Confirm", "Connect", "Connect to Lunora Studio", "Connected", "Connecting…", "Polling", "Enter your admin token to access the studio.", "From your worker's LUNORA_ADMIN_TOKEN — your project's .dev.vars in dev, or a deployment secret in production.", "Local", "Not connected", "content-type", "Copy", "Copy link", "Copy-paste snippets for calling your functions and tables.", "created", "Cron triggers", "Dashboards", "Data", "Data migrations you run against this shard will be tracked here.", "Data model", "Database", "Database size", "db size", "Instruments", "Instruments unavailable: {error}", "Counter", "Gauge", "Histogram", "count", "range", "trend", "trace", "{name} trend", "Open the exemplar trace {trace}", "Delete", "Delete saved query {name}", "Delete?", "direction", "Direction", "Discard", "down", "Dry run", "Dry run: ", "Edit", "Edit widget", "email", "Email preview", "Email your app sends in dev is captured here — nothing is delivered.", "Email your app sent, captured in dev.", "Enter a migration id", "error", "Error rate", "errors", "Errors", "Errors over time", "expires", "Export", "PNG", "SVG", "Export / Import", "Exported {count} rows.", "Importing rows {from}–{to} of {total}…", "Facets", "file:function", "Files", "Filter messages", "Filter tables", "Find table…", "Foreign key", "From", "function", "Function", "Function path", "Functions", "Functions by error rate", "Graph", "Headers", "Health", "Indexes", "Hide", "HTML", "id", "Idle", "Import", "Import (writes rows)?", "Import file", "Couldn't read the columns of {table}: {message}", "Import stopped after {rows} rows: {message}. The counts below cover completed chunks only. The chunk from line {line} may have written rows: check the table for rows from line {line} onward before importing again, or delete the written rows first and then import the whole file.", "Import stopped after {rows} rows: {message}. The counts below cover those rows. Rows from line {line} onward were not sent: do not import the whole file again, import from that line onward, or delete the written rows first and then import the whole file.", "Inserted {inserted}, replaced {replaced}, {conflicts} conflicts, {errors} errors.", "Overwrite rows whose _id already exists (otherwise they are left unchanged and counted as conflicts)", "This shard cannot overwrite existing rows. Nothing was sent. Update the app and import again.", "Interactive OpenAPI reference and copy-paste snippets for your functions.", "Invalid JSON args: {message}", "Invalid JSON: {message}", "Invalid NDJSON: {message}", "Invalid CSV: {message}", "The CSV has no data rows after the header.", "The header “{name}” appears more than once.", "Header column {column} is empty.", "CSV rows have no table column, so choose the table they go into.", "Choose a table", "Checking {total} rows before writing…", "Nothing was written, because some rows would be refused. Fix the rows listed below and import again.", "The shard refused {count} rows, so the rest of the file was not sent. Nothing was written. Fix the rows listed below and import again.", "The shard refused {count} rows, so the rest of the file was not sent. {written} rows were already written, so do not import the whole file again. Import the refused rows and any rows from line {line} onward, or delete the written rows first and then import the whole file.", "This shard predates import checks, so it would write the file while checking it. Nothing was sent. Update the app and import again.", "Target table", "ip", "Jobs queued with runAfter / runAt will appear here.", "JSON", "key", "Key prefix", "key prefix (optional)", "Level filter", "line {line} ({table}): {message}", "line {line}: expected {expected} cells, found {found}.", "line {line}: text follows a closing quote.", "line {line}: a quoted field is never closed.", "line {line}: column “{column}” holds “{value}”, which a number column cannot store exactly. Store a whole number past 9007199254740991 in a bigint column.", "line {line}: column “{column}” must be a number, got “{value}”.", "line {line}: column “{column}” must be true or false, got “{value}”.", "line {line}: column “{column}” must be an integer, got “{value}”.", "line {line}: column “{column}” holds an integer longer than the import can send.", "line {line}: column “{column}” must be an ISO-8601 date or epoch milliseconds of at least 11 digits, got “{value}”.", "List", "Live", "Live — changes stream in automatically", "Live unavailable", "Live unavailable: {liveError}", "{capability} is not supported on {platform}.", "Durable agents", "Cross-shard fan-out", "Key-value storage", "Mail delivery", "Object storage", "Point-in-time recovery", "Scheduling", "Server reactors", "Vector search", "Live: on", "Load", "Load more", "Load tables", "Logic", "Logs", "Mail", "Mask sensitive columns", "Metrics", "migration id", "Migration id", "Migrations", "Missing index", "name", "Next", "no", "No active sessions.", "no cache configured", "No captured email.", "No cron triggers.", "No function activity yet.", "No functions or tables to document yet.", "No global tables.", "No headers.", "No HTML body.", "No logs.", "Archive", "Log archive not configured", "Wire pipelineLogSink to a Cloudflare Pipeline → R2 Data Catalog table and set R2_SQL_ACCOUNT_ID, R2_SQL_TOKEN, R2_SQL_BUCKET to browse the durable log archive here.", "No archived logs.", "No archived logs match these filters. The durable archive fills as pipelineLogSink flushes records to R2.", "Function path prefix", "function path…", "user id…", "Minimum level", "min level", "Time", "Level", "Trace", "User", "No migrations have run on this shard.", "No objects.", "No recent errors.", "No scheduled jobs.", "No tables to graph.", "No tables match your filter.", "No text body.", "No users.", "No widgets yet", "Objects you upload to your R2 buckets will appear here.", "Observability", "of {pages}", "off", "Offline", "ok", "OK", "on", "Open {target} {id}", "Open in new tab", "Outcome filter", "Page", "Plain text", "Prefill", "Previous", "Primary key", "processed", "React", "Read and write this table through the typed data model.", "Move widget down", "Move widget up", "Re-enter the sensitive values before running this again.", "Recent errors", "Recent logs", "Recently visited shards — click to switch", "Refresh", "Reload tables", "Remove widget", "RLS Policies", "Policies", "No policies defined", "No `definePolicy` is wired through `.use(rls(...))` in this deployment. Add one to guard a table's rows.", "Read", "Insert", "Update", "Guarded by", "Guarded", "Roles", "No roles defined", "No `defineRole` is registered via `rls(policies, { roles })`. Roles back `ctx.auth.can(...)` permission checks.", "Permissions", "Run as identity (userId)", "Leave empty to run as admin", "Required — the identity to probe as", "Not run", "Dev only: runs the function as this user so you can test auth and RLS. Forged over the admin gate.", "as {userId}", "No policy", "Covered by {procedure}", "Uncovered — reachable without a policy", "Masked columns", "No tables in this deployment's schema.", "Add a `definePolicy` and wire it through `.use(rls(...))` to populate this matrix.", "Pick a function and an identity, then run it to see the access outcome.", "Probe", "Probe this", "Run as (userId)", "Identity (userId) to run as", "Run probe", "Include mutations and actions", "This will execute `{functionPath}` as user `{userId}`.", "Allowed", "Denied", "Errored", "The call failed for a reason that is not an access verdict, so it says nothing about the policy.", "Probing…", "Set `runAsIdentity` to forge an identity and probe access.", "Dev only: runs the selected function as this user over the admin gate so you can test auth and RLS.", "Inspect access policies per table, and probe a function as any identity.", "Scaffold access rules", "Writes a new deny-by-default policy file under lunora/, or wires one into a procedure, then reruns codegen. Local dev only.", "New policy file", "Wire into a procedure", "Policy name", "Create policy file", "Procedure file path", "Exported procedure", "Policy set identifier", "Wire RLS", "Creating…", "Wiring…", "Scaffolded {label} and reran codegen. Fill in the `when` predicates before relying on it.", "This change must be made by hand — the scaffolder only adds new, deny-by-default rules.", "requests", "Requests", "Requests / interval", "Requests over time", "Requests per interval over time", "Row actions", "Row document JSON", "Rows per page", "Run", "Run migration", "Run migration?", "Running…", "Query name", "Save", "Save query", "Save widget", "Saved", "schedule", "target", "workflow", "Run now", "Run now?", "Running…", "ran", "attempts", "backlog", "Dead letter", "Drop", "Drop job?", "in flight", "Jobs that exhaust their retry budget are parked here instead of being dropped.", "last tried", "max concurrency", "No dead-letter jobs.", "No workpools.", "pool", "Pools", "pools", "Pools created with createWorkpool appear here once they have activity.", "queued", "Retry", "Schedule view", "Scheduled", "scheduled for", "Scheduled jobs", "Scheduler backlog", "Schema", "Schema graph", "Schema view", "search message", "Search messages", "Search rows", "search table…", "Search…", "Select a function or table to see how to call it from your app.", "Select all rows", "Select row", "Send test", "Sent", "Service level", "Sessions", "Sessions for {userId}", "shard", "Shard", "Shard key", "shard key (optional)", "Shard key (optional)", "Shards", "Shards seen", "Signature", "size", "Snippet flavour", "State-changing admin operations are recorded here.", "status", "Storage", "Storage tier", "Storage tiers", "Studio", "Studio areas", "Studio failed", "Switch to dark theme", "Switch to light theme", "Table", "Table list", "Table touched", "Tables", "To", "Token rides the WebSocket URL — it can surface in browser DevTools and server logs. Use a dev-only token.", "Total database size", "Total errors", "Total requests", "Triggers declared with the cronJobs() builder appear here.", "Try again", "unreachable", "up", "updated", "Uptime", "user agent", "User id", "userId", "Users", "Users who sign up to your app will appear here.", "verified", "Widget title", "yes", "A live stream of recent function logs.", "Browse and edit rows across your shard and global tables.", "Browse auth users and their active sessions.", "Browse objects in your R2 storage buckets.", "Export a shard to NDJSON, or import rows from it.", "At-a-glance connection, error, and shard signals.", "Inspect and cancel scheduled jobs.", "Inspect each table and its columns.", "Inspect row-level-security policies and roles, per table.", "Per-shard health and aggregate metrics.", "Review migration status and run them.", "Run registered queries, mutations, and actions.", "Global tables (D1)", "Shard tables", "{shard} tables", "Tables marked .global() (D1-backed, region-replicated) will appear here.", "Select a table to browse its rows.", "Shared across every tenant, stored once in D1. Includes auth tables.", "Partitioned per shard key into separate Durable Objects — scoped to the shard above.", "avg", "calls", "conflicts", "kind", "last error", "last run", "max", "Most called", "No functions have run on this shard yet.", "Recent", "Slowest", "Insights", "Surface slow functions, error spikes, and cache problems.", "No issues detected.", "Low cache hit rate", "High cache eviction rate", "Slow function", "High error rate", "High write contention", "Storage headroom", "{rate} hit rate over recent traffic.", "{count} entries evicted recently.", "Slowest call took {duration}.", "Slowest call took {duration} — it full-scanned {tables} with no index.", "{rate} of calls failed.", "{rate} of calls hit a write conflict — consider sharding to cut contention.", "{size} of the 10 GiB per-shard ceiling — plan a .shardBy() migration while it still has runway.", "Home", "Reports", "SQL / Functions", "Table editor", "Connection, health, and advisor summary for your deployment.", "Collapse sidebar", "Expand sidebar", "SQL editor", "Run read-only SQL against a shard.", "Run", "SQL query", "SQL problems", "Operation console", "Suggest chart", "Chart type", "Widget type", "Could not suggest a chart for that result.", "Add a chart, a single value, a table, or a note. Everything is saved on this browser.", "Keyboard shortcuts", "Command palette", "Reset", "Stored in this browser. Focus a box and press a key to rebind it.", "Single value", "Text", "Notes for whoever reads this dashboard.", "Charts, values, tables, and notes. Drag a tile to reorder.", "—", "Bar", "Line", "Area", "Suggesting…", "Describe the query you want", "Draft SQL", "Thinking…", "Fix this", "Tell the model what to change", "Rewrite", "Proposed edit", "Accept", "Reject", "Selection", "Whole query", "Added", "Removed", "The model could not be reached.", "The model returned a statement that is not read-only, so it was discarded.", "The model returned nothing usable.", "The statement is too long to rewrite. Select a shorter part of it.", "Related", "p50", "p95", "showing a capped set", "Statements executed in the selected window appear here, with throughput and latency over time.", "No queries in this window.", "Throughput", "Mean latency (ms)", "Schema versions", "Data migrations", "{count} pushes", "live", "Show in console", "Every admin call this studio makes is recorded here.", "{count} rows", "Filter", "Each distinct schema shape this shard runs is recorded here, so you can see what changed and when.", "No schema versions recorded yet.", "First recorded version — every table is new.", "{count} change(s)", "change", "Diagram", "Changes", "added", "changed", "removed", "schema", "{count} columns", "changes", "tables", "{count} breaking", "breaking", "safe", "{count} rows", "Showing the first {max} rows.", "Showing the {n} most common values.", "No rows returned.", "Private", "Reference", "Search queries…", "New query", "Untitled query", "Delete query", "No saved queries yet — they save to this browser as you type.", "Results", "Explain", "Chart", "Split editor and results", "History", "Format", "Clear history", "Keep history on this browser", "No numeric column to chart.", "Click Run to execute your query.", "Untitled", "New tab", "Close tab", "Tab title", "Double-click to rename", "Discard?", "Discard changes", "Keep editing", "Close other tabs", "Close tabs to the right", "Close all tabs", "Discard unsaved tabs?", "column", "keyword", "Columns", "Show all", "Hide all", "Transpose", "Swap rows and columns", "Field", "Row {n}", "Loading…", "No matching row.", "CSV", "SQL", "{count} selected", "Delete {count}", "Delete {count} rows and everything that cascades?", "Copy", "Copied", "Cell value", "Filter by this value", "Close", "Form", "Invalid JSON", "Command palette", "No results.", "Quick links", "Security findings", "Performance issues", "View", "All clear", "No data yet", "Get connected", "No issues found", "No security or performance issues detected.", "Client SDK", "React", "CLI", "Connect an AI agent", "Drive this deployment from an AI agent over the Model Context Protocol — it can list functions and tables, read schemas, and run read-only queries. Writes stay off unless you opt in.", "Copy MCP config", "Copy agent prompt", "Advisors", "Security", "Performance", "Warnings", "Info", "Issue type", "Entity/item", "Description", "{count} errors", "{count} warnings", "{count} suggestions", "No errors detected", "No warnings detected", "No suggestions", "Nothing to report for this deployment.", "Security and performance findings for your deployment.", "Review admin gates, credentials, and log redaction.", "Lunora checks admin-token strength, the live-subscription gate, and request-log redaction here.", "No security issues detected.", "Weak admin token", "Weak auth secret", "Session cookies are not Secure", "Wildcard CORS with credentials", "CSRF/origin guard is off", "Security headers are off", "User subscriptions are ungated", "Request log keeps un-redacted args", "Unknown security finding", "Update your worker to a version of Lunora that describes this finding.", "Your admin token is {length} characters — use at least {min} for a brute-force-resistant secret.", "Your auth secret is {length} characters — use at least {min} (e.g. `openssl rand -hex 32`) to sign sessions safely.", "BETTER_AUTH_URL is a plaintext http:// origin, so session cookies cannot be Secure and ride in cleartext. Serve auth over https:// in production.", "LUNORA_ALLOWED_ORIGINS includes a wildcard while credentials are allowed — browsers reject this and it defeats the allowlist. Name explicit origins instead of *.", "LUNORA_SECURITY_CSRF is off, so cross-origin state-changing cookie requests are not blocked. Re-enable it in production to keep mutations un-forgeable.", "LUNORA_SECURITY_HEADERS is off, so HSTS, CSP, nosniff, and frame-options are not applied. Re-enable the baseline headers in production.", "Copy index declaration for {table}", "Copy?", "Index declaration copied — add it to {table} in lunora/schema.ts.", "Could not reach the clipboard — add this to {table} in lunora/schema.ts:", "LUNORA_WS_BEARER is unset, so the WebSocket upgrade gate is open: anyone who can reach the worker can open a socket and run ordinary user subscriptions. Admin subscriptions are unaffected — they need the admin token. Set it if subscribers should present a shared credential.", "This worker reports a development environment, so the request log stores raw args and identity. Confirm it isn't a mislabeled production deploy.", "Audit", "A durable log of admin state-changing operations.", "Filter audit log", "filter op, table, id", "No audit entries.", "Privacy requests", "Open data-subject export and erasure requests, with due dates and failed-run retries.", "Privacy requests not configured", "Pass privacyRequests to the Studio to list and retry data-subject requests.", "Loading privacy requests…", "No open privacy requests.", "ID", "Subject", "Received", "Due", "Extended due", "Overdue", "Erasure", "Notifications", "Registered push devices — endpoint, kind, last-send status, and delivery errors.", "Registered Web Push / FCM devices appear here. Configure lunora/notify.ts with defineNotify({ store }) and register a device with ctx.push.register(...).", "No registered devices.", "Filter devices", "filter endpoint, user", "{count} devices", "endpoint", "last seen", "n/a", "time", "op", "table", "detail", "Auth audit", "Authentication and security events — sign-ins, MFA, and session changes.", "Filter security events", "filter event, actor, IP", "Authentication and security events are recorded here.", "No security events.", "event", "actor", "ip / user agent", "outcome", "success", "failure", "Settings", "Deployment", "Read-only deployment config — vars, secrets, and bindings.", "Environment & bindings", "No environment variables or bindings.", "Open in Cloudflare", "Remove filter", "View-only — values are masked. Edit vars, secrets, and bindings in wrangler or the Cloudflare dashboard.", "URL", "Environment", "Version", "value", "Cascade impact", "Delete preview — rows that would cascade or be blocked", "No related rows found.", "Restrict relations will block this delete.", "Generate rows", "Generate dummy rows", "Seed {table} with Faker-generated rows. Existing rows are not affected.", "Row count", "(max {max})", "Columns to seed", "FK: no rows in {ref} — seed it first", "→ {ref}", "No rows generated — all columns were skipped.", "Cannot generate rows: these columns reference tables with no rows: {cols}. Seed those tables first.", "Inserted {count} rows successfully.", "Inserted {inserted} of {total} rows — {conflicts} skipped as id conflicts.", "Generate & insert", "Inserting…", "Time Travel", "Restore a shard to a point in the last 30 days.", "root", "In-place recovery to any moment in the last 30 days. For older or portable recovery, use the snapshot backup tier.", "Current bookmark", "Restore", "Time (ISO or epoch-ms, last 30 days)", "Not a time — use epoch-ms or ISO 8601.", "Resolves to {instant} (a date-time without an offset is read in this browser's time zone; a bare date is UTC)", "Preview", "Bookmark for that time", "Or an explicit bookmark (wins over time)", "bookmark string", "Restart the shard now so recovery applies immediately", "Restore {shard} to {target}?", "the given bookmark", "restarted now", "on next restart", "Restore armed", "Restored to", "Undo bookmark", "Confirm undo", "Undo restore", "role", "Role", "Role (optional)", "Active", "Banned", "unverified", "Manage", "New user", "Create", "Create user", "Creating…", "Password (optional)", "Search users", "Search by email or name…", "Filter by role", "Set role", "Ban user", "Ban reason (optional)", "Days", "Permanent", "Unban", "New password", "Set password", "Impersonate", "Impersonation token", "Revoke", "Revoke all sessions", "Delete user", "Confirm delete", "User details", "Fields", "Linked accounts", "No linked accounts.", "provider", "Unlink", "Security", "Disable two-factor", "No passkeys.", "Operations", "Toggle operation console", "Organizations", "slug", "Members", "Invitations", "Remove", "No organizations.", "Select an organization to view its members and invitations.", "Organizations are not enabled.", "Enable the organization() plugin in your auth config to manage organizations here.", "Browse and manage organizations, members, and invitations.", "Reload", "Manage auth users — roles, bans, sessions, and identity.", "Auth config", "Configuration", "Enabled plugins and session config (read-only).", "Enabled capabilities", "Loading auth configuration…", "Accounts", "Admin", "Passkeys", "Two-factor", "Enabled", "Disabled", "OAuth providers, email templates, and rate limits are configured at deploy time in the better-auth setup and aren't editable here. See the Mail tab for email output.", "Sessions", "Browse and revoke active sessions across all users.", "user", "impersonated by", "Log drains", "Forward logs to Logpush, Tail Workers, or a webhook collector.", "Cloudflare destinations", "Lunora does not ship logs itself — forwarding is handled by Cloudflare. Configure a destination below, then test your collector.", "Logpush", "Stream every request log to R2, a SIEM, or a third-party log service.", "Tail Workers", "Send logs programmatically to a Worker for custom capture and forwarding.", "Workers Logs", "Retain and query recent request logs directly in Cloudflare's dashboard.", "Webhook test", "POST a sample Lunora request-log envelope to your collector to confirm it is reachable.", "https://example.com/logs", "Send test event", "Delivered — status {status} in {latency}ms", "Failed: {message}", "fetch is unavailable in this environment.", "Realtime", "Active WebSocket subscriptions on this shard.", "{count} connections", "{count} subscriptions", "This Studio session's sync client", "Reading the sync client's state…", "Sync client", "{count} pending writes", "Reads client.debug() for the client running in this page — not your application's client. Call client.debug() in your app to diagnose a specific stuck overlay there.", "No shard connection has been opened yet.", "No shards", "Shard", "Socket", "Confirmed watermark", "(default)", "This client holds no live queries or shapes.", "No subscriptions", "Subscription", "Kind", "Acked", "Cursor", "Pending overlays", "No active subscriptions.", "Connection", "admin", "Folder path", "Grid", "Sort", "Name", "Type", "Modified", "Toggle sort direction", "Thumbnail size", "Link expiry", "15m", "1h", "24h", "7d", "Upload", "Uploading…", "Copy URL", "Download", "Delete object?", "Uploaded {key}", "Deleted {key}", "Summary", "Time range", "All time", "Last 5m", "Last 15m", "Last hour", "filter path", "By level", "By function", "Count", "{count} entries", "Snippets", "Couldn't load the OpenAPI spec: {message}", "No OpenAPI spec configured", "Run `lunora codegen` and wire `_generated/openapi.json` to the worker to render the API reference here.", "API operations", "Filter operations", "No operations match your filter.", "Try it", "Request arguments", "Response body", "Response", "application/json", "Arguments (JSON)", "Send", "Sending…", "Send a request to see the response.", "No example for this response.", "Error", "{ms} ms", "Range", "Value in", "relation", "API spec format", "OpenAPI", "OpenRPC", "Params", "Result", "Field", "Required", "JSON-RPC request", "Couldn't load the OpenRPC spec: {message}", "No OpenRPC spec configured", "Run `lunora codegen --api-spec openrpc` and wire `_generated/openrpc.json` to the worker to render the OpenRPC reference here.", "used by", "Orphan", "1 record", "{count} records", "References shard", "Which shard's records are checked for references to these files. Empty = root shard.", "Orphaned objects", "Find records whose file reference points at an object the bucket no longer has.", "Check for orphans", "Checking…", "No dangling references.", "Every record's file reference points at an object that exists in the bucket.", "Missing object", "→", "Showing the first {count} dangling references — the scan was truncated.", "The bucket is larger than the scan's key limit, so dangling references could not be checked.", "Per-function call counts, error rates, and latency land here after your first request.", "Function and request logs for this shard show up here as your app handles traffic.", "No tables in this shard.", "Browse Vectorize indexes and run similarity searches.", "dimensions", "field", "Indexes declared with .vectorize() or defineVectorIndex() appear here.", "metadata", "metric", "No matches.", "No vector indexes.", "score", "Search", "Search by similarity…", "Searching…", "vectors", "Vectors", "Add a kv_namespaces binding to wrangler.jsonc — it appears here automatically, no wiring needed.", "Browse and edit key-value pairs in your Workers KV namespaces.", "Deleting…", "Expiration", "Filter", "Filter by prefix…", "Filter keys by prefix", "Key is absent or has no value.", "KV", "KV value", "Copy key", "Copy value", "Create key", "Failed to delete {count} keys.", "Format JSON", "Key name", "Expires after", "TTL unit", "TTL must be at least 60 seconds.", "seconds", "minutes", "hours", "days", "Leave blank to keep the current expiration.", "Metadata (JSON)", "Metadata must be valid JSON.", "New key", "No expiration", "Select all", "Select {name}", "Metadata", "Namespace", "No keys.", "No KV namespaces.", "Saving…", "vs. prev.", "Top functions", "No functions called yet.", "Calls", "Avg", "Err", "Avg latency", "cache hit", "cache not enabled", "no cache traffic yet", "Live connections", "sockets", "active subscriptions", "Recent activity", "No recent activity.", "last interval", "{rate} error rate", "cache entries", "Critical", "Degraded", "All systems healthy", "One or more service levels are breached.", "Some service levels need attention.", "All service levels are within target.", "Showing a partial request/error history — one or more shards have more data than the trend chart can display.", "Analytics", "Analytics usage panels are not wired up.", "Hot shards", "Latency p50 / p95 per function", "No data points yet.", "Request volume per function", "Analytics usage panels read through your worker, never from the browser. Pass studio.analyticsSqlQuery, a runner that calls an admin-only action running functionUsageQuery(panel) through ctx.analyticsSql, to enable these panels.", "Usage and latency from Analytics Engine — request volume, p50/p95, and hot shards.", "(whole bucket)", "Access Rules", "Bucket", "Inspect storage access rules — per bucket, operation, and key prefix.", "No defineStorageRule is wired through .use(storageRules(...)) in this deployment. Add one to gate object access by key prefix.", "No storage rules defined", "Operation", "Storage rules are declared in code with defineStorageRule and gate ctx.storage access per bucket. This view is read-only.", "Write", "Queues", "Queue", "Mode", "Dead-letter", "No queues defined", "Inspect declared Cloudflare Queues — their producer bindings, consumer mode, and dead-letter queue.", "No defineQueue is declared in lunora/queues.ts in this deployment. Add one to offload async work to a Cloudflare Queue.", "Queues are declared in code with defineQueue. Enqueue from a mutation or action with ctx.queues.<name>.send(...); push consumers process batches in the worker.", "No dead-letter queue on {queues}.", "Exhausted messages are dropped after retries. Add a deadLetterQueue to capture them.", "1 message was recently dead-lettered.", "{count} messages were recently dead-lettered.", "Batch mode needs a JSON array body — each element is enqueued as one message.", "Body", "Body must be valid JSON.", "Captured", "Clear log", "Clear the whole message log?", "Cloudflare Queues have no peek API, so this is what push consumers actually processed — not pending depth.", "Consumed messages appear here once a push consumer processes a batch in dev. Send one from the Send tab to see it captured.", "Declare a queue with defineQueue in lunora/queues.ts to enqueue a test message.", "Declared", "Delay must be a non-negative number of seconds.", "Delay (s)", "Delay (seconds)", "DLQ", "Enqueue a JSON message to a declared producer to exercise its consumer. Nothing is captured until the consumer processes it.", "Message", "Message body (JSON)", "Messages", "No consumed messages yet.", "No queues to send to", "Outcome", "Replay", "Replaying…", "Send as batch (JSON array)", "Send message", "Flags", "Inspect feature flags and their live evaluation under a targeting context.", "Feature flags are read in code with ctx.flags.<type>(\"key\", default). They evaluate through the OpenFeature provider configured in lunora/flags.ts; edit the targeting context below to see how each flag resolves for a given audience.", "Targeting context (JSON)", "Targeting context must be a JSON object.", "Targeting context is not valid JSON.", "Live updates unavailable; showing the last evaluation.", "No @lunora/flags provider is wired in this deployment. Add lunora/flags.ts with defineFlags({ provider }) to gate code paths on feature flags.", "No flags provider configured", "A flags provider is configured, but no handler reads a flag yet. Call ctx.flags.boolean(\"key\", false) in a query, mutation, or action.", "No flags read", "Key", "Value", "Reason", "Variant", "Workflows", "Inspect declared Cloudflare Workflows and their bindings.", "Binding", "Class", "No workflows defined", "No defineWorkflow is declared in lunora/workflows.ts in this deployment. Add one to run a durable, multi-step workflow.", "Workflows are declared in code with defineWorkflow and run as durable Cloudflare Workflows. This view is read-only.", "Workflows are declared in code with defineWorkflow and run as durable Cloudflare Workflows. Start an instance and observe its status below.", "Start instance", "Starting…", "Workflow", "Instance id", "Instance id (optional)", "Params (JSON)", "Params (JSON, optional)", "Params must be valid JSON", "Send event", "Event type", "Payload (JSON)", "Payload (JSON, optional)", "Payload must be valid JSON", "Event sent, but refreshing the instance failed", "Instances", "Status", "Output", "Refresh", "Refreshing…", "Instance history", "Filter by status", "All statuses", "Workflow inspection not configured", "Set CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN in your .dev.vars to enable workflow instance history.", "No instances", "No instances match this filter for the selected workflow.", "Created", "Ended", "Steps", "Step", "Attempts", "Started", "This instance has no recorded steps yet.", "pause", "resume", "restart", "Restart?", "terminate", ">100ms avg execution", "50–100ms avg execution", "<50ms avg execution", "{count} tracked statements", "Avg time", "avg", "avg time", "avgTime", "Critical queries", "Exec count", "exec count", "execCount", "Execution count", "Fast queries", "Full statement", "Moderate queries", "No query insights yet", "Overview", "P90 latency", "P95 latency", "Query insights", "Query insights appear once statements are executed against this shard.", "Query leaderboard", "Rows read", "Rows written", "rowsRead", "Slow queries sorted by {sortField}", "Sort by", "Sort queries by", "Statements", "total", "Total time", "total time", "totalTime", "Edit schema", "Add table", "Add column", "Add index", "Rename / drop / change type…", "Table name", "Column name", "Column type", "Index name", "Index fields (comma-separated)", "Optional", "Unique", "Cancel", "Apply", "Applying…", "This edit changes stored data and must go through a migration. Review the migration before applying.", "Open Migrations", "Schema updated.", "Codegen reported diagnostics:", "Editing the schema is only available in local dev.", "Adds a table, column, or index to lunora/schema.ts and reruns codegen.", "Theme", "Dark theme", "Light theme", "System theme", "Integrity", "Fan-out", "auto-scaled: {relayCount}/{maxRelays} relays", "auto-scaled: {relayCount}/{maxRelays} relays (at ceiling)", "Realtime fan-out cost and per-topic subscriber counts for this shard.", "No fan-out activity yet.", "peak {count} subscribers", "Hot topics", "Topic", "Kind", "Subscribers", "Fan-out cost since this instance woke", "Shape pokes", "Whisper broadcasts", "Passes", "Sockets iterated", "Delivered", "Peak width", "Max time", "Membership probes", "Queries run", "Shared from cache", "Global shape polls", "Global reads", "Pairs skipped", "Containers", "Container", "Instance", "Last event", "Detail", "Exit", "When", "No container activity", "Live Cloudflare Containers — current lifecycle state per instance from the log stream.", "Cloudflare Containers are observed from their lifecycle log stream. This shows the current state per instance — ports and health checks aren't carried in that stream.", "No container lifecycle activity yet. Instances declared with defineContainer show up here once they start, sleep, stop, or error.", "Traces", "Recent ctx.trace waterfalls for this shard — the drill-down from a log line.", "Evals", "Queued", "Scores recorded by recordEvaluation — the latest verdict per eval, its trend, and the graded runs behind it.", "min {min} · mean {mean} · max {max}", "Score trend for {name}", "No durable history yet — pass ctx.metrics to recordEvaluation to chart a trend.", "Open the trace {trace}", "No evals recorded", "Call recordEvaluation from a graded run and its score shows up here.", "AI usage", "Tokens and spend from ctx.ai.model calls — totals, per function and per model, and the recent calls behind them.", "Estimated", "Partly estimated", "Derived from a price table, not reported by the provider.", "Includes cost derived from a price table, not reported by the provider.", "Input tokens", "Output tokens", "Cost", "Recent calls", "Model", "stream", "failed", "Cost per minute", "No cost reported", "{provider} provider-reported · {estimated} estimated", "Total cost", "By model", "Spend shows up here once an action calls ctx.ai.model(...) — tokens and cost per function and per model.", "No AI usage recorded", "No durable history yet — these totals come from the live trace ring and reset when the shard hibernates.", "Totals cover the retained metric history (up to the last 24 hours).", "No recent calls in the live trace ring — it empties when the shard hibernates.", "Search traces", "search trace, span, or function", "Errors only", "Recent traces", "Trace waterfall", "{count} spans", "{name}, {duration}, starts {offset} in{failure}", ", failed: {message}", "Showing the {shown} most recent of {total} traces in the buffer.", "No traces", "Span ID", "Parent span ID", "— (trace root)", "Started at", "+{offset}", "Duration", "Attributes", "Logs ({count})", "Traces recorded with ctx.trace show up here as your app handles traffic. The span buffer resets when the shard hibernates.", "Issues", "Issue", "Source", "Events", "First seen", "Last seen", "No issues", "Grouped error triage — Worker throws and container crashes folded by fingerprint.", "No grouped errors yet. When a function throws or a container crashes, matching errors fold into a single issue here.", "Severity", "Assignee", "Set severity", "Unassigned", "Resolve", "Ignore", "Reopen", "All", "Open", "Resolved", "Ignored", "—", "Toggle issue details", "Suggested fix", "No known fix for this error yet.", "Explain in plain language", "Explaining…", "AI explanation", "Generated by {model}", "No AI binding is configured. Wire an AI binding to enable plain-language explanations — the suggested fix above is always available.", "The AI model could not explain this error right now. The suggested fix above still applies.", "No catalog fix matched this error, so this explanation is the model's own reading of the message. Verify before acting on it.", "optional", "required", "unique", "Plugin fields", "New organization", "Edit organization", "Delete organization", "Delete this organization? Its members, invitations, teams, and custom roles are removed. This cannot be undone.", "Slug (optional — derived from name)", "Logo URL (optional)", "Owner user id (optional)", "Metadata (JSON, optional)", "Add member", "Invite member", "Send invitation", "Change member role", "Change role", "New team", "Rename team", "Rename", "Delete team", "Delete this team and its memberships? This cannot be undone.", "Add team member", "Team members", "No members.", "No teams.", "No team members.", "Teams", "New role", "Edit role", "Delete role", "Delete this custom role? Members keeping it will lose its grants.", "No custom roles.", "Role name", "Permission", "Permission (JSON, e.g. {\"project\":[\"create\",\"update\"]})", "Plugins", "No plugins enabled.", "Sign-in methods", "Email & password", "Social providers", "None", "Custom roles", "Session policy", "Expires in", "Refresh after", "Fresh window", "Cookie cache", "Rate limit", "Max requests", "Window", "Plugin user fields", "Deployment health", "Live liveness, readiness, and per-binding health from the deployment's /_lunora/health endpoint.", "Live liveness, readiness, and per-binding health from the deployment's /_lunora/health endpoint — wire an uptime monitor or a Cloudflare Health Check at it.", "Liveness", "Readiness", "Ready", "Not ready", "Healthy", "Unhealthy", "Checked", "Subsystem checks", "No checks reported.", "Up", "Down", "Health endpoint unavailable", "The health endpoint is in the admin posture. Paste a valid admin token in the connect popover, or set its auth to public.", "Couldn't reach the health endpoint: {message}", "no response", "Set a column on matching rows", "Writes {total} rows of {table} through the schema-aware writer — validators and indexes apply, exactly like a mutation.", "Column", "Enter a JSON value — for example true, 0, null, or \"done\".", "Set on {total} rows", "Set column on {total} matching", "Permanently delete {total} matching rows and everything that cascades?", "Permanently delete all matching rows and everything that cascades?", "Delete {total} matching", "Delete matching", "Permanently clear all {total} rows and everything that cascades?", "Permanently clear every row and everything that cascades?", "Clear table ({total})", "Clear table", "Shard: root", "has", "Nested field path", "nested path, e.g. geo.city", "value (\"10\" in quotes matches text)", "Shard: {shardKey} — rows in other shards are not touched.", "{column} has a unique index — the same value cannot be set on {total} rows."];
1259
+ /** A known studio message id — one of the entries in {@link MESSAGE_IDS}. */
1260
+ type MessageId = (typeof MESSAGE_IDS)[number];
1261
+ /** The locale the studio ships with and falls back to. */
1262
+ declare const DEFAULT_LOCALE = "en";
1263
+ /**
1264
+ * Locale code to catalog. Each catalog maps an English source string (which
1265
+ * doubles as the message id) to its translation. English ships empty: Lingui
1266
+ * compiles the id verbatim when a translation is missing, so the source strings
1267
+ * render as-is. To add a language, register `{ "Some English text": "…" }`.
1268
+ */
1269
+ type StudioCatalogs = Readonly<Record<string, Messages>>;
1270
+ /**
1271
+ * Translate function: `t("Clear")` or `t("{title} failed", { title })`.
1272
+ *
1273
+ * `id` is constrained to a known {@link MessageId}, so a typo is a compile error.
1274
+ * The interpolation `values` stay loosely typed: mapping each id to its exact
1275
+ * placeholder set isn't worth the machinery for the handful of interpolated
1276
+ * strings, so a wrong or missing value key isn't caught at this boundary.
1277
+ */
1278
+ type TFunction = (id: MessageId, values?: Record<string, unknown>) => string;
1279
+ /**
1280
+ * Build a studio-scoped Lingui instance. We deliberately use `@lingui/core`'s
1281
+ * `setupI18n` (a fresh instance) rather than the global singleton so the
1282
+ * studio can never clobber — or be clobbered by — a host app that also uses
1283
+ * Lingui.
1284
+ *
1285
+ * The message compiler is installed explicitly. `@lingui/core` only auto-installs
1286
+ * it when `NODE_ENV !== "production"`, but the studio ships as a library and
1287
+ * relies on the compiler at runtime to interpolate uncompiled source strings
1288
+ * (e.g. `t("{title} failed", { title })`). Without this, a consumer's production
1289
+ * build would render `{title}` literally and `console.warn` on every `t(...)`.
1290
+ *
1291
+ * Pass extra `catalogs` to ship more locales; unknown `locale` codes fall back
1292
+ * to `DEFAULT_LOCALE`.
1293
+ */
1294
+ declare const createStudioI18n: (locale?: string, catalogs?: StudioCatalogs) => I18n;
1295
+ /**
1296
+ * Shared default instance. Backs the i18n context's default value so the
1297
+ * composable studio and individual exported panels resolve their strings even
1298
+ * when rendered without `StudioI18nProvider` (e.g. in tests, or a host's own
1299
+ * admin UI). English-only, so it renders source strings as-is.
1300
+ */
1301
+ declare const studioI18n: I18n;
1302
+ /**
1303
+ * Hook returning a `t` bound to the nearest `StudioI18nProvider` (or the
1304
+ * shared instance when there's none). This is the runtime stand-in for Lingui's
1305
+ * `t` macro — the studio builds with esbuild and tests under Vite 8/Rolldown,
1306
+ * neither of which runs Lingui's Babel macro transform, so call sites pass the
1307
+ * English string as the id directly.
1308
+ */
1309
+ declare const useT: () => TFunction;
1033
1310
  interface HomePanelProps {
1034
1311
  /** Shard key the health digest targets on first load. Defaults to the root shard. */
1035
1312
  readonly initialShardKey?: string;
1036
1313
  }
1037
1314
  /**
1038
- * The Home overview — the studio's landing page. It pulls the root shard's
1039
- * health snapshot, the function stats, the two advisor signals, the live
1040
- * subscription pulse, and the recent admin audit log, then presents an
1041
- * at-a-glance digest: a KPI row (requests, errors, latency, database size), a
1042
- * busiest-functions leaderboard, live connections, recent activity, the advisor
1043
- * summary, and connect/quick-link shortcuts. Every read is best-effort — a
1044
- * missing admin token or a cold instance leaves a card showing a muted
1045
- * placeholder rather than blanking the page.
1046
- */
1047
- declare const HomePanel: ({
1048
- initialShardKey
1049
- }: HomePanelProps) => ReactElement;
1315
+ * The Home overview — the studio's landing page. It pulls the root shard's
1316
+ * health snapshot, the function stats, the two advisor signals, the live
1317
+ * subscription pulse, and the recent admin audit log, then presents an
1318
+ * at-a-glance digest: a KPI row (requests, errors, latency, database size), a
1319
+ * busiest-functions leaderboard, live connections, recent activity, the advisor
1320
+ * summary, and connect/quick-link shortcuts. Every read is best-effort — a
1321
+ * missing admin token or a cold instance leaves a card showing a muted
1322
+ * placeholder rather than blanking the page.
1323
+ */
1324
+ declare const HomePanel: ({ initialShardKey }: HomePanelProps) => ReactElement;
1050
1325
  interface AuditPanelProps {
1051
1326
  /** Shard key the panel reports on. Defaults to the root shard. */
1052
1327
  readonly initialShardKey?: string;
1053
1328
  }
1054
1329
  /**
1055
- * Durable audit log for one shard: the admin state-changing operations
1056
- * (`writeRow`, `runMigration`, `importShard`, `applyCdc`) recorded to the
1057
- * reserved `__lunora_audit__` table, newest first. Reads via the
1058
- * `__lunora_admin__:getAuditLog` RPC through `useAdminQuery`; gated by the
1059
- * server's `LUNORA_ADMIN_TOKEN`.
1060
- *
1061
- * Unlike the logs panel (an in-memory ring that resets on hibernation), the
1062
- * audit log is durable and bounded only by a retention cap. The panel is always
1063
- * live: `useAdminQuery`'s `live` subscription re-pushes on every server
1064
- * write-flush so new entries appear without a manual refresh. The op filter is
1065
- * client-side over the already-fetched buffer — it never triggers a refetch.
1066
- */
1067
- declare const AuditPanel: ({
1068
- initialShardKey
1069
- }: AuditPanelProps) => ReactElement;
1330
+ * Durable audit log for one shard: the admin state-changing operations
1331
+ * (`writeRow`, `runMigration`, `importShard`, `applyCdc`) recorded to the
1332
+ * reserved `__lunora_audit__` table, newest first. Reads via the
1333
+ * `__lunora_admin__:getAuditLog` RPC through `useAdminQuery`; gated by the
1334
+ * server's `LUNORA_ADMIN_TOKEN`.
1335
+ *
1336
+ * Unlike the logs panel (an in-memory ring that resets on hibernation), the
1337
+ * audit log is durable and bounded only by a retention cap. The panel is always
1338
+ * live: `useAdminQuery`'s `live` subscription re-pushes on every server
1339
+ * write-flush so new entries appear without a manual refresh. The op filter is
1340
+ * client-side over the already-fetched buffer — it never triggers a refetch.
1341
+ */
1342
+ declare const AuditPanel: ({ initialShardKey }: AuditPanelProps) => ReactElement;
1070
1343
  interface LogsPanelProps {
1071
1344
  /** Shard key the panel reports on. Defaults to the root shard. */
1072
1345
  readonly initialShardKey?: string;
1073
1346
  }
1074
- /** A relative time-range window over the Errors buffer, or `all` (no bound). */
1075
- /**
1076
- * The shard's log feed, newest first, over the gated `__lunora_admin__:*` RPC
1077
- * layer (gated by the server's `LUNORA_ADMIN_TOKEN`). Two views.
1078
- *
1079
- * The Requests view (`getRequestLog`) is the durable, structured per-request log
1080
- * `@lunora/do` writes once per `/rpc` dispatch (PLAN3 §1.1): function path,
1081
- * shard, acting user/identity, redacted args, outcome, duration, and tables
1082
- * read/written. It survives hibernation/restart (bounded retention) and is
1083
- * filtered/correlated SERVER-side on function-path prefix, userId, shard,
1084
- * outcome, and a touched table.
1085
- *
1086
- * The Errors view (`getLogs`) is the legacy in-memory RPC-error buffer, which
1087
- * only captures dispatch failures (path + message) and resets on hibernation —
1088
- * kept for the "what's failing on this instance right now" view, filtered
1089
- * client-side.
1090
- *
1091
- * For the raw, un-attributed request firehose (which Lunora deliberately does
1092
- * NOT re-stream), a deep-link to Cloudflare Workers Observability is provided.
1093
- */
1094
- declare const LogsPanel: ({
1095
- initialShardKey
1096
- }: LogsPanelProps) => ReactElement;
1347
+ /**
1348
+ * The shard's log feed, newest first, over the gated `__lunora_admin__:*` RPC
1349
+ * layer (gated by the server's `LUNORA_ADMIN_TOKEN`). Two views.
1350
+ *
1351
+ * The Requests view (`getRequestLog`) is the durable, structured per-request log
1352
+ * `@lunora/do` writes once per `/rpc` dispatch (PLAN3 §1.1): function path,
1353
+ * shard, acting user/identity, redacted args, outcome, duration, and tables
1354
+ * read/written. It survives hibernation/restart (bounded retention) and is
1355
+ * filtered/correlated SERVER-side on function-path prefix, userId, shard,
1356
+ * outcome, and a touched table.
1357
+ *
1358
+ * The Errors view (`getLogs`) is the legacy in-memory RPC-error buffer, which
1359
+ * only captures dispatch failures (path + message) and resets on hibernation —
1360
+ * kept for the "what's failing on this instance right now" view, filtered
1361
+ * client-side.
1362
+ *
1363
+ * For the raw, un-attributed request firehose (which Lunora deliberately does
1364
+ * NOT re-stream), a deep-link to Cloudflare Workers Observability is provided.
1365
+ */
1366
+ declare const LogsPanel: ({ initialShardKey }: LogsPanelProps) => ReactElement;
1097
1367
  interface MailPanelProps {
1098
1368
  /** Newest-N to load (default 100). */
1099
1369
  readonly limit?: number;
1100
1370
  }
1101
1371
  /**
1102
- * Dev mail catcher — a unified inbox of every email the app sent. `@lunora/mail`'s
1103
- * capture transport (wired in dev) intercepts each send and persists it to the
1104
- * root-shard mailbox instead of delivering, so verification / forgot-password and
1105
- * any app mail show up here with nothing leaving the machine. Reads the
1106
- * `__lunora_admin__:getCapturedMail` RPC over the {@link useLunora} client;
1107
- * gated by the server's `LUNORA_ADMIN_TOKEN`.
1108
- *
1109
- * The inbox is a single root-shard table with no write-flush to subscribe to, so
1110
- * it polls on a fixed interval (paused while the tab is hidden) — new captured
1111
- * mail appears without a manual refresh. The HTML body is rendered in a fully
1112
- * sandboxed iframe (no script execution) so captured markup can't run in the studio.
1113
- */
1114
- declare const MailPanel: ({
1115
- limit
1116
- }: MailPanelProps) => ReactElement;
1372
+ * Dev mail catcher — a unified inbox of every email the app sent. `@lunora/mail`'s
1373
+ * capture transport (wired in dev) intercepts each send and persists it to the
1374
+ * root-shard mailbox instead of delivering, so verification / forgot-password and
1375
+ * any app mail show up here with nothing leaving the machine. The inbox model —
1376
+ * the `__lunora_admin__:getCapturedMail` read, its poll, the clear / send-test
1377
+ * actions, and the selection state — lives in {@link useMailCapture}; this
1378
+ * component is markup and copy.
1379
+ *
1380
+ * The inbox is a single root-shard table with no write-flush to subscribe to, so
1381
+ * it polls on a fixed interval (paused while the tab is hidden) — new captured
1382
+ * mail appears without a manual refresh. The HTML body is rendered in a fully
1383
+ * sandboxed iframe (no script execution) so captured markup can't run in the studio.
1384
+ */
1385
+ declare const MailPanel: ({ limit }: MailPanelProps) => ReactElement;
1386
+ /**
1387
+ * The Notifications inspector — the app's registered `@lunora/notify` push
1388
+ * devices, read through the gated `__lunora_admin__:listPushSubscriptions` admin
1389
+ * RPC (`useAdminQuery`; gated by the server's `LUNORA_ADMIN_TOKEN`). Each row is
1390
+ * one registered device: its delivery kind, target endpoint, owning user, last
1391
+ * register/send touch, and the last-send status + any delivery error.
1392
+ *
1393
+ * The subscription store is a WORKER option (built from `env` via
1394
+ * `defineNotify({ store })`), not shard state, so this is a one-shot read with a
1395
+ * manual Refresh — there is no DO write-flush to subscribe to. When the app wires
1396
+ * no `@lunora/notify` store (or none yet registered), the RPC returns an empty
1397
+ * device list and the panel shows an empty state rather than erroring.
1398
+ */
1399
+ declare const NotificationsPanel: () => ReactElement;
1117
1400
  interface HealthPanelProps {
1118
1401
  /** Shard key the metric/log reads target on first load. Defaults to the root shard. */
1119
1402
  readonly initialShardKey?: string;
1120
1403
  }
1121
1404
  /**
1122
- * App-level health & SLO overview. On top of the original single-shard snapshot
1123
- * (recent errors, request/error counts, shards seen) it composes the
1124
- * lunora-attributed SLO signals the studio can already reach — app error
1125
- * rate, auth-failure rate, scheduler backlog, and migration status — each with a
1126
- * status badge, plus durable request/error and auth sparklines, and a
1127
- * worst-first per-function error-rate list. None of this is CF's per-Worker
1128
- * charting: it is attributed to lunora functions, the auth flow, and the
1129
- * scheduler/migration subsystems.
1130
- *
1131
- * Every read is independent and best-effort (via `Promise.allSettled`): a
1132
- * missing `LUNORA_ADMIN_TOKEN`, an unconfigured scheduler, or a cold instance
1133
- * degrades that one tile to `—` without blanking the rest. The overview is always
1134
- * live: a root-shard `getMetrics` subscription drives a full cross-shard re-pull
1135
- * on every write-flush (coalesced so a burst yields at most one in-flight pull).
1136
- */
1137
- declare const HealthPanel: ({
1138
- initialShardKey
1139
- }: HealthPanelProps) => ReactElement;
1405
+ * App-level health & SLO overview. On top of the original single-shard snapshot
1406
+ * (recent errors, request/error counts, shards seen) it composes the
1407
+ * lunora-attributed SLO signals the studio can already reach — app error
1408
+ * rate, auth-failure rate, scheduler backlog, and migration status — each with a
1409
+ * status badge, plus durable request/error and auth sparklines, and a
1410
+ * worst-first per-function error-rate list. None of this is CF's per-Worker
1411
+ * charting: it is attributed to lunora functions, the auth flow, and the
1412
+ * scheduler/migration subsystems.
1413
+ *
1414
+ * Every read is independent and best-effort (via `Promise.allSettled`): a
1415
+ * missing `LUNORA_ADMIN_TOKEN`, an unconfigured scheduler, or a cold instance
1416
+ * degrades that one tile to `—` without blanking the rest. The overview is always
1417
+ * live: a root-shard `getMetrics` subscription drives a full cross-shard re-pull
1418
+ * on every write-flush (coalesced so a burst yields at most one in-flight pull).
1419
+ */
1420
+ declare const HealthPanel: ({ initialShardKey }: HealthPanelProps) => ReactElement;
1140
1421
  /** One shard's metrics fetch outcome: the snapshot, or the error that shard returned. */
1141
1422
  interface ShardMetricsResult {
1142
1423
  error: null | string;
@@ -1157,120 +1438,100 @@ interface AggregateMetrics {
1157
1438
  totalRequests: number;
1158
1439
  }
1159
1440
  /**
1160
- * Roll up per-shard metrics into repo-wide totals. Errors-per-shard are kept as
1161
- * `failed` (a shard that's down is data, not a hard failure), and counters are
1162
- * summed only over reachable shards. The combined cache hit-rate weights by each
1163
- * shard's hits+misses so a busy shard dominates a quiet one.
1164
- */
1441
+ * Roll up per-shard metrics into repo-wide totals. Errors-per-shard are kept as
1442
+ * `failed` (a shard that's down is data, not a hard failure), and counters are
1443
+ * summed only over reachable shards. The combined cache hit-rate weights by each
1444
+ * shard's hits+misses so a busy shard dominates a quiet one.
1445
+ */
1165
1446
  declare const aggregateMetrics: (results: ReadonlyArray<ShardMetricsResult>) => AggregateMetrics;
1166
1447
  /**
1167
- * The shard keys to aggregate over. Durable Objects aren't enumerable, so this
1168
- * is the union of the root shard (`""`), an explicit current shard, and the
1169
- * recently-visited shards — de-duplicated, order-stable (root first). It's a
1170
- * best-effort "shards we know about", not every shard that exists.
1171
- */
1448
+ * The shard keys to aggregate over. Durable Objects aren't enumerable, so this
1449
+ * is the union of the root shard (`""`), an explicit current shard, and the
1450
+ * recently-visited shards — de-duplicated, order-stable (root first). It's a
1451
+ * best-effort "shards we know about", not every shard that exists.
1452
+ */
1172
1453
  declare const shardsToAggregate: (current: string, recents: ReadonlyArray<string>) => string[];
1173
1454
  interface MetricsPanelProps {
1174
1455
  /** Shard key the panel reports on. Defaults to the root shard. */
1175
1456
  readonly initialShardKey?: string;
1176
1457
  }
1177
1458
  /**
1178
- * Health snapshot for a single shard: request / error counts (since the DO last
1179
- * woke), its live SQLite size, and reactive-cache hit/miss stats when a cache is
1180
- * configured. Reads via the `__lunora_admin__:getMetrics` RPC over the
1181
- * {@link useLunora} client; gated by the server's `LUNORA_ADMIN_TOKEN`.
1182
- *
1183
- * Counters are per-DO-instance and reset on hibernation/restart — this is a
1184
- * "since this instance woke" readout, not a durable time series.
1185
- *
1186
- * The panel is always live: a `getMetrics` WebSocket subscription opens once the
1187
- * first one-shot seed commits a shard and re-pushes on every server write-flush,
1188
- * accumulating a client-side, in-memory series of requests-per-sample (the delta
1189
- * of `requests` between consecutive samples), rendered as an inline-SVG
1190
- * sparkline. The series is capped at {@link MAX_HISTORY} points and is lost on
1191
- * remount.
1192
- */
1193
- declare const MetricsPanel: ({
1194
- initialShardKey
1195
- }: MetricsPanelProps) => ReactElement;
1459
+ * Health snapshot for a single shard: request / error counts (since the DO last
1460
+ * woke), its live SQLite size, and reactive-cache hit/miss stats when a cache is
1461
+ * configured. Reads via the `__lunora_admin__:getMetrics` RPC over the
1462
+ * {@link useStudioClient} client; gated by the server's `LUNORA_ADMIN_TOKEN`.
1463
+ *
1464
+ * Counters are per-DO-instance and reset on hibernation/restart — this is a
1465
+ * "since this instance woke" readout, not a durable time series.
1466
+ *
1467
+ * The panel is always live: a `getMetrics` WebSocket subscription opens once the
1468
+ * first one-shot seed commits a shard and re-pushes on every server write-flush,
1469
+ * accumulating a client-side, in-memory series of requests-per-sample (the delta
1470
+ * of `requests` between consecutive samples), rendered as an inline-SVG
1471
+ * sparkline. The series is capped at {@link MAX_HISTORY} points and is lost on
1472
+ * remount.
1473
+ */
1474
+ declare const MetricsPanel: ({ initialShardKey }: MetricsPanelProps) => ReactElement;
1196
1475
  interface SchemaViewerProps {
1197
1476
  /** Shard key the viewer targets. Defaults to the root shard. */
1198
1477
  readonly initialShardKey?: string;
1199
1478
  /**
1200
- * Table to auto-expand once the shard's tables load. Set by the Insights
1201
- * "add the index" deep-link (`/schema?table=&lt;name>`) so the operator lands
1202
- * directly on the scanned table's index list instead of hunting for it.
1203
- * Re-applied whenever the value changes, so following the link a second time
1204
- * (same tab already open) re-expands the target.
1205
- */
1479
+ * Table to auto-expand once the shard's tables load. Set by the Insights
1480
+ * "add the index" deep-link (`/schema?table=<name>`) so the operator lands
1481
+ * directly on the scanned table's index list instead of hunting for it.
1482
+ * Re-applied whenever the value changes, so following the link a second time
1483
+ * (same tab already open) re-expands the target.
1484
+ */
1206
1485
  readonly initialTable?: string;
1207
1486
  /**
1208
- * Enable the visual schema-editor overlay (add table / column / index). Off by
1209
- * default so the diagram stays read-only. Set only by the loopback dev hosts
1210
- * (see `StudioProps.schemaEditable`); when true, the authoring overlay
1211
- * (plan 024 Item 4) renders above the table lists and applies additive edits
1212
- * through the dev host's local schema-edit endpoint.
1213
- */
1487
+ * Enable the visual schema-editor overlay (add table / column / index). Off by
1488
+ * default so the diagram stays read-only. Set only by the loopback dev hosts
1489
+ * (see `StudioProps.schemaEditable`); when true, the authoring overlay
1490
+ * (plan 024 Item 4) renders above the table lists and applies additive edits
1491
+ * through the dev host's local schema-edit endpoint.
1492
+ */
1214
1493
  readonly schemaEditable?: boolean;
1215
1494
  }
1216
1495
  /**
1217
- * Schema overview that shows both storage tiers so the distinction is never a
1218
- * mystery. The shard section lists every user table in the selected Durable
1219
- * Object with row counts, and probes a table's columns on expand via a one-row
1220
- * `__lunora_admin__:readTablePage` (`PRAGMA table_info`). The global section
1221
- * lists every `.global()` table — including the auth tables (`user`, `session`,
1222
- * …) — via the client's `listGlobalTables()`, reading columns from a one-row
1223
- * `readGlobalTablePage` on expand.
1224
- *
1225
- * Two presentations: a **Table list** (searchable, expandable cards per tier)
1226
- * and a **Graph** — a single React Flow relationship diagram showing both tiers
1227
- * on one canvas, with cross-tier FK edges and its own in-canvas find-table box,
1228
- * tier filter, and legend.
1229
- *
1230
- * Read-only and gated by the server's `LUNORA_ADMIN_TOKEN`, like the rest of the
1231
- * studio's admin surface. Global discovery is best-effort: if D1 isn't
1232
- * configured the global section simply reports it, and the shard section still
1233
- * works.
1234
- */
1235
- declare const SchemaViewer: ({
1236
- initialShardKey,
1237
- initialTable,
1238
- schemaEditable
1239
- }: SchemaViewerProps) => ReactElement;
1496
+ * Schema overview that shows both storage tiers so the distinction is never a
1497
+ * mystery. The shard section lists every user table in the selected Durable
1498
+ * Object with row counts, and probes a table's columns on expand via a one-row
1499
+ * `__lunora_admin__:readTablePage` (`PRAGMA table_info`). The global section
1500
+ * lists every `.global()` table — including the auth tables (`user`, `session`,
1501
+ * …) — via the client's `listGlobalTables()`, reading columns from a one-row
1502
+ * `readGlobalTablePage` on expand.
1503
+ *
1504
+ * Two presentations: a **Table list** (searchable, expandable cards per tier)
1505
+ * and a **Graph** — a single React Flow relationship diagram showing both tiers
1506
+ * on one canvas, with cross-tier FK edges and its own in-canvas find-table box,
1507
+ * tier filter, and legend.
1508
+ *
1509
+ * Read-only and gated by the server's `LUNORA_ADMIN_TOKEN`, like the rest of the
1510
+ * studio's admin surface. Global discovery is best-effort: if D1 isn't
1511
+ * configured the global section simply reports it, and the shard section still
1512
+ * works.
1513
+ */
1514
+ declare const SchemaViewer: ({ initialShardKey, initialTable, schemaEditable }: SchemaViewerProps) => ReactElement;
1240
1515
  interface SettingsPanelProps {
1241
1516
  /** Shard key the settings read targets on first load. Defaults to the root shard. */
1242
1517
  readonly initialShardKey?: string;
1243
1518
  }
1244
- /**
1245
- * Read-only **Settings** view of the deployment's config: the Worker vars,
1246
- * secrets, and bindings exposed via `env`, plus best-effort deploy metadata.
1247
- * Reads the `__lunora_admin__:getSettings` RPC via {@link useAdminQuery} (gated
1248
- * by the server's `LUNORA_ADMIN_TOKEN`).
1249
- *
1250
- * Strictly view-only: secret values are masked server-side and never returned
1251
- * raw, and there is no editing here. The infrastructure plane lives in
1252
- * Cloudflare/wrangler — a deep-link to the Cloudflare dashboard is provided so
1253
- * you can edit there. Deployment config is static at runtime (it only changes on
1254
- * redeploy), so this loads once on mount — there is no live channel or poll.
1255
- */
1256
- declare const SettingsPanel: ({
1257
- initialShardKey
1258
- }: SettingsPanelProps) => ReactElement;
1519
+ declare const SettingsPanel: ({ initialShardKey }: SettingsPanelProps) => ReactElement;
1259
1520
  interface SqlEditorPanelProps {
1260
1521
  /** Shard key the query runs against on first load. Defaults to the root shard. */
1261
1522
  readonly initialShardKey?: string;
1523
+ /** Clock the run timer reads. Injected by tests so a duration is asserted, not measured. */
1524
+ readonly now?: () => number;
1262
1525
  }
1263
1526
  /**
1264
- * A full-height, Supabase-style SQL editor: a left query sidebar (search + new,
1265
- * a browser-persisted PRIVATE list, and REFERENCE templates), a line-numbered
1266
- * editor pane, and a Results / Explain pane with a Run control + shard selector.
1267
- * Read-only — the `__lunora_admin__:runSql` RPC rejects everything but
1268
- * SELECT / WITH / EXPLAIN, so raw writes can't desync the doc-store's shadow
1269
- * tables (use the Data grid's inline edit for mutations).
1270
- */
1271
- declare const SqlEditorPanel: ({
1272
- initialShardKey
1273
- }: SqlEditorPanelProps) => ReactElement;
1527
+ * A full-height, Supabase-style SQL editor: a left query sidebar (search + new,
1528
+ * a browser-persisted PRIVATE list, and REFERENCE templates), a line-numbered
1529
+ * editor pane, and a Results / Explain pane with a Run control + shard selector.
1530
+ * Read-only — the `__lunora_admin__:runSql` RPC rejects everything but
1531
+ * SELECT / WITH / EXPLAIN, so raw writes can't desync the doc-store's shadow
1532
+ * tables (use the Data grid's inline edit for mutations).
1533
+ */
1534
+ declare const SqlEditorPanel: ({ initialShardKey, now }: SqlEditorPanelProps) => ReactElement;
1274
1535
  interface FileBrowserProps {
1275
1536
  /** Object-key prefix the browser filters by on first load. */
1276
1537
  readonly initialPrefix?: string;
@@ -1278,121 +1539,69 @@ interface FileBrowserProps {
1278
1539
  readonly pageSize?: number;
1279
1540
  }
1280
1541
  /**
1281
- * Browse — and mutate — objects in the storage (R2) bucket. Lists keys under an
1282
- * optional prefix via the client's `listStorageObjects`, which hits the worker's
1283
- * admin-gated `GET /_lunora/admin/storage` endpoint — so the worker must be built
1284
- * with a `storageList` function and `adminToken`. Paginates forward by cursor.
1285
- *
1286
- * Each row offers a "Copy URL" (signed/public URL via `signedStorageUrl`) and a
1287
- * confirm-gated "Delete" (`deleteStorageObject`); the toolbar offers an upload
1288
- * (`uploadStorageObject`) into the current prefix. Those write paths require the
1289
- * worker to be built with `storageSignedUrl` / `storageDelete` / `storageUpload`
1290
- * respectively — when absent, the worker responds with a clear `*_NOT_CONFIGURED`
1291
- * error that surfaces inline rather than crashing the panel.
1292
- *
1293
- * All state + behavior lives in {@link useFileBrowser}; this shell only wires the
1294
- * view-model into the toolbar, breadcrumbs, selection bar, list/gallery and the
1295
- * load-more / error / empty affordances.
1296
- */
1297
- declare const FileBrowser: ({
1298
- initialPrefix,
1299
- pageSize
1300
- }: FileBrowserProps) => ReactElement;
1542
+ * Browse — and mutate — objects in the storage (R2) bucket. Lists keys under an
1543
+ * optional prefix via the client's `listStorageObjects`, which hits the worker's
1544
+ * admin-gated `GET /_lunora/admin/storage` endpoint — so the worker must be built
1545
+ * with a `storageList` function and `adminToken`. Paginates forward by cursor.
1546
+ *
1547
+ * Each row offers a "Copy URL" (signed/public URL via `signedStorageUrl`) and a
1548
+ * confirm-gated "Delete" (`deleteStorageObject`); the toolbar offers an upload
1549
+ * (`uploadStorageObject`) into the current prefix. Those write paths require the
1550
+ * worker to be built with `storageSignedUrl` / `storageDelete` / `storageUpload`
1551
+ * respectively — when absent, the worker responds with a clear `*_NOT_CONFIGURED`
1552
+ * error that surfaces inline rather than crashing the panel.
1553
+ *
1554
+ * All state + behavior lives in {@link useFileBrowser}; this shell only wires the
1555
+ * view-model into the toolbar, breadcrumbs, selection bar, list/gallery and the
1556
+ * load-more / error / empty affordances.
1557
+ */
1558
+ declare const FileBrowser: ({ initialPrefix, pageSize }: FileBrowserProps) => ReactElement;
1301
1559
  /** Default polling cadence for auto-refresh, in milliseconds. */
1302
1560
  declare const DEFAULT_AUTO_REFRESH_MS = 5e3;
1303
1561
  /**
1304
- * Call `onTick` on a fixed interval while `enabled`, for panels whose backend
1305
- * has no live subscription channel (the scheduler, R2, D1, the SessionDO — all
1306
- * HTTP-only). Polling is the honest "live" here: a timer-driven scheduler has no
1307
- * client-observable write event to push on, so the UI watches jobs count down
1308
- * and disappear by re-asking.
1309
- *
1310
- * Ticks are skipped while the tab is hidden (`document.hidden`) so a backgrounded
1311
- * studio doesn't keep hammering the worker. `onTick` is held in a ref so a
1312
- * fresh closure each render doesn't reset the interval; only `enabled`/`intervalMs`
1313
- * do. The interval is cleared on disable and unmount.
1314
- */
1315
- declare const useAutoRefresh: (onTick: () => void, enabled: boolean, intervalMs?: number) => void;
1316
- /**
1317
- * Debounced mirror of `value`: returns the latest value only after it has been
1318
- * stable for `delayMs`. Used so a per-keystroke search box drives at most one
1319
- * server round-trip per pause, instead of one request per character.
1320
- */
1321
- declare const useDebounced: <T>(value: T, delayMs?: number) => T;
1322
- /**
1323
- * The registry of every English source string a call site may pass to `t(...)`.
1324
- *
1325
- * English is the source locale, so each id doubles as the rendered text: Lingui
1326
- * compiles an id verbatim when a catalog has no entry for it. This list is the
1327
- * single source of known strings — {@link MessageId} is derived from it and
1328
- * `TFunction` is typed against that union, so `t("Dat")` (or any string absent
1329
- * here) is a compile error rather than a silently-rendered typo.
1330
- *
1331
- * Add a string here the moment a new call site needs it. To translate, create a
1332
- * sibling catalog (for example `de.ts`) mapping each id to its translation and
1333
- * register it via `createStudioI18n(locale, { en: enMessages, de: deMessages })`.
1334
- */
1335
- declare const MESSAGE_IDS: readonly ["Bindings", "KV Namespaces", "R2 Buckets", "Vectorize Indexes", "{count} bindings", "1 binding", "Lunora AI rules aren't installed.", "lets your coding agent use Lunora correctly.", "Dismiss", ", changed", "(no subject)", "(root)", "{count} active", "{count} calls", "{count} failed", "{total} total", "No subscriptions yet", "Payments", "Plan", "Provider", "Recent webhook events", "Renews", "State", "Subscriptions", "Synced customers, subscriptions, and webhook events.", "{count} messages", "{count} pending changes", "{count} running", "{name} ({rowCount})", "{rangeStart}-{rangeEnd} of {total}", "{rate} ({count} entries)", "{reachable} reachable", "{reachable} reachable, {failed} unreachable", "{status} — processed", "{title} failed", "Actions", "Actions have no React hook — call them through the client.", "Add a widget to chart a saved SQL query on this browser.", "Add index on {table}", "Add row", "Add widget", "admin token", "Aggregating…", "all", "All shards", "API", "API reference unavailable", "API resources", "API usage snippets", "API view", "Arguments", "Auth", "Auth failures", "Auth failures over time", "Cache hit rate", "Call this {kind} from your app.", "Cancel", "Cancel job?", "Cc", "changed", "Chart widgets backed by saved read-only SQL queries.", "Lunora surfaces slow functions, error spikes, and cache problems here.", "Clear", "Clear inbox", "Columns unavailable", "CLI", "Client", "collecting samples…", "Combined cache hit rate", "Commit", "Committing…", "Breadcrumb", "Confirm", "Connect", "Connect to Lunora Studio", "Connected", "Connecting…", "Enter your admin token to access the studio.", "From your worker's LUNORA_ADMIN_TOKEN — your project's .dev.vars in dev, or a deployment secret in production.", "Local", "Not connected", "content-type", "Copy", "Copy link", "Copy-paste snippets for calling your functions and tables.", "created", "Cron triggers", "Dashboards", "Data", "Data migrations you run against this shard will be tracked here.", "Data model", "Database", "Database size", "db size", "Delete", "Delete saved query {name}", "Delete?", "direction", "Direction", "Discard", "down", "Dry run", "Dry run: ", "Edit", "Edit widget", "email", "Email preview", "Email your app sends in dev is captured here — nothing is delivered.", "Email your app sent, captured in dev.", "Enter a migration id", "error", "Error rate", "errors", "Errors", "Errors over time", "expires", "Export", "PNG", "SVG", "Export / Import", "Exported {count} rows.", "Facets", "file:function", "Files", "Filter messages", "Filter tables", "Find table…", "Foreign key", "From", "function", "Function", "Function path", "Functions", "Functions by error rate", "Graph", "Headers", "Health", "Indexes", "Hide", "HTML", "id", "Idle", "Import", "Import (writes rows)?", "Inserted {inserted}, {conflicts} conflicts, {errors} errors.", "Interactive OpenAPI reference and copy-paste snippets for your functions.", "Invalid JSON args: {message}", "Invalid JSON: {message}", "Invalid NDJSON: {message}", "ip", "Jobs queued with runAfter / runAt will appear here.", "JSON", "key", "Key prefix", "key prefix (optional)", "Level filter", "line {line} ({table}): {message}", "List", "Live", "Live — changes stream in automatically", "Live unavailable", "Live unavailable: {liveError}", "Live: on", "Load", "Load more", "Load tables", "Logic", "Logs", "Mail", "Mask sensitive columns", "Metrics", "migration id", "Migration id", "Migrations", "Missing index", "name", "Next", "no", "No active sessions.", "no cache configured", "No captured email.", "No cron triggers.", "No function activity yet.", "No functions or tables to document yet.", "No global tables.", "No headers.", "No HTML body.", "No logs.", "No migrations have run on this shard.", "No objects.", "No recent errors.", "No scheduled jobs.", "No tables to graph.", "No tables match your filter.", "No text body.", "No users.", "No widgets yet", "Objects you upload to your R2 buckets will appear here.", "Observability", "of {pages}", "off", "Offline", "ok", "OK", "on", "Open {target} {id}", "Open in new tab", "Outcome filter", "Page", "Plain text", "Prefill", "Previous", "Primary key", "processed", "React", "Read and write this table through the typed data model.", "Recent errors", "Recent logs", "Recently visited shards — click to switch", "Refresh", "Reload tables", "Remove widget", "RLS Policies", "Policies", "No policies defined", "No `definePolicy` is wired through `.use(rls(...))` in this deployment. Add one to guard a table's rows.", "Read", "Insert", "Update", "Guarded by", "Guarded", "Roles", "No roles defined", "No `defineRole` is registered via `rls(policies, { roles })`. Roles back `ctx.auth.can(...)` permission checks.", "Permissions", "Run as identity (userId)", "Leave empty to run as admin", "Dev only: runs the function as this user so you can test auth and RLS. Forged over the admin gate.", "as {userId}", "No policy", "Covered by {procedure}", "Uncovered — reachable without a policy", "Masked columns", "No tables in this deployment's schema.", "Add a `definePolicy` and wire it through `.use(rls(...))` to populate this matrix.", "Pick a function and an identity, then run it to see the access outcome.", "Probe", "Probe this", "Run as (userId)", "Identity (userId) to run as", "Run probe", "Allowed", "Denied", "Probing…", "Set `runAsIdentity` to forge an identity and probe access.", "Dev only: runs the selected function as this user over the admin gate so you can test auth and RLS.", "Inspect access policies per table, and probe a function as any identity.", "Scaffold access rules", "Writes a new deny-by-default policy file under lunora/, or wires one into a procedure, then reruns codegen. Local dev only.", "New policy file", "Wire into a procedure", "Policy name", "Create policy file", "Procedure file path", "Exported procedure", "Policy set identifier", "Wire RLS", "Creating…", "Wiring…", "Scaffolded {label} and reran codegen. Fill in the `when` predicates before relying on it.", "This change must be made by hand — the scaffolder only adds new, deny-by-default rules.", "requests", "Requests", "Requests / interval", "Requests over time", "Requests per interval over time", "Row actions", "Row document JSON", "Rows per page", "Run", "Run migration", "Run migration?", "Running…", "Query name", "Save", "Save query", "Save widget", "Saved", "schedule", "target", "workflow", "Run now", "Run now?", "Running…", "ran", "attempts", "backlog", "Dead letter", "Drop", "Drop job?", "in flight", "Jobs that exhaust their retry budget are parked here instead of being dropped.", "last tried", "max concurrency", "No dead-letter jobs.", "No workpools.", "pool", "Pools", "pools", "Pools created with createWorkpool appear here once they have activity.", "queued", "Retry", "Schedule view", "Scheduled", "scheduled for", "Scheduled jobs", "Scheduler backlog", "Schema", "Schema graph", "Schema view", "search message", "Search messages", "Search rows", "search table…", "Search…", "Select a function or table to see how to call it from your app.", "Select all rows", "Select row", "Send test", "Sent", "Service level", "Sessions", "Sessions for {userId}", "shard", "Shard", "Shard key", "shard key (optional)", "Shard key (optional)", "Shards", "Shards seen", "Signature", "size", "Snippet flavour", "State-changing admin operations are recorded here.", "status", "Storage", "Storage tier", "Storage tiers", "Studio", "Studio areas", "Studio failed", "Switch to dark theme", "Switch to light theme", "Table", "Table list", "Table touched", "Tables", "To", "Token rides the WebSocket URL — it can surface in browser DevTools and server logs. Use a dev-only token.", "Total database size", "Total errors", "Total requests", "Triggers declared with the cronJobs() builder appear here.", "Try again", "unreachable", "up", "updated", "Uptime", "user agent", "User id", "userId", "Users", "Users who sign up to your app will appear here.", "verified", "Widget title", "yes", "A live stream of recent function logs.", "Browse and edit rows across your shard and global tables.", "Browse auth users and their active sessions.", "Browse objects in your R2 storage buckets.", "Export a shard to NDJSON, or import rows from it.", "At-a-glance connection, error, and shard signals.", "Inspect and cancel scheduled jobs.", "Inspect each table and its columns.", "Inspect row-level-security policies and roles, per table.", "Per-shard health and aggregate metrics.", "Review migration status and run them.", "Run registered queries, mutations, and actions.", "Global tables (D1)", "Shard tables", "{shard} tables", "Tables marked .global() (D1-backed, region-replicated) will appear here.", "Select a table to browse its rows.", "Shared across every tenant, stored once in D1. Includes auth tables.", "Partitioned per shard key into separate Durable Objects — scoped to the shard above.", "avg", "calls", "conflicts", "kind", "last error", "last run", "max", "Most called", "No functions have run on this shard yet.", "Recent", "Slowest", "Insights", "Surface slow functions, error spikes, and cache problems.", "No issues detected.", "Low cache hit rate", "High cache eviction rate", "Slow function", "High error rate", "High write contention", "{rate} hit rate over recent traffic.", "{count} entries evicted recently.", "Slowest call took {duration}.", "Slowest call took {duration} — it full-scanned {tables} with no index.", "{rate} of calls failed.", "{rate} of calls hit a write conflict — consider sharding to cut contention.", "Home", "Reports", "SQL / Functions", "Table editor", "Connection, health, and advisor summary for your deployment.", "Collapse sidebar", "Expand sidebar", "SQL editor", "Run read-only SQL against a shard.", "Run", "SQL query", "{count} rows", "Showing the first {max} of {count} rows.", "Showing the {n} most common values.", "No rows returned.", "Private", "Reference", "Search queries…", "New query", "Untitled query", "Delete query", "No saved queries yet — they save to this browser as you type.", "Results", "Explain", "Chart", "History", "Format", "Clear history", "No numeric column to chart.", "Click Run to execute your query.", "Untitled", "New tab", "Close tab", "Tab title", "Double-click to rename", "Discard?", "Discard changes", "Keep editing", "Close other tabs", "Close tabs to the right", "Close all tabs", "Discard unsaved tabs?", "column", "keyword", "Columns", "Show all", "Hide all", "Transpose", "Swap rows and columns", "Field", "Row {n}", "Loading…", "No matching row.", "CSV", "{count} selected", "Delete {count}", "Delete {count} rows?", "Copy", "Copied", "Cell value", "Close", "Form", "Invalid JSON", "Command palette", "No results.", "Quick links", "Security findings", "Performance issues", "View", "All clear", "No data yet", "Get connected", "No issues found", "No security or performance issues detected.", "Client SDK", "React", "CLI", "Advisors", "Security", "Performance", "Warnings", "Info", "Issue type", "Entity/item", "Description", "{count} errors", "{count} warnings", "{count} suggestions", "No errors detected", "No warnings detected", "No suggestions", "Nothing to report for this deployment.", "Security and performance findings for your deployment.", "Review admin gates, credentials, and log redaction.", "Lunora checks admin-token strength, the live-subscription gate, and request-log redaction here.", "No security issues detected.", "Weak admin token", "Weak auth secret", "Session cookies are not Secure", "Wildcard CORS with credentials", "CSRF/origin guard is off", "Security headers are off", "Live admin subscriptions are ungated", "Request log keeps un-redacted args", "Unknown security finding", "Update your worker to a version of Lunora that describes this finding.", "Your admin token is {length} characters — use at least {min} for a brute-force-resistant secret.", "Your auth secret is {length} characters — use at least {min} (e.g. `openssl rand -hex 32`) to sign sessions safely.", "BETTER_AUTH_URL is a plaintext http:// origin, so session cookies cannot be Secure and ride in cleartext. Serve auth over https:// in production.", "LUNORA_ALLOWED_ORIGINS includes a wildcard while credentials are allowed — browsers reject this and it defeats the allowlist. Name explicit origins instead of *.", "LUNORA_SECURITY_CSRF is off, so cross-origin state-changing cookie requests are not blocked. Re-enable it in production to keep mutations un-forgeable.", "LUNORA_SECURITY_HEADERS is off, so HSTS, CSP, nosniff, and frame-options are not applied. Re-enable the baseline headers in production.", "Apply index", "Apply index on {table}", "Apply?", "CREATE INDEX SQL copied to clipboard.", "LUNORA_WS_BEARER is unset, so the WebSocket upgrade gate is open: live admin subscriptions need no credential. Set it to gate them like the HTTP admin RPCs.", "This worker reports a development environment, so the request log stores raw args and identity. Confirm it isn't a mislabeled production deploy.", "Audit", "A durable log of admin state-changing operations.", "Filter audit log", "filter op, table, id", "No audit entries.", "time", "op", "table", "detail", "Settings", "Deployment", "Read-only deployment config — vars, secrets, and bindings.", "Environment & bindings", "No environment variables or bindings.", "Open in Cloudflare", "Remove filter", "View-only — values are masked. Edit vars, secrets, and bindings in wrangler or the Cloudflare dashboard.", "URL", "Environment", "Version", "value", "Cascade impact", "Delete preview — rows that would cascade or be blocked", "No related rows found.", "Restrict relations will block this delete.", "Generate rows", "Generate dummy rows", "Seed {table} with Faker-generated rows. Existing rows are not affected.", "Row count", "(max {max})", "Columns to seed", "FK: no rows in {ref} — will skip", "→ {ref}", "No rows generated — all columns were skipped.", "Inserted {count} rows. Skipped FK columns: {cols}", "Inserted {count} rows successfully.", "Generate & insert", "Inserting…", "Time Travel", "Restore a shard to a point in the last 30 days.", "root", "In-place recovery to any moment in the last 30 days. For older or portable recovery, use the snapshot backup tier.", "Current bookmark", "Restore", "Time (ISO or epoch-ms, last 30 days)", "Preview", "Bookmark for that time", "Or an explicit bookmark (wins over time)", "bookmark string", "Restart the shard now so recovery applies immediately", "Confirm restore", "restarted now", "on next restart", "Restore armed", "Restored to", "Undo bookmark", "Confirm undo", "Undo restore", "role", "Role", "Role (optional)", "Active", "Banned", "unverified", "Manage", "New user", "Create", "Create user", "Creating…", "Password (optional)", "Search users", "Search by email or name…", "Filter by role", "Set role", "Ban user", "Ban reason (optional)", "Days", "Unban", "New password", "Set password", "Impersonate", "Impersonation token", "Revoke", "Revoke all sessions", "Delete user", "Confirm delete", "User details", "Fields", "Linked accounts", "No linked accounts.", "provider", "Unlink", "Security", "Disable two-factor", "No passkeys.", "Operations", "Organizations", "slug", "Members", "Invitations", "Remove", "No organizations.", "Select an organization to view its members and invitations.", "Organizations are not enabled.", "Enable the organization() plugin in your auth config to manage organizations here.", "Browse and manage organizations, members, and invitations.", "Reload", "Manage auth users — roles, bans, sessions, and identity.", "Auth config", "Configuration", "Enabled plugins and session config (read-only).", "Enabled capabilities", "Loading auth configuration…", "Accounts", "Admin", "Passkeys", "Two-factor", "Enabled", "Disabled", "OAuth providers, email templates, and rate limits are configured at deploy time in the better-auth setup and aren't editable here. See the Mail tab for email output.", "Sessions", "Browse and revoke active sessions across all users.", "user", "impersonated by", "Log drains", "Forward logs to Logpush, Tail Workers, or a webhook collector.", "Cloudflare destinations", "Lunora does not ship logs itself — forwarding is handled by Cloudflare. Configure a destination below, then test your collector.", "Logpush", "Stream every request log to R2, a SIEM, or a third-party log service.", "Tail Workers", "Send logs programmatically to a Worker for custom capture and forwarding.", "Workers Logs", "Retain and query recent request logs directly in Cloudflare's dashboard.", "Webhook test", "POST a sample Lunora request-log envelope to your collector to confirm it is reachable.", "https://example.com/logs", "Send test event", "Delivered — status {status} in {latency}ms", "Failed: {message}", "fetch is unavailable in this environment.", "Realtime", "Active WebSocket subscriptions on this shard.", "{count} connections", "{count} subscriptions", "No active subscriptions.", "Connection", "admin", "Folder path", "Grid", "Sort", "Name", "Type", "Modified", "Toggle sort direction", "Thumbnail size", "Link expiry", "15m", "1h", "24h", "7d", "Upload", "Uploading…", "Copy URL", "Download", "Delete object?", "Uploaded {key}", "Deleted {key}", "Summary", "Time range", "All time", "Last 5m", "Last 15m", "Last hour", "filter path", "By level", "By function", "Count", "{count} entries", "Snippets", "Couldn't load the OpenAPI spec: {message}", "No OpenAPI spec configured", "Run `lunora codegen` and wire `_generated/openapi.json` to the worker to render the API reference here.", "API operations", "Filter operations", "No operations match your filter.", "Try it", "Request arguments", "Response body", "Response", "application/json", "Arguments (JSON)", "Send", "Sending…", "Send a request to see the response.", "No example for this response.", "Error", "{ms} ms", "Range", "Value in", "relation", "API spec format", "OpenAPI", "OpenRPC", "Params", "Result", "Field", "Required", "JSON-RPC request", "Couldn't load the OpenRPC spec: {message}", "No OpenRPC spec configured", "Run `lunora codegen --api-spec openrpc` and wire `_generated/openrpc.json` to the worker to render the OpenRPC reference here.", "used by", "Orphan", "1 record", "{count} records", "References shard", "Which shard's records are checked for references to these files. Empty = root shard.", "Orphaned objects", "Find records whose file reference points at an object the bucket no longer has.", "Check for orphans", "Checking…", "No dangling references.", "Every record's file reference points at an object that exists in the bucket.", "Missing object", "→", "Showing the first {count} dangling references — the scan was truncated.", "Per-function call counts, error rates, and latency land here after your first request.", "Function and request logs for this shard show up here as your app handles traffic.", "No tables in this shard.", "Browse Vectorize indexes and run similarity searches.", "dimensions", "field", "Indexes declared with .vectorize() or defineVectorIndex() appear here.", "metadata", "metric", "No matches.", "No vector indexes.", "score", "Search", "Search by similarity…", "Searching…", "vectors", "Vectors", "Add a kv_namespaces binding to wrangler.jsonc — it appears here automatically, no wiring needed.", "Browse and edit key-value pairs in your Workers KV namespaces.", "Deleting…", "Expiration", "Filter", "Filter by prefix…", "Filter keys by prefix", "Key is absent or has no value.", "KV", "KV value", "Copy key", "Copy value", "Create key", "Failed to delete {count} keys.", "Format JSON", "Key name", "Expires after", "TTL unit", "TTL must be at least 60 seconds.", "seconds", "minutes", "hours", "days", "Leave blank to keep the current expiration.", "Metadata (JSON)", "Metadata must be valid JSON.", "New key", "No expiration", "Select all", "Select {name}", "Metadata", "Namespace", "No keys.", "No KV namespaces.", "Saving…", "vs. prev.", "Top functions", "No functions called yet.", "Calls", "Avg", "Err", "Avg latency", "cache hit", "Live connections", "sockets", "active subscriptions", "Recent activity", "No recent activity.", "last interval", "{rate} error rate", "cache entries", "Critical", "Degraded", "All systems healthy", "One or more service levels are breached.", "Some service levels need attention.", "All service levels are within target.", "Analytics", "Analytics is not configured.", "Hot shards", "Latency p50 / p95 per function", "No data points yet.", "Request volume per function", "Set CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN (Analytics Read) in your .dev.vars to enable usage panels.", "Usage and latency from Analytics Engine — request volume, p50/p95, and hot shards.", "(whole bucket)", "Access Rules", "Bucket", "Inspect storage access rules — per bucket, operation, and key prefix.", "No defineStorageRule is wired through .use(storageRules(...)) in this deployment. Add one to gate object access by key prefix.", "No storage rules defined", "Operation", "Storage rules are declared in code with defineStorageRule and gate ctx.storage access per bucket. This view is read-only.", "Write", "Queues", "Queue", "Mode", "Dead-letter", "No queues defined", "Inspect declared Cloudflare Queues — their producer bindings, consumer mode, and dead-letter queue.", "No defineQueue is declared in lunora/queues.ts in this deployment. Add one to offload async work to a Cloudflare Queue.", "Queues are declared in code with defineQueue. Enqueue from a mutation or action with ctx.queues.<name>.send(...); push consumers process batches in the worker.", "Batch mode needs a JSON array body — each element is enqueued as one message.", "Body", "Body must be valid JSON.", "Captured", "Clear log", "Cloudflare Queues have no peek API, so this is what push consumers actually processed — not pending depth.", "Consumed messages appear here once a push consumer processes a batch in dev. Send one from the Send tab to see it captured.", "Declare a queue with defineQueue in lunora/queues.ts to enqueue a test message.", "Declared", "Delay must be a non-negative number of seconds.", "Delay (s)", "Delay (seconds)", "DLQ", "Enqueue a JSON message to a declared producer to exercise its consumer. Nothing is captured until the consumer processes it.", "Message", "Message body (JSON)", "Messages", "No consumed messages yet.", "No queues to send to", "Outcome", "Replay", "Replaying…", "Send as batch (JSON array)", "Send message", "Flags", "Inspect feature flags and their live evaluation under a targeting context.", "Feature flags are read in code with ctx.flags.<type>(\"key\", default). They evaluate through the OpenFeature provider configured in lunora/flags.ts; edit the targeting context below to see how each flag resolves for a given audience.", "Targeting context (JSON)", "Targeting context must be a JSON object.", "Targeting context is not valid JSON.", "Live updates unavailable; showing the last evaluation.", "No @lunora/flags provider is wired in this deployment. Add lunora/flags.ts with defineFlags({ provider }) to gate code paths on feature flags.", "No flags provider configured", "A flags provider is configured, but no handler reads a flag yet. Call ctx.flags.boolean(\"key\", false) in a query, mutation, or action.", "No flags read", "Key", "Value", "Reason", "Variant", "Workflows", "Inspect declared Cloudflare Workflows and their bindings.", "Binding", "Class", "No workflows defined", "No defineWorkflow is declared in lunora/workflows.ts in this deployment. Add one to run a durable, multi-step workflow.", "Workflows are declared in code with defineWorkflow and run as durable Cloudflare Workflows. This view is read-only.", "Workflows are declared in code with defineWorkflow and run as durable Cloudflare Workflows. Start an instance and observe its status below.", "Start instance", "Starting…", "Workflow", "Instance id", "Instance id (optional)", "Params (JSON)", "Params (JSON, optional)", "Params must be valid JSON", "Instances", "Status", "Output", "Refresh", "Refreshing…", "Instance history", "Filter by status", "All statuses", "Workflow inspection not configured", "Set CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN in your .dev.vars to enable workflow instance history.", "No instances", "No instances match this filter for the selected workflow.", "Created", "Ended", "Steps", "Step", "Attempts", "Started", "This instance has no recorded steps yet.", "pause", "resume", "terminate", ">100ms avg execution", "50–100ms avg execution", "<50ms avg execution", "{count} tracked statements", "Avg time", "avg", "avg time", "avgTime", "Critical queries", "Exec count", "exec count", "execCount", "Execution count", "Fast queries", "Full statement", "Moderate queries", "No query insights yet", "Overview", "P90 latency", "P95 latency", "Query insights", "Query insights appear once statements are executed against this shard.", "Query leaderboard", "Rows read", "Rows written", "rowsRead", "Slow queries sorted by {sortField}", "Sort by", "Sort queries by", "Statements", "total", "Total time", "total time", "totalTime", "Edit schema", "Add table", "Add column", "Add index", "Rename / drop / change type…", "Table name", "Column name", "Column type", "Index name", "Index fields (comma-separated)", "Optional", "Unique", "Cancel", "Apply", "Applying…", "This edit changes stored data and must go through a migration. Review the migration before applying.", "Open Migrations", "Schema updated.", "Codegen reported diagnostics:", "Editing the schema is only available in local dev.", "Adds a table, column, or index to lunora/schema.ts and reruns codegen.", "Theme", "Dark theme", "Light theme", "System theme", "Integrity", "Fan-out", "auto-scaled: {relayCount}/{maxRelays} relays", "auto-scaled: {relayCount}/{maxRelays} relays (at ceiling)", "Realtime fan-out cost and per-topic subscriber counts for this shard.", "No fan-out activity yet.", "peak {count} subscribers", "Hot topics", "Topic", "Kind", "Subscribers", "Fan-out cost since this instance woke", "Shape pokes", "Whisper broadcasts", "Passes", "Sockets iterated", "Delivered", "Peak width", "Max time", "Containers", "Container", "Last event", "Detail", "When", "No container activity", "Live Cloudflare Containers — current lifecycle state per container from the log stream.", "Cloudflare Containers are observed from their lifecycle log stream. This shows the current state per container — ports and health checks aren't carried in that stream.", "No container lifecycle activity yet. Instances declared with defineContainer show up here once they start, sleep, stop, or error."];
1336
- /** A known studio message id — one of the entries in {@link MESSAGE_IDS}. */
1337
- type MessageId = (typeof MESSAGE_IDS)[number];
1338
- /**
1339
- * English message catalog.
1340
- *
1341
- * English is the source locale: every call site passes its English string as the
1342
- * message id (e.g. `t("Save")`), and Lingui compiles the id verbatim when a
1343
- * catalog has no entry for it. So English needs no translations — this stays
1344
- * empty and the source strings render as-is. The known ids live in
1345
- * {@link MESSAGE_IDS}, which types the `t` function.
1346
- */
1347
- /** The locale the studio ships with and falls back to. */
1348
- declare const DEFAULT_LOCALE = "en";
1562
+ * Call `onTick` on a timer while `enabled`, for panels whose backend has no live
1563
+ * subscription channel (the scheduler, R2, D1, the SessionDO — all HTTP-only).
1564
+ * Polling is the honest "live" here: a timer-driven scheduler has no
1565
+ * client-observable write event to push on, so the UI watches jobs count down
1566
+ * and disappear by re-asking.
1567
+ *
1568
+ * Each tick is scheduled after the previous one settles (`setTimeout` chaining,
1569
+ * not `setInterval`), so a slow request never overlaps the next. When `onTick`
1570
+ * returns a promise that rejects (or throws), the delay doubles up to
1571
+ * {@link MAX_BACKOFF_MS} and resets to `intervalMs` on the next success; an
1572
+ * `UNAUTHORIZED` / `FORBIDDEN` rejection stops polling until `enabled` toggles,
1573
+ * since re-asking cannot fix a missing credential. A sync `onTick` counts as a
1574
+ * success, so `onTick` must return the promise of the request it starts: one that
1575
+ * returns void is timed as if it had already finished.
1576
+ *
1577
+ * Ticks are skipped while the tab is hidden (`document.hidden`) so a backgrounded
1578
+ * studio doesn't keep hammering the worker. `onTick` is held in a ref so a
1579
+ * fresh closure each render doesn't reset the timer. The timer restarts when
1580
+ * `enabled`/`intervalMs` change or the Lunora client is replaced (new credentials),
1581
+ * so a panel stopped by a terminal error resumes once its client changes. The
1582
+ * timer is cleared on disable and unmount.
1583
+ */
1584
+ declare const useAutoRefresh: (onTick: () => unknown, enabled: boolean, intervalMs?: number) => void;
1349
1585
  /**
1350
- * Locale code to catalog. Each catalog maps an English source string (which
1351
- * doubles as the message id) to its translation. English ships empty: Lingui
1352
- * compiles the id verbatim when a translation is missing, so the source strings
1353
- * render as-is. To add a language, register `{ "Some English text": "…" }`.
1354
- */
1355
- type StudioCatalogs = Readonly<Record<string, Messages>>;
1356
- /**
1357
- * Translate function: `t("Clear")` or `t("{title} failed", { title })`.
1358
- *
1359
- * `id` is constrained to a known {@link MessageId}, so a typo is a compile error.
1360
- * The interpolation `values` stay loosely typed: mapping each id to its exact
1361
- * placeholder set isn't worth the machinery for the handful of interpolated
1362
- * strings, so a wrong or missing value key isn't caught at this boundary.
1363
- */
1364
- type TFunction = (id: MessageId, values?: Record<string, unknown>) => string;
1365
- /**
1366
- * Build a studio-scoped Lingui instance. We deliberately use `@lingui/core`'s
1367
- * `setupI18n` (a fresh instance) rather than the global singleton so the
1368
- * studio can never clobber — or be clobbered by — a host app that also uses
1369
- * Lingui.
1370
- *
1371
- * The message compiler is installed explicitly. `@lingui/core` only auto-installs
1372
- * it when `NODE_ENV !== "production"`, but the studio ships as a library and
1373
- * relies on the compiler at runtime to interpolate uncompiled source strings
1374
- * (e.g. `t("{title} failed", { title })`). Without this, a consumer's production
1375
- * build would render `{title}` literally and `console.warn` on every `t(...)`.
1376
- *
1377
- * Pass extra `catalogs` to ship more locales; unknown `locale` codes fall back
1378
- * to `DEFAULT_LOCALE`.
1379
- */
1380
- declare const createStudioI18n: (locale?: string, catalogs?: StudioCatalogs) => I18n;
1381
- /**
1382
- * Shared default instance. Backs the i18n context's default value so the
1383
- * composable studio and individual exported panels resolve their strings even
1384
- * when rendered without `StudioI18nProvider` (e.g. in tests, or a host's own
1385
- * admin UI). English-only, so it renders source strings as-is.
1386
- */
1387
- declare const studioI18n: I18n;
1388
- /**
1389
- * Hook returning a `t` bound to the nearest `StudioI18nProvider` (or the
1390
- * shared instance when there's none). This is the runtime stand-in for Lingui's
1391
- * `t` macro — the studio builds with esbuild and tests under Vite 8/Rolldown,
1392
- * neither of which runs Lingui's Babel macro transform, so call sites pass the
1393
- * English string as the id directly.
1394
- */
1395
- declare const useT: () => TFunction;
1586
+ * Debounced mirror of `value`: returns the latest value only after it has been
1587
+ * stable for `delayMs`. Used so a per-keystroke search box drives at most one
1588
+ * server round-trip per pause, instead of one request per character.
1589
+ *
1590
+ * `resetKey` is an optional escape hatch from the trailing delay: when it
1591
+ * changes relative to the PREVIOUS call, the mirror snaps to `value`
1592
+ * immediately — no `delayMs` window at all. It exists for callers that key a
1593
+ * debounced input (a search box, a shard key) to a coarser identity (e.g. the
1594
+ * open table): on that identity's change the caller usually re-seeds `value`
1595
+ * itself in the same render, and without `resetKey` the debounced mirror would
1596
+ * still trail the OLD value behind its own timer for up to `delayMs`, ignoring
1597
+ * the reseed. The snap happens render-time (the "adjusting state when a prop
1598
+ * changes" pattern): calling the setters below makes React discard this render
1599
+ * and retry synchronously with the caught-up state, so the returned value is
1600
+ * already correct on the render that reads it — no extra commit, no trailing
1601
+ * window. Omit `resetKey` (the default) to keep the original always-debounced
1602
+ * behavior; every other caller in the codebase does this.
1603
+ */
1604
+ declare const useDebounced: <T>(value: T, delayMs?: number, resetKey?: unknown) => T;
1396
1605
  interface StudioI18nProviderProps {
1397
1606
  /** Catalogs to register in addition to the built-in English one. */
1398
1607
  readonly catalogs?: StudioCatalogs;
@@ -1403,15 +1612,10 @@ interface StudioI18nProviderProps {
1403
1612
  readonly locale?: string;
1404
1613
  }
1405
1614
  /**
1406
- * Provides a studio-scoped Lingui instance to `useT`. Nesting is safe:
1407
- * providers sharing the same instance resolve to the same context value.
1408
- */
1409
- declare const StudioI18nProvider: ({
1410
- catalogs,
1411
- children,
1412
- i18n,
1413
- locale
1414
- }: StudioI18nProviderProps) => ReactElement;
1615
+ * Provides a studio-scoped Lingui instance to `useT`. Nesting is safe:
1616
+ * providers sharing the same instance resolve to the same context value.
1617
+ */
1618
+ declare const StudioI18nProvider: ({ catalogs, children, i18n, locale }: StudioI18nProviderProps) => ReactElement;
1415
1619
  /** Root class the batteries-included app sets so the studio styles stay scoped. */
1416
1620
  declare const STUDIO_ROOT_CLASS = "lunora-studio-root";
1417
- export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, type AggregateMetrics, ApiDocsPanel, type ApiDocsPanelProps, ApiReferencePanel, type ApiReferencePanelProps, ApiTab, type ApiTabProps, type AuditEntry, type AuditLogResult, AuditPanel, type AuditPanelProps, type CacheStats, type CapturedMailResult, type CommandItem, CommandPalette, type CommandPaletteProps, ConfirmButton, type ConfirmButtonProps, ConnectionBadge, DEFAULT_AUTO_REFRESH_MS, DEFAULT_INSIGHT_THRESHOLDS, DEFAULT_LOCALE, DataBrowser, type DataBrowserProps, DataFilters, type DeployInfo, type EditableFilter, ErrorBoundary, type ErrorBoundaryProps, ExportImportPanel, type ExportImportPanelProps, type ExportRow, FileBrowser, type FileBrowserProps, type FilterClause, type FilterOperator, type FunctionCallStat, type FunctionDescriptor, FunctionRunner, type FunctionRunnerProps, FunctionStatsPanel, type FunctionStatsPanelProps, type FunctionStatsResult, GlobalDataBrowser, type GlobalDataBrowserProps, HealthPanel, type HealthPanelProps, HomePanel, type HomePanelProps, type ImportError, type ImportShardResult, type Insight, type InsightKind, type InsightSeverity, type InsightThresholds, InsightsPanel, type InsightsPanelProps, type LogEntry, type LogLevel, LogsPanel, type LogsPanelProps, type LogsResult, MailPanel, type MailPanelProps, type MessageId, MetricsPanel, type MetricsPanelProps, type MigrationDirection, type MigrationRunResult, type MigrationStatus, type MigrationStatusRow, MigrationsPanel, type MigrationsPanelProps, OpenRpcReferencePanel, type OpenRpcReferencePanelProps, PitrPanel, type PitrPanelProps, type RunMigrationArgs, STUDIO_ROOT_CLASS, SchemaViewer, type SchemaViewerProps, SecurityAdvisorPanel, type SecurityAuditResult, type SecurityFinding, type SecurityFindingKind, type SecurityFindingLevel, type SettingEntry, type SettingKind, SettingsPanel, type SettingsPanelProps, type SettingsResult, ShardInput, type ShardInputProps, type ShardMetrics, type ShardMetricsResult, SqlEditorPanel, type SqlEditorPanelProps, type StudioCatalogs, StudioI18nProvider, type StudioI18nProviderProps, type TFunction, TableEditor, type TableEditorProps, type TableIndexInfo, type TableIndexesResult, type TableInfo, type TablePage, type WriteRowArgs, type WriteRowOp, type WriteRowResult, aggregateMetrics, createStudioI18n, deriveInsights, openCommandPalette, shardsToAggregate, studioI18n, toFilterClauses, useAutoRefresh, useDebounced, useT };
1621
+ export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, AdvisorHealthPanel, type AggregateMetrics, ApiDocsPanel, type ApiDocsPanelProps, ApiReferencePanel, type ApiReferencePanelProps, ApiTab, type ApiTabProps, type AuditEntry, type AuditLogResult, AuditPanel, type AuditPanelProps, type CacheStats, type CapturedMailResult, type CommandItem, CommandPalette, type CommandPaletteProps, ConfirmButton, type ConfirmButtonProps, ConnectionBadge, DEFAULT_AUTO_REFRESH_MS, DEFAULT_INSIGHT_THRESHOLDS, DEFAULT_LOCALE, DataBrowser, type DataBrowserProps, DataFilters, type DeployInfo, DeploymentHealthPanel, type DeploymentHealthPanelProps, type DeploymentHealthProbe, type EditableFilter, ErrorBoundary, type ErrorBoundaryProps, ExportImportPanel, type ExportImportPanelProps, type ExportRow, FileBrowser, type FileBrowserProps, type FilterClause, type FilterOperator, type FunctionCallStat, type FunctionDescriptor, FunctionRunner, type FunctionRunnerProps, FunctionStatsPanel, type FunctionStatsPanelProps, type FunctionStatsResult, GlobalDataBrowser, type GlobalDataBrowserProps, HealthPanel, type HealthPanelProps, HomePanel, type HomePanelProps, type ImportError, type ImportShardResult, type Insight, type InsightKind, type InsightSeverity, type InsightThresholds, InsightsPanel, type InsightsPanelProps, type LogEntry, type LogLevel, LogsPanel, type LogsPanelProps, type LogsResult, MailPanel, type MailPanelProps, type MessageId, MetricsPanel, type MetricsPanelProps, type MigrationDirection, type MigrationRunResult, type MigrationStatus, type MigrationStatusRow, MigrationsPanel, type MigrationsPanelProps, NotificationsPanel, OpenRpcReferencePanel, type OpenRpcReferencePanelProps, PitrPanel, type PitrPanelProps, type ProbeSnapshot, type RunMigrationArgs, STUDIO_ROOT_CLASS, SchemaViewer, type SchemaViewerProps, SecurityAdvisorPanel, type SecurityAuditResult, type SecurityFinding, type SecurityFindingKind, type SecurityFindingLevel, type SettingEntry, type SettingKind, SettingsPanel, type SettingsPanelProps, type SettingsResult, ShardInput, type ShardInputProps, type ShardMetrics, type ShardMetricsResult, SqlEditorPanel, type SqlEditorPanelProps, type StudioCatalogs, StudioI18nProvider, type StudioI18nProviderProps, type StudioTab, type TFunction, TableEditor, type TableEditorProps, type TableIndexInfo, type TableIndexesResult, type TableInfo, type TablePage, type WriteRowArgs, type WriteRowOp, type WriteRowResult, aggregateMetrics, createStudioI18n, deriveInsights, openCommandPalette, shardsToAggregate, studioI18n, toFilterClauses, useAutoRefresh, useDebounced, useT };