@xano/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/CHANGELOG.md +788 -0
  2. package/LICENSE +21 -0
  3. package/README.md +541 -0
  4. package/dist/.build-fingerprint +1 -0
  5. package/dist/agent-file-refresh-ZEMK33AX.js +38 -0
  6. package/dist/answer-shape-K67TAAPY.js +33 -0
  7. package/dist/backend-dir-2U53CIAL.js +39 -0
  8. package/dist/backend-slot-7QXW2QYC.js +28 -0
  9. package/dist/bin.d.ts +1 -0
  10. package/dist/bin.js +255 -0
  11. package/dist/branch-NCRNWQBQ.js +61 -0
  12. package/dist/branch-commands-ACIRCEQJ.js +79 -0
  13. package/dist/bundle.d.ts +223 -0
  14. package/dist/bundle.js +153 -0
  15. package/dist/capture-WAXPD7DR.js +41 -0
  16. package/dist/chunk-27GWNP2I.js +23 -0
  17. package/dist/chunk-2CMJZDCL.js +177 -0
  18. package/dist/chunk-2EZ3ZJZZ.js +302 -0
  19. package/dist/chunk-2GNFDZA2.js +390 -0
  20. package/dist/chunk-2MNLRIOX.js +11 -0
  21. package/dist/chunk-2TFRR6JV.js +104 -0
  22. package/dist/chunk-2ZUEE4EK.js +408 -0
  23. package/dist/chunk-36JUQZVQ.js +22 -0
  24. package/dist/chunk-3DRXWLJ5.js +83 -0
  25. package/dist/chunk-3JDU4VRL.js +137 -0
  26. package/dist/chunk-3KZCLN4Z.js +241 -0
  27. package/dist/chunk-3LDULPRE.js +168 -0
  28. package/dist/chunk-3M4LFYNQ.js +111 -0
  29. package/dist/chunk-3XI5CTUE.js +22 -0
  30. package/dist/chunk-3YW23UFH.js +50 -0
  31. package/dist/chunk-45UIT5T2.js +862 -0
  32. package/dist/chunk-4BW2SG2N.js +46 -0
  33. package/dist/chunk-4KHEMC32.js +79 -0
  34. package/dist/chunk-4POWHT2K.js +321 -0
  35. package/dist/chunk-4Q2GN7NW.js +192 -0
  36. package/dist/chunk-5A2PLKZB.js +70 -0
  37. package/dist/chunk-5FBYXK5P.js +159 -0
  38. package/dist/chunk-5HVXPTU4.js +323 -0
  39. package/dist/chunk-5QU2P5CA.js +304 -0
  40. package/dist/chunk-5V5XU32D.js +191 -0
  41. package/dist/chunk-5ZSO4T2G.js +10 -0
  42. package/dist/chunk-622HUCZT.js +10 -0
  43. package/dist/chunk-65HWOMGV.js +177 -0
  44. package/dist/chunk-6ELFRN3P.js +365 -0
  45. package/dist/chunk-6HO3NCSJ.js +1055 -0
  46. package/dist/chunk-6IUMKYWI.js +457 -0
  47. package/dist/chunk-6KEB3C3U.js +65 -0
  48. package/dist/chunk-6MR5TI5V.js +987 -0
  49. package/dist/chunk-6NNTNXN7.js +157 -0
  50. package/dist/chunk-6PBR37LN.js +97 -0
  51. package/dist/chunk-6QXLMMT3.js +155 -0
  52. package/dist/chunk-6ZGJCBZS.js +224 -0
  53. package/dist/chunk-73IVBKMA.js +250 -0
  54. package/dist/chunk-7G3CTU7I.js +286 -0
  55. package/dist/chunk-A3UDOZB6.js +222 -0
  56. package/dist/chunk-A6E77GDW.js +85 -0
  57. package/dist/chunk-AHJWCYQO.js +660 -0
  58. package/dist/chunk-AKNCFVKZ.js +36 -0
  59. package/dist/chunk-AM4FKL4J.js +237 -0
  60. package/dist/chunk-AN6BL47T.js +26 -0
  61. package/dist/chunk-AOSYVMUS.js +147 -0
  62. package/dist/chunk-APWXY5SL.js +182 -0
  63. package/dist/chunk-AWEIIR2U.js +218 -0
  64. package/dist/chunk-AWQ7BQTQ.js +73 -0
  65. package/dist/chunk-BAUZOWGX.js +393 -0
  66. package/dist/chunk-BHACRS6R.js +940 -0
  67. package/dist/chunk-BWPNT55T.js +680 -0
  68. package/dist/chunk-C6RIMRU4.js +187 -0
  69. package/dist/chunk-CGVQZXYG.js +263 -0
  70. package/dist/chunk-CIMQZRRE.js +162 -0
  71. package/dist/chunk-CJHQKJU4.js +113 -0
  72. package/dist/chunk-CTMO46PK.js +1897 -0
  73. package/dist/chunk-D53J55C5.js +106 -0
  74. package/dist/chunk-D7VGG3WS.js +90 -0
  75. package/dist/chunk-DAD3ONIS.js +245 -0
  76. package/dist/chunk-DGWHAVRG.js +162 -0
  77. package/dist/chunk-DX4QR4B2.js +483 -0
  78. package/dist/chunk-EHP3WPEG.js +21 -0
  79. package/dist/chunk-ELP2HMXC.js +432 -0
  80. package/dist/chunk-ERVIASGL.js +21 -0
  81. package/dist/chunk-ET4Y4XCB.js +865 -0
  82. package/dist/chunk-ETO6LGLD.js +4750 -0
  83. package/dist/chunk-EUUUMY7J.js +24 -0
  84. package/dist/chunk-FQJ2TTHP.js +218 -0
  85. package/dist/chunk-FQOF7E2E.js +133 -0
  86. package/dist/chunk-FWD7AL6N.js +21 -0
  87. package/dist/chunk-FXFV3KU6.js +138 -0
  88. package/dist/chunk-FXRQOWTE.js +171 -0
  89. package/dist/chunk-G554NZNI.js +210 -0
  90. package/dist/chunk-GSGDWJB5.js +13 -0
  91. package/dist/chunk-H2V3N23D.js +66 -0
  92. package/dist/chunk-H5C7MBCR.js +159 -0
  93. package/dist/chunk-HHN734BU.js +371 -0
  94. package/dist/chunk-HRVBLCVJ.js +243 -0
  95. package/dist/chunk-HVRUQXGD.js +1264 -0
  96. package/dist/chunk-I4F5TCJH.js +130 -0
  97. package/dist/chunk-IDOTCMDV.js +57 -0
  98. package/dist/chunk-IGOLHKWF.js +427 -0
  99. package/dist/chunk-JGE7CAWB.js +148 -0
  100. package/dist/chunk-JTUKLCXS.js +92 -0
  101. package/dist/chunk-JZGVVJSI.js +66 -0
  102. package/dist/chunk-K4WX6UUU.js +923 -0
  103. package/dist/chunk-K5BBGTYZ.js +217 -0
  104. package/dist/chunk-K6RXBGUB.js +427 -0
  105. package/dist/chunk-KTSDSD36.js +165 -0
  106. package/dist/chunk-L5JYN3NM.js +1038 -0
  107. package/dist/chunk-LIEOKXKD.js +354 -0
  108. package/dist/chunk-LLNZGEFK.js +51 -0
  109. package/dist/chunk-LPECSJ2J.js +55 -0
  110. package/dist/chunk-LQCMKAJ7.js +413 -0
  111. package/dist/chunk-LRN4ZJCQ.js +1145 -0
  112. package/dist/chunk-MJ4ZVHKN.js +17 -0
  113. package/dist/chunk-MXHSQOC4.js +3061 -0
  114. package/dist/chunk-N5GKCWE5.js +367 -0
  115. package/dist/chunk-NA3PXMEF.js +10 -0
  116. package/dist/chunk-NAQDMEHV.js +76 -0
  117. package/dist/chunk-NWKXM5RD.js +109 -0
  118. package/dist/chunk-NZOWWHU5.js +196 -0
  119. package/dist/chunk-OHX6MIUZ.js +184 -0
  120. package/dist/chunk-OOXWYAA4.js +15 -0
  121. package/dist/chunk-OPHB5ORL.js +1990 -0
  122. package/dist/chunk-OXA6PSZT.js +1725 -0
  123. package/dist/chunk-P2HAGF6H.js +73 -0
  124. package/dist/chunk-PTHVMXZI.js +3036 -0
  125. package/dist/chunk-PZ5AY32C.js +10 -0
  126. package/dist/chunk-Q325JKYB.js +189 -0
  127. package/dist/chunk-Q7DGTQ5G.js +255 -0
  128. package/dist/chunk-QCNYHBL7.js +601 -0
  129. package/dist/chunk-QO6BVGS5.js +145 -0
  130. package/dist/chunk-QXTKSOFI.js +76 -0
  131. package/dist/chunk-ROY4YAEQ.js +66 -0
  132. package/dist/chunk-RTJRZFFY.js +447 -0
  133. package/dist/chunk-SAVJUS2X.js +128 -0
  134. package/dist/chunk-SFLHVCKX.js +173 -0
  135. package/dist/chunk-STSFNCY4.js +127 -0
  136. package/dist/chunk-SWBF2LTK.js +170 -0
  137. package/dist/chunk-T5KELPAR.js +109 -0
  138. package/dist/chunk-TFFGOFVZ.js +1481 -0
  139. package/dist/chunk-TLHIFK4M.js +256 -0
  140. package/dist/chunk-TLQE7ZN3.js +156 -0
  141. package/dist/chunk-TPHWJ7UG.js +1981 -0
  142. package/dist/chunk-TRJCALW3.js +291 -0
  143. package/dist/chunk-TTEIYD5P.js +133 -0
  144. package/dist/chunk-U64O2MXY.js +407 -0
  145. package/dist/chunk-UCQ2VUTG.js +630 -0
  146. package/dist/chunk-UTI5G6OJ.js +44 -0
  147. package/dist/chunk-UVHDMMIP.js +188 -0
  148. package/dist/chunk-UZ6QQWJT.js +120 -0
  149. package/dist/chunk-VAX3UZOY.js +686 -0
  150. package/dist/chunk-W3HBUKFO.js +57 -0
  151. package/dist/chunk-WKQLGKCL.js +2823 -0
  152. package/dist/chunk-WQFNASK4.js +560 -0
  153. package/dist/chunk-WRBKLYSJ.js +224 -0
  154. package/dist/chunk-WTPZRR4I.js +17 -0
  155. package/dist/chunk-WZDJ2LLX.js +2385 -0
  156. package/dist/chunk-X2NL4KUO.js +14 -0
  157. package/dist/chunk-X4DVXBFY.js +38 -0
  158. package/dist/chunk-X677DMZM.js +7050 -0
  159. package/dist/chunk-XBKMWY7F.js +612 -0
  160. package/dist/chunk-XNCP4KYO.js +78 -0
  161. package/dist/chunk-XVBGLISP.js +35 -0
  162. package/dist/chunk-XW6KISBB.js +1192 -0
  163. package/dist/chunk-YGZHHAAB.js +8156 -0
  164. package/dist/chunk-YHEFQUQB.js +186 -0
  165. package/dist/chunk-YLDALTWZ.js +653 -0
  166. package/dist/chunk-YU4HSQW7.js +229 -0
  167. package/dist/chunk-ZDPP6RKB.js +27 -0
  168. package/dist/chunk-ZFDZKNGG.js +194 -0
  169. package/dist/chunk-ZIY7RNUT.js +49 -0
  170. package/dist/chunk-ZYJP6BOO.js +30 -0
  171. package/dist/cli.d.ts +1111 -0
  172. package/dist/cli.js +165 -0
  173. package/dist/codegen-command-VR2GWR6C.js +173 -0
  174. package/dist/codegen.d.ts +115 -0
  175. package/dist/codegen.js +19 -0
  176. package/dist/commands-GJMJ4XYZ.js +76 -0
  177. package/dist/completion-ZQLO6PB6.js +738 -0
  178. package/dist/config-MBYGCAFK.js +136 -0
  179. package/dist/deploy-command-JVZPWHMK.js +180 -0
  180. package/dist/deploy-source-3W45CXMP.js +81 -0
  181. package/dist/dev-env-sync-HN44K4D5.js +188 -0
  182. package/dist/diagnostics-UEAAHWVF.js +30 -0
  183. package/dist/display-name-hint-ABBPVQIR.js +46 -0
  184. package/dist/emit-CyhBDxli.d.ts +7007 -0
  185. package/dist/env-example-refresh-ET5HMMDW.js +126 -0
  186. package/dist/env-pull-command-TNMNB3CV.js +323 -0
  187. package/dist/env-target-O4HRKTGZ.js +40 -0
  188. package/dist/env-var-command-ZIRDCAZA.js +427 -0
  189. package/dist/ephemeral-P7F3PMAD.js +54 -0
  190. package/dist/ephemeral-command-CLJJKOFT.js +592 -0
  191. package/dist/ephemeral-state-PYCBSOGX.js +61 -0
  192. package/dist/file-lock-PT74GWYW.js +10 -0
  193. package/dist/generate-command-AYEOLA26.js +510 -0
  194. package/dist/gitignore-3SJ3WNRG.js +51 -0
  195. package/dist/guards-4EBNCZDC.js +162 -0
  196. package/dist/hosted-file-PSHJB3HX.js +28 -0
  197. package/dist/impersonate-command-5JAS3WSV.js +152 -0
  198. package/dist/import-EQSFU6JC.js +19 -0
  199. package/dist/index.d.ts +5470 -0
  200. package/dist/index.js +371 -0
  201. package/dist/init-command-X2FR4UAK.js +125 -0
  202. package/dist/init-modules-RY7UHAOL.js +50 -0
  203. package/dist/init-web-M4YZSZK6.js +42 -0
  204. package/dist/internal.d.ts +179 -0
  205. package/dist/internal.js +2634 -0
  206. package/dist/io-RC56QSN5.js +26 -0
  207. package/dist/keep-data-merge-7MPLVAVI.js +1119 -0
  208. package/dist/lambda-config-reconcile-OUZ4OYAB.js +116 -0
  209. package/dist/landed-753YLJ5H.js +40 -0
  210. package/dist/landing-record-SU52SKXU.js +61 -0
  211. package/dist/live-diff-YONW2VI3.js +65 -0
  212. package/dist/local-engine-choice-CH5X3W7E.js +79 -0
  213. package/dist/local-engine-command-Z3OL7VOD.js +766 -0
  214. package/dist/local-engine-config-5U3SC434.js +39 -0
  215. package/dist/local-engine-deploy-PCQ4SNPB.js +39 -0
  216. package/dist/local-engine-process-EHTE5LLU.js +63 -0
  217. package/dist/local-engine-state-A4FTRFAF.js +32 -0
  218. package/dist/local-engine-update-check-6L645VBL.js +162 -0
  219. package/dist/lock-MRRHW5GS.js +87 -0
  220. package/dist/lock-commands-2QG25HL7.js +963 -0
  221. package/dist/login-command-QPYRWOXZ.js +538 -0
  222. package/dist/logout-command-WOIQLDP6.js +56 -0
  223. package/dist/loop-ALIZLOSX.js +191 -0
  224. package/dist/marketplace-command-K5YL42NO.js +977 -0
  225. package/dist/marketplace-resolve-LY32JES5.js +40 -0
  226. package/dist/meta-client-YXGPW53C.js +244 -0
  227. package/dist/module-manifest-JFGHU2TC.js +38 -0
  228. package/dist/near-key.d.ts +13 -0
  229. package/dist/near-key.js +8 -0
  230. package/dist/node.d.ts +95 -0
  231. package/dist/node.js +969 -0
  232. package/dist/operation-outcome-TZSESNC7.js +51 -0
  233. package/dist/output-target-AL3I44GG.js +47 -0
  234. package/dist/package-manager-PRAHUSCN.js +34 -0
  235. package/dist/plan-disclosure-6G4MLZKD.js +114 -0
  236. package/dist/plugin-contributions-WRNY5ABG.js +28 -0
  237. package/dist/plugin-prompt-4VA3B4FF.js +20 -0
  238. package/dist/plugin-questions-JTSYA74Q.js +24 -0
  239. package/dist/plugin.d.ts +396 -0
  240. package/dist/plugin.js +1 -0
  241. package/dist/preflight-command-2T5Z36MI.js +321 -0
  242. package/dist/profile-command-AH3PIM4X.js +800 -0
  243. package/dist/profile-pointer-GRWJU3YD.js +31 -0
  244. package/dist/profile-select-74TRDEPD.js +23 -0
  245. package/dist/project-dependency-KSH63ODT.js +35 -0
  246. package/dist/project-sdk-REPPOIBD.js +24 -0
  247. package/dist/promote-command-PCWT5N6S.js +140 -0
  248. package/dist/prompt-II3F3LND.js +27 -0
  249. package/dist/publish-command-TTDUUJI5.js +414 -0
  250. package/dist/pull-command-VBO7C4S3.js +161 -0
  251. package/dist/pull-superseded-GJWLG7XO.js +20 -0
  252. package/dist/release-command-N4ZPKMHR.js +146 -0
  253. package/dist/release-ns-command-3KFDMZ6G.js +1745 -0
  254. package/dist/response-HlXahv4K.d.ts +925 -0
  255. package/dist/retry-command-AS5EVREX.js +34 -0
  256. package/dist/routes-manifest-SNWUVBT6.js +43 -0
  257. package/dist/runtime-XETHVF33.js +14 -0
  258. package/dist/scaffold.d.ts +1911 -0
  259. package/dist/scaffold.js +107 -0
  260. package/dist/secrets-file-LVZD6IIM.js +56 -0
  261. package/dist/secrets-fill-command-TTCPSVXN.js +218 -0
  262. package/dist/seed-VU7C3QYS.js +46 -0
  263. package/dist/sent-writes-N7X4OVXT.js +22 -0
  264. package/dist/source-resolve-S2XA3XZF.js +83 -0
  265. package/dist/static-host-B2Y6AG3W.js +352 -0
  266. package/dist/status-command-RUDXTF7I.js +554 -0
  267. package/dist/store-6VNCD4D7.js +20 -0
  268. package/dist/store-ARM6VMO5.js +98 -0
  269. package/dist/store-DuYfzKlW.d.ts +3144 -0
  270. package/dist/suggest-6FOOYKHG.js +12 -0
  271. package/dist/sveltekit.d.ts +154 -0
  272. package/dist/sveltekit.js +109 -0
  273. package/dist/sync-contributions-UCEROO26.js +415 -0
  274. package/dist/table-ENAVMITR.js +42 -0
  275. package/dist/tables-command-GUPXXSB5.js +156 -0
  276. package/dist/tenant-IIHPOHGP.js +42 -0
  277. package/dist/tenant-command-D5HGI2X4.js +965 -0
  278. package/dist/test-command-TIKZMDPZ.js +476 -0
  279. package/dist/tests-BGGIOK3L.js +26 -0
  280. package/dist/token-NICJUTMT.js +72 -0
  281. package/dist/toolchain-hooks-GHKLUJOH.js +96 -0
  282. package/dist/toolchain-modules-5EAZUONB.js +24 -0
  283. package/dist/tracked-backend-EIBUMDZA.js +80 -0
  284. package/dist/update-check-2W2NLDTC.js +136 -0
  285. package/dist/upgrade-command-QHNFWM7O.js +531 -0
  286. package/dist/verify-rollout-DRCK5TDD.js +61 -0
  287. package/dist/whoami-command-STGINTXH.js +51 -0
  288. package/dist/workspace-2CLHU2LK.js +93 -0
  289. package/dist/workspace-binding-56PIIPCP.js +54 -0
  290. package/dist/workspace-command-JEXQETJD.js +535 -0
  291. package/dist/workspace-env-F2RFMSC5.js +70 -0
  292. package/dist/workspace-export-OJSH2HIW.js +21 -0
  293. package/dist/writable-VA7OISSK.js +25 -0
  294. package/dist/xano-ICFUSPFR.js +42 -0
  295. package/dist/xanosdk-import-GN42TO2B.js +56 -0
  296. package/dist/xanosdk-project-S6DXJONQ.js +41 -0
  297. package/dist/xdo-CxDr2Q1C.d.ts +1371 -0
  298. package/guides/README.md +33 -0
  299. package/guides/authoring.md +921 -0
  300. package/guides/cli.md +401 -0
  301. package/guides/codegen.md +177 -0
  302. package/guides/codes.md +404 -0
  303. package/guides/coverage.md +74 -0
  304. package/guides/deploying.md +1525 -0
  305. package/guides/environment.md +400 -0
  306. package/guides/marketplace.md +415 -0
  307. package/guides/module-contract.md +558 -0
  308. package/guides/object-kinds.md +433 -0
  309. package/guides/project-structure.md +43 -0
  310. package/guides/scaffold.md +351 -0
  311. package/guides/typed-frontend.md +242 -0
  312. package/llms/client.md +63 -0
  313. package/llms/errors.md +56 -0
  314. package/llms/fields.md +176 -0
  315. package/llms/filters.md +183 -0
  316. package/llms/kinds-agent-mcp.md +30 -0
  317. package/llms/kinds-core.md +100 -0
  318. package/llms/kinds-knowledge.md +20 -0
  319. package/llms/kinds-realtime.md +76 -0
  320. package/llms/lambda.md +94 -0
  321. package/llms/legacy.md +44 -0
  322. package/llms/lock.md +40 -0
  323. package/llms/object-kinds.md +34 -0
  324. package/llms/statements-calls.md +62 -0
  325. package/llms/statements-catalog.md +320 -0
  326. package/llms/statements-data.md +66 -0
  327. package/llms/statements-runtime.md +68 -0
  328. package/llms/tests.md +59 -0
  329. package/llms/toolchain.md +16 -0
  330. package/llms/triggers.md +36 -0
  331. package/llms/values.md +29 -0
  332. package/llms-full.txt +2085 -0
  333. package/llms.txt +493 -0
  334. package/manifest.json +11224 -0
  335. package/package.json +162 -0
  336. package/types/lambda-globals.d.ts +129 -0
@@ -0,0 +1,1897 @@
1
+ import {
2
+ resolveAuthRef
3
+ } from "./chunk-ZDPP6RKB.js";
4
+ import {
5
+ obj
6
+ } from "./chunk-K5BBGTYZ.js";
7
+ import {
8
+ buildBundle
9
+ } from "./chunk-LQCMKAJ7.js";
10
+ import {
11
+ checkAddonAttachments,
12
+ checkAddonOutput,
13
+ checkAgentApiKeys,
14
+ checkAgentArgPlaceholders,
15
+ checkApiGroupDocsExposure,
16
+ checkAssertionsOutsideTests,
17
+ checkAuthNoCaller,
18
+ checkCacheTtl,
19
+ checkDecodeOnlyStatements,
20
+ checkDocumentationTokens,
21
+ checkExpressionOperands,
22
+ checkGuardRoleColumns,
23
+ checkIntRange,
24
+ checkInterpolatedValues,
25
+ checkKnowledge,
26
+ checkLiveDatasourceTests,
27
+ checkLoopControl,
28
+ checkMcpResourceUris,
29
+ checkMcpStackHazards,
30
+ checkMicroserviceBlocks,
31
+ checkMicroserviceReferences,
32
+ checkMicroserviceSecrets,
33
+ checkNonJsonValues,
34
+ checkNonNullVectorColumns,
35
+ checkNullMatchArgs,
36
+ checkOmittedCallInputs,
37
+ checkPasswordInputHashing,
38
+ checkPathSegmentCandidates,
39
+ checkPrimitiveAuthIdentity,
40
+ checkRatelimitWithoutError,
41
+ checkRealtimeDeliver,
42
+ checkRealtimeGates,
43
+ checkRealtimeJoinDeliver,
44
+ checkRealtimePublish,
45
+ checkRealtimeSilentShapes,
46
+ checkReferences,
47
+ checkRegexOperandOrder,
48
+ checkReservedColumnNames,
49
+ checkReservedInputNames,
50
+ checkRouteShadowing,
51
+ checkRunFamilyHosts,
52
+ checkSafeRefMatchArgs,
53
+ checkSameNameSiblings,
54
+ checkSearchOperandFilters,
55
+ checkSeed,
56
+ checkStackAuthRatelimit,
57
+ checkStacks,
58
+ checkSwitchFallthrough,
59
+ checkTimezoneArgs,
60
+ checkToThrowScope,
61
+ checkToolAuthIdentity,
62
+ checkToolOutputSchema,
63
+ checkTriggerBindings,
64
+ checkUnboundVarRefs,
65
+ checkUnitTests,
66
+ checkUnknownCallInputs,
67
+ checkUnusableColumnNames,
68
+ checkWriteBeforeElicit,
69
+ checkZeroBasedObjects,
70
+ checkZipPasswordKeys,
71
+ postEnvelopeMisreads,
72
+ unnestedEnvelopeReads,
73
+ walkNodes
74
+ } from "./chunk-YGZHHAAB.js";
75
+ import {
76
+ WORKSPACE_HISTORY_TYPES,
77
+ assertNameAsStored,
78
+ middlewareEntryGuid,
79
+ stackReferencesAuth
80
+ } from "./chunk-5V5XU32D.js";
81
+ import {
82
+ defKindOf
83
+ } from "./chunk-ERVIASGL.js";
84
+ import {
85
+ AUTHOR_KIND_NAME,
86
+ assertDefShape,
87
+ assertMockKeysResolved,
88
+ assertNoProtoKeys,
89
+ assertTestIds,
90
+ encodeObject,
91
+ getKind
92
+ } from "./chunk-4POWHT2K.js";
93
+ import {
94
+ documentationTokenDeclarations,
95
+ resolveDocumentationTokens
96
+ } from "./chunk-3JDU4VRL.js";
97
+ import {
98
+ nearestKey
99
+ } from "./chunk-WTPZRR4I.js";
100
+ import {
101
+ DiagnosticBag,
102
+ allowableWarnings,
103
+ setDiagnosticSink
104
+ } from "./chunk-2EZ3ZJZZ.js";
105
+ import {
106
+ CANONICAL_PAYLOAD_KEYS,
107
+ LOCK_PAYLOAD_KEYS,
108
+ WORKSPACE_KEY,
109
+ identityNamesByGuid,
110
+ lockKey,
111
+ lockNameForObject,
112
+ mintCanonical,
113
+ recordObserved,
114
+ sdkKindName
115
+ } from "./chunk-6MR5TI5V.js";
116
+ import {
117
+ HOSTED_ICON_KINDS,
118
+ pendingHostedFile
119
+ } from "./chunk-XNCP4KYO.js";
120
+ import {
121
+ isTaggedValue
122
+ } from "./chunk-OXA6PSZT.js";
123
+ import {
124
+ REFERENCEABLE_KINDS,
125
+ deriveGuid,
126
+ refSpelling,
127
+ resolveRef
128
+ } from "./chunk-NZOWWHU5.js";
129
+ import {
130
+ getLockedCanonical
131
+ } from "./chunk-4BW2SG2N.js";
132
+ import {
133
+ describeEntry
134
+ } from "./chunk-CIMQZRRE.js";
135
+ import {
136
+ withArticle
137
+ } from "./chunk-36JUQZVQ.js";
138
+
139
+ // src/kinds/def-keys.ts
140
+ var keys = (roster, ...extra) => [...Object.keys(roster), ...extra];
141
+ var COMMON = { __kind: 1, name: 1, guid: 1, description: 1, tags: 1 };
142
+ var STACK = { input: 1, stack: 1, response: 1, responseShape: 1, history: 1, middleware: 1 };
143
+ var TOOLSET = { ...COMMON, docs: 1, history: 1, output: 1, enabled: 1, canonical: 1, tools: 1, llm: 1, diagnostics: 1 };
144
+ var DEF_KEYS = {
145
+ query: keys(
146
+ {
147
+ ...COMMON,
148
+ ...STACK,
149
+ verb: 1,
150
+ apiGroup: 1,
151
+ apiGroupId: 1,
152
+ diagnostics: 1,
153
+ auth: 1,
154
+ docs: 1,
155
+ responseType: 1,
156
+ apiEnabled: 1,
157
+ disabled: 1,
158
+ cache: 1,
159
+ tests: 1,
160
+ example: 1
161
+ },
162
+ "getPath",
163
+ "toSearchParams"
164
+ ),
165
+ function: keys(
166
+ { ...COMMON, ...STACK, docs: 1, cache: 1, tests: 1, workspace: 1, diagnostics: 1 }
167
+ ),
168
+ task: keys(
169
+ { ...COMMON, docs: 1, middleware: 1, history: 1, stack: 1, datasource: 1, active: 1, schedule: 1, diagnostics: 1 }
170
+ ),
171
+ table: keys(
172
+ {
173
+ ...COMMON,
174
+ auth: 1,
175
+ docs: 1,
176
+ __cols: 1,
177
+ __row: 1,
178
+ __internal: 1,
179
+ install: 1,
180
+ schema: 1,
181
+ system: 1,
182
+ idType: 1,
183
+ useXdo: 1,
184
+ index: 1,
185
+ autocomplete: 1,
186
+ external: 1,
187
+ views: 1,
188
+ seed: 1,
189
+ publicSeed: 1,
190
+ diagnostics: 1
191
+ }
192
+ ),
193
+ middleware: keys(
194
+ { ...COMMON, ...STACK, docs: 1, tests: 1, resultStrategy: 1, exceptionPolicy: 1, diagnostics: 1 }
195
+ ),
196
+ addon: keys(
197
+ {
198
+ ...COMMON,
199
+ input: 1,
200
+ table: 1,
201
+ tableAlias: 1,
202
+ where: 1,
203
+ sort: 1,
204
+ context: 1,
205
+ output: 1,
206
+ cardinality: 1,
207
+ group: 1,
208
+ eval: 1,
209
+ __graft: 1,
210
+ diagnostics: 1
211
+ }
212
+ ),
213
+ agent: keys(TOOLSET, "getCanonical"),
214
+ mcp_server: keys(
215
+ { ...TOOLSET, instructions: 1, spec: 1, prompts: 1, resources: 1, oauth: 1 },
216
+ "getCanonical",
217
+ "getPath",
218
+ "getUrl"
219
+ ),
220
+ tool: keys(
221
+ {
222
+ ...COMMON,
223
+ ...STACK,
224
+ docs: 1,
225
+ enabled: 1,
226
+ instructions: 1,
227
+ toolsetId: 1,
228
+ diagnostics: 1,
229
+ title: 1,
230
+ annotations: 1,
231
+ icons: 1,
232
+ output: 1
233
+ }
234
+ ),
235
+ prompt: keys(
236
+ { ...COMMON, ...STACK, docs: 1, title: 1, icons: 1, diagnostics: 1 }
237
+ ),
238
+ resource: keys(
239
+ { ...COMMON, ...STACK, docs: 1, uri: 1, mimeType: 1, title: 1, icons: 1, annotations: 1, diagnostics: 1 }
240
+ ),
241
+ realtime_server: keys(
242
+ { ...COMMON, diagnostics: 1, middleware: 1, history: 1, enabled: 1, canonical: 1 },
243
+ "getCanonical",
244
+ "getPath",
245
+ "getUrl"
246
+ ),
247
+ channel: keys(
248
+ {
249
+ ...COMMON,
250
+ middleware: 1,
251
+ history: 1,
252
+ input: 1,
253
+ active: 1,
254
+ server: 1,
255
+ anonymousClients: 1,
256
+ presence: 1,
257
+ publish: 1,
258
+ conversation: 1,
259
+ delivery: 1,
260
+ rateLimit: 1,
261
+ diagnostics: 1
262
+ },
263
+ "getChannel"
264
+ ),
265
+ message: keys(
266
+ { ...COMMON, ...STACK, auth: 1, disabled: 1, active: 1, server: 1, channel: 1, deliverTo: 1, diagnostics: 1 }
267
+ ),
268
+ knowledge: keys({ ...COMMON, enabled: 1, type: 1, mode: 1, body: 1, refs: 1, diagnostics: 1 }),
269
+ workflow_test: keys(
270
+ { ...COMMON, docs: 1, stack: 1, datasource: 1, active: 1, diagnostics: 1 }
271
+ ),
272
+ api_group: keys(
273
+ {
274
+ ...COMMON,
275
+ docs: 1,
276
+ middleware: 1,
277
+ history: 1,
278
+ canonical: 1,
279
+ documentation: 1,
280
+ swagger: 1,
281
+ apiGroupEnabled: 1,
282
+ cors: 1,
283
+ diagnostics: 1
284
+ }
285
+ ),
286
+ microservice: keys(
287
+ {
288
+ ...COMMON,
289
+ kind: 1,
290
+ tenantDeploy: 1,
291
+ deployment: 1,
292
+ ingresses: 1,
293
+ configs: 1,
294
+ volumes: 1,
295
+ chart: 1,
296
+ registryAuth: 1,
297
+ diagnostics: 1
298
+ }
299
+ ),
300
+ trigger: keys(
301
+ {
302
+ ...COMMON,
303
+ history: 1,
304
+ stack: 1,
305
+ response: 1,
306
+ responseShape: 1,
307
+ active: 1,
308
+ objType: 1,
309
+ toolsetType: 1,
310
+ objId: 1,
311
+ hasResult: 1,
312
+ meta: 1,
313
+ diagnostics: 1
314
+ }
315
+ ),
316
+ workspace: keys(
317
+ {
318
+ __kind: 1,
319
+ name: 1,
320
+ diagnostics: 1,
321
+ description: 1,
322
+ middleware: 1,
323
+ history: 1,
324
+ canonical: 1,
325
+ use_xdo: 1,
326
+ preferences: 1,
327
+ realtime: 1,
328
+ documentation: 1,
329
+ swagger: 1,
330
+ env: 1,
331
+ settings: 1,
332
+ use_custom_names: 1,
333
+ defaults: 1,
334
+ datasources: 1,
335
+ datasource_live: 1
336
+ }
337
+ )
338
+ };
339
+ var MIDDLEWARE = keys({ pre: 1, post: 1 });
340
+ var CACHE = keys({ active: 1, ttl: 1, input: 1, auth: 1, datasource: 1, ip: 1, headers: 1, env: 1 });
341
+ var NESTED_DEF_KEYS = {
342
+ query: { cache: CACHE },
343
+ function: { cache: CACHE },
344
+ table: {
345
+ "views[]": keys({ name: 1, id: 1, alias: 1, hide: 1, q: 1, where: 1, sort: 1 })
346
+ },
347
+ task: {
348
+ "schedule[]": keys(
349
+ { startsOn: 1, freq: 1, repeatEnabled: 1, endsOn: 1, endsEnabled: 1 }
350
+ )
351
+ },
352
+ microservice: {
353
+ deployment: keys({ replicas: 1, strategy: 1, docker: 1, containers: 1 }),
354
+ "deployment.containers[]": keys(
355
+ { name: 1, image: 1, pullSecret: 1, type: 1, command: 1, args: 1, env: 1, ports: 1, resources: 1, volumes: 1 }
356
+ ),
357
+ "deployment.containers[].env[]": keys({ name: 1, value: 1, fromEnv: 1 }),
358
+ "deployment.containers[].ports[]": keys({ servicePort: 1, containerPort: 1 }),
359
+ "deployment.containers[].resources": keys({ cpu: 1, ram: 1 }),
360
+ "deployment.containers[].volumes[]": keys(
361
+ { name: 1, type: 1, persistent: 1, emptyDir: 1, config: 1 }
362
+ ),
363
+ "ingresses[]": keys({ name: 1, domain: 1, paths: 1 }),
364
+ "ingresses[].paths[]": keys({ service: 1, path: 1 }),
365
+ "configs[]": keys({ name: 1, type: 1, value: 1 }),
366
+ "volumes[]": keys({ name: 1, size: 1, class: 1 }),
367
+ chart: keys({ ref: 1, values: 1, version: 1 }),
368
+ registryAuth: keys({ type: 1, server: 1, dockerconfigjson: 1 })
369
+ },
370
+ api_group: {
371
+ cors: keys(
372
+ { mode: 1, allowOrigins: 1, allowHeaders: 1, allowCredentials: 1, maxAge: 1, allowMethods: 1 }
373
+ ),
374
+ "cors.allowMethods": keys(
375
+ { delete: 1, get: 1, head: 1, patch: 1, post: 1, put: 1 }
376
+ ),
377
+ documentation: keys({ require_token: 1, token: 1 })
378
+ },
379
+ channel: {
380
+ publish: keys({ who: 1, direct: 1 }),
381
+ conversation: keys({ enabled: 1, limit: 1, ttl: 1 }),
382
+ delivery: keys({ guarantee: 1, perRecipient: 1 }),
383
+ rateLimit: keys({ messagesPerMinute: 1 })
384
+ },
385
+ workspace: {
386
+ preferences: keys({ allow_push: 1, track_performance: 1, use_internal_docs: 1 }),
387
+ // The workspace's own middleware is per host tier, each a `{ pre, post }`.
388
+ middleware: keys({ query: 1, function: 1, task: 1, tool: 1 }),
389
+ "middleware.query": MIDDLEWARE,
390
+ "middleware.function": MIDDLEWARE,
391
+ "middleware.task": MIDDLEWARE,
392
+ "middleware.tool": MIDDLEWARE,
393
+ // WHOLESALE maps: a key nothing reads falls back to its default silently.
394
+ history: WORKSPACE_HISTORY_TYPES,
395
+ defaults: keys({ db_primary_key: 1 })
396
+ }
397
+ };
398
+ var NEAR_MISS_DEF_KEYS = {
399
+ workspace: {
400
+ realtime: ["hash", "mode", "enabled", "channels"],
401
+ documentation: ["require_token", "token", "whitelist"]
402
+ }
403
+ };
404
+ function recordsAt(def, path) {
405
+ let at = [["", def]];
406
+ for (const part of path.split(".")) {
407
+ const list = part.endsWith("[]");
408
+ const field = list ? part.slice(0, -2) : part;
409
+ at = at.flatMap(([where, v]) => {
410
+ if (typeof v !== "object" || v === null) return [];
411
+ const next = v[field];
412
+ const label = where ? `${where}.${field}` : field;
413
+ if (!list) return [[label, next]];
414
+ return Array.isArray(next) ? next.map((e, i) => [`${label}[${i}]`, e]) : [];
415
+ });
416
+ }
417
+ return at.filter(([, v]) => typeof v === "object" && v !== null && !Array.isArray(v));
418
+ }
419
+ function assertDefKeys(owner, def, known, kind) {
420
+ if (known === void 0 || typeof def !== "object" || def === null) return;
421
+ refuseUnknown(owner, def, known);
422
+ const nested = { middleware: MIDDLEWARE, ...kind ? NESTED_DEF_KEYS[kind] : {} };
423
+ for (const [path, roster] of Object.entries(nested)) {
424
+ for (const [where, record] of recordsAt(def, path)) refuseUnknown(`${owner} \`${where}\``, record, roster);
425
+ }
426
+ for (const [path, roster] of Object.entries(kind && NEAR_MISS_DEF_KEYS[kind] || {})) {
427
+ for (const [where, record] of recordsAt(def, path)) {
428
+ const typos = Object.keys(record).filter((k) => !roster.includes(k) && nearestKey(k, roster) !== void 0);
429
+ if (typos.length > 0) refuseUnknown(`${owner} \`${where}\``, Object.fromEntries(typos.map((k) => [k, 1])), roster);
430
+ }
431
+ }
432
+ }
433
+ function refuseUnknown(owner, def, known) {
434
+ for (const key of Object.keys(def)) {
435
+ if (known.includes(key)) continue;
436
+ const near = nearestKey(key, known) ?? known.find((k) => k.length > 3 && (key.startsWith(k) || k.startsWith(key)));
437
+ throw new Error(
438
+ `${owner}: unknown key "${key}"${near ? ` \u2014 did you mean "${near}"?` : "."} Nothing reads it, so it would not do what it says. Keys this def takes: ${known.filter((k) => !k.startsWith("__") && !/^get[A-Z]/.test(k) && k !== "token").join(", ")}.` + // A literal token is refused at export: it is a secret, never source.
439
+ (known.includes("token") ? " A token is not written here \u2014 it comes from `xano/.secrets.json`." : "")
440
+ );
441
+ }
442
+ }
443
+
444
+ // src/kinds/mcp-oauth.ts
445
+ var MCP_OAUTH_PRESETS = ["auth0", "clerk", "workos", "entra", "okta", "cognito", "generic"];
446
+ var MCP_OAUTH_PRESETS_WITHOUT_AUD = ["clerk"];
447
+ var MCP_OAUTH_STABLE_CLAIMS = ["sub", "oid", "email"];
448
+ var HOSTED_KEYS = ["mode", "authTable", "loginUrl"];
449
+ var EXTERNAL_KEYS = [
450
+ "mode",
451
+ "authTable",
452
+ "issuer",
453
+ "column",
454
+ "audience",
455
+ "audienceAck",
456
+ "claim",
457
+ "claimAck",
458
+ "preset",
459
+ "allowedClientIds"
460
+ ];
461
+ var REMOVED_KEYS = ["consent", "branding", "trustedClients"];
462
+ var ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
463
+ var MCP_OAUTH_ENV_REF = /^\$\{env\.([A-Za-z_][A-Za-z0-9_]*)\}$/;
464
+ function envString(owner, field, v) {
465
+ if (typeof v === "string") return v;
466
+ if (isTaggedValue(v)) {
467
+ const name = v.value;
468
+ if (v.tag === "setting" && v.filters.length === 0 && ENV_NAME.test(name)) return `\${env.${name}}`;
469
+ throw new Error(
470
+ `${owner} \`oauth.${field}\`: only \`env("NAME")\` (a workspace environment variable) is accepted here, not ${JSON.stringify({ tag: v.tag, value: name })}. Built-in settings (\`$remote_ip\` and the like) and filtered values are not resolved in this setting \u2014 pass a string or \`env("NAME")\`.`
471
+ );
472
+ }
473
+ throw new Error(`${owner} \`oauth.${field}\`: expected a string or \`env("NAME")\` (got ${v === null ? "null" : typeof v}).`);
474
+ }
475
+ function strings(owner, field, v, envAllowed) {
476
+ if (v === void 0) return [];
477
+ if (!Array.isArray(v)) throw new Error(`${owner} \`oauth.${field}\`: expected a list of strings.`);
478
+ return v.map((item, i) => {
479
+ if (envAllowed) return envString(owner, `${field}[${i}]`, item);
480
+ if (typeof item !== "string") throw new Error(`${owner} \`oauth.${field}[${i}]\`: expected a string.`);
481
+ return item;
482
+ });
483
+ }
484
+ function oneOf(owner, field, v, allowed) {
485
+ if (v === void 0) return;
486
+ if (typeof v !== "string" || !allowed.includes(v)) {
487
+ throw new Error(
488
+ `${owner} \`oauth.${field}\` must be ${allowed.map((a) => JSON.stringify(a)).join(", ")} \u2014 got ${JSON.stringify(v)}. The platform refuses any other spelling rather than reading it as a different sign-in flow.`
489
+ );
490
+ }
491
+ }
492
+ function encodeMcpOauth(owner, oauth) {
493
+ if (oauth === null || typeof oauth !== "object" || Array.isArray(oauth)) {
494
+ throw new Error(`${owner} \`oauth\`: expected { mode: "hosted" | "external", authTable, \u2026 }.`);
495
+ }
496
+ const raw = oauth;
497
+ oneOf(owner, "mode", raw.mode, ["hosted", "external"]);
498
+ if (raw.mode === void 0) throw new Error(`${owner} \`oauth.mode\` is required: "hosted" or "external".`);
499
+ for (const key of REMOVED_KEYS) {
500
+ if (key in raw) {
501
+ throw new Error(
502
+ `${owner} \`oauth.${key}\` no longer exists: the platform dropped \`consent\`, \`branding\` and \`trustedClients\`. Your \`loginUrl\` page is the consent screen \u2014 show what \`s.mcp.oauth.request\` returns (client name, logo, callback host, whether the client is verified) and pass the user's choice to \`s.mcp.oauth.complete\` as \`decision\`. Remove the key.`
503
+ );
504
+ }
505
+ }
506
+ refuseUnknown(`${owner} \`oauth\` (mode "${String(raw.mode)}")`, raw, raw.mode === "hosted" ? HOSTED_KEYS : EXTERNAL_KEYS);
507
+ const table = raw.authTable;
508
+ if (table === void 0 || table === null || table === false || table === "") {
509
+ throw new Error(
510
+ `${owner} \`oauth.authTable\` is required: the auth table (a \`table({ auth: true })\` handle or its name) whose row a sign-in resolves to.`
511
+ );
512
+ }
513
+ const authTable = resolveAuthRef("mcpServer oauth", owner, table);
514
+ const out = {
515
+ mode: raw.mode,
516
+ auth_table: authTable,
517
+ login_url: "",
518
+ issuer: "",
519
+ audience: [],
520
+ audience_ack: false,
521
+ claim: "sub",
522
+ claim_ack: false,
523
+ column: "",
524
+ preset: "",
525
+ allowed_client_ids: []
526
+ };
527
+ if (oauth.mode === "hosted") {
528
+ out.login_url = envString(owner, "loginUrl", oauth.loginUrl ?? "");
529
+ return out;
530
+ }
531
+ oneOf(owner, "preset", oauth.preset, MCP_OAUTH_PRESETS);
532
+ out.issuer = envString(owner, "issuer", oauth.issuer ?? "");
533
+ out.audience = strings(owner, "audience", oauth.audience, true);
534
+ out.audience_ack = oauth.audienceAck === true;
535
+ if (oauth.claim !== void 0 && typeof oauth.claim !== "string") throw new Error(`${owner} \`oauth.claim\`: expected a string.`);
536
+ out.claim = oauth.claim || "sub";
537
+ out.claim_ack = oauth.claimAck === true;
538
+ if (oauth.column !== void 0 && typeof oauth.column !== "string") throw new Error(`${owner} \`oauth.column\`: expected a string.`);
539
+ out.column = oauth.column ?? "";
540
+ out.preset = oauth.preset ?? "";
541
+ out.allowed_client_ids = strings(owner, "allowedClientIds", oauth.allowedClientIds, false);
542
+ return out;
543
+ }
544
+
545
+ // src/workspace/guards-mcp-oauth.ts
546
+ function checkMcpOauth(sections, bag) {
547
+ for (const set of sections.toolset ?? []) {
548
+ if (!set || typeof set !== "object") continue;
549
+ const { name, oauth } = set;
550
+ if (!oauth || typeof oauth !== "object" || Array.isArray(oauth)) continue;
551
+ const o = oauth;
552
+ const server = `mcpServer "${String(name ?? "?")}"`;
553
+ const text = (k) => typeof o[k] === "string" ? o[k].trim() : "";
554
+ if (o.mode === "hosted" && text("login_url") === "") {
555
+ bag.error(
556
+ "mcp.oauth-hosted-incomplete",
557
+ `${server}: \`oauth\` is hosted mode with no \`loginUrl\`. A client signing in is sent to that page, so the platform refuses the push without one. Set \`loginUrl\` to your login page (https), or \`env("NAME")\`.`,
558
+ set
559
+ );
560
+ }
561
+ if (o.mode !== "external") continue;
562
+ const missing = ["issuer", "column"].filter((k) => text(k) === "");
563
+ if (missing.length > 0) {
564
+ bag.error(
565
+ "mcp.oauth-external-incomplete",
566
+ `${server}: \`oauth\` is external mode with no ${missing.map((k) => `\`${k}\``).join(" or ")}. The \`issuer\` is what a token is verified against and the \`column\` is the auth-table column its claim names a row by; the platform refuses the push without both.`,
567
+ set
568
+ );
569
+ }
570
+ const preset = text("preset");
571
+ const clientIds = Array.isArray(o.allowed_client_ids) ? o.allowed_client_ids : [];
572
+ if (MCP_OAUTH_PRESETS_WITHOUT_AUD.includes(preset) && clientIds.length === 0) {
573
+ bag.error(
574
+ "mcp.oauth-preset-client-ids",
575
+ `${server}: \`oauth.preset\` "${preset}" issues access tokens without an audience, so nothing ties a token to this server. Set \`allowedClientIds\` to the client ids allowed to call it; the platform refuses the push without them.`,
576
+ set
577
+ );
578
+ }
579
+ const claim = typeof o.claim === "string" && o.claim !== "" ? o.claim : "sub";
580
+ if (!MCP_OAUTH_STABLE_CLAIMS.includes(claim) && o.claim_ack !== true) {
581
+ bag.error(
582
+ "mcp.oauth-claim-unacked",
583
+ `${server}: \`oauth.claim\` "${claim}" can be edited by users at many identity providers, which would let a user choose the row they sign in as. Use "sub", "oid" or "email", or set \`claimAck: true\` to accept it; the platform refuses the push otherwise.`,
584
+ set
585
+ );
586
+ }
587
+ }
588
+ }
589
+ function isEmptyRevokeTarget(input) {
590
+ if (typeof input?.tag !== "string" || !input.tag.startsWith("const")) return false;
591
+ const value = String(input.value ?? "");
592
+ if (input.name === "user_id") return value === "";
593
+ if (input.name === "grant_id") return value === "" || Number(value) <= 0;
594
+ if (input.name === "all") return value === "" || value === "false" || value === "0";
595
+ return false;
596
+ }
597
+ function checkMcpOauthRevoke(sections, bag) {
598
+ for (const [payloadKey, arr] of Object.entries(sections)) {
599
+ for (const obj2 of arr ?? []) {
600
+ if (!obj2 || typeof obj2 !== "object") continue;
601
+ walkNodes(obj2, (node) => {
602
+ if (node.name !== "mvp:mcp_oauth_revoke" || !Array.isArray(node.input)) return;
603
+ const targets = node.input.filter((i) => !isEmptyRevokeTarget(i)).map((i) => i?.name).filter((n) => n === "user_id" || n === "grant_id" || n === "all");
604
+ if (targets.length === 1) return;
605
+ const name = obj2.name;
606
+ const owner = `${sdkKindName(payloadKey, obj2)} "${typeof name === "string" ? name : "?"}"`;
607
+ bag.error(
608
+ "mcp.oauth-revoke-target",
609
+ `${owner}: \`s.mcp.oauth.revoke\` needs exactly one of \`user_id\`, \`grant_id\` or \`all\`, but it names ${targets.length === 0 ? "no target" : targets.map((t) => `\`${t}\``).join(" and ")} \u2014 the platform refuses any other combination every time the statement runs.`,
610
+ obj2
611
+ );
612
+ });
613
+ }
614
+ }
615
+ }
616
+
617
+ // src/workspace/filter-operands.ts
618
+ var SCALAR_COLUMN_TYPES = /* @__PURE__ */ new Set([
619
+ "int",
620
+ "decimal",
621
+ "text",
622
+ "bool",
623
+ "epochms",
624
+ "timestamp",
625
+ "date",
626
+ "email",
627
+ "password",
628
+ "enum",
629
+ "uuid"
630
+ ]);
631
+ var SCALAR_TAGS = /* @__PURE__ */ new Set(["const", "const:encoded", "const:int", "const:decimal", "const:bool", "const:null"]);
632
+ var NUMERIC_TEXT = {
633
+ int: /^\s*[+-]?\d+\s*$/,
634
+ decimal: /^\s*(?:[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?|nan|[+-]?inf(?:inity)?)\s*$/i
635
+ };
636
+ function outsideInt64(v) {
637
+ const text = typeof v === "number" && Number.isInteger(v) ? BigInt(v).toString() : typeof v === "string" ? v.trim() : void 0;
638
+ if (text === void 0 || !/^[+-]?\d+$/.test(text)) return false;
639
+ const n = BigInt(text);
640
+ return n > 2n ** 63n - 1n || n < -(2n ** 63n);
641
+ }
642
+ function isScalar(v) {
643
+ return typeof v === "string" || typeof v === "number" || typeof v === "boolean";
644
+ }
645
+ var COMPARISON_OPS = /* @__PURE__ */ new Set(["=", "==", "!=", "===", "!==", "<", "<=", ">", ">="]);
646
+ var PATTERN_OPS = /* @__PURE__ */ new Set(["like", "not like", "ilike", "not ilike", "~", "!~", "includes", "not includes", "search"]);
647
+ var CONTAINMENT_OPS = /* @__PURE__ */ new Set(["contains", "not contains", "overlaps", "not overlaps"]);
648
+ function unfiltered(o) {
649
+ return !Array.isArray(o.filters) || o.filters.length === 0;
650
+ }
651
+ function literalShape(o) {
652
+ if (typeof o.tag !== "string" || !unfiltered(o)) return void 0;
653
+ const text = typeof o.operand === "string" ? o.operand : void 0;
654
+ if (text?.startsWith("(")) return void 0;
655
+ if (SCALAR_TAGS.has(o.tag)) return { kind: "scalar" };
656
+ if (o.tag !== "const:array" && o.tag !== "const:obj") return void 0;
657
+ let value;
658
+ try {
659
+ value = JSON.parse(text ?? "");
660
+ } catch {
661
+ return void 0;
662
+ }
663
+ if (Array.isArray(value)) return { kind: "list", length: value.length, items: value };
664
+ if (!value || typeof value !== "object") return void 0;
665
+ const keys2 = Object.keys(value);
666
+ if (keys2.every((k, i) => k === String(i))) return void 0;
667
+ return { kind: "object" };
668
+ }
669
+ function objectLiteral(o) {
670
+ return o.tag === "const:obj" && o.operand === "{}" && Array.isArray(o.filters) && o.filters.length > 0 && o.filters.every((x) => x?.name === "set");
671
+ }
672
+ function emptyLiteral(o) {
673
+ if (o.tag === "const:null") return true;
674
+ return typeof o.operand !== "string" || ["", "0", "[]", "{}", "false", "null"].includes(o.operand);
675
+ }
676
+ function tableShapes(sections) {
677
+ const out = /* @__PURE__ */ new Map();
678
+ for (const raw of sections.dbo ?? []) {
679
+ const t = raw;
680
+ if (typeof t?.guid !== "string" || !Array.isArray(t.schema)) continue;
681
+ const cols = /* @__PURE__ */ new Map();
682
+ for (const c of t.schema) {
683
+ if (typeof c?.name !== "string" || typeof c.type !== "string") continue;
684
+ cols.set(c.name, { type: c.type, list: c.style?.type === "list" });
685
+ }
686
+ out.set(t.guid, cols);
687
+ }
688
+ return out;
689
+ }
690
+ function describeColumn(name, c) {
691
+ return `\`${name}\` (${c.type}${c.list ? " list" : ""})`;
692
+ }
693
+ function describeLiteral(s) {
694
+ if (s.kind === "list") return `a ${s.length}-element list`;
695
+ return s.kind === "object" ? "an object" : "a scalar";
696
+ }
697
+ function problem(op, left, right, columns) {
698
+ if (right.ignore_empty === true && emptyLiteral(right)) return void 0;
699
+ const lit = literalShape(right);
700
+ const leftName = left.tag === "col" && typeof left.operand === "string" && unfiltered(left) ? left.operand : void 0;
701
+ const column = leftName !== void 0 && !leftName.includes(".") ? columns?.get(leftName) : void 0;
702
+ if (op === "between" || op === "not between") {
703
+ if (left.tag !== "col") return void 0;
704
+ if (right.tag === "col") return `\`${op}\` takes a literal two-value list on the right, not a column`;
705
+ if (lit && !(lit.kind === "list" && lit.length === 2)) {
706
+ return `\`${op}\` needs exactly a two-value list (\`c.array([low, high])\`) on the right; it has ${describeLiteral(lit)}`;
707
+ }
708
+ return void 0;
709
+ }
710
+ if (!column) return void 0;
711
+ const col = describeColumn(leftName, column);
712
+ if (CONTAINMENT_OPS.has(op) && !column.list && SCALAR_COLUMN_TYPES.has(column.type)) {
713
+ return `\`${op}\` is json/list containment and ${col} is neither \u2014 for a substring match use \`includes\``;
714
+ }
715
+ if (CONTAINMENT_OPS.has(op) && column.type === "json" && !column.list && right.tag !== "col") {
716
+ return `\`${op}\` on a json column has no working operand: the database cannot compare ${col} with the list it builds, whatever the value. Store the values in a list column (\`f.text({ array: true })\`), where \`${op}\` works, or match a json array of objects with \`@>\` (\`c.array([{ \u2026 }])\`)`;
717
+ }
718
+ if (op === "@>" && SCALAR_COLUMN_TYPES.has(column.type)) {
719
+ return `\`@>\` needs a json column on the left, and ${col} is not one`;
720
+ }
721
+ if (op === "@>" && !column.list && objectLiteral(right)) {
722
+ return `\`@>\` with an object literal on the right fails with "Invalid expression" \u2014 bind the object first (\`s.set_var("match", c.obj({ \u2026 }))\`, then \`ref("match")\`) or take it as a json input; a json array of objects matches with \`c.array([{ \u2026 }])\``;
723
+ }
724
+ if ((op === "includes" || op === "not includes") && column.type === "bool") {
725
+ return `\`${op}\` does not take a bool column (${col})`;
726
+ }
727
+ if (!lit) return void 0;
728
+ if (op === "in" || op === "not in") {
729
+ if (!column.list && lit.kind !== "list") return `\`${op}\` on ${col} needs a list on the right; it has ${describeLiteral(lit)}`;
730
+ if (column.list && lit.kind === "list") return `\`${op}\` needs a scalar on one side, and ${col} and the right side are both lists`;
731
+ return void 0;
732
+ }
733
+ if (op === "@>" && column.type === "json") {
734
+ if (lit.kind === "scalar" || lit.kind === "list" && isScalar(lit.items[0])) {
735
+ return `\`@>\` needs a json value on the right, and a ${lit.kind === "scalar" ? "scalar" : "list of scalars"} is not one \u2014 the engine reads a list by its first element. A list of objects works (\`c.array([{ \u2026 }])\`); matching scalar elements needs a list column (\`f.text({ array: true })\`) with \`contains\``;
736
+ }
737
+ return void 0;
738
+ }
739
+ const numeric = NUMERIC_TEXT[column.type];
740
+ if (CONTAINMENT_OPS.has(op) && column.list && numeric !== void 0 && lit.kind === "list") {
741
+ const bad = lit.items.find((v) => typeof v === "string" && !numeric.test(v));
742
+ if (bad !== void 0) {
743
+ return `\`${op}\` on ${col} casts every element to ${column.type === "int" ? "a whole number" : "a number"}, and ${JSON.stringify(bad)} is not one`;
744
+ }
745
+ const big = column.type === "int" ? lit.items.find(outsideInt64) : void 0;
746
+ if (big !== void 0) {
747
+ return `\`${op}\` on ${col} casts every element to a 64-bit whole number, and ${JSON.stringify(big)} is out of its range`;
748
+ }
749
+ }
750
+ if (CONTAINMENT_OPS.has(op)) {
751
+ if (lit.kind === "scalar") return `\`${op}\` needs json or a list on the right; it has a scalar \u2014 wrap it: \`c.array([value])\``;
752
+ return void 0;
753
+ }
754
+ if (COMPARISON_OPS.has(op)) {
755
+ if (lit.kind === "list") return `\`${op}\` does not compare lists; the right side is ${describeLiteral(lit)} \u2014 use \`in\``;
756
+ if (column.list && right.tag !== "const:null") return `\`${op}\` does not compare lists, and ${col} is one`;
757
+ return void 0;
758
+ }
759
+ if (PATTERN_OPS.has(op)) {
760
+ if (lit.kind === "list") return `\`${op}\` does not take a list on the right; it has ${describeLiteral(lit)}`;
761
+ }
762
+ return void 0;
763
+ }
764
+ function walk(node, visit) {
765
+ const stack = [node];
766
+ while (stack.length > 0) {
767
+ const n = stack.pop();
768
+ if (Array.isArray(n)) {
769
+ for (let i = n.length - 1; i >= 0; i--) stack.push(n[i]);
770
+ } else if (n && typeof n === "object") {
771
+ const record = n;
772
+ visit(record);
773
+ const values = Object.values(record);
774
+ for (let i = values.length - 1; i >= 0; i--) stack.push(values[i]);
775
+ }
776
+ }
777
+ }
778
+ function checkFilterOperands(sections, bag) {
779
+ const tables = tableShapes(sections);
780
+ for (const [payloadKey, arr] of Object.entries(sections)) {
781
+ for (const obj2 of arr ?? []) {
782
+ if (!obj2 || typeof obj2 !== "object") continue;
783
+ const found = [];
784
+ walk(obj2, (record) => {
785
+ const context = record.context;
786
+ if (!context || typeof context.search !== "object" || context.search === null) return;
787
+ const id = context.dbo?.id;
788
+ const columns = typeof id === "string" ? tables.get(id) : void 0;
789
+ walk(context.search, (node) => {
790
+ const s = node.statement;
791
+ if (!s || typeof s !== "object" || typeof s.op !== "string") return;
792
+ const why = problem(s.op, s.left ?? {}, s.right ?? {}, columns);
793
+ if (why !== void 0) found.push(why);
794
+ });
795
+ });
796
+ if (found.length === 0) continue;
797
+ const name = obj2.name;
798
+ const owner = `${sdkKindName(payloadKey, obj2)} "${typeof name === "string" ? name : "?"}"`;
799
+ for (const why of [...new Set(found)]) {
800
+ bag.warn(
801
+ "db.filter-operand-invalid",
802
+ `${owner}: a \`where\` clause fails every request that reaches it, whatever the data \u2014 ${why}.`,
803
+ obj2
804
+ );
805
+ }
806
+ }
807
+ }
808
+ }
809
+
810
+ // src/workspace/xano.ts
811
+ var MIDDLEWARE_HOST_KINDS = ["query", "task", "function", "tool", "prompt", "resource"];
812
+ var XANO_BRAND = /* @__PURE__ */ Symbol.for("xanosdk.Xano");
813
+ var XANO_ORIGIN = /* @__PURE__ */ Symbol.for("xanosdk.Xano.origin");
814
+ function nameResponseRecordError(err, kindName, def) {
815
+ if (!(err instanceof Error)) return err;
816
+ const response = def?.response;
817
+ if (response === null || typeof response !== "object" || isTaggedValue(response)) return err;
818
+ if (err.message.startsWith("`response.")) {
819
+ err.message = `${authorKindName(kindName)} "${String(def.name)}": ${err.message}`;
820
+ return err;
821
+ }
822
+ if (err.message.startsWith("obj() takes a { key: value } record")) {
823
+ const bad = Object.entries(response).find(([, m]) => typeof m !== "object" || m === null || Array.isArray(m));
824
+ if (bad !== void 0) {
825
+ const [key, member] = bad;
826
+ err.message = `${authorKindName(kindName)} "${String(def.name)}": \`response.${key}\` is ${describeEntry(member)} \u2014 a response key takes a value (\`ref("x")\`, \`c.*\`) or a { key: value } record.` + (Array.isArray(member) ? ` A list of values goes inside a record member (\`${key}: { items: [ \u2026 ] }\`), or bind it first (\`s.set_var\`) and use \`ref()\`; a list of constants is \`c.array([ \u2026 ])\`.` : "");
827
+ }
828
+ return err;
829
+ }
830
+ if (!err.message.startsWith("obj(): `")) return err;
831
+ for (const [key, member] of Object.entries(response)) {
832
+ if (member === null || typeof member !== "object" || Array.isArray(member) || isTaggedValue(member)) continue;
833
+ try {
834
+ obj(member);
835
+ } catch {
836
+ err.message = `${authorKindName(kindName)} "${String(def.name)}": ` + err.message.replace("obj(): `", `\`response.${key}.`) + ` A nested response record is one object expression; a top-level response key can carry this value as it is.`;
837
+ break;
838
+ }
839
+ }
840
+ return err;
841
+ }
842
+ function assertDefEntry(via, kindName, def, index) {
843
+ if (typeof def === "object" && def !== null && !Array.isArray(def)) return;
844
+ const at = index === void 0 ? "its argument" : `entry [${index}]`;
845
+ const hint = def === false || def === void 0 ? " A `cond && def` entry leaves false/undefined behind \u2014 spread it instead: `...(cond ? [def] : [])`." : typeof def === "function" ? " A factory passed uncalled is a function \u2014 call it: `table({ \u2026 })`, not `table`." : Array.isArray(def) && index === void 0 ? ` It takes one def, not a list \u2014 \`${via}(def)\`.` : "";
846
+ throw new Error(`${via}: ${at} must be ${withArticle(authorKindName(kindName))} def \u2014 got ${describeEntry(def)}.${hint}`);
847
+ }
848
+ function authorKindName(kindName) {
849
+ return AUTHOR_KIND_NAME[kindName] ?? (kindName === "workspace" ? "workspaceConfig" : kindName);
850
+ }
851
+ var REGISTER_METHOD = {
852
+ workspace: "registerWorkspace",
853
+ table: "registerTables",
854
+ function: "registerFunctions",
855
+ query: "registerQueries",
856
+ api_group: "registerApiGroups",
857
+ task: "registerTasks",
858
+ middleware: "registerMiddleware",
859
+ addon: "registerAddons",
860
+ tool: "registerTools",
861
+ prompt: "registerPrompts",
862
+ resource: "registerResources",
863
+ mcp_server: "registerMcpServers",
864
+ agent: "registerAgents",
865
+ trigger: "registerTriggers",
866
+ knowledge: "registerKnowledge",
867
+ microservice: "registerMicroservices",
868
+ realtime_server: "registerRealtimeServers",
869
+ channel: "registerRealtimeChannels",
870
+ message: "registerRealtimeMessages",
871
+ workflow_test: "registerWorkflowTests"
872
+ };
873
+ function structuralKind(def, kindName) {
874
+ if (typeof def !== "object" || def === null) return void 0;
875
+ const d = def;
876
+ if (typeof d.verb === "string") return "query";
877
+ if (typeof d.objType === "string") return "trigger";
878
+ if (d.cors !== void 0 || d.swagger !== void 0 && kindName !== "workspace") return "api_group";
879
+ if (d.canonical !== void 0 && !CANONICAL_KINDS.has(kindName)) return "api_group";
880
+ return void 0;
881
+ }
882
+ function standaloneDefKind(def) {
883
+ const branded = defKindOf(def);
884
+ if (branded !== void 0) return branded;
885
+ const structural = structuralKind(def, "");
886
+ if (structural !== void 0) return structural;
887
+ if (typeof def !== "object" || def === null) return void 0;
888
+ if (def.schema !== void 0) return "table";
889
+ const keys2 = Object.keys(def);
890
+ if (keys2.includes("name") && keys2.every((k) => API_GROUP_KEYS.has(k))) return "api_group";
891
+ return void 0;
892
+ }
893
+ var API_GROUP_KEYS = new Set(DEF_KEYS["api_group"]);
894
+ var CANONICAL_KINDS = /* @__PURE__ */ new Set(["api_group", "mcp_server", "agent", "realtime_server", "workspace"]);
895
+ function assertDefKind(via, kindName, def, index) {
896
+ const made = defKindOf(def) ?? structuralKind(def, kindName);
897
+ if (made === void 0 || made === kindName) return;
898
+ const at = index === void 0 ? "its argument" : `entry [${index}]`;
899
+ const method = REGISTER_METHOD[made];
900
+ throw new Error(
901
+ `${via}: ${at} is ${withArticle(authorKindName(made))} def, not ${withArticle(authorKindName(kindName))} def` + (method === void 0 ? "." : ` \u2014 use ${method}.`)
902
+ );
903
+ }
904
+ function acceptedWarnings(kindName, def) {
905
+ const diagnostics = def?.diagnostics;
906
+ if (diagnostics === void 0 || diagnostics === null) return void 0;
907
+ const offered = allowableWarnings(kindName);
908
+ const name = def.name;
909
+ const owner = `${authorKindName(kindName)}${typeof name === "string" ? ` "${name}"` : ""}`;
910
+ const codes = offered.map((c) => `"${c}"`).join(", ");
911
+ if (offered.length === 0) throw new Error(`${owner}: \`diagnostics\` \u2014 this def raises no warning that can be accepted.`);
912
+ const allow = diagnostics.allow;
913
+ const extra = typeof diagnostics === "object" ? Object.keys(diagnostics).find((k) => k !== "allow") : void 0;
914
+ if (typeof diagnostics !== "object" || !Array.isArray(allow) || extra !== void 0) {
915
+ throw new Error(
916
+ `${owner}: \`diagnostics\` must be { allow: [...] } \u2014 got ${describeEntry(extra ?? allow ?? diagnostics)}${extra === void 0 ? "" : " as a key"}. Codes this def can accept: ${codes}.`
917
+ );
918
+ }
919
+ for (const code of allow) {
920
+ if (typeof code === "string" && offered.includes(code)) continue;
921
+ const near = typeof code === "string" ? nearestCode(code, offered) : void 0;
922
+ throw new Error(
923
+ `${owner}: \`diagnostics.allow\` names ${typeof code === "string" ? `unknown code "${code}"` : describeEntry(code)} for ${withArticle(authorKindName(kindName))}${near === void 0 ? "." : ` \u2014 did you mean "${near}"?`} Codes this def can accept: ${codes}.`
924
+ );
925
+ }
926
+ return new Set(allow);
927
+ }
928
+ function asAuthoringRefusal(err) {
929
+ if (err instanceof Error && Object.getPrototypeOf(err) === Error.prototype && err.code === void 0) {
930
+ Object.defineProperty(err, "name", { value: "UsageError", configurable: true, writable: true });
931
+ }
932
+ return err;
933
+ }
934
+ function nearestCode(code, offered) {
935
+ return nearestKey(code, offered) ?? offered.find((c) => c.includes(code) || code.includes(c));
936
+ }
937
+ var Xano = class {
938
+ /** @internal cross-realm identity brand — see {@link Xano.isXano}. */
939
+ [XANO_BRAND] = true;
940
+ constructor() {
941
+ Object.defineProperty(this, XANO_ORIGIN, { value: new Error("registry created"), enumerable: false });
942
+ }
943
+ /** Encoded objects keyed by `packageExport` payload key. */
944
+ sections = /* @__PURE__ */ new Map();
945
+ /** Table defs, encoded lazily at {@link export} so each can inherit the workspace `use_xdo`. */
946
+ tableDefs = [];
947
+ knowledgeDefs = [];
948
+ workspaceConfig = {};
949
+ /**
950
+ * Whether the attached config named `env` at all — `env: {}` included. The
951
+ * encoded config always carries an `env` list, so it cannot tell a config that
952
+ * declares none on purpose from one that was never attached; this can.
953
+ */
954
+ envAuthored = false;
955
+ /**
956
+ * Whether a config was passed to {@link registerWorkspace} by the author, as
957
+ * opposed to the `{ name }` the {@link workspace} shorthand registers. Lets the
958
+ * env guard tell "no config attached" from "the attached config has no `env`".
959
+ */
960
+ configAttached = false;
961
+ bundleType = "workspace";
962
+ /**
963
+ * Encoded objects whose `canonical` a locked {@link export} filled in (from
964
+ * the lock or freshly minted) rather than the author writing it.
965
+ *
966
+ * The fill mutates the registered object, so a second `export()` off the same
967
+ * registry can no longer see that the slug started empty. Without this the
968
+ * re-export would classify a minted token as a pinned one and a later release
969
+ * would refuse over a URL nobody promised.
970
+ */
971
+ filledCanonicals = /* @__PURE__ */ new WeakSet();
972
+ /** The filled canonicals whose lock entry was adopted from a live backend (`canonical_source: "adopted"`). */
973
+ adoptedCanonicals = /* @__PURE__ */ new WeakSet();
974
+ /** Every guid a def pins with its own `guid:` — recorded in the lock as `guid_source: "code"`. */
975
+ codeGuids = /* @__PURE__ */ new Set();
976
+ /** True for any `Xano` registry, even one created by a different module instance. */
977
+ static isXano(value) {
978
+ return typeof value === "object" && value !== null && value[XANO_BRAND] === true;
979
+ }
980
+ /** Encode one def and stamp its deterministic guid (the engine's sync/reference anchor). */
981
+ encodeOne(kind, def) {
982
+ let encoded;
983
+ const raised = [];
984
+ const previous = setDiagnosticSink((d) => raised.push(d));
985
+ try {
986
+ encoded = kind.encode(def);
987
+ } catch (err) {
988
+ throw asAuthoringRefusal(nameResponseRecordError(err, kind.name, def));
989
+ } finally {
990
+ setDiagnosticSink(previous);
991
+ }
992
+ if (raised.length > 0 && encoded !== null && typeof encoded === "object") this.encodeWarnings.set(encoded, raised);
993
+ assertTestIds(encoded, kind.name);
994
+ assertMockKeysResolved(encoded, kind.name);
995
+ if (REFERENCEABLE_KINDS.has(kind.name) && encoded && typeof encoded === "object") {
996
+ const obj2 = encoded;
997
+ const explicit = def.guid;
998
+ if (obj2.guid === void 0 && typeof obj2.name === "string") {
999
+ obj2.guid = explicit ?? kind.guidOf?.(def) ?? deriveGuid(kind.payloadKey, obj2.name);
1000
+ }
1001
+ if (typeof explicit === "string" && explicit !== "" && obj2.guid === explicit) this.codeGuids.add(explicit);
1002
+ }
1003
+ return encoded;
1004
+ }
1005
+ /** Register one or more authoring defs of a given kind. */
1006
+ register(kindName, defOrDefs, via = `register(${JSON.stringify(kindName)})`) {
1007
+ const kind = getKind(kindName);
1008
+ const defs = Array.isArray(defOrDefs) ? defOrDefs : [defOrDefs];
1009
+ defs.forEach((def, i) => {
1010
+ assertDefEntry(via, kind.name, def, Array.isArray(defOrDefs) ? i : void 0);
1011
+ assertDefKind(via, kind.name, def, Array.isArray(defOrDefs) ? i : void 0);
1012
+ const name = def.name;
1013
+ assertDefKeys(`${authorKindName(kind.name)}${typeof name === "string" ? ` "${name}"` : ""}`, def, DEF_KEYS[kind.name], kind.name);
1014
+ assertDefShape(kind.name, def);
1015
+ assertNameAsStored(authorKindName(kind.name), name);
1016
+ });
1017
+ const allows = defs.map((def) => acceptedWarnings(kind.name, def));
1018
+ for (const def of defs) this.assertNotAlreadyRegistered(kind.name, def);
1019
+ if (kind.name === "table") {
1020
+ defs.forEach((def, i) => {
1021
+ this.tableDefs.push(def);
1022
+ if (allows[i]) this.accepted.set(def, allows[i]);
1023
+ });
1024
+ return this;
1025
+ }
1026
+ if (kind.name === "knowledge") {
1027
+ for (const def of defs) this.knowledgeDefs.push(def);
1028
+ }
1029
+ const bucket = this.sections.get(kind.payloadKey) ?? [];
1030
+ defs.forEach((def, i) => {
1031
+ const encoded = this.encodeOne(kind, def);
1032
+ const allow = allows[i];
1033
+ if (allow && encoded && typeof encoded === "object") this.accepted.set(encoded, allow);
1034
+ bucket.push(encoded);
1035
+ });
1036
+ this.sections.set(kind.payloadKey, bucket);
1037
+ return this;
1038
+ }
1039
+ /**
1040
+ * A table's bundle entry, encoded now that the workspace `use_xdo` is known: a
1041
+ * table without an explicit `useXdo` inherits the workspace default.
1042
+ */
1043
+ encodeTableEntry(def) {
1044
+ const wsUseXdo = this.workspaceConfig.use_xdo === true;
1045
+ const encoded = this.encodeOne(
1046
+ getKind("table"),
1047
+ def.useXdo === void 0 ? { ...def, useXdo: wsUseXdo } : def
1048
+ );
1049
+ const dbo = { ...encoded, import: { mode: "standard" } };
1050
+ const allow = this.accepted.get(def);
1051
+ if (allow) this.accepted.set(dbo, allow);
1052
+ const raised = this.encodeWarnings.get(encoded);
1053
+ if (raised) this.encodeWarnings.set(dbo, raised);
1054
+ return dbo;
1055
+ }
1056
+ /**
1057
+ * @internal The entry `def` becomes in the bundle a registry holding only it
1058
+ * exports — what `emit` and `xanosdk compile` print. Registered first, so the
1059
+ * def is validated exactly as a `register*` call validates it; the encoder's
1060
+ * warnings are returned rather than printed, for the caller's checks to raise.
1061
+ * The cross-object fills a lone def can take are applied as export applies
1062
+ * them: an empty canonical from the seeded lock, hosted-file icons from
1063
+ * `opts.hostedFiles`, a group's documentation token from
1064
+ * `opts.documentationTokens`. Knowledge bodies are export's.
1065
+ */
1066
+ encodeEntry(kindName, def, opts = {}) {
1067
+ const kind = getKind(kindName);
1068
+ if (kind.name === "workspace") {
1069
+ this.registerWorkspace(def);
1070
+ return { payloadKey: kind.payloadKey, entry: this.export().payload.workspace, warnings: [] };
1071
+ }
1072
+ this.register(kind.name, def);
1073
+ const encoded = kind.name === "table" ? this.encodeTableEntry(def) : this.sections.get(kind.payloadKey).at(-1);
1074
+ const warnings = this.encodeWarnings.get(encoded) ?? [];
1075
+ let entry = encoded;
1076
+ if (CANONICAL_PAYLOAD_KEYS.has(kind.payloadKey) && entry.canonical === "" && typeof entry.name === "string") {
1077
+ const locked = getLockedCanonical(lockKey(kind.payloadKey, entry.name));
1078
+ if (locked !== void 0) entry = { ...entry, canonical: locked };
1079
+ }
1080
+ if (opts.hostedFiles !== void 0 && HOSTED_ICON_KINDS.includes(kind.payloadKey)) {
1081
+ const sections = { [kind.payloadKey]: [entry] };
1082
+ this.fillHostedFiles(sections, opts.hostedFiles);
1083
+ entry = sections[kind.payloadKey][0];
1084
+ }
1085
+ if (kind.name === "api_group") {
1086
+ entry = resolveDocumentationTokens({
1087
+ workspace: {},
1088
+ apiGroups: [entry],
1089
+ values: opts.documentationTokens ?? {}
1090
+ }).apiGroups[0];
1091
+ }
1092
+ return { payloadKey: kind.payloadKey, entry, warnings };
1093
+ }
1094
+ /**
1095
+ * Every def object handed to {@link register}, by identity, so the SAME one
1096
+ * registered twice is caught at the call that did it.
1097
+ *
1098
+ * Identity, not structure. Two separately constructed defs sharing a name are
1099
+ * a genuine collision, and the guid check at export already diagnoses that
1100
+ * correctly — it explains that identity derives from `(type, name)` and names
1101
+ * both objects. This guard must not shadow it.
1102
+ */
1103
+ registered = /* @__PURE__ */ new Set();
1104
+ /** The warnings each encoded object's encoder raised, raised again about it by every export. */
1105
+ encodeWarnings = /* @__PURE__ */ new WeakMap();
1106
+ /** Each encoded object's accepted warning codes, from its def's `diagnostics.allow`. */
1107
+ accepted = /* @__PURE__ */ new WeakMap();
1108
+ /** The workspace config's accepted warning codes — they hold for every object. */
1109
+ workspaceAccepted;
1110
+ /**
1111
+ * Refuse the same def object twice.
1112
+ *
1113
+ * The failure this front-runs: a helper registers a def on your behalf and
1114
+ * you then register it again yourself — `registerAuth(ws).registerTables([userTable])`
1115
+ * is the reported shape. Nothing objected at the second call; it surfaced much
1116
+ * later at `emitBundle` as `Duplicate object guid (efb55…) shared by "dbo/user"
1117
+ * and "dbo/user"`, a message that names a guid and the same label twice and
1118
+ * points at neither line.
1119
+ */
1120
+ assertNotAlreadyRegistered(kindName, def) {
1121
+ if (def === null || typeof def !== "object") return;
1122
+ if (!this.registered.has(def)) {
1123
+ this.registered.add(def);
1124
+ return;
1125
+ }
1126
+ const name = def.name;
1127
+ const label = typeof name === "string" ? `"${name}"` : "it";
1128
+ throw new Error(
1129
+ `register: the same ${kindName} def ${label} was registered twice on this workspace. The second registration is always a mistake \u2014 the bundle would carry the object twice under one guid, which fails the import. A helper that registers on your behalf is the usual cause (\`registerAuth(ws)\` registers its own tables, so a following \`registerTables([userTable])\` is the duplicate): drop the manual call. Two DIFFERENT defs that share a name are a separate problem, and export reports that one by guid.`
1130
+ );
1131
+ }
1132
+ /**
1133
+ * Register the workspace settings object (singleton).
1134
+ *
1135
+ * A config with no `name` inherits the one already on the registry — which is
1136
+ * what `workspace("my-app")` set — so the natural chain
1137
+ * `workspace("my-app").registerWorkspace(workspaceConfig({ history }))` no
1138
+ * longer makes an author restate a name this registry has held since its
1139
+ * first call. An explicit `name` still wins, and a rename this way is
1140
+ * a rename of the workspace.
1141
+ */
1142
+ registerWorkspace(def) {
1143
+ if (def !== void 0 && def !== null) {
1144
+ assertDefEntry("registerWorkspace", "workspace", def, void 0);
1145
+ assertDefKind("registerWorkspace", "workspace", def, void 0);
1146
+ assertNoProtoKeys("registerWorkspace", def);
1147
+ assertDefKeys("workspaceConfig", def, DEF_KEYS.workspace, "workspace");
1148
+ assertDefShape("workspace", def);
1149
+ }
1150
+ const authored = def ?? {};
1151
+ if (typeof authored.name === "string" && authored.name.trim() === "") {
1152
+ throw new Error(
1153
+ `registerWorkspace: the workspace name must not be blank \u2014 got ${describeEntry(authored.name)}. Name it, or leave \`name\` out to keep the one \`workspace("\u2026")\` gave.`
1154
+ );
1155
+ }
1156
+ const inherited = this.workspaceConfig.name;
1157
+ const withName = authored.name === void 0 && typeof inherited === "string" ? { ...authored, name: inherited } : authored;
1158
+ this.workspaceConfig = encodeObject("workspace", withName);
1159
+ this.workspaceAccepted = acceptedWarnings("workspace", authored);
1160
+ this.envAuthored = authored.env !== void 0;
1161
+ this.configAttached = SHORTHAND_CONFIGS.has(def) ? this.configAttached : true;
1162
+ return this;
1163
+ }
1164
+ /**
1165
+ * Fill each encoded knowledge item's `content` and emit its reference files as
1166
+ * the sibling `knowledge_file` section.
1167
+ *
1168
+ * Reference rows name their parent by GUID rather than by row id: the id does
1169
+ * not exist until the import inserts the parent, and the importer resolves the
1170
+ * guid back to it. `references` stays empty — the platform derives that list
1171
+ * from the stored files itself, so anything written here is overwritten.
1172
+ */
1173
+ fillKnowledge(sections, resolved) {
1174
+ const byName = new Map(resolved.map((r) => [r.name, r]));
1175
+ const files = [];
1176
+ const warnings = [];
1177
+ const items = (sections.knowledge ?? []).map((source) => {
1178
+ if (!byName.has(source.name)) return source;
1179
+ const copy = { ...source };
1180
+ const allow = this.accepted.get(source);
1181
+ if (allow) this.accepted.set(copy, allow);
1182
+ const raised = this.encodeWarnings.get(source);
1183
+ if (raised) this.encodeWarnings.set(copy, raised);
1184
+ return copy;
1185
+ });
1186
+ if (sections.knowledge !== void 0) sections.knowledge = items;
1187
+ for (const item of items) {
1188
+ const match = byName.get(item.name);
1189
+ if (match === void 0) continue;
1190
+ item.content = match.content;
1191
+ for (const w of match.warnings ?? []) warnings.push({ item, ...w });
1192
+ for (const file of match.files) {
1193
+ files.push({
1194
+ knowledge: { id: item.guid },
1195
+ path: file.path,
1196
+ content: file.content,
1197
+ size: file.size,
1198
+ guid: deriveGuid("knowledge_file", `${item.name}/${file.path}`)
1199
+ });
1200
+ }
1201
+ }
1202
+ if (files.length > 0) sections.knowledge_file = files;
1203
+ return warnings;
1204
+ }
1205
+ /**
1206
+ * Replace every pending hosted-file placeholder with the resolver's value and
1207
+ * list the files it read as the `vault` section.
1208
+ *
1209
+ * The encoded MCP objects are the registry's own, shared by every export, so
1210
+ * each is copied rather than edited: an unresolved `export()` after a
1211
+ * resolved one still sees the inert placeholder.
1212
+ */
1213
+ fillHostedFiles(sections, resolver) {
1214
+ for (const key of HOSTED_ICON_KINDS) {
1215
+ const items = sections[key];
1216
+ if (items === void 0) continue;
1217
+ sections[key] = items.map((item) => {
1218
+ const icons = item.icons;
1219
+ if (!Array.isArray(icons) || !icons.some((icon) => pendingHostedFile(icon) !== void 0)) return item;
1220
+ const copy = {
1221
+ ...item,
1222
+ icons: icons.map((icon) => {
1223
+ const hosted = pendingHostedFile(icon);
1224
+ return hosted === void 0 ? icon : { ...icon, src: resolver.resolve(hosted.ref, hosted.rules) };
1225
+ })
1226
+ };
1227
+ const allow = this.accepted.get(item);
1228
+ if (allow) this.accepted.set(copy, allow);
1229
+ return copy;
1230
+ });
1231
+ }
1232
+ const rows = resolver.libraryRows();
1233
+ if (rows.length > 0) sections.vault = rows;
1234
+ }
1235
+ /** Set the bundle `type` (defaults to "workspace"). */
1236
+ setBundleType(type) {
1237
+ this.bundleType = type;
1238
+ return this;
1239
+ }
1240
+ /**
1241
+ * The registered table defs (with their authored `seed`), for the Node deploy
1242
+ * path to build `content/` seed entries. Deliberately NOT reached from
1243
+ * `export()` — seed values are resolved only in the deploy pipeline, so they
1244
+ * never enter the browser-safe bundle. See {@link import("./seed.js")}.
1245
+ */
1246
+ tables() {
1247
+ return [...this.tableDefs];
1248
+ }
1249
+ /**
1250
+ * The ENCODED workspace config, read-only.
1251
+ *
1252
+ * For the deploy path, which needs to know which env variable names the
1253
+ * workspace declares before the bundle exists — so an `--env-var` naming
1254
+ * something undeclared can be reported as an addition rather than silently
1255
+ * appended, and so a declared name with no value anywhere can refuse a deploy
1256
+ * rather than clear the live one. A shallow copy: nothing outside
1257
+ * `registerWorkspace` may write it.
1258
+ */
1259
+ workspaceSettings() {
1260
+ return { ...this.workspaceConfig };
1261
+ }
1262
+ /**
1263
+ * Every scope in this workspace that declares a documentation gate, with the
1264
+ * sidecar key its token is stored under.
1265
+ *
1266
+ * For the deploy path, which has to know them before the bundle exists — so a
1267
+ * gate with no token anywhere can refuse a deploy rather than ship a workspace
1268
+ * whose doc site silently does not match its source. Read off the ENCODED
1269
+ * shapes, so a decoded workspace is covered exactly like a hand-authored one,
1270
+ * and so the guid each key is built from is the one already stamped at
1271
+ * registration.
1272
+ */
1273
+ documentationTokenNames() {
1274
+ return documentationTokenDeclarations({
1275
+ workspace: this.workspaceConfig,
1276
+ apiGroups: this.sections.get("app")
1277
+ });
1278
+ }
1279
+ /**
1280
+ * The registered knowledge defs (with their authored `body`/`refs` path
1281
+ * markers), for the Node compile path to read markdown off disk. Deliberately
1282
+ * NOT reached from `export()` — a file read has no place in the browser-safe
1283
+ * bundle, so the encoder emits an empty `content` and the compile path fills
1284
+ * it. See {@link import("./knowledge.js")}.
1285
+ */
1286
+ knowledge() {
1287
+ return [...this.knowledgeDefs];
1288
+ }
1289
+ registerFunctions(defs) {
1290
+ return this.register("function", defs, "registerFunctions");
1291
+ }
1292
+ /** Register knowledge items — the markdown a workspace's AI agents read. */
1293
+ registerKnowledge(defs) {
1294
+ return this.register("knowledge", defs, "registerKnowledge");
1295
+ }
1296
+ registerTriggers(defs) {
1297
+ return this.register("trigger", defs, "registerTriggers");
1298
+ }
1299
+ registerTools(defs) {
1300
+ return this.register("tool", defs, "registerTools");
1301
+ }
1302
+ /** Register MCP prompts. Expose one by listing it in an `mcpServer({ prompts })`. */
1303
+ registerPrompts(defs) {
1304
+ return this.register("prompt", defs, "registerPrompts");
1305
+ }
1306
+ /** Register MCP resources. Expose one by listing it in an `mcpServer({ resources })`. */
1307
+ registerResources(defs) {
1308
+ return this.register("resource", defs, "registerResources");
1309
+ }
1310
+ registerMcpServers(defs) {
1311
+ return this.register("mcp_server", defs, "registerMcpServers");
1312
+ }
1313
+ registerAgents(defs) {
1314
+ return this.register("agent", defs, "registerAgents");
1315
+ }
1316
+ registerTables(defs) {
1317
+ return this.register("table", defs, "registerTables");
1318
+ }
1319
+ registerQueries(defs) {
1320
+ return this.register("query", defs, "registerQueries");
1321
+ }
1322
+ registerApiGroups(defs) {
1323
+ return this.register("api_group", defs, "registerApiGroups");
1324
+ }
1325
+ registerTasks(defs) {
1326
+ return this.register("task", defs, "registerTasks");
1327
+ }
1328
+ registerMiddleware(defs) {
1329
+ return this.register("middleware", defs, "registerMiddleware");
1330
+ }
1331
+ registerAddons(defs) {
1332
+ return this.register("addon", defs, "registerAddons");
1333
+ }
1334
+ registerMicroservices(defs) {
1335
+ return this.register("microservice", defs, "registerMicroservices");
1336
+ }
1337
+ registerRealtimeServers(defs) {
1338
+ return this.register("realtime_server", defs, "registerRealtimeServers");
1339
+ }
1340
+ registerRealtimeChannels(defs) {
1341
+ return this.register("channel", defs, "registerRealtimeChannels");
1342
+ }
1343
+ registerRealtimeMessages(defs) {
1344
+ return this.register("message", defs, "registerRealtimeMessages");
1345
+ }
1346
+ registerWorkflowTests(defs) {
1347
+ return this.register("workflow_test", defs, "registerWorkflowTests");
1348
+ }
1349
+ /**
1350
+ * Assemble the signed aggregate `packageExport` bundle.
1351
+ *
1352
+ * With `options.lock` (a {@link LockExportContext}), the export participates
1353
+ * in identity locking: empty api-group/toolset canonicals are filled from the
1354
+ * lock — minted fresh on first sight — and every identity the bundle emits is
1355
+ * reported back through `ctx.observed` (MUTATING the passed context), which
1356
+ * the caller merges into the lock file. All lock work happens before the
1357
+ * bundle is signed. Without options the output is byte-identical to before.
1358
+ *
1359
+ * With `options.strict`, every build WARNING fails the export instead of
1360
+ * printing — the shapes that deploy clean and then lose data or return the
1361
+ * wrong rows. Nothing about the emitted bundle changes; it either exports or
1362
+ * it does not.
1363
+ */
1364
+ export(options = {}) {
1365
+ try {
1366
+ return this.assemble(options);
1367
+ } catch (err) {
1368
+ throw asAuthoringRefusal(err);
1369
+ }
1370
+ }
1371
+ /** {@link export}'s work, its refusals not yet classed. */
1372
+ assemble(options) {
1373
+ const lockCtx = options.lock;
1374
+ const sections = {};
1375
+ for (const [key, arr] of this.sections) {
1376
+ sections[key] = arr;
1377
+ }
1378
+ if (this.tableDefs.length > 0) {
1379
+ sections[getKind("table").payloadKey] = this.tableDefs.map((def) => this.encodeTableEntry(def));
1380
+ }
1381
+ const knowledgeWarnings = options.knowledge !== void 0 && options.knowledge.length > 0 ? this.fillKnowledge(sections, options.knowledge) : [];
1382
+ if (options.hostedFiles !== void 0) {
1383
+ this.fillHostedFiles(sections, options.hostedFiles);
1384
+ }
1385
+ const resolveDocs = () => resolveDocumentationTokens({
1386
+ workspace: this.workspaceConfig,
1387
+ apiGroups: sections["app"],
1388
+ values: options.documentationTokens ?? {},
1389
+ ...options.allowEmptyDocToken ? { allowEmpty: options.allowEmptyDocToken } : {}
1390
+ });
1391
+ const docsView = resolveDocs();
1392
+ docsView.apiGroups?.forEach((copy, i) => {
1393
+ const allow = this.accepted.get(sections["app"]?.[i]);
1394
+ if (allow && copy !== null && typeof copy === "object") this.accepted.set(copy, allow);
1395
+ });
1396
+ const bag = new DiagnosticBag(options.strict === true);
1397
+ const used = /* @__PURE__ */ new Map();
1398
+ const use = (allow, code) => {
1399
+ if (allow?.has(code) !== true) return false;
1400
+ used.set(allow, (used.get(allow) ?? /* @__PURE__ */ new Set()).add(code));
1401
+ return true;
1402
+ };
1403
+ bag.accepts = (code, subject) => {
1404
+ const own = use(subject === void 0 ? void 0 : this.accepted.get(subject), code);
1405
+ return use(this.workspaceAccepted, code) || own;
1406
+ };
1407
+ let subjectMap;
1408
+ const subjects = () => subjectMap ??= this.diagnosticSubjects(sections, docsView.apiGroups);
1409
+ bag.describe = (subject) => subjects().get(subject);
1410
+ for (const arr of Object.values(sections)) {
1411
+ for (const obj2 of arr ?? []) {
1412
+ if (obj2 === null || typeof obj2 !== "object") continue;
1413
+ for (const d of this.encodeWarnings.get(obj2) ?? []) bag.warn(d.code, d.message, obj2);
1414
+ }
1415
+ }
1416
+ for (const { item, code, message } of knowledgeWarnings) bag.warn(code, message, item);
1417
+ checkDocumentationTokens(this.workspaceConfig, sections, bag, options.secretsRemedy);
1418
+ const documentedSections = docsView.apiGroups === void 0 ? sections : { ...sections, app: docsView.apiGroups };
1419
+ checkApiGroupDocsExposure(documentedSections, bag, new Set(docsView.unresolvedGroups), options.secretsRemedy);
1420
+ this.validateQueryAuth(sections, bag);
1421
+ this.validateMiddlewareAuth(sections, bag);
1422
+ this.validatePostMiddlewareEnvelope(sections, bag);
1423
+ checkMicroserviceSecrets(sections, bag);
1424
+ checkMicroserviceBlocks(sections, bag);
1425
+ checkNonJsonValues(sections, bag, this.workspaceConfig);
1426
+ checkLiveDatasourceTests(sections, bag);
1427
+ checkStacks(
1428
+ this.tableDefs,
1429
+ sections,
1430
+ bag,
1431
+ this.workspaceConfig,
1432
+ this.envAuthored ? "authored" : this.configAttached ? "no-env" : "unattached"
1433
+ );
1434
+ checkExpressionOperands(sections, bag);
1435
+ checkInterpolatedValues(sections, bag);
1436
+ checkZeroBasedObjects(sections, bag);
1437
+ checkIntRange(sections, bag);
1438
+ checkRegexOperandOrder(sections, bag);
1439
+ checkTimezoneArgs(sections, bag);
1440
+ checkReferences(this.bundleType, sections, this.workspaceConfig.guid, bag);
1441
+ checkMicroserviceReferences(this.bundleType, sections, bag);
1442
+ checkDecodeOnlyStatements(sections, bag);
1443
+ checkRunFamilyHosts(sections, bag);
1444
+ checkLoopControl(sections, bag);
1445
+ checkSwitchFallthrough(sections, bag);
1446
+ checkSearchOperandFilters(sections, bag);
1447
+ checkFilterOperands(sections, bag);
1448
+ checkToolAuthIdentity(sections, bag);
1449
+ checkPrimitiveAuthIdentity(sections, bag);
1450
+ checkWriteBeforeElicit(sections, bag);
1451
+ checkMcpStackHazards(sections, bag);
1452
+ checkMcpResourceUris(sections, bag);
1453
+ checkMcpOauth(sections, bag);
1454
+ checkMcpOauthRevoke(sections, bag);
1455
+ checkStackAuthRatelimit(sections, bag);
1456
+ checkRatelimitWithoutError(sections, bag);
1457
+ checkAuthNoCaller(sections, bag);
1458
+ checkRealtimeGates(sections, bag);
1459
+ checkRealtimeSilentShapes(sections, bag);
1460
+ checkNonNullVectorColumns(sections, bag);
1461
+ checkRealtimeDeliver(this.bundleType, sections, bag);
1462
+ checkRealtimeJoinDeliver(sections, bag);
1463
+ checkTriggerBindings(sections, bag);
1464
+ checkUnboundVarRefs(sections, bag);
1465
+ checkToThrowScope(sections, bag);
1466
+ checkPasswordInputHashing(sections, bag);
1467
+ checkZipPasswordKeys(sections, bag);
1468
+ checkSafeRefMatchArgs(sections, bag);
1469
+ checkNullMatchArgs(sections, bag);
1470
+ checkPathSegmentCandidates(sections, bag);
1471
+ checkRouteShadowing(sections, bag);
1472
+ checkSameNameSiblings(sections, bag);
1473
+ checkSeed(this.tableDefs, bag, this.workspaceConfig.use_xdo === true);
1474
+ checkReservedColumnNames(this.tableDefs, bag);
1475
+ checkUnusableColumnNames(this.tableDefs, bag);
1476
+ checkCacheTtl(sections, bag);
1477
+ checkReservedInputNames(sections, bag);
1478
+ checkOmittedCallInputs(sections, bag);
1479
+ checkUnknownCallInputs(sections, bag);
1480
+ checkAddonAttachments(sections, bag);
1481
+ checkUnitTests(sections, bag);
1482
+ checkAddonOutput(sections, bag);
1483
+ checkGuardRoleColumns(sections, this.tableDefs, bag);
1484
+ checkToolOutputSchema(sections, bag);
1485
+ checkAgentArgPlaceholders(sections, bag);
1486
+ checkAssertionsOutsideTests(sections, bag);
1487
+ checkAgentApiKeys(sections, bag);
1488
+ checkKnowledge(sections, bag, { resolved: options.knowledge !== void 0 });
1489
+ checkRealtimePublish(this.bundleType, sections, bag);
1490
+ this.checkAllowsUsed(bag, subjects, used);
1491
+ options.accepted?.push(...bag.accepted());
1492
+ bag.flush();
1493
+ if (lockCtx) this.applyLock(lockCtx, sections);
1494
+ if (this.workspaceConfig.guid === void 0) {
1495
+ const wsName = typeof this.workspaceConfig.name === "string" ? this.workspaceConfig.name : "workspace";
1496
+ this.workspaceConfig.guid = deriveGuid("workspace", wsName);
1497
+ }
1498
+ const shipped = resolveDocs();
1499
+ if (shipped.apiGroups !== void 0) sections["app"] = shipped.apiGroups;
1500
+ return buildBundle({
1501
+ type: this.bundleType,
1502
+ workspace: shipped.workspace,
1503
+ sections,
1504
+ lock: lockCtx?.lock,
1505
+ ...options.envOverrides ? { envOverrides: options.envOverrides } : {},
1506
+ ...options.knowledge !== void 0 ? { knowledgeRead: true } : {}
1507
+ });
1508
+ }
1509
+ /**
1510
+ * The def each object this export checks was registered from — the encoded
1511
+ * objects, the table defs whose columns are read directly, and the copies the
1512
+ * docs view took — for a finding to name its subject.
1513
+ */
1514
+ diagnosticSubjects(sections, docsCopies) {
1515
+ const subjects = /* @__PURE__ */ new Map();
1516
+ const add = (obj2, kind) => {
1517
+ if (obj2 === null || typeof obj2 !== "object") return;
1518
+ const name = obj2.name;
1519
+ if (typeof name === "string") subjects.set(obj2, { kind, name });
1520
+ };
1521
+ add(this.workspaceConfig, "workspace");
1522
+ for (const [key, items] of Object.entries(sections)) {
1523
+ for (const obj2 of items ?? []) add(obj2, sdkKindName(key, obj2));
1524
+ }
1525
+ for (const def of this.tableDefs) add(def, "table");
1526
+ docsCopies?.forEach((copy, i) => {
1527
+ const source = subjects.get(sections["app"]?.[i]);
1528
+ if (source && copy !== null && typeof copy === "object") subjects.set(copy, source);
1529
+ });
1530
+ return subjects;
1531
+ }
1532
+ /**
1533
+ * Warn on each `diagnostics.allow` code that accepted nothing in this export.
1534
+ * The shape it named is gone, or the check stopped finding it — either way
1535
+ * the source still reads as "this def has a known hazard". Raised directly
1536
+ * rather than through `warn`: it is about the allow itself, so no allow can
1537
+ * accept it. A code whose check did not run here had nothing to accept.
1538
+ */
1539
+ checkAllowsUsed(bag, subjects, used) {
1540
+ const owners = /* @__PURE__ */ new Map();
1541
+ for (const [obj2, subject] of subjects()) {
1542
+ const allow = obj2 === this.workspaceConfig ? this.workspaceAccepted : this.accepted.get(obj2);
1543
+ if (allow && !owners.has(allow)) owners.set(allow, subject);
1544
+ }
1545
+ for (const [allow, subject] of owners) {
1546
+ const unused = [...allow].filter((code) => used.get(allow)?.has(code) !== true && !bag.wasSkipped(code));
1547
+ if (unused.length === 0) continue;
1548
+ const one = unused.length === 1;
1549
+ bag.add({
1550
+ severity: "warning",
1551
+ code: "diagnostics.allow-unused",
1552
+ message: `${subject.kind} "${subject.name}": \`diagnostics.allow\` accepts ${unused.map((c) => `"${c}"`).join(", ")}, but this export raised no such warning about ${allow === this.workspaceAccepted ? "any def" : "it"} \u2014 the shape ${one ? "it" : "they"} accepted is gone, or the check no longer finds it. Remove ${one ? "it" : "them"} from \`allow\`.`,
1553
+ subject
1554
+ });
1555
+ }
1556
+ }
1557
+ /**
1558
+ * Cross-check every query's resolved `auth` against the registered auth tables.
1559
+ *
1560
+ * `resolveAuth` (in `encodeQuery`) turns a table ref into a guid with no
1561
+ * registry visibility, so a bare-name typo produces a valid-looking guid that
1562
+ * only fails at deploy with an opaque engine error. Here we have the registry,
1563
+ * so we catch it at export and name the offending query.
1564
+ *
1565
+ * A registered table that is not `table({ auth: true })` only WARNS: the
1566
+ * engine reads that flag nowhere at request time (it compares the token's
1567
+ * `dbo` to the endpoint's by name, and mints tokens for any table by name), so
1568
+ * refusing the combination blocked a real workspace's round trip. A numeric
1569
+ * `auth` (raw `dbo.id` escape hatch) references a table by id xanosdk never
1570
+ * sees, so it's left as-is; `false` is a public endpoint. A table that pins an
1571
+ * explicit `guid` referenced by bare name lands in the "not registered" branch
1572
+ * (its name-derived guid diverges from the pinned one) — pass the def instead.
1573
+ */
1574
+ validateQueryAuth(sections, bag) {
1575
+ const queries = sections["query"];
1576
+ if (!Array.isArray(queries) || queries.length === 0) return;
1577
+ const tableNameByGuid = /* @__PURE__ */ new Map();
1578
+ const authGuids = /* @__PURE__ */ new Set();
1579
+ for (const def of this.tableDefs) {
1580
+ const guid = resolveRef("dbo", def);
1581
+ tableNameByGuid.set(guid, def.name);
1582
+ if (def.auth === true) authGuids.add(guid);
1583
+ }
1584
+ for (const q of queries) {
1585
+ if (!q || typeof q !== "object") continue;
1586
+ const auth = q.auth;
1587
+ if (typeof auth !== "string" || authGuids.has(auth)) continue;
1588
+ const name = String(q.name ?? "?");
1589
+ const known = tableNameByGuid.get(auth);
1590
+ if (known) {
1591
+ bag.warn(
1592
+ "query.auth-table-unflagged",
1593
+ `query "${name}" requires auth against table "${known}", which is not marked \`table({ auth: true })\`. The engine allows it \u2014 a token minted for that table is accepted \u2014 but the editor will not offer the table as an auth source. Mark it if that is what you meant.`,
1594
+ q
1595
+ );
1596
+ continue;
1597
+ }
1598
+ if (this.bundleType === "workspace") continue;
1599
+ bag.error(
1600
+ "query.auth-table-unregistered",
1601
+ refSpelling(auth) === "handle" ? `query "${name}": \`auth\` is a table def that isn't registered on this workspace \u2014 add it with \`registerTables([\u2026])\`.` : `query "${name}": \`auth\` references a table that isn't registered on this workspace. Check the name for a typo, or register the auth table with \`registerTables([\u2026])\`; if it pins an explicit \`guid\`, pass the table def rather than its name.`
1602
+ );
1603
+ }
1604
+ }
1605
+ /**
1606
+ * Warn about an `auth()`-keyed middleware **directly attached** to a host where
1607
+ * there is no caller identity for `auth()` to resolve.
1608
+ *
1609
+ * The footgun: a rate limiter keyed by `auth("id")` is the canonical middleware,
1610
+ * but attach it to a host with no authenticated caller and `auth()` cannot
1611
+ * resolve — every request 403s before the host runs, with no signal at author
1612
+ * or export time. This surfaces it at export, where the
1613
+ * middleware registry is known (an attachment entry only carries the target's
1614
+ * guid; we resolve it back to the encoded `run` to inspect for `auth()`).
1615
+ *
1616
+ * It **warns, never throws** — a bare `auth()` reference is not proof the
1617
+ * request will fail: the statement holding it may sit on a branch that never
1618
+ * runs on this host, and the same middleware object is often attached to
1619
+ * authenticated hosts too. Blocking the export would produce false positives
1620
+ * on legitimate use. The warning names the host and reason so
1621
+ * the author can confirm intent, key off `sys.remoteIp()`, or move to an
1622
+ * authenticated host.
1623
+ *
1624
+ * Scope: the host's EFFECTIVE chain, across all three tiers. Seeing only a
1625
+ * host's own `middleware.pre`/`post` would let an author who DRY'd a per-user
1626
+ * limiter up to `apiGroup({ middleware })` or to the workspace tier silently
1627
+ * reintroduce the failure — the same unresolvable key, attached one level up,
1628
+ * with the warning switched off. The limiter is most naturally written once at
1629
+ * the group, so that is the tier that most needs the warning.
1630
+ *
1631
+ * The cascade is the engine's own: a phase whose `_customize` flag is set is
1632
+ * answered by that tier (including `clear()`, which customizes with an empty
1633
+ * list and therefore stops inheritance); an un-customized phase falls through
1634
+ * to the API group, then to the workspace's `{objType}_{phase}` map. A query
1635
+ * that clears a phase is NOT warned about a group middleware it does not run.
1636
+ *
1637
+ * An authenticated `query` (its own `auth` table set) resolves an identity, so
1638
+ * it is skipped at every tier.
1639
+ */
1640
+ validateMiddlewareAuth(sections, bag) {
1641
+ const authCache = /* @__PURE__ */ new Map();
1642
+ const referencesAuth = (guid, mw) => {
1643
+ let hit = authCache.get(guid);
1644
+ if (hit === void 0) {
1645
+ const run = mw?.run;
1646
+ hit = stackReferencesAuth(Array.isArray(run) ? run : void 0);
1647
+ authCache.set(guid, hit);
1648
+ }
1649
+ return hit;
1650
+ };
1651
+ const reasons = {
1652
+ query: "this endpoint has no auth table",
1653
+ task: "a task is scheduled/background and never has a request identity",
1654
+ function: "there is no caller identity unless an authenticated caller invokes it",
1655
+ tool: "there is no caller identity unless an authenticated caller invokes it",
1656
+ prompt: "there is no caller identity unless an authenticated caller invokes it",
1657
+ resource: "there is no caller identity unless an authenticated caller invokes it"
1658
+ };
1659
+ for (const { label, host, hostName, tier, guid, middleware } of this.attachedMiddleware(sections)) {
1660
+ if (label === "query" && host.auth) continue;
1661
+ if (!referencesAuth(guid, middleware)) continue;
1662
+ const mwName = String(middleware?.name ?? guid);
1663
+ bag.warn(
1664
+ "middleware.auth-null-host",
1665
+ `middleware "${mwName}" references auth() and is attached to ${label} "${hostName}"${tier}, where ${reasons[label]}. auth() cannot resolve there and the request FAILS (403) rather than degrading to a shared key \u2014 attach it to an authenticated host, key off sys.remoteIp(), or remove auth().`,
1666
+ middleware
1667
+ );
1668
+ }
1669
+ }
1670
+ /**
1671
+ * Warn about a middleware in a host's effective **`post`** chain that reads a
1672
+ * request field out of `s.util.get_all_input` — see `postEnvelopeMisreads`.
1673
+ *
1674
+ * In `post` that envelope holds the host's outcome (`{ status, result }`), not
1675
+ * the request, so the read cannot resolve. Under the default `rethrow` policy
1676
+ * it fails the request with `Unable to locate var` after the host's stack has
1677
+ * run and its writes have landed. Checked on the effective chain for the same
1678
+ * reason as {@link validateMiddlewareAuth}: a post middleware is most often
1679
+ * attached once, at the group or the workspace tier.
1680
+ *
1681
+ * Warns rather than throws: the same middleware is valid in a `pre` chain, and
1682
+ * a read on a branch the post path never takes fails nothing.
1683
+ */
1684
+ validatePostMiddlewareEnvelope(sections, bag) {
1685
+ for (const middleware of sections["middleware"] ?? []) {
1686
+ const unnested = unnestedEnvelopeReads(middleware);
1687
+ if (unnested.length === 0) continue;
1688
+ const hard = unnested.filter((r) => !r.safe);
1689
+ const soft = unnested.filter((r) => r.safe);
1690
+ const list = (rs) => rs.map((r) => `\`${r.path}\``).join(", ");
1691
+ const fixed = unnested.map((r) => `\`${r.path.replace(".", ".vars.")}\``).join(", ");
1692
+ const outcome = [
1693
+ hard.length > 0 ? `${list(hard)} fails with \`Unable to locate var\` (a 500)` : "",
1694
+ soft.length > 0 ? `${list(soft)} (a safe/\`get\` read) is always null, silently` : ""
1695
+ ].filter(Boolean);
1696
+ bag.warn(
1697
+ "middleware.envelope-unnested",
1698
+ `middleware "${String(middleware.name ?? "?")}" reads ${list(unnested)} straight off \`s.util.get_all_input\`, which binds a \`{ type, vars }\` envelope \u2014 the request is under \`vars\`, so ${outcome.join("; ")}. In \`pre\` read ${fixed} (or unwrap once: \`asFilters: [fl.get(c.text("vars"))]\`); in \`post\`, \`vars\` is \`{ status, result }\` and the request body is \`s.util.get_raw_input\`.`,
1699
+ middleware
1700
+ );
1701
+ }
1702
+ const misreadCache = /* @__PURE__ */ new Map();
1703
+ for (const { label, hostName, phase, tier, guid, middleware } of this.attachedMiddleware(sections)) {
1704
+ if (phase !== "post") continue;
1705
+ let misreads = misreadCache.get(guid);
1706
+ if (misreads === void 0) {
1707
+ misreads = postEnvelopeMisreads(middleware);
1708
+ misreadCache.set(guid, misreads);
1709
+ }
1710
+ if (misreads.length === 0) continue;
1711
+ const mwName = String(middleware?.name ?? guid);
1712
+ const results = [...new Set(misreads.map((p) => p.split(".")[0]))].map((b) => `\`${b}.vars.result.<field>\``).join(" / ");
1713
+ bag.warn(
1714
+ "middleware.post-reads-request",
1715
+ `middleware "${mwName}" is in the post chain of ${label} "${hostName}"${tier} and reads ${misreads.map((p) => `\`${p}\``).join(", ")} from \`s.util.get_all_input\`. In \`post\` that envelope is \`{ type, vars: { status, result } }\` (plus \`payload\` on an error) \u2014 the host's outcome, not the request \u2014 so the read fails with \`Unable to locate var\` after the host already ran (under \`rethrow\`, a failed response for committed work). Read the response at ${results}, or the request body with \`s.util.get_raw_input\`.`,
1716
+ middleware
1717
+ );
1718
+ }
1719
+ }
1720
+ /**
1721
+ * Every enabled middleware attachment in each leaf host's EFFECTIVE chain,
1722
+ * resolved across all three tiers — one row per host, phase and entry.
1723
+ *
1724
+ * The cascade is the engine's own: a phase whose `_customize` flag is set is
1725
+ * answered by that tier (including `clear()`, which customizes with an empty
1726
+ * list and therefore stops inheritance); an un-customized phase falls through
1727
+ * to the API group (queries only), then to the workspace's
1728
+ * `{objType}_{phase}` map. The apiGroup and workspace tiers are not hosts —
1729
+ * they are resolved INTO each host's chain. A disabled attachment does not run
1730
+ * and is not yielded.
1731
+ */
1732
+ *attachedMiddleware(sections) {
1733
+ const middlewares = sections["middleware"];
1734
+ if (!Array.isArray(middlewares) || middlewares.length === 0) return;
1735
+ const byGuid = /* @__PURE__ */ new Map();
1736
+ for (const mw of middlewares) {
1737
+ if (!mw || typeof mw !== "object") continue;
1738
+ const guid = mw.guid;
1739
+ if (typeof guid === "string") byGuid.set(guid, mw);
1740
+ }
1741
+ const groupByGuid = /* @__PURE__ */ new Map();
1742
+ for (const group of sections["app"] ?? []) {
1743
+ if (!group || typeof group !== "object") continue;
1744
+ const guid = group.guid;
1745
+ if (typeof guid === "string") groupByGuid.set(guid, group);
1746
+ }
1747
+ const workspaceTier = this.workspaceConfig.middleware ?? {};
1748
+ const list = (x) => Array.isArray(x) ? x : [];
1749
+ const customizes = (block, phase) => !!block && typeof block === "object" && block[`${phase}_customize`] === true;
1750
+ for (const label of MIDDLEWARE_HOST_KINDS) {
1751
+ const hosts = sections[label];
1752
+ if (!Array.isArray(hosts)) continue;
1753
+ for (const host of hosts) {
1754
+ if (!host || typeof host !== "object") continue;
1755
+ const block = host.middleware;
1756
+ const hostName = String(host.name ?? "?");
1757
+ const groupId = label === "query" ? host.app?.id : void 0;
1758
+ const group = typeof groupId === "string" ? groupByGuid.get(groupId) : void 0;
1759
+ for (const phase of ["pre", "post"]) {
1760
+ let entries;
1761
+ let tier;
1762
+ if (customizes(block, phase)) {
1763
+ entries = list(block[phase]);
1764
+ tier = "";
1765
+ } else if (group && customizes(group.middleware, phase)) {
1766
+ entries = list(group.middleware[phase]);
1767
+ tier = ` (inherited from apiGroup "${String(group.name ?? "?")}")`;
1768
+ } else {
1769
+ entries = list(workspaceTier[`${label}_${phase}`]);
1770
+ tier = " (inherited from the workspace tier)";
1771
+ }
1772
+ for (const entry of entries) {
1773
+ if (entry?.disabled === true) continue;
1774
+ const guid = middlewareEntryGuid(entry);
1775
+ if (!guid) continue;
1776
+ yield {
1777
+ label,
1778
+ host,
1779
+ hostName,
1780
+ phase,
1781
+ tier,
1782
+ guid,
1783
+ middleware: byGuid.get(guid)
1784
+ };
1785
+ }
1786
+ }
1787
+ }
1788
+ }
1789
+ }
1790
+ /**
1791
+ * Lock participation (see {@link export}): canonical fill + identity report.
1792
+ * Runs after all sections are assembled and before signing.
1793
+ */
1794
+ applyLock(ctx, sections) {
1795
+ const usedCanonicals = /* @__PURE__ */ new Set();
1796
+ for (const entry of Object.values(ctx.lock.objects)) {
1797
+ if (entry.canonical) usedCanonicals.add(entry.canonical);
1798
+ }
1799
+ for (const arr of Object.values(sections)) {
1800
+ for (const obj2 of arr ?? []) {
1801
+ const canonical = obj2.canonical;
1802
+ if (typeof canonical === "string" && canonical !== "") usedCanonicals.add(canonical);
1803
+ }
1804
+ }
1805
+ const mintUnique = () => {
1806
+ let token = mintCanonical();
1807
+ while (usedCanonicals.has(token)) token = mintCanonical();
1808
+ usedCanonicals.add(token);
1809
+ return token;
1810
+ };
1811
+ const canonicalByGuid = (guid) => {
1812
+ if (typeof guid !== "string") return void 0;
1813
+ for (const entry of Object.values(ctx.lock.objects)) {
1814
+ if (entry.guid === guid && entry.canonical !== void 0) return entry.canonical;
1815
+ }
1816
+ return void 0;
1817
+ };
1818
+ const sourceByKey = /* @__PURE__ */ new Map();
1819
+ for (const key of CANONICAL_PAYLOAD_KEYS) {
1820
+ for (const obj2 of sections[key] ?? []) {
1821
+ if (!obj2 || typeof obj2 !== "object") continue;
1822
+ const o = obj2;
1823
+ if (typeof o.name !== "string") continue;
1824
+ if (o.canonical === "") {
1825
+ const locked = ctx.lock.objects[lockKey(key, o.name)];
1826
+ o.canonical = locked?.canonical ?? canonicalByGuid(o.guid) ?? mintUnique();
1827
+ if (locked?.canonical !== void 0 && locked.canonical_source === "adopted") this.adoptedCanonicals.add(obj2);
1828
+ this.filledCanonicals.add(obj2);
1829
+ }
1830
+ sourceByKey.set(
1831
+ lockKey(key, o.name),
1832
+ this.adoptedCanonicals.has(obj2) ? "adopted" : this.filledCanonicals.has(obj2) ? "minted" : "code"
1833
+ );
1834
+ }
1835
+ }
1836
+ const ws = this.workspaceConfig;
1837
+ if (ws.canonical === "") {
1838
+ ws.canonical = ctx.lock.objects[WORKSPACE_KEY]?.canonical ?? "";
1839
+ }
1840
+ if (typeof ws.canonical === "string" && ws.canonical !== "") {
1841
+ recordObserved(ctx, WORKSPACE_KEY, { canonical: ws.canonical });
1842
+ }
1843
+ const appNames = identityNamesByGuid(sections);
1844
+ const claimed = /* @__PURE__ */ new Map();
1845
+ for (const [payloadKey, arr] of Object.entries(sections)) {
1846
+ if (!LOCK_PAYLOAD_KEYS.has(payloadKey)) continue;
1847
+ for (const obj2 of arr ?? []) {
1848
+ if (!obj2 || typeof obj2 !== "object") continue;
1849
+ const o = obj2;
1850
+ if (typeof o.name !== "string" || typeof o.guid !== "string") continue;
1851
+ const identity = { guid: o.guid };
1852
+ if (this.codeGuids.has(o.guid)) identity.guid_source = "code";
1853
+ const lockName = lockNameForObject(payloadKey, o, appNames);
1854
+ const key = lockKey(payloadKey, lockName);
1855
+ const label = `${sdkKindName(payloadKey, o)} "${o.name}"`;
1856
+ const prior = claimed.get(key);
1857
+ if (prior !== void 0 && prior.guid !== o.guid) {
1858
+ const why = payloadKey === "toolset" ? "Agents and MCP servers share ONE name space." : `Two objects of one kind sharing a name behind explicit guids.`;
1859
+ throw new Error(
1860
+ `Two exported objects collapse onto lock key "${sdkKindName(payloadKey, o)}:${lockName}" \u2014 ${prior.label} and ${label}, with different guids (${prior.guid} vs ${o.guid}). ${why} A lock entry holds ONE guid per name, so an explicit \`guid\` cannot separate them: rename one.`
1861
+ );
1862
+ }
1863
+ claimed.set(key, { label, guid: o.guid });
1864
+ if (typeof o.canonical === "string" && o.canonical !== "") {
1865
+ identity.canonical = o.canonical;
1866
+ const source = sourceByKey.get(key);
1867
+ if (source !== void 0) identity.canonical_source = source;
1868
+ }
1869
+ if (payloadKey === "toolset" && o.type === "agent") identity.type = "agent";
1870
+ recordObserved(ctx, key, identity);
1871
+ }
1872
+ }
1873
+ }
1874
+ };
1875
+ function workspace(name) {
1876
+ if (typeof name !== "string" || name.trim() === "") {
1877
+ throw new Error(
1878
+ `workspace(name): the workspace name must be a non-empty string \u2014 got ${describeEntry(name)}. Name it: \`workspace("my-app")\`.`
1879
+ );
1880
+ }
1881
+ const shorthand = { name };
1882
+ SHORTHAND_CONFIGS.add(shorthand);
1883
+ return new Xano().registerWorkspace(shorthand);
1884
+ }
1885
+ var SHORTHAND_CONFIGS = /* @__PURE__ */ new WeakSet();
1886
+
1887
+ export {
1888
+ refuseUnknown,
1889
+ MCP_OAUTH_ENV_REF,
1890
+ encodeMcpOauth,
1891
+ checkFilterOperands,
1892
+ XANO_ORIGIN,
1893
+ standaloneDefKind,
1894
+ Xano,
1895
+ workspace
1896
+ };
1897
+ //# sourceMappingURL=chunk-CTMO46PK.js.map