@voltro/cli 0.54.0 → 0.56.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 (173) hide show
  1. package/CHANGELOG.md +639 -2
  2. package/bin/voltro.mjs +24 -0
  3. package/dist/{apiBuild-DTWp0S_q.js → apiBuild-Bdaetr37.js} +119 -88
  4. package/dist/apiBuild-Vw1figjO.js +2 -0
  5. package/dist/bin.js +1 -1
  6. package/dist/{build-D4ygSbnV.js → build-CI36wL4R.js} +339 -314
  7. package/dist/buildReport-52gHKgfO.js +64 -0
  8. package/dist/{checkCommand-Dg1G7Gwd.js → checkCommand-CAwFXrxA.js} +6 -6
  9. package/dist/{checkCommand-L7DTlpIF.js → checkCommand-D0QV_zM_.js} +1 -1
  10. package/dist/{clusterCmd-DrVFCzSj.js → clusterCmd-CdLB1GkT.js} +1 -1
  11. package/dist/{codegen-DSLM8Su9.js → codegen-Bth5lUTU.js} +76 -64
  12. package/dist/codegen-DbH7NbCR.js +2 -0
  13. package/dist/{codegenCommand-CG_Vx4lc.js → codegenCommand-CidbQzbv.js} +15 -14
  14. package/dist/{codemodRunner-Cd4xkC6u.js → codemodRunner-BlQPfjzA.js} +277 -0
  15. package/dist/{commands-6Kzi92Np.js → commands-CWjfThXv.js} +35 -35
  16. package/dist/{dashboardCommand-Cq1PWvI1.js → dashboardCommand-BekcY5Ls.js} +3 -3
  17. package/dist/{dataCommand-DYzW8vkv.js → dataCommand-2pccgbIy.js} +267 -195
  18. package/dist/{dbCommand-B4NWZtGL.js → dbCommand-DpK_vQET.js} +457 -441
  19. package/dist/dbCommand-DrycGWWt.js +2 -0
  20. package/dist/{dev-cKUiZZsB.js → dev-B9Gz0k85.js} +1 -1
  21. package/dist/{dev-CmuvUKRq.js → dev-Dw263KPu.js} +2598 -2452
  22. package/dist/doctorCommand-BMWs6aVm.js +2 -0
  23. package/dist/{doctorCommand-DCiFVMtZ.js → doctorCommand-aR_bFmIi.js} +353 -251
  24. package/dist/{dormancyCommand-w1TrmgYP.js → dormancyCommand-eXTQMbHU.js} +1 -1
  25. package/dist/{embeddingsCommand-CMgPyRTr.js → embeddingsCommand-CTmiQvwa.js} +1 -1
  26. package/dist/{envCommand-Cyynmcfa.js → envCommand-BDUgV7EM.js} +12 -12
  27. package/dist/{evolveCommand-BwvQ8dVH.js → evolveCommand-YV8qW1LU.js} +2 -2
  28. package/dist/frameworkTableAssembly-CGNC0qr7.js +2 -0
  29. package/dist/{frameworkTableAssembly-D7LJuALW.js → frameworkTableAssembly-DNOFXfEQ.js} +102 -100
  30. package/dist/index.js +1 -1
  31. package/dist/{infoCommand-DlYlUPqs.js → infoCommand-BjVXpMlP.js} +1 -1
  32. package/dist/inspect-CNYvNXPU.js +1484 -0
  33. package/dist/inspect-S2rWy1Ys.js +2 -0
  34. package/dist/{inspectCmd-niF97fAq.js → inspectCmd-CP-G0sVK.js} +1 -1
  35. package/dist/{inspectFetch-EMuhTG_9.js → inspectFetch-BU1NyzxV.js} +36 -24
  36. package/dist/{inspectMetrics-CGF94puw.js → inspectMetrics-BY0Sjb2F.js} +19 -19
  37. package/dist/interruptedReplace-CwnkBb2X.js +41 -0
  38. package/dist/interruptedReplace-qzmFI020.js +2 -0
  39. package/dist/{logsCmd-B6oNsfaZ.js → logsCmd-BU8uCdys.js} +1 -1
  40. package/dist/{manifestBuild-Cqgsx2bM.js → manifestBuild-CEkjfpwc.js} +1 -1
  41. package/dist/manifestBuild-DIa_s6u0.js +2 -0
  42. package/dist/{migrate-BK_Bbx-_.js → migrate-SICulyz1.js} +2 -2
  43. package/dist/precompressAssets-YhTi1aWp.js +40 -0
  44. package/dist/{probeCommand-_C0YU207.js → probeCommand-6HxEkNDG.js} +2 -2
  45. package/dist/{runtimeTrace-CGWx1Q6l.js → runtimeTrace-DgYMc09E.js} +1 -1
  46. package/dist/{scheduleCmd-DQRu6BZC.js → scheduleCmd-DYBUfo_T.js} +1 -1
  47. package/dist/{sdkgen-CDGHQUFj.js → sdkgen-PY-umd6O.js} +1 -1
  48. package/dist/{seedRunner-Dgsiwk_e.js → seedRunner-DISBKow-.js} +16 -16
  49. package/dist/serveCommand-BITS8Hpj.js +2 -0
  50. package/dist/{serveCommand-Bje09q1v.js → serveCommand-DIJ3ma76.js} +951 -909
  51. package/dist/serveEntry.js +1 -1
  52. package/dist/{start-Clz-1BHB.js → start-B9NGB8gn.js} +627 -588
  53. package/dist/{start-B0bnJgxI.js → start-BFQQkL1i.js} +1 -1
  54. package/dist/startEntry.js +1 -1
  55. package/dist/staticCachePolicy-CIyj6DbS.js +15 -0
  56. package/dist/{test-D_kW4KMj.js → test-jipIQ5Mx.js} +1 -1
  57. package/dist/{tracesCmd-DgtgOUdi.js → tracesCmd-BWYDqMy6.js} +1 -1
  58. package/dist/{updateCommand-CRJlAOaM.js → updateCommand-C9n_Z_oG.js} +8 -2
  59. package/dist/updateCommand-DsXEAHbd.js +2 -0
  60. package/dist/webDev-C2dRz9s5.js +2 -0
  61. package/dist/{webDev-DSI9SOhs.js → webDev-C53hJdcL.js} +1265 -1288
  62. package/dist/{webhooksCommand-BvzXNHji.js → webhooksCommand-uuPu8qQX.js} +1 -1
  63. package/dist/{workflowsCmd-BGF-mRZ5.js → workflowsCmd-g-DNpaUc.js} +1 -1
  64. package/package.json +67 -19
  65. package/templates/AGENTS.core.md +20 -1
  66. package/templates/AGENTS.md +21 -2
  67. package/templates/agent-docs/_index.md +1 -1
  68. package/templates/agent-docs/_manifest.json +1 -1
  69. package/templates/agent-docs/authentication.md +49 -6
  70. package/templates/agent-docs/cli.md +216 -11
  71. package/templates/agent-docs/data.md +209 -18
  72. package/templates/agent-docs/database/scaling.md +40 -1
  73. package/templates/agent-docs/deployment.md +53 -1
  74. package/templates/agent-docs/internationalization.md +32 -0
  75. package/templates/agent-docs/local-first-mobile.md +9 -2
  76. package/templates/agent-docs/observability.md +227 -0
  77. package/templates/agent-docs/plugins/billing.md +15 -0
  78. package/templates/agent-docs/plugins/broadcast.md +2 -1
  79. package/templates/agent-docs/plugins/ratelimit.md +6 -1
  80. package/templates/agent-docs/plugins/row-history.md +11 -0
  81. package/templates/agent-docs/plugins.md +65 -8
  82. package/templates/agent-docs/reference.md +5 -3
  83. package/templates/agent-docs/routing.md +18 -0
  84. package/templates/agent-docs/schema-driven-ui.md +125 -0
  85. package/templates/agent-docs/templates/appshells.md +3 -3
  86. package/templates/agent-docs/whats-new.md +408 -106
  87. package/templates/apps/api-ai/package.json +6 -6
  88. package/templates/apps/api-auth/package.json +8 -8
  89. package/templates/apps/api-backend/package.json +7 -7
  90. package/templates/apps/api-backend-deactivation/package.json +7 -7
  91. package/templates/apps/api-backend-mail/package.json +8 -8
  92. package/templates/apps/api-backend-mariadb/package.json +9 -9
  93. package/templates/apps/api-backend-sqlite/package.json +8 -8
  94. package/templates/apps/api-backend-storage/package.json +8 -8
  95. package/templates/apps/api-cms/package.json +9 -9
  96. package/templates/apps/api-collab/package.json +8 -8
  97. package/templates/apps/api-data-advanced/package.json +8 -8
  98. package/templates/apps/api-durable/package.json +8 -8
  99. package/templates/apps/api-feature-flags/package.json +9 -9
  100. package/templates/apps/api-governance/package.json +8 -8
  101. package/templates/apps/api-kv/package.json +8 -8
  102. package/templates/apps/api-moderation/package.json +8 -8
  103. package/templates/apps/api-observability/package.json +8 -8
  104. package/templates/apps/api-ratelimit/package.json +8 -8
  105. package/templates/apps/api-rbac/package.json +8 -8
  106. package/templates/apps/api-rest/package.json +7 -7
  107. package/templates/apps/api-row-history/package.json +8 -8
  108. package/templates/apps/api-saas/package.json +11 -11
  109. package/templates/apps/api-saas-starter/package.json +10 -10
  110. package/templates/apps/api-search/package.json +8 -8
  111. package/templates/apps/api-status/package.json +8 -8
  112. package/templates/apps/api-webhooks/package.json +9 -9
  113. package/templates/apps/changelog/package.json +7 -7
  114. package/templates/apps/changelog/src/pages/[locale]/page.tsx +7 -1
  115. package/templates/apps/edge-functions/package.json +2 -2
  116. package/templates/apps/frontend-admin/package.json +7 -8
  117. package/templates/apps/frontend-admin/src/pages/(marketing)/layout.tsx +1 -2
  118. package/templates/apps/frontend-admin/src/pages/admin/layout.tsx +1 -2
  119. package/templates/apps/frontend-app/package.json +8 -9
  120. package/templates/apps/frontend-app/src/pages/layout.tsx +1 -2
  121. package/templates/apps/frontend-auth/package.json +7 -8
  122. package/templates/apps/frontend-auth/src/components/AuthShell.tsx +1 -2
  123. package/templates/apps/frontend-blank/package.json +6 -7
  124. package/templates/apps/frontend-blank/src/pages/layout.tsx +1 -2
  125. package/templates/apps/frontend-cms/package.json +8 -9
  126. package/templates/apps/frontend-cms/src/pages/(app)/layout.tsx +1 -2
  127. package/templates/apps/frontend-collab/README.md +7 -2
  128. package/templates/apps/frontend-collab/package.json +9 -10
  129. package/templates/apps/frontend-collab/src/pages/layout.tsx +1 -2
  130. package/templates/apps/frontend-collab/src/pages/page.test.tsx +8 -4
  131. package/templates/apps/frontend-collab/src/pages/page.tsx +10 -5
  132. package/templates/apps/frontend-contact/package.json +7 -7
  133. package/templates/apps/frontend-contact/src/components/ContactForm.island.tsx +1 -1
  134. package/templates/apps/frontend-dashboard/package.json +6 -7
  135. package/templates/apps/frontend-dashboard/src/pages/(marketing)/layout.tsx +1 -2
  136. package/templates/apps/frontend-dashboard/src/pages/dashboard/layout.tsx +1 -2
  137. package/templates/apps/frontend-docs/package.json +8 -8
  138. package/templates/apps/frontend-i18n/package.json +6 -6
  139. package/templates/apps/frontend-landing/package.json +7 -7
  140. package/templates/apps/frontend-portal/package.json +7 -8
  141. package/templates/apps/frontend-portal/src/pages/(portal)/layout.tsx +1 -2
  142. package/templates/apps/frontend-saas/package.json +7 -8
  143. package/templates/apps/frontend-saas/src/pages/(marketing)/layout.tsx +1 -2
  144. package/templates/apps/frontend-saas/src/pages/dashboard/layout.tsx +1 -2
  145. package/templates/apps/frontend-spa/package.json +6 -7
  146. package/templates/apps/frontend-spa/src/pages/layout.tsx +1 -2
  147. package/templates/apps/frontend-ssr/package.json +6 -7
  148. package/templates/apps/frontend-ssr/src/pages/layout.tsx +1 -2
  149. package/templates/apps/frontend-ssr-api/package.json +7 -8
  150. package/templates/apps/frontend-ssr-api/src/pages/layout.tsx +1 -2
  151. package/templates/apps/frontend-static-blog/package.json +8 -8
  152. package/templates/apps/frontend-static-blog/src/components/ReadingProgress.island.tsx +1 -1
  153. package/templates/apps/frontend-static-blog/src/pages/[locale]/page.tsx +7 -1
  154. package/templates/apps/frontend-status/package.json +7 -8
  155. package/templates/apps/frontend-status/src/pages/layout.tsx +1 -2
  156. package/templates/apps/mobile-app/package.json +4 -4
  157. package/templates/baselines/compose/docker/api.Dockerfile +61 -5
  158. package/templates/baselines/compose/docker/web.Dockerfile +55 -10
  159. package/templates/baselines/compose-mariadb/docker/api.Dockerfile +61 -5
  160. package/templates/baselines/compose-mariadb/docker/web.Dockerfile +55 -10
  161. package/dist/apiBuild-CeUN55uk.js +0 -2
  162. package/dist/codegen-DjgxEOnD.js +0 -2
  163. package/dist/dbCommand-CSFWs9ev.js +0 -2
  164. package/dist/doctorCommand-J3qu4E0Y.js +0 -2
  165. package/dist/frameworkTableAssembly-IPD1pUnZ.js +0 -2
  166. package/dist/inspect-Bd8-9wsi.js +0 -1193
  167. package/dist/inspect-CuoDInfZ.js +0 -2
  168. package/dist/interruptedReplace-C3O3M1MM.js +0 -28
  169. package/dist/interruptedReplace-CvmiAM9K.js +0 -2
  170. package/dist/manifestBuild-C4-J1-m_.js +0 -2
  171. package/dist/serveCommand-BiPe8BJm.js +0 -2
  172. package/dist/updateCommand-CIoVDKnj.js +0 -2
  173. package/dist/webDev-DlvZO30c.js +0 -2
@@ -0,0 +1,1484 @@
1
+ import { n as e } from "./inspectGateHint-4LxkNtrz.js";
2
+ import { processIdentity as t, replicaId as n } from "@voltro/protocol/identity";
3
+ import { lastWriteProvenance as r } from "@voltro/runtime";
4
+ import { timingSafeStringEqual as i } from "@voltro/protocol/session";
5
+ //#region src/observation.ts
6
+ var a = (e) => ({
7
+ replicaId: e.replicaId,
8
+ instanceId: e.instanceId,
9
+ startedAt: e.startedAt,
10
+ version: e.version,
11
+ bootPath: e.bootPath
12
+ }), o = (e) => e === void 0 ? {
13
+ complete: !1,
14
+ reason: "process-scoped, and membership could not say how many replicas exist"
15
+ } : e <= 1 ? {
16
+ complete: !0,
17
+ fleetSize: e
18
+ } : {
19
+ complete: !1,
20
+ fleetSize: e,
21
+ reason: `process-scoped: this is 1 of ${e} replicas`
22
+ }, s = () => ({ complete: !0 }), c = () => ({ complete: !0 }), l = [
23
+ ["", "declaration"],
24
+ ["/", "declaration"],
25
+ ["/app", "declaration"],
26
+ ["/routes", "declaration"],
27
+ ["/manifest", "declaration"],
28
+ ["/rpc", "declaration"],
29
+ ["/env", "declaration"],
30
+ ["/checks", "declaration"],
31
+ ["/agent/tools", "declaration"],
32
+ ["/subscriptions", "process"],
33
+ ["/metrics", "process"],
34
+ ["/logs", "process"],
35
+ ["/cache", "process"],
36
+ ["/data-cache", "process"],
37
+ ["/events", "process"],
38
+ ["/traces", "process"],
39
+ ["/aggregates", "process"],
40
+ ["/flags", "process"],
41
+ ["/cluster", "process"],
42
+ ["/members", "observed-fleet"],
43
+ ["/schedules", "shared-store"],
44
+ ["/schedules/runs", "shared-store"],
45
+ ["/workflows", "shared-store"],
46
+ ["/migrations", "shared-store"],
47
+ ["/database", "shared-store"],
48
+ ["/data/tables", "shared-store"],
49
+ ["/data/rows", "shared-store"],
50
+ ["/provenance", "shared-store"],
51
+ ["/storage", "shared-store"],
52
+ ["/webhooks", "shared-store"],
53
+ ["/plugins", "shared-store"],
54
+ ["/invoke", "write"],
55
+ ["/seeds/run", "write"],
56
+ ["/data/import", "write"],
57
+ ["/migrations/rollback", "write"],
58
+ ["/migrations/squash", "write"],
59
+ ["/migrations/restore-snapshot", "write"],
60
+ ["/migrations/compare-env", "write"],
61
+ ["/webhooks/", "write"],
62
+ ["/agent/call", "write"]
63
+ ], u = (e) => {
64
+ let t;
65
+ for (let n of l) {
66
+ let [r] = n;
67
+ (e === r || r.length > 0 && r !== "/" && (e.startsWith(`${r}/`) || e.startsWith(r))) && (t === void 0 || r.length > t[0].length) && (t = n);
68
+ }
69
+ return t?.[1];
70
+ }, d = "voltro-inspect-hop", f = (e, t) => {
71
+ let [n, r = ""] = e.split("?"), i = new URLSearchParams(r);
72
+ i.delete("replica"), i.set("scope", "process");
73
+ let a = i.toString();
74
+ return `http://${t}${n}${a === "" ? "" : `?${a}`}`;
75
+ }, p = async (e) => {
76
+ let t = (e.url.split("?")[0] ?? e.url).replace(/^.*\/_voltro\/inspect/, ""), n = u(t);
77
+ if (n === "write") return {
78
+ kind: "refused",
79
+ status: 400,
80
+ body: {
81
+ error: "a mutating endpoint cannot be addressed to a replica",
82
+ reason: "choosing which replica runs a destructive operation is not something a query parameter should hand out; call the replica directly if that is genuinely what you mean"
83
+ }
84
+ };
85
+ if (n === void 0) return {
86
+ kind: "refused",
87
+ status: 404,
88
+ body: {
89
+ error: "inspect route has no declared scope",
90
+ path: t
91
+ }
92
+ };
93
+ let r = await e.lookup.addressOf(e.replicaId);
94
+ if (r === void 0) return {
95
+ kind: "refused",
96
+ status: 404,
97
+ body: {
98
+ error: `no reachable replica named ${JSON.stringify(e.replicaId)}`,
99
+ reason: "the id is unknown, or that replica published no address a peer can reach (a loopback address is recorded as unreachable rather than attempted)",
100
+ fix: "read `/_voltro/inspect/subscriptions?scope=fleet` for the replicas that can be addressed"
101
+ }
102
+ };
103
+ let i = new AbortController(), a = setTimeout(() => i.abort(), e.timeoutMs ?? 3e3);
104
+ try {
105
+ let t = await (e.fetchImpl ?? fetch)(f(e.url, r), {
106
+ headers: {
107
+ ...e.authorization === void 0 ? {} : { authorization: e.authorization },
108
+ [d]: "1",
109
+ accept: "application/json"
110
+ },
111
+ signal: i.signal
112
+ });
113
+ return {
114
+ kind: "answered",
115
+ status: t.status,
116
+ body: await t.text()
117
+ };
118
+ } catch (t) {
119
+ return {
120
+ kind: "refused",
121
+ status: 504,
122
+ body: {
123
+ error: `replica ${JSON.stringify(e.replicaId)} did not answer`,
124
+ reason: String(t?.message ?? t)
125
+ }
126
+ };
127
+ } finally {
128
+ clearTimeout(a);
129
+ }
130
+ }, m = "/_voltro/inspect", h = () => process.env.VOLTRO_INSPECT === "off", g = /* @__PURE__ */ new Set([
131
+ "GET",
132
+ "HEAD",
133
+ "OPTIONS"
134
+ ]), _ = (t, n) => {
135
+ let r = process.env.VOLTRO_INSPECT_TOKEN;
136
+ if (!r || r.length === 0) return {
137
+ ok: !1,
138
+ reason: "inspect is closed: no VOLTRO_INSPECT_TOKEN configured. `voltro dev` mints one per project; for serve/start set it explicitly (it is never minted outside dev)."
139
+ };
140
+ let a = t.authorization ?? t.Authorization;
141
+ if (!a) return {
142
+ ok: !1,
143
+ reason: "missing Authorization header"
144
+ };
145
+ if (!a.startsWith("Bearer ")) return {
146
+ ok: !1,
147
+ reason: "expected \"Bearer <token>\" auth scheme"
148
+ };
149
+ let o = a.slice(7).trim();
150
+ if (!i(o, r)) return {
151
+ ok: !1,
152
+ reason: "token mismatch"
153
+ };
154
+ if (!g.has(n.toUpperCase())) {
155
+ let r = process.env.VOLTRO_INSPECT_WRITE_TOKEN;
156
+ if (!r || r.length === 0) return {
157
+ ok: !1,
158
+ reason: e("unset", n)
159
+ };
160
+ let a = (t["x-voltro-inspect-write"] ?? t["X-Voltro-Inspect-Write"] ?? "").trim();
161
+ if (a.length === 0) return {
162
+ ok: !1,
163
+ reason: e("absent", n)
164
+ };
165
+ if (!i(a, r)) return {
166
+ ok: !1,
167
+ reason: e("mismatch", n)
168
+ };
169
+ }
170
+ return { ok: !0 };
171
+ }, v = (e) => {
172
+ if (!Array.isArray(e) || e.length === 0) return;
173
+ let t = [];
174
+ for (let n of e) {
175
+ if (typeof n != "object" || !n) continue;
176
+ if (typeof n.open == "string") {
177
+ t.push({
178
+ kind: "open",
179
+ reason: n.open
180
+ });
181
+ continue;
182
+ }
183
+ if (typeof n.action == "string" && typeof n.resourceType == "string") {
184
+ t.push({
185
+ kind: "policy",
186
+ action: n.action,
187
+ resourceType: n.resourceType
188
+ });
189
+ continue;
190
+ }
191
+ let e = n.scope;
192
+ typeof e != "string" && !Array.isArray(e) || t.push({
193
+ kind: "scope",
194
+ scope: typeof e == "string" ? [e] : e.filter((e) => typeof e == "string"),
195
+ mode: n.mode === "any" ? "any" : "all",
196
+ resourceScoped: typeof n.resource == "function"
197
+ });
198
+ }
199
+ return t.length > 0 ? t : void 0;
200
+ }, y = (e, t, n = {}) => ({
201
+ status: e,
202
+ contentType: "application/json; charset=utf-8",
203
+ body: JSON.stringify(t),
204
+ headers: n,
205
+ payload: t
206
+ }), b = (e) => {
207
+ let t;
208
+ try {
209
+ t = new URL(e).hostname;
210
+ } catch {
211
+ return !1;
212
+ }
213
+ return t = t.replace(/^\[|\]$/g, ""), t === "localhost" || t.endsWith(".localhost") || t === "::1" ? !0 : /^127(?:\.\d{1,3}){3}$/.test(t);
214
+ }, x = (e) => !e || e.length === 0 ? {} : b(e) ? {
215
+ "access-control-allow-origin": e,
216
+ "access-control-allow-credentials": "true",
217
+ "access-control-allow-methods": "GET, POST, OPTIONS",
218
+ "access-control-allow-headers": "authorization, content-type, accept",
219
+ "access-control-expose-headers": "content-type, content-length",
220
+ vary: "Origin"
221
+ } : { vary: "Origin" }, S = "voltro_devtools_stream_token", C = (e, t, n = process.env) => {
222
+ let r = (e) => Array.isArray(e) ? e[0] : e, i = r(e.authorization);
223
+ if (i !== void 0 && i !== "") return i;
224
+ let a = r(e.cookie);
225
+ if (a !== void 0) for (let e of a.split(";")) {
226
+ let [t, ...n] = e.trim().split("=");
227
+ if (t === "voltro_devtools_stream_token" && n.length > 0) {
228
+ let e = decodeURIComponent(n.join("="));
229
+ if (e !== "") return `Bearer ${e}`;
230
+ }
231
+ }
232
+ let o = n.VOLTRO_INSPECT_TOKEN;
233
+ return b(t) && o !== void 0 && o !== "" ? `Bearer ${o}` : void 0;
234
+ }, w = (e, t = process.env.VOLTRO_DASHBOARD_APPS) => {
235
+ if (b(e)) return !0;
236
+ let n;
237
+ try {
238
+ n = new URL(e).origin;
239
+ } catch {
240
+ return !1;
241
+ }
242
+ if (!t || t.trim() === "") return !1;
243
+ try {
244
+ let e = JSON.parse(t);
245
+ return Array.isArray(e) ? e.some((e) => {
246
+ let t = e?.url;
247
+ if (typeof t != "string") return !1;
248
+ try {
249
+ return new URL(t).origin === n;
250
+ } catch {
251
+ return !1;
252
+ }
253
+ }) : !1;
254
+ } catch {
255
+ return !1;
256
+ }
257
+ }, T = (e, t, n = {}) => {
258
+ let r = (e ?? "GET").toUpperCase();
259
+ if (r === "GET" || r === "HEAD" || r === "OPTIONS") return null;
260
+ let i = t.origin ?? t.Origin;
261
+ return i === void 0 || i === "" || b(i) ? null : y(403, {
262
+ error: "cross-site write rejected",
263
+ reason: `a state-changing inspect request may not come from origin "${i}" — only same-machine (loopback) origins may write`
264
+ }, n);
265
+ }, E = (e = process.env.VOLTRO_INSPECT_ALLOWED_HOSTS) => (e ?? "").split(/[,\s]+/).map((e) => e.trim().toLowerCase()).filter((e) => e.length > 0), D = (e) => {
266
+ if (e === void 0) return "";
267
+ let t = e.trim();
268
+ if (t === "") return "";
269
+ if (t.startsWith("[")) {
270
+ let e = t.indexOf("]");
271
+ return (e === -1 ? t.slice(1) : t.slice(1, e)).toLowerCase();
272
+ }
273
+ let n = t.indexOf(":");
274
+ return (n === -1 ? t : t.slice(0, n)).toLowerCase();
275
+ }, O = (e) => /^\d{1,3}(?:\.\d{1,3}){3}$/.test(e) || e.includes(":"), k = (e, t = E()) => {
276
+ let n = D(e);
277
+ return n === "" || n === "localhost" || n.endsWith(".localhost") || O(n) ? !0 : t.includes(n);
278
+ }, A = (e, t = {}, n) => k(e, n) ? null : y(403, {
279
+ error: "forbidden host",
280
+ reason: `the dev inspect surface refuses a request with Host "${e ?? ""}" — a DNS-rebinding guard. Only loopback names, IP literals, and hosts listed in VOLTRO_INSPECT_ALLOWED_HOSTS may reach it.`
281
+ }, t), j = (e) => {
282
+ let t = e.indexOf("?");
283
+ return t === -1 ? e : e.slice(0, t);
284
+ }, M = (e) => {
285
+ let t = e.indexOf("?");
286
+ return t === -1 ? new URLSearchParams() : new URLSearchParams(e.slice(t + 1));
287
+ }, N = (e) => e === "/_voltro/inspect" || e.startsWith("/_voltro/inspect/"), P = [
288
+ "text",
289
+ "textarea",
290
+ "rich-text",
291
+ "number",
292
+ "checkbox",
293
+ "switch",
294
+ "select",
295
+ "radio",
296
+ "async-select",
297
+ "multi-select",
298
+ "date",
299
+ "datetime",
300
+ "daterange",
301
+ "file",
302
+ "hidden",
303
+ "array",
304
+ "reference",
305
+ "custom"
306
+ ], F = (e, t, n = [], r = []) => ({
307
+ version: 2,
308
+ scopes: [...new Set(r.flatMap((e) => e.declaredScopes ?? []))].sort(),
309
+ procedures: [...e].sort((e, t) => e.tag.localeCompare(t.tag)).map((e) => ({
310
+ tag: e.tag,
311
+ kind: e.kind,
312
+ ...e.inputSchema === void 0 ? {} : { input: e.inputSchema },
313
+ ...e.outputSchema === void 0 ? {} : { output: e.outputSchema },
314
+ ...e.source === void 0 ? {} : { source: e.source },
315
+ ...e.targets === void 0 ? {} : { targets: e.targets },
316
+ ...e.guards === void 0 ? {} : { guards: e.guards },
317
+ ...e.internal === !0 ? { internal: !0 } : {},
318
+ ...e.publicApi === void 0 ? {} : { publicApi: e.publicApi },
319
+ ...e.exposeAsTool === void 0 ? {} : { exposeAsTool: e.exposeAsTool }
320
+ })),
321
+ workflows: [...t].sort((e, t) => e.tag.localeCompare(t.tag)).map((e) => ({ name: e.tag })),
322
+ widgets: P,
323
+ tables: [...n].filter((e) => !e.isFrameworkTable).sort((e, t) => e.name.localeCompare(t.name)).map((e) => ({
324
+ name: e.name,
325
+ reactive: e.isReactive,
326
+ framework: e.isFrameworkTable,
327
+ editable: e.editable ?? !0,
328
+ ...e.pkColumn === void 0 ? {} : { pkColumn: e.pkColumn },
329
+ columns: e.columns.map((e) => ({
330
+ name: e.name,
331
+ type: String(e.type),
332
+ nullable: e.nullable,
333
+ ...e.referencesTable === void 0 ? {} : { refersTo: e.referencesTable },
334
+ ...e.oneOf === void 0 ? {} : { enum: e.oneOf },
335
+ ...e.serverOnly === !0 ? { serverOnly: !0 } : {},
336
+ ...e.encrypted === !0 ? { encrypted: !0 } : {},
337
+ ...e.sensitive === void 0 ? {} : { sensitive: e.sensitive }
338
+ }))
339
+ }))
340
+ }), I = (e) => {
341
+ let t = String(e?.message ?? e);
342
+ return /no such table/i.test(t) || /relation ".*" does not exist/i.test(t) || /Table '.*' doesn't exist/i.test(t) || /Invalid object name/i.test(t) || /Failed to prepare statement/i.test(t);
343
+ }, L = Symbol("inspect.parseFailed"), R = (e) => {
344
+ try {
345
+ return JSON.parse(e);
346
+ } catch {
347
+ return L;
348
+ }
349
+ }, z = (e, n, r) => {
350
+ if (n.status < 200 || n.status >= 300 || !n.contentType.startsWith("application/json")) return n;
351
+ let i = e.startsWith("/_voltro/inspect") ? e.slice(16) : e, l = u(i);
352
+ if (l === void 0) return y(500, {
353
+ error: "inspect route has no declared scope",
354
+ path: i,
355
+ fix: "add it to ROUTE_SCOPES in packages/cli/src/observation.ts — a payload that does not say whether it describes this process or the fleet cannot be acted on."
356
+ }, n.headers ?? {});
357
+ if (l === "write") return n;
358
+ let d = t();
359
+ if (n.assembled !== void 0) {
360
+ let e = n.assembled, t = n.payload === void 0 ? R(n.body) : n.payload;
361
+ return t === L ? n : y(n.status, {
362
+ data: t,
363
+ scope: {
364
+ kind: "fleet",
365
+ assembledBy: d.replicaId,
366
+ assembledAt: Date.now()
367
+ },
368
+ origin: a(d),
369
+ completeness: {
370
+ complete: e.missing.length === 0 && e.stale.length === 0,
371
+ responded: e.responded,
372
+ expected: e.expected,
373
+ ...e.missing.length > 0 ? { missing: e.missing } : {},
374
+ ...e.stale.length > 0 ? { stale: e.stale } : {},
375
+ ...e.versions === void 0 ? {} : { versions: e.versions },
376
+ ...e.missing.length > 0 || e.stale.length > 0 ? { reason: [e.missing.length > 0 ? `${e.missing.length} replica(s) have written nothing readable` : "", e.stale.length > 0 ? `${e.stale.length} answer(s) are older than the freshness window` : ""].filter((e) => e !== "").join("; ") } : {}
377
+ },
378
+ capturedAt: Date.now()
379
+ }, n.headers ?? {});
380
+ }
381
+ let f = l === "process" ? { kind: "process" } : l === "shared-store" ? { kind: "shared-store" } : l === "declaration" ? { kind: "declaration" } : {
382
+ kind: "fleet",
383
+ assembledBy: d.replicaId,
384
+ assembledAt: Date.now()
385
+ }, p = l === "process" ? o(r) : l === "shared-store" ? s() : l === "declaration" ? c() : {
386
+ complete: !0,
387
+ ...r === void 0 ? {} : { fleetSize: r },
388
+ reason: "one observer’s view: another replica may reach a different set, and that disagreement is the diagnostic rather than a fault to smooth over"
389
+ }, m = n.payload === void 0 ? R(n.body) : n.payload;
390
+ if (m === L) return n;
391
+ let h = {
392
+ data: m,
393
+ scope: f,
394
+ origin: a(d),
395
+ completeness: p,
396
+ capturedAt: Date.now()
397
+ };
398
+ return y(n.status, h, n.headers ?? {});
399
+ }, B = (e, t, n = {}, r = {}) => {
400
+ let i = V(e, t, n, r);
401
+ return i === null ? null : z(j(e), i, r.fleetSize);
402
+ }, V = (e, t, n = {}, r = {}) => {
403
+ let i = j(e);
404
+ if (!N(i)) return null;
405
+ let a = x(n.origin ?? n.Origin), o = (r.method ?? "GET").toUpperCase();
406
+ if (o === "OPTIONS") return {
407
+ status: 204,
408
+ contentType: "text/plain",
409
+ body: "",
410
+ headers: a
411
+ };
412
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, a);
413
+ let s = (r.authResolver ?? _)(n, o);
414
+ if (!s.ok) return y(401, {
415
+ error: "unauthorized",
416
+ reason: s.reason
417
+ }, a);
418
+ if (i === "/_voltro/inspect" || i === "/_voltro/inspect/" || i === "/_voltro/inspect/app") return y(200, {
419
+ kind: t.kind,
420
+ ...t.meta
421
+ }, a);
422
+ if (i === "/_voltro/inspect/routes") return t.kind === "web" ? y(200, {
423
+ pages: t.routes,
424
+ dirs: t.dirs
425
+ }, a) : y(404, { error: "routes endpoint is web-only" }, a);
426
+ if (i === "/_voltro/inspect/cache") return t.kind === "web" ? y(200, t.cache(), a) : y(404, { error: "cache endpoint is web-only" }, a);
427
+ if (i === "/_voltro/inspect/rpc") return t.kind === "api" ? y(200, {
428
+ procedures: t.rpc,
429
+ workflows: t.workflows
430
+ }, a) : y(404, { error: "rpc endpoint is api-only" }, a);
431
+ if (i === "/_voltro/inspect/manifest") {
432
+ if (t.kind !== "api") return y(404, { error: "manifest endpoint is api-only" }, a);
433
+ let e = t.inspectTables?.().tables ?? [];
434
+ return y(200, F(t.rpc, t.workflows, e, t.plugins?.().plugins ?? []), a);
435
+ }
436
+ return i === "/_voltro/inspect/metrics" ? t.metrics === void 0 ? y(200, [], a) : y(200, t.metrics(), a) : i === "/_voltro/inspect/subscriptions" ? t.kind === "api" ? t.subscriptions === void 0 ? y(200, {
437
+ subscriptions: [],
438
+ matcherStats: [],
439
+ resume: [],
440
+ capturedAt: Date.now()
441
+ }, a) : y(200, t.subscriptions(), a) : y(404, { error: "subscriptions endpoint is api-only" }, a) : i === "/_voltro/inspect/members" ? t.kind === "api" ? t.members === void 0 ? y(200, {
442
+ members: [],
443
+ capturedAt: Date.now()
444
+ }, a) : y(200, t.members(), a) : y(404, { error: "members endpoint is api-only" }, a) : i === "/_voltro/inspect/events" ? t.kind === "api" ? t.events === void 0 ? y(200, {
445
+ declared: [],
446
+ routes: [],
447
+ origin: "",
448
+ capturedAt: Date.now(),
449
+ totals: {
450
+ routes: 0,
451
+ subscribers: 0,
452
+ buffered: 0
453
+ }
454
+ }, a) : y(200, t.events(), a) : y(404, { error: "events endpoint is api-only" }, a) : i === "/_voltro/inspect/data-cache" ? t.kind === "api" ? t.dataCache === void 0 ? y(200, {
455
+ backend: "memory",
456
+ engine: "memory",
457
+ driver: "resp",
458
+ hits: 0,
459
+ misses: 0,
460
+ hitRate: 0
461
+ }, a) : y(200, t.dataCache(), a) : y(404, { error: "data-cache endpoint is api-only" }, a) : i === "/_voltro/inspect/database" ? t.kind === "api" ? t.database === void 0 ? y(200, {
462
+ migrations: [],
463
+ seeds: [],
464
+ dialect: "memory",
465
+ replication: {
466
+ replicaCount: 0,
467
+ rywPolicy: "off",
468
+ rywStore: "memory",
469
+ region: null,
470
+ localityEnabled: !1
471
+ }
472
+ }, a) : y(200, t.database(), a) : y(404, { error: "database endpoint is api-only" }, a) : i === "/_voltro/inspect/plugins" ? t.kind === "api" ? t.plugins === void 0 ? y(200, {
473
+ plugins: [],
474
+ capturedAt: Date.now()
475
+ }, a) : y(200, t.plugins(), a) : y(404, { error: "plugins endpoint is api-only" }, a) : i === "/_voltro/inspect/env" ? t.env === void 0 ? y(200, {
476
+ app: t.meta.name ?? "app",
477
+ entries: [],
478
+ summary: {
479
+ total: 0,
480
+ set: 0,
481
+ missingRequired: 0
482
+ }
483
+ }, a) : y(200, t.env(), a) : i === "/_voltro/inspect/data/tables" ? t.kind === "api" ? t.inspectTables === void 0 ? y(200, { tables: [] }, a) : y(200, t.inspectTables(), a) : y(404, { error: "data viewer is api-only" }, a) : i === "/_voltro/inspect/invoke" ? y(404, { error: "invoke not enabled here — use POST handler" }, a) : H.has(i) ? y(404, {
484
+ error: "endpoint not mounted on this instance",
485
+ path: i,
486
+ reason: "This inspect endpoint is served by `voltro dev`. A production `voltro serve` does not mount it — the data behind it (the in-memory log ring, the span buffer, the dev route table) is not collected there. This is not a missing token: the same request with no token would be 401."
487
+ }, a) : y(404, {
488
+ error: "unknown inspect endpoint",
489
+ path: i
490
+ }, a);
491
+ }, H = /* @__PURE__ */ new Set([
492
+ `${m}/logs`,
493
+ `${m}/traces`,
494
+ `${m}/workflows`,
495
+ `${m}/storage`,
496
+ `${m}/aggregates`,
497
+ `${m}/flags`
498
+ ]), U = async (e, t, n, r = {}) => {
499
+ let i = x(t.origin ?? t.Origin);
500
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, i);
501
+ let a = (r.method ?? "POST").toUpperCase();
502
+ if (a !== "POST") return y(405, {
503
+ error: "method not allowed",
504
+ expected: "POST"
505
+ }, i);
506
+ let o = (r.authResolver ?? _)(t, a);
507
+ if (!o.ok) return y(401, {
508
+ error: "unauthorized",
509
+ reason: o.reason
510
+ }, i);
511
+ if (e.kind !== "api") return y(404, { error: "invoke endpoint is api-only" }, i);
512
+ if (!e.invokers || e.invokers.size === 0) return y(404, { error: "invoke not configured" }, i);
513
+ let s;
514
+ try {
515
+ s = JSON.parse(n || "{}");
516
+ } catch {
517
+ return y(400, { error: "body must be JSON" }, i);
518
+ }
519
+ let c = s;
520
+ if (typeof c.tag != "string") return y(400, { error: "body.tag must be a string" }, i);
521
+ let l = e.invokers.get(c.tag);
522
+ if (!l) return y(404, {
523
+ error: "unknown tag",
524
+ tag: c.tag
525
+ }, i);
526
+ let u = typeof c.headers == "object" && c.headers !== null ? c.headers : {}, d = {};
527
+ for (let [e, n] of Object.entries(t)) d[e.toLowerCase()] = n;
528
+ for (let [e, t] of Object.entries(u)) {
529
+ let n = e.toLowerCase();
530
+ n !== "cookie" && (d[n] = t);
531
+ }
532
+ return y(200, await l(c.input, d), i);
533
+ }, W = async (e, t, n, r = {}) => {
534
+ let i = /[?&]replica=([^&]+)/.exec(e)?.[1], a = n[d] !== void 0;
535
+ if (i !== void 0 && !a && t.kind === "api") {
536
+ let a = x(n.origin ?? n.Origin), o = (r.authResolver ?? _)(n, (r.method ?? "GET").toUpperCase());
537
+ if (!o.ok) return y(401, {
538
+ error: "unauthorized",
539
+ reason: o.reason
540
+ }, a);
541
+ if (t.peerAddress === void 0) return y(501, {
542
+ error: "this process cannot address another replica",
543
+ reason: "peer addresses are published into `_voltro_replica_observations`, which needs a shared store — a memory-store app is a single process by construction"
544
+ }, a);
545
+ let s = await p({
546
+ url: e,
547
+ replicaId: decodeURIComponent(i),
548
+ authorization: n.authorization ?? n.Authorization,
549
+ lookup: { addressOf: t.peerAddress }
550
+ });
551
+ return s.kind === "answered" ? {
552
+ status: s.status,
553
+ contentType: "application/json; charset=utf-8",
554
+ body: s.body,
555
+ headers: a
556
+ } : y(s.status, s.body, a);
557
+ }
558
+ let o = await G(e, t, n, r);
559
+ return o === null ? null : z(j(e), o, r.fleetSize);
560
+ }, G = async (e, t, n, r = {}) => {
561
+ let i = j(e);
562
+ if (!N(i)) return null;
563
+ let a = /[?&]scope=fleet(?:&|$)/.test(e), o = i === "/_voltro/inspect/subscriptions" && a;
564
+ if (i !== "/_voltro/inspect/migrations" && !o || (r.method ?? "GET").toUpperCase() !== "GET") return null;
565
+ let s = x(n.origin ?? n.Origin);
566
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, s);
567
+ let c = (r.authResolver ?? _)(n, "GET");
568
+ if (!c.ok) return y(401, {
569
+ error: "unauthorized",
570
+ reason: c.reason
571
+ }, s);
572
+ if (t.kind !== "api") return y(404, { error: `${o ? "subscriptions" : "migrations"} endpoint is api-only` }, s);
573
+ if (o) {
574
+ if (t.fleetObservations === void 0) return y(501, {
575
+ error: "fleet-scoped subscriptions are not available on this process",
576
+ reason: "the app has no shared store to read other replicas’ observations from (a memory-store app is a single process by construction)",
577
+ fix: "omit `?scope=fleet` for this replica’s own answer"
578
+ }, s);
579
+ let e;
580
+ try {
581
+ e = await t.fleetObservations("resume");
582
+ } catch (e) {
583
+ return y(503, {
584
+ error: "the fleet view could not be read",
585
+ reason: String(e?.message ?? e),
586
+ fix: "run `voltro db apply` — the fleet view reads `_voltro_replica_observations`, which a database migrated before this version does not have yet"
587
+ }, s);
588
+ }
589
+ return {
590
+ ...y(200, { resume: e.byReplica }, s),
591
+ assembled: {
592
+ responded: e.responded,
593
+ expected: e.expected,
594
+ missing: e.missing,
595
+ stale: e.stale,
596
+ versions: e.versions
597
+ }
598
+ };
599
+ }
600
+ return t.migrations === void 0 ? y(200, {
601
+ drift: {
602
+ isDrifted: !1,
603
+ liveFingerprint: "",
604
+ liveSnapshot: { tables: [] }
605
+ },
606
+ pending: null,
607
+ history: [],
608
+ softDropSnapshots: []
609
+ }, s) : y(200, await t.migrations(), s);
610
+ }, K = async (e, t, n, r, i = {}) => {
611
+ let a = j(e);
612
+ if (!N(a) || !a.startsWith("/_voltro/inspect/webhooks/")) return null;
613
+ let o = x(n.origin ?? n.Origin);
614
+ if ((i.method ?? "POST").toUpperCase() !== "POST") return null;
615
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
616
+ let s = (i.authResolver ?? _)(n, i.method ?? "POST");
617
+ if (!s.ok) return y(401, {
618
+ error: "unauthorized",
619
+ reason: s.reason
620
+ }, o);
621
+ let c = T(i.method, n, o);
622
+ if (c) return c;
623
+ if (t.kind !== "api") return y(404, { error: "webhook actions are api-only" }, o);
624
+ if (!t.webhookActions) return y(404, { error: "webhook actions not configured — is @voltro/plugin-webhooks active?" }, o);
625
+ let l;
626
+ try {
627
+ l = JSON.parse(r || "{}");
628
+ } catch {
629
+ return y(400, { error: "body must be JSON" }, o);
630
+ }
631
+ let u = a.slice(`${m}/webhooks/`.length);
632
+ try {
633
+ switch (u) {
634
+ case "subscribe": {
635
+ let e = l;
636
+ return typeof e.event != "string" || e.event.length === 0 ? y(400, { error: "event required" }, o) : typeof e.url != "string" || e.url.length === 0 ? y(400, { error: "url required" }, o) : y(200, await t.webhookActions.subscribe(e), o);
637
+ }
638
+ case "pause": {
639
+ let e = l.targetId;
640
+ return typeof e != "string" || e.length === 0 ? y(400, { error: "targetId required" }, o) : (await t.webhookActions.pause(e), y(200, { ok: !0 }, o));
641
+ }
642
+ case "resume": {
643
+ let e = l.targetId;
644
+ return typeof e != "string" || e.length === 0 ? y(400, { error: "targetId required" }, o) : (await t.webhookActions.resume(e), y(200, { ok: !0 }, o));
645
+ }
646
+ case "delete": {
647
+ let e = l.targetId;
648
+ return typeof e != "string" || e.length === 0 ? y(400, { error: "targetId required" }, o) : (await t.webhookActions.delete(e), y(200, { ok: !0 }, o));
649
+ }
650
+ case "rotateSecret": {
651
+ let e = l.targetId;
652
+ return typeof e != "string" || e.length === 0 ? y(400, { error: "targetId required" }, o) : y(200, await t.webhookActions.rotateSecret(e), o);
653
+ }
654
+ case "replay": {
655
+ let e = l.deliveryId;
656
+ return typeof e != "string" || e.length === 0 ? y(400, { error: "deliveryId required" }, o) : (await t.webhookActions.replay(e), y(200, { ok: !0 }, o));
657
+ }
658
+ case "repinVersion": {
659
+ let e = l.targetId, n = l.version;
660
+ return typeof e != "string" || e.length === 0 ? y(400, { error: "targetId required" }, o) : typeof n != "number" || !Number.isInteger(n) || n < 1 ? y(400, { error: "version must be a positive integer" }, o) : (await t.webhookActions.updateTargetPayloadVersion(e, n), y(200, { ok: !0 }, o));
661
+ }
662
+ default: return y(404, { error: `unknown webhook action: ${u}` }, o);
663
+ }
664
+ } catch (e) {
665
+ return y(500, {
666
+ error: "webhook action failed",
667
+ message: e?.message ?? String(e)
668
+ }, o);
669
+ }
670
+ }, q = async (e, t, n, r, i = {}) => {
671
+ let a = j(e);
672
+ if (!N(a)) return null;
673
+ let o = x(n.origin ?? n.Origin), s = (i.method ?? "POST").toUpperCase();
674
+ if (s !== "POST") return null;
675
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
676
+ let c = (i.authResolver ?? _)(n, s);
677
+ if (!c.ok) return y(401, {
678
+ error: "unauthorized",
679
+ reason: c.reason
680
+ }, o);
681
+ if (t.kind !== "api") return y(404, { error: "framework-action endpoints are api-only" }, o);
682
+ let l = `${m}/seeds/run`, u = `${m}/migrations/rollback`, d = `${m}/migrations/squash`, f = `${m}/migrations/restore-snapshot`;
683
+ if (a !== l && a !== u && a !== d && a !== f && a !== "/_voltro/inspect/migrations/compare-env") return null;
684
+ let p;
685
+ try {
686
+ p = JSON.parse(r || "{}");
687
+ } catch {
688
+ return y(400, { error: "body must be JSON" }, o);
689
+ }
690
+ try {
691
+ if (a === l) return typeof p.id != "string" || p.id.length === 0 ? y(400, { error: "body.id must be a non-empty string" }, o) : t.runSeed ? y(200, await t.runSeed(p.id), o) : y(404, { error: "runSeed not configured" }, o);
692
+ if (a === u) return typeof p.id != "string" || p.id.length === 0 ? y(400, { error: "body.id must be a non-empty string" }, o) : t.rollbackMigration ? y(200, await t.rollbackMigration(p.id), o) : y(404, { error: "rollbackMigration not configured" }, o);
693
+ if (a === d) {
694
+ if (typeof p.before != "string" || p.before.length === 0) return y(400, { error: "body.before must be a non-empty ISO date string" }, o);
695
+ if (!t.squashMigrationHistory) return y(404, { error: "squashMigrationHistory not configured" }, o);
696
+ let e = typeof p.note == "string" ? p.note : void 0;
697
+ return y(200, await t.squashMigrationHistory({
698
+ before: p.before,
699
+ note: e
700
+ }), o);
701
+ }
702
+ return a === f ? typeof p.planId != "string" || p.planId.length === 0 ? y(400, { error: "body.planId must be a non-empty string" }, o) : t.restoreSnapshot ? y(200, await t.restoreSnapshot({ planId: p.planId }), o) : y(404, { error: "restoreSnapshot not configured" }, o) : typeof p.url != "string" || p.url.length === 0 ? y(400, { error: "body.url must be a non-empty URL string" }, o) : t.compareCrossEnv ? (await t.compareCrossEnv({
703
+ url: p.url,
704
+ label: typeof p.label == "string" ? p.label : void 0,
705
+ token: typeof p.token == "string" ? p.token : void 0
706
+ }), y(200, { ok: !0 }, o)) : y(404, { error: "compareCrossEnv not configured" }, o);
707
+ } catch (e) {
708
+ return y(500, {
709
+ error: "framework action failed",
710
+ message: e?.message ?? String(e)
711
+ }, o);
712
+ }
713
+ }, J = async (e, t, n, r = {}) => {
714
+ if (j(e) !== "/_voltro/inspect/data/rows") return null;
715
+ let i = x(n.origin ?? n.Origin), a = (r.method ?? "GET").toUpperCase();
716
+ if (a !== "GET") return y(405, {
717
+ error: "method not allowed",
718
+ expected: "GET"
719
+ }, i);
720
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, i);
721
+ let o = (r.authResolver ?? _)(n, a);
722
+ if (!o.ok) return y(401, {
723
+ error: "unauthorized",
724
+ reason: o.reason
725
+ }, i);
726
+ if (t.kind !== "api") return y(404, { error: "data viewer is api-only" }, i);
727
+ if (t.inspectRows === void 0) return y(404, { error: "inspectRows not configured" }, i);
728
+ let s = X(e), c = s.get("table");
729
+ if (!c) return y(400, { error: "query.table is required" }, i);
730
+ let l = Z(s.get("offset")) ?? 0, u = Z(s.get("limit")) ?? 50, d = {}, f = s.get("q");
731
+ if (f) {
732
+ if (f.length > 8192) return y(400, { error: "query.q too large" }, i);
733
+ try {
734
+ d = JSON.parse(Buffer.from(f, "base64url").toString("utf8"));
735
+ } catch {
736
+ return y(400, { error: "query.q is not valid base64url JSON" }, i);
737
+ }
738
+ }
739
+ try {
740
+ return y(200, await t.inspectRows({
741
+ table: c,
742
+ offset: l,
743
+ limit: u,
744
+ ...d
745
+ }), i);
746
+ } catch (e) {
747
+ return e?.name === "InspectQueryError" ? y(400, {
748
+ error: "invalid query",
749
+ message: e.message
750
+ }, i) : y(500, {
751
+ error: "data-rows query failed",
752
+ message: e?.message ?? String(e)
753
+ }, i);
754
+ }
755
+ }, Y = async (e, t, n, i = {}) => {
756
+ if (j(e) !== "/_voltro/inspect/provenance") return null;
757
+ let a = x(n.origin ?? n.Origin), o = (i.method ?? "GET").toUpperCase();
758
+ if (o !== "GET") return y(405, {
759
+ error: "method not allowed",
760
+ expected: "GET"
761
+ }, a);
762
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, a);
763
+ let s = (i.authResolver ?? _)(n, o);
764
+ if (!s.ok) return y(401, {
765
+ error: "unauthorized",
766
+ reason: s.reason
767
+ }, a);
768
+ let c = T(i.method, n, a);
769
+ if (c) return c;
770
+ if (t.kind !== "api") return y(404, { error: "provenance is api-only" }, a);
771
+ if (t.inspectRows === void 0) return y(404, { error: "inspectRows not configured" }, a);
772
+ let l = X(e), u = l.get("table"), d = l.get("id"), f = l.get("column") ?? void 0;
773
+ if (!u || !d) return y(400, { error: "query.table and query.id are required" }, a);
774
+ try {
775
+ let e = (await t.inspectRows({
776
+ table: u,
777
+ limit: 1,
778
+ filter: {
779
+ kind: "leaf",
780
+ column: "id",
781
+ op: "eq",
782
+ value: d
783
+ }
784
+ })).rows[0];
785
+ return y(200, r(e, {
786
+ table: u,
787
+ id: d,
788
+ ...f === void 0 ? {} : { column: f }
789
+ }), a);
790
+ } catch (e) {
791
+ return e?.name === "InspectQueryError" ? y(400, {
792
+ error: "invalid query",
793
+ message: e.message
794
+ }, a) : y(500, {
795
+ error: "provenance query failed",
796
+ message: e?.message ?? String(e)
797
+ }, a);
798
+ }
799
+ }, X = (e) => {
800
+ let t = e.indexOf("?");
801
+ return t < 0 ? new URLSearchParams() : new URLSearchParams(e.slice(t + 1));
802
+ }, Z = (e) => {
803
+ if (e === null || e === "") return;
804
+ let t = Number(e);
805
+ return Number.isFinite(t) && t >= 0 ? Math.floor(t) : void 0;
806
+ }, Q = async (e, t, n, r = {}) => {
807
+ if (j(e) !== "/_voltro/inspect/workflows/runs") return null;
808
+ let i = x(n.origin ?? n.Origin), a = (r.method ?? "GET").toUpperCase();
809
+ if (a !== "GET") return y(405, {
810
+ error: "method not allowed",
811
+ expected: "GET"
812
+ }, i);
813
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, i);
814
+ let o = (r.authResolver ?? _)(n, a);
815
+ if (!o.ok) return y(401, {
816
+ error: "unauthorized",
817
+ reason: o.reason
818
+ }, i);
819
+ if (t.kind !== "api") return y(404, { error: "workflows endpoint is api-only" }, i);
820
+ if (t.inspectWorkflowRuns === void 0) return y(200, {
821
+ runs: [],
822
+ total: 0,
823
+ offset: 0,
824
+ limit: 50
825
+ }, i);
826
+ let s = X(e);
827
+ try {
828
+ let e = s.get("deadLettered") === "1" || s.get("deadLettered") === "true", n = (s.get("statuses") ?? "").split(",").map((e) => e.trim()).filter((e) => e !== "");
829
+ return y(200, await t.inspectWorkflowRuns({
830
+ ...s.get("tag") === null ? {} : { tag: s.get("tag") },
831
+ ...e ? { deadLettered: !0 } : s.get("status") === null ? n.length > 0 ? { statuses: n } : {} : { status: s.get("status") },
832
+ ...s.get("q") === null ? {} : { tagContains: s.get("q") },
833
+ ...s.get("source") === null ? {} : { source: s.get("source") },
834
+ ...s.get("idPrefix") === null ? {} : { idPrefix: s.get("idPrefix") },
835
+ ...s.get("from") === null ? {} : { startedAfter: s.get("from") },
836
+ ...s.get("to") === null ? {} : { startedBefore: s.get("to") },
837
+ offset: Z(s.get("offset")) ?? 0,
838
+ limit: Z(s.get("limit")) ?? 50
839
+ }), i);
840
+ } catch (e) {
841
+ return I(e) ? y(200, {
842
+ runs: [],
843
+ total: 0,
844
+ offset: 0,
845
+ limit: 0,
846
+ unavailable: "this app declares no workflows, so there is no run history to read"
847
+ }, i) : y(500, {
848
+ error: "workflow-runs query failed",
849
+ message: e?.message ?? String(e)
850
+ }, i);
851
+ }
852
+ }, $ = async (e, t, n, r = {}) => {
853
+ if (j(e) !== "/_voltro/inspect/workflows/stats") return null;
854
+ let i = x(n.origin ?? n.Origin), a = (r.method ?? "GET").toUpperCase();
855
+ if (a !== "GET") return y(405, {
856
+ error: "method not allowed",
857
+ expected: "GET"
858
+ }, i);
859
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, i);
860
+ let o = (r.authResolver ?? _)(n, a);
861
+ if (!o.ok) return y(401, {
862
+ error: "unauthorized",
863
+ reason: o.reason
864
+ }, i);
865
+ if (t.kind !== "api") return y(404, { error: "workflows endpoint is api-only" }, i);
866
+ if (t.inspectWorkflowRunStats === void 0) return y(200, {
867
+ windowHours: 24,
868
+ bucketMinutes: 30,
869
+ buckets: [],
870
+ byTag: [],
871
+ total: 0,
872
+ truncated: !1
873
+ }, i);
874
+ let s = X(e);
875
+ try {
876
+ return y(200, await t.inspectWorkflowRunStats({
877
+ ...s.get("tag") === null ? {} : { tag: s.get("tag") },
878
+ ...Z(s.get("hours")) === void 0 ? {} : { hours: Z(s.get("hours")) }
879
+ }), i);
880
+ } catch (e) {
881
+ return I(e) ? y(200, {
882
+ windowHours: 24,
883
+ bucketMinutes: 30,
884
+ buckets: [],
885
+ byTag: [],
886
+ total: 0,
887
+ truncated: !1,
888
+ unavailable: "this app declares no workflows, so there is no run history to read"
889
+ }, i) : y(500, {
890
+ error: "workflow-stats query failed",
891
+ message: e?.message ?? String(e)
892
+ }, i);
893
+ }
894
+ }, ee = async (e, t, n, r, i = {}) => {
895
+ let a = j(e).match(/^\/_voltro\/inspect\/workflows\/start\/([^/]+)$/);
896
+ if (!a) return null;
897
+ let o = decodeURIComponent(a[1] ?? ""), s = x(n.origin ?? n.Origin), c = (i.method ?? "POST").toUpperCase();
898
+ if (c !== "POST") return y(405, {
899
+ error: "method not allowed",
900
+ expected: "POST"
901
+ }, s);
902
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, s);
903
+ let l = (i.authResolver ?? _)(n, c);
904
+ if (!l.ok) return y(401, {
905
+ error: "unauthorized",
906
+ reason: l.reason
907
+ }, s);
908
+ if (t.kind !== "api") return y(404, { error: "workflow start is api-only" }, s);
909
+ if (t.inspectStartWorkflow === void 0) return y(404, { error: "inspectStartWorkflow not configured" }, s);
910
+ let u = {};
911
+ if (r.length > 0) try {
912
+ u = JSON.parse(r).payload ?? {};
913
+ } catch {
914
+ return y(400, { error: "start requires JSON body `{ payload?: unknown }`" }, s);
915
+ }
916
+ try {
917
+ return y(200, await t.inspectStartWorkflow({
918
+ name: o,
919
+ payload: u
920
+ }), s);
921
+ } catch (e) {
922
+ return y(500, {
923
+ error: "workflow start failed",
924
+ message: e?.message ?? String(e)
925
+ }, s);
926
+ }
927
+ }, te = async (e, t, n, r = {}) => {
928
+ let i = j(e);
929
+ if (!i.startsWith("/_voltro/inspect/schedules")) return null;
930
+ let a = x(n.origin ?? n.Origin);
931
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, a);
932
+ let o = (r.authResolver ?? _)(n, r.method ?? "POST");
933
+ if (!o.ok) return y(401, {
934
+ error: "unauthorized",
935
+ reason: o.reason
936
+ }, a);
937
+ let s = T(r.method, n, a);
938
+ if (s) return s;
939
+ if (t.kind !== "api") return y(404, { error: "schedules are api-only" }, a);
940
+ let c = (r.method ?? "GET").toUpperCase(), l = i.match(/^\/_voltro\/inspect\/schedules\/([^/]+)\/backfill$/);
941
+ if (l) {
942
+ if (c !== "POST") return y(405, {
943
+ error: "method not allowed",
944
+ expected: "POST"
945
+ }, a);
946
+ if (!t.inspectBackfillSchedule) return y(404, { error: "inspectBackfillSchedule not configured" }, a);
947
+ let e = decodeURIComponent(l[1] ?? ""), n;
948
+ try {
949
+ n = JSON.parse(r.body ?? "{}");
950
+ } catch {
951
+ return y(400, { error: "invalid JSON body — expected { from, to, confirm?, limit? }" }, a);
952
+ }
953
+ if (typeof n.from != "string" || typeof n.to != "string") return y(400, { error: "body must carry ISO 'from' and 'to' instants" }, a);
954
+ try {
955
+ let r = await t.inspectBackfillSchedule({
956
+ name: e,
957
+ from: n.from,
958
+ to: n.to,
959
+ confirm: n.confirm === !0,
960
+ ...typeof n.limit == "number" ? { limit: n.limit } : {}
961
+ });
962
+ return y(r.kind === "refused" ? 409 : 200, r, a);
963
+ } catch (e) {
964
+ return y(500, {
965
+ error: "backfill failed",
966
+ message: e?.message ?? String(e)
967
+ }, a);
968
+ }
969
+ }
970
+ let u = i.match(/^\/_voltro\/inspect\/schedules\/([^/]+)\/fire$/);
971
+ if (u) {
972
+ if (c !== "POST") return y(405, {
973
+ error: "method not allowed",
974
+ expected: "POST"
975
+ }, a);
976
+ if (!t.inspectFireSchedule) return y(404, { error: "inspectFireSchedule not configured" }, a);
977
+ let n = decodeURIComponent(u[1] ?? ""), r = X(e).get("trigger") === "external" ? "external" : "manual";
978
+ try {
979
+ return y(200, await t.inspectFireSchedule({
980
+ name: n,
981
+ trigger: r
982
+ }), a);
983
+ } catch (e) {
984
+ return y(500, {
985
+ error: "fire failed",
986
+ message: e?.message ?? String(e)
987
+ }, a);
988
+ }
989
+ }
990
+ if (i === "/_voltro/inspect/schedules/runs") {
991
+ if (c !== "GET") return y(405, {
992
+ error: "method not allowed",
993
+ expected: "GET"
994
+ }, a);
995
+ if (!t.inspectScheduleRuns) return y(200, {
996
+ runs: [],
997
+ total: 0,
998
+ offset: 0,
999
+ limit: 50
1000
+ }, a);
1001
+ let n = X(e);
1002
+ try {
1003
+ return y(200, await t.inspectScheduleRuns({
1004
+ ...n.get("name") === null ? {} : { name: n.get("name") },
1005
+ offset: Z(n.get("offset")) ?? 0,
1006
+ limit: Z(n.get("limit")) ?? 50
1007
+ }), a);
1008
+ } catch (e) {
1009
+ return y(500, {
1010
+ error: "schedule-runs query failed",
1011
+ message: e?.message ?? String(e)
1012
+ }, a);
1013
+ }
1014
+ }
1015
+ return i === "/_voltro/inspect/schedules" ? c === "GET" ? t.inspectSchedules ? y(200, t.inspectSchedules(), a) : y(200, {
1016
+ schedules: [],
1017
+ coordination: "single"
1018
+ }, a) : y(405, {
1019
+ error: "method not allowed",
1020
+ expected: "GET"
1021
+ }, a) : y(404, {
1022
+ error: "unknown schedules endpoint",
1023
+ path: i
1024
+ }, a);
1025
+ }, ne = async (e, t, r, i = {}) => {
1026
+ if (j(e) !== "/_voltro/inspect/cluster") return null;
1027
+ let a = x(r.origin ?? r.Origin);
1028
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, a);
1029
+ let o = (i.authResolver ?? _)(r, i.method ?? "POST");
1030
+ if (!o.ok) return y(401, {
1031
+ error: "unauthorized",
1032
+ reason: o.reason
1033
+ }, a);
1034
+ let s = T(i.method, r, a);
1035
+ if (s) return s;
1036
+ if (t.kind !== "api") return y(404, { error: "cluster is api-only" }, a);
1037
+ if ((i.method ?? "GET").toUpperCase() !== "GET") return y(405, {
1038
+ error: "method not allowed",
1039
+ expected: "GET"
1040
+ }, a);
1041
+ if (!t.cluster) return y(200, {
1042
+ instance: {
1043
+ replicaId: n(),
1044
+ dialect: "memory",
1045
+ runnerHost: "localhost",
1046
+ runnerPort: 0,
1047
+ runnerStorage: "none",
1048
+ shardLock: "none",
1049
+ coordination: "single",
1050
+ cdc: {
1051
+ enabled: !1,
1052
+ flavor: "none (single-process)"
1053
+ },
1054
+ tier: "none",
1055
+ localhostRisk: !1
1056
+ },
1057
+ coordinationState: {
1058
+ recentReplicaIds: [],
1059
+ scheduleClaims: [],
1060
+ runningScheduleRuns: 0,
1061
+ runningWorkflowRuns: 0
1062
+ },
1063
+ capturedAt: Date.now()
1064
+ }, a);
1065
+ try {
1066
+ return y(200, await t.cluster(), a);
1067
+ } catch (e) {
1068
+ return y(500, {
1069
+ error: "cluster snapshot failed",
1070
+ message: e?.message ?? String(e)
1071
+ }, a);
1072
+ }
1073
+ }, re = async (e, t, n, r = {}) => {
1074
+ let i = j(e).match(/^\/_voltro\/inspect\/workflows\/runs\/([^/]+)\/steps$/);
1075
+ if (!i) return null;
1076
+ let a = decodeURIComponent(i[1] ?? ""), o = x(n.origin ?? n.Origin), s = (r.method ?? "GET").toUpperCase();
1077
+ if (s !== "GET") return y(405, {
1078
+ error: "method not allowed",
1079
+ expected: "GET"
1080
+ }, o);
1081
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
1082
+ let c = (r.authResolver ?? _)(n, s);
1083
+ if (!c.ok) return y(401, {
1084
+ error: "unauthorized",
1085
+ reason: c.reason
1086
+ }, o);
1087
+ if (t.kind !== "api") return y(404, { error: "workflow steps are api-only" }, o);
1088
+ if (t.inspectWorkflowRunSteps === void 0) return y(200, { steps: [] }, o);
1089
+ try {
1090
+ return y(200, await t.inspectWorkflowRunSteps({ runId: a }), o);
1091
+ } catch (e) {
1092
+ return y(500, {
1093
+ error: "steps query failed",
1094
+ message: e?.message ?? String(e)
1095
+ }, o);
1096
+ }
1097
+ }, ie = async (e, t, n, r = {}) => {
1098
+ let i = j(e).match(/^\/_voltro\/inspect\/workflows\/runs\/([^/]+)\/events$/);
1099
+ if (!i) return null;
1100
+ let a = decodeURIComponent(i[1] ?? ""), o = x(n.origin ?? n.Origin), s = (r.method ?? "GET").toUpperCase();
1101
+ if (s !== "GET") return y(405, {
1102
+ error: "method not allowed",
1103
+ expected: "GET"
1104
+ }, o);
1105
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
1106
+ let c = (r.authResolver ?? _)(n, s);
1107
+ if (!c.ok) return y(401, {
1108
+ error: "unauthorized",
1109
+ reason: c.reason
1110
+ }, o);
1111
+ if (t.kind !== "api") return y(404, { error: "workflow events are api-only" }, o);
1112
+ if (t.inspectWorkflowRunEvents === void 0) return y(200, { events: [] }, o);
1113
+ try {
1114
+ return y(200, await t.inspectWorkflowRunEvents({ runId: a }), o);
1115
+ } catch (e) {
1116
+ return y(500, {
1117
+ error: "events query failed",
1118
+ message: e?.message ?? String(e)
1119
+ }, o);
1120
+ }
1121
+ }, ae = async (e, t, n, r = {}) => {
1122
+ if (j(t) !== "/_voltro/inspect/workflows/events") return null;
1123
+ let i = x(n.origin ?? n.Origin), a = (r.method ?? "GET").toUpperCase();
1124
+ if (a !== "GET") return y(405, {
1125
+ error: "method not allowed",
1126
+ expected: "GET"
1127
+ }, i);
1128
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, i);
1129
+ let o = (r.authResolver ?? _)(n, a);
1130
+ if (!o.ok) return y(401, {
1131
+ error: "unauthorized",
1132
+ reason: o.reason
1133
+ }, i);
1134
+ if (e.kind !== "api") return y(404, { error: "workflow domain events are api-only" }, i);
1135
+ if (e.inspectWorkflowDomainEvents === void 0) return y(200, {
1136
+ events: [],
1137
+ total: 0,
1138
+ offset: 0,
1139
+ limit: 100
1140
+ }, i);
1141
+ let s = M(t), c = s.get("name") ?? void 0, l = Number(s.get("offset") ?? "0"), u = Number(s.get("limit") ?? "100");
1142
+ try {
1143
+ return y(200, await e.inspectWorkflowDomainEvents({
1144
+ ...c !== void 0 && c !== "" ? { name: c } : {},
1145
+ offset: Number.isFinite(l) ? l : 0,
1146
+ limit: Number.isFinite(u) ? u : 100
1147
+ }), i);
1148
+ } catch (e) {
1149
+ return I(e) ? y(200, {
1150
+ events: [],
1151
+ total: 0,
1152
+ offset: 0,
1153
+ limit: 100,
1154
+ unavailable: "this app declares no workflows, so there is no event history to read"
1155
+ }, i) : y(500, {
1156
+ error: "workflow domain events query failed",
1157
+ message: e?.message ?? String(e)
1158
+ }, i);
1159
+ }
1160
+ }, oe = async (e, t, n, r = {}) => {
1161
+ let i = j(t).match(/^\/_voltro\/inspect\/workflows\/events\/([^/]+)\/deliveries$/);
1162
+ if (!i) return null;
1163
+ let a = decodeURIComponent(i[1] ?? ""), o = x(n.origin ?? n.Origin), s = (r.method ?? "GET").toUpperCase();
1164
+ if (s !== "GET") return y(405, {
1165
+ error: "method not allowed",
1166
+ expected: "GET"
1167
+ }, o);
1168
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
1169
+ let c = (r.authResolver ?? _)(n, s);
1170
+ if (!c.ok) return y(401, {
1171
+ error: "unauthorized",
1172
+ reason: c.reason
1173
+ }, o);
1174
+ if (e.kind !== "api") return y(404, { error: "workflow event deliveries are api-only" }, o);
1175
+ if (e.inspectWorkflowEventDeliveries === void 0) return y(200, { deliveries: [] }, o);
1176
+ try {
1177
+ return y(200, await e.inspectWorkflowEventDeliveries({ eventId: a }), o);
1178
+ } catch (e) {
1179
+ return y(500, {
1180
+ error: "workflow event deliveries query failed",
1181
+ message: e?.message ?? String(e)
1182
+ }, o);
1183
+ }
1184
+ }, se = async (e, t, n, r = {}) => {
1185
+ if (j(e) !== "/_voltro/inspect/workflows/children") return null;
1186
+ let i = x(n.origin ?? n.Origin), a = (r.method ?? "GET").toUpperCase();
1187
+ if (a !== "GET") return y(405, {
1188
+ error: "method not allowed",
1189
+ expected: "GET"
1190
+ }, i);
1191
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, i);
1192
+ let o = (r.authResolver ?? _)(n, a);
1193
+ if (!o.ok) return y(401, {
1194
+ error: "unauthorized",
1195
+ reason: o.reason
1196
+ }, i);
1197
+ if (t.kind !== "api") return y(404, { error: "workflow children are api-only" }, i);
1198
+ let s = X(e).get("parentExecutionId");
1199
+ if (s === null || s === "") return y(400, { error: "parentExecutionId query param required" }, i);
1200
+ if (t.inspectWorkflowChildren === void 0) return y(200, {
1201
+ runs: [],
1202
+ total: 0,
1203
+ offset: 0,
1204
+ limit: 200
1205
+ }, i);
1206
+ try {
1207
+ return y(200, await t.inspectWorkflowChildren({ parentExecutionId: s }), i);
1208
+ } catch (e) {
1209
+ return y(500, {
1210
+ error: "children query failed",
1211
+ message: e?.message ?? String(e)
1212
+ }, i);
1213
+ }
1214
+ }, ce = async (e, t, n, r, i = {}) => {
1215
+ let a = j(e).match(/^\/_voltro\/inspect\/workflows\/runs\/([^/]+)\/(cancel|retry|suspend|resume-from-step|resume|signal|update|discard|redrive)$/);
1216
+ if (!a) return null;
1217
+ let o = decodeURIComponent(a[1] ?? ""), s = a[2], c = x(n.origin ?? n.Origin), l = (i.method ?? "POST").toUpperCase();
1218
+ if (l !== "POST") return y(405, {
1219
+ error: "method not allowed",
1220
+ expected: "POST"
1221
+ }, c);
1222
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, c);
1223
+ let u = (i.authResolver ?? _)(n, l);
1224
+ if (!u.ok) return y(401, {
1225
+ error: "unauthorized",
1226
+ reason: u.reason
1227
+ }, c);
1228
+ if (t.kind !== "api") return y(404, { error: "workflow actions are api-only" }, c);
1229
+ let d = {
1230
+ cancel: t.inspectCancelWorkflowRun,
1231
+ retry: t.inspectRetryWorkflowRun,
1232
+ suspend: t.inspectSuspendWorkflowRun,
1233
+ resume: t.inspectResumeWorkflowRun,
1234
+ signal: t.inspectSignalWorkflowRun,
1235
+ update: t.inspectUpdateWorkflowRun,
1236
+ discard: t.inspectDiscardWorkflowRun,
1237
+ redrive: t.inspectRedriveWorkflowRun,
1238
+ "resume-from-step": t.inspectResumeWorkflowRunFromStep
1239
+ }[s];
1240
+ if (!d) return y(404, { error: s === "resume-from-step" ? "inspectResumeWorkflowRunFromStep not configured" : `inspect${s[0]?.toUpperCase() ?? ""}${s.slice(1)}WorkflowRun not configured` }, c);
1241
+ let f, p, m, g, v, b, S;
1242
+ if (r.length > 0) try {
1243
+ let e = JSON.parse(r);
1244
+ s === "retry" && (f = e.payloadOverride), s === "resume-from-step" && typeof e.step == "string" && e.step.length > 0 && (S = e.step), s === "signal" && (typeof e.signalName == "string" && e.signalName.length > 0 && (p = e.signalName), m = e.payload), s === "update" && (typeof e.updateName == "string" && e.updateName.length > 0 && (g = e.updateName), v = e.payload, typeof e.timeoutMs == "number" && Number.isFinite(e.timeoutMs) && (b = e.timeoutMs));
1245
+ } catch {}
1246
+ if (s === "signal" && p === void 0) return y(400, { error: "signal requires JSON body `{ signalName: string, payload?: unknown }`" }, c);
1247
+ if (s === "update" && g === void 0) return y(400, { error: "update requires JSON body `{ updateName: string, payload?: unknown, timeoutMs?: number }`" }, c);
1248
+ if (s === "resume-from-step" && S === void 0) return y(400, { error: "resume-from-step requires JSON body `{ step: string }` (the step name to rewind to)" }, c);
1249
+ try {
1250
+ return y(200, s === "retry" && f !== void 0 ? await d({
1251
+ runId: o,
1252
+ payloadOverride: f
1253
+ }) : s === "signal" ? await d({
1254
+ runId: o,
1255
+ signalName: p,
1256
+ payload: m
1257
+ }) : s === "update" ? await d({
1258
+ runId: o,
1259
+ updateName: g,
1260
+ payload: v,
1261
+ ...b === void 0 ? {} : { timeoutMs: b }
1262
+ }) : s === "resume-from-step" ? await d({
1263
+ runId: o,
1264
+ step: S
1265
+ }) : await d({ runId: o }), c);
1266
+ } catch (e) {
1267
+ return y(500, {
1268
+ error: `${s} failed`,
1269
+ message: e?.message ?? String(e)
1270
+ }, c);
1271
+ }
1272
+ }, le = async (e, t, n, r, i = {}) => {
1273
+ if (j(e) !== "/_voltro/inspect/data/import" || (i.method ?? "POST").toUpperCase() !== "POST") return null;
1274
+ let a = x(n.origin ?? n.Origin);
1275
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, a);
1276
+ let o = (i.authResolver ?? _)(n, "POST");
1277
+ if (!o.ok) return y(401, {
1278
+ error: "unauthorized",
1279
+ reason: o.reason
1280
+ }, a);
1281
+ let s = T(i.method, n, a);
1282
+ if (s) return s;
1283
+ if (t.kind !== "api") return y(404, { error: "data import is api-only" }, a);
1284
+ if (!t.inspectImport) return y(404, { error: "inspectImport not configured" }, a);
1285
+ let c;
1286
+ try {
1287
+ c = JSON.parse(r || "{}");
1288
+ } catch {
1289
+ return y(400, { error: "body must be JSON" }, a);
1290
+ }
1291
+ if (typeof c.bundleDir != "string" || !c.bundleDir) return y(400, { error: "body.bundleDir (string) is required" }, a);
1292
+ try {
1293
+ return y(200, await t.inspectImport({
1294
+ bundleDir: c.bundleDir,
1295
+ ...c.mode === "upsert" || c.mode === "append" || c.mode === "replace" ? { mode: c.mode } : {},
1296
+ ...c.onConflict === "skip" || c.onConflict === "fail" ? { onConflict: c.onConflict } : {},
1297
+ ...typeof c.atomic == "boolean" ? { atomic: c.atomic } : {}
1298
+ }), a);
1299
+ } catch (e) {
1300
+ return y(500, {
1301
+ error: "import failed",
1302
+ message: e?.message ?? String(e)
1303
+ }, a);
1304
+ }
1305
+ }, ue = async (e, t, n, r, i = {}) => {
1306
+ let a = j(e);
1307
+ if (!a.startsWith("/_voltro/inspect/data/rows")) return null;
1308
+ let o = (i.method ?? "POST").toUpperCase();
1309
+ if (o === "GET" && a === "/_voltro/inspect/data/rows") return null;
1310
+ let s = x(n.origin ?? n.Origin);
1311
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, s);
1312
+ let c = (i.authResolver ?? _)(n, o);
1313
+ if (!c.ok) return y(401, {
1314
+ error: "unauthorized",
1315
+ reason: c.reason
1316
+ }, s);
1317
+ if (t.kind !== "api") return y(404, { error: "data viewer is api-only" }, s);
1318
+ if (o === "POST" && a === "/_voltro/inspect/data/rows") {
1319
+ if (!t.inspectInsertRow) return y(404, { error: "inspectInsertRow not configured" }, s);
1320
+ let e;
1321
+ try {
1322
+ e = JSON.parse(r || "{}");
1323
+ } catch {
1324
+ return y(400, { error: "body must be JSON" }, s);
1325
+ }
1326
+ if (typeof e.table != "string" || !e.row || typeof e.row != "object") return y(400, { error: "body must be { table: string, row: object }" }, s);
1327
+ try {
1328
+ return y(200, await t.inspectInsertRow({
1329
+ table: e.table,
1330
+ row: e.row
1331
+ }), s);
1332
+ } catch (e) {
1333
+ return y(500, {
1334
+ error: "insert failed",
1335
+ message: e?.message ?? String(e)
1336
+ }, s);
1337
+ }
1338
+ }
1339
+ let l = a.match(/^\/_voltro\/inspect\/data\/rows\/([^/]+)$/);
1340
+ if (!l) return null;
1341
+ let u = decodeURIComponent(l[1] ?? "");
1342
+ if (!u) return y(400, { error: "row id is required in URL" }, s);
1343
+ let d = X(e).get("table") ?? "";
1344
+ if (!d) return y(400, { error: "query.table is required" }, s);
1345
+ if (o === "PATCH") {
1346
+ if (!t.inspectUpdateRow) return y(404, { error: "inspectUpdateRow not configured" }, s);
1347
+ let e;
1348
+ try {
1349
+ e = JSON.parse(r || "{}");
1350
+ } catch {
1351
+ return y(400, { error: "body must be JSON" }, s);
1352
+ }
1353
+ if (!e.patch || typeof e.patch != "object") return y(400, { error: "body.patch must be an object" }, s);
1354
+ try {
1355
+ return y(200, await t.inspectUpdateRow({
1356
+ table: d,
1357
+ id: u,
1358
+ patch: e.patch
1359
+ }), s);
1360
+ } catch (e) {
1361
+ return y(500, {
1362
+ error: "update failed",
1363
+ message: e?.message ?? String(e)
1364
+ }, s);
1365
+ }
1366
+ }
1367
+ if (o === "DELETE") {
1368
+ if (!t.inspectDeleteRow) return y(404, { error: "inspectDeleteRow not configured" }, s);
1369
+ try {
1370
+ return y(200, await t.inspectDeleteRow({
1371
+ table: d,
1372
+ id: u
1373
+ }), s);
1374
+ } catch (e) {
1375
+ return y(500, {
1376
+ error: "delete failed",
1377
+ message: e?.message ?? String(e)
1378
+ }, s);
1379
+ }
1380
+ }
1381
+ return y(405, {
1382
+ error: "method not allowed",
1383
+ expected: "POST | PATCH | DELETE"
1384
+ }, s);
1385
+ }, de = async (e, t, n, r, i = {}) => {
1386
+ let a = j(e), o = `${m}/workflows/flow-control`;
1387
+ if (a !== o && !a.startsWith(`${o}/`)) return null;
1388
+ let s = x(n.origin ?? n.Origin), c = (i.method ?? "GET").toUpperCase();
1389
+ if (h()) return y(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, s);
1390
+ let l = (i.authResolver ?? _)(n, c);
1391
+ if (!l.ok) return y(401, {
1392
+ error: "unauthorized",
1393
+ reason: l.reason
1394
+ }, s);
1395
+ if (t.kind !== "api") return y(404, { error: "flow control is api-only" }, s);
1396
+ if (a === `${o}/inferences`) {
1397
+ if (c !== "GET") return y(405, {
1398
+ error: "method not allowed",
1399
+ expected: "GET"
1400
+ }, s);
1401
+ if (t.inspectInferences === void 0) return y(404, { error: "inspectInferences not configured" }, s);
1402
+ let n = X(e).get("limit"), r = n === null ? void 0 : Number(n);
1403
+ try {
1404
+ return y(200, await t.inspectInferences(r !== void 0 && Number.isFinite(r) ? { limit: r } : {}), s);
1405
+ } catch (e) {
1406
+ return y(500, {
1407
+ error: "inference queue read failed",
1408
+ message: e?.message ?? String(e)
1409
+ }, s);
1410
+ }
1411
+ }
1412
+ if (a === o) {
1413
+ if (c !== "GET") return y(405, {
1414
+ error: "method not allowed",
1415
+ expected: "GET"
1416
+ }, s);
1417
+ if (t.inspectFlowControl === void 0) return y(404, { error: "inspectFlowControl not configured" }, s);
1418
+ let n = X(e).get("limit"), r = n === null ? void 0 : Number(n);
1419
+ try {
1420
+ return y(200, await t.inspectFlowControl(r !== void 0 && Number.isFinite(r) ? { limit: r } : {}), s);
1421
+ } catch (e) {
1422
+ return y(500, {
1423
+ error: "flow control read failed",
1424
+ message: e?.message ?? String(e)
1425
+ }, s);
1426
+ }
1427
+ }
1428
+ if (c !== "POST") return y(405, {
1429
+ error: "method not allowed",
1430
+ expected: "POST"
1431
+ }, s);
1432
+ let u = {};
1433
+ if (r.length > 0) try {
1434
+ u = JSON.parse(r);
1435
+ } catch {
1436
+ return y(400, { error: "expected a JSON body" }, s);
1437
+ }
1438
+ let d = a.slice(o.length + 1);
1439
+ try {
1440
+ if (d === "pause") return t.inspectPauseWorkflow === void 0 ? y(404, { error: "inspectPauseWorkflow not configured" }, s) : u.workflow ? y(200, await t.inspectPauseWorkflow({
1441
+ workflow: u.workflow,
1442
+ ...u.reason === void 0 ? {} : { reason: u.reason }
1443
+ }), s) : y(400, { error: "body.workflow is required" }, s);
1444
+ if (d === "resume") return t.inspectResumeWorkflow === void 0 ? y(404, { error: "inspectResumeWorkflow not configured" }, s) : u.workflow ? y(200, await t.inspectResumeWorkflow({ workflow: u.workflow }), s) : y(400, { error: "body.workflow is required" }, s);
1445
+ if (d === "discard") return t.inspectDiscardIntent === void 0 ? y(404, { error: "inspectDiscardIntent not configured" }, s) : u.intentId ? y(200, await t.inspectDiscardIntent({ intentId: u.intentId }), s) : y(400, { error: "body.intentId is required" }, s);
1446
+ if (d === "bulk") {
1447
+ if (t.inspectBulkWorkflowRuns === void 0) return y(404, { error: "inspectBulkWorkflowRuns not configured" }, s);
1448
+ if (u.op !== "cancel" && u.op !== "replay") return y(400, { error: "body.op must be 'cancel' or 'replay'" }, s);
1449
+ if (typeof u.limit != "number") return y(400, { error: "body.limit is required — a bulk operation has no unbounded form, the cap IS the blast radius. The response reports `truncated` when more matched." }, s);
1450
+ try {
1451
+ return y(200, await t.inspectBulkWorkflowRuns({
1452
+ op: u.op,
1453
+ limit: u.limit,
1454
+ ...u.reason === void 0 ? {} : { reason: u.reason },
1455
+ ...u.mode === void 0 ? {} : { mode: u.mode },
1456
+ ...u.dryRun === void 0 ? {} : { dryRun: u.dryRun },
1457
+ ...u.workflow === void 0 ? {} : { workflow: u.workflow },
1458
+ ...u.status === void 0 ? {} : { status: u.status },
1459
+ ...u.startedAfter === void 0 ? {} : { startedAfter: u.startedAfter },
1460
+ ...u.startedBefore === void 0 ? {} : { startedBefore: u.startedBefore }
1461
+ }), s);
1462
+ } catch (e) {
1463
+ if (e?.name === "BulkRequestError") return y(400, { error: e.message }, s);
1464
+ throw e;
1465
+ }
1466
+ }
1467
+ } catch (e) {
1468
+ return y(500, {
1469
+ error: "flow control action failed",
1470
+ message: e?.message ?? String(e)
1471
+ }, s);
1472
+ }
1473
+ return y(404, {
1474
+ error: `unknown flow-control action '${d}'`,
1475
+ expected: [
1476
+ "pause",
1477
+ "resume",
1478
+ "discard",
1479
+ "bulk"
1480
+ ]
1481
+ }, s);
1482
+ };
1483
+ //#endregion
1484
+ export { w as A, ie as C, ee as D, Q as E, A as F, C as I, v as L, b as M, z as N, x as O, E as P, oe as S, re as T, te as _, T as a, se as b, ne as c, ue as d, de as f, B as g, Y as h, F as i, h as j, k, le as l, U as m, P as n, _ as o, q as p, S as r, W as s, m as t, J as u, K as v, $ as w, ae as x, ce as y };