@voltro/cli 0.34.0 → 0.36.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 (138) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/dist/{apiBuild-DZF_f0_I.js → apiBuild-DiE9zcj6.js} +2 -2
  3. package/dist/apiBuild-ZEZnCXn2.js +2 -0
  4. package/dist/{appGraph-gQ_6GkQQ.js → appGraph-KGDPTuTy.js} +1 -1
  5. package/dist/appGraph-zuMGKVYX.js +2 -0
  6. package/dist/bin.js +1 -1
  7. package/dist/{build-CE7Ca9gm.js → build-DBe6c7qC.js} +7 -7
  8. package/dist/{checkCommand-YZDmkAGd.js → checkCommand-BTA6P3Yr.js} +1 -1
  9. package/dist/{checkCommand-Dv8r9tGO.js → checkCommand-BhG0gmUD.js} +8 -7
  10. package/dist/{clusterCmd-CNXKlcvD.js → clusterCmd-D5wsCmA_.js} +1 -1
  11. package/dist/{codegenCommand-DC6w2tNZ.js → codegenCommand-DH-8ZXzR.js} +3 -3
  12. package/dist/{codemodRunner-DRRqXR74.js → codemodRunner-DjQGrdmg.js} +195 -37
  13. package/dist/{commands-gutsz-Ac.js → commands-Bp7utV-7.js} +37 -29
  14. package/dist/{dashboardCommand-3YG8p-UA.js → dashboardCommand-D5Jwjmr1.js} +3 -3
  15. package/dist/{dataCommand-qL0r7fPO.js → dataCommand-DnCm0B2C.js} +56 -54
  16. package/dist/dbCommand-DS4b97Is.js +2 -0
  17. package/dist/{dbCommand-B6X0FZbq.js → dbCommand-O8HA63s2.js} +6 -6
  18. package/dist/{dev-CoG-ZPx8.js → dev-BSFTgCQ5.js} +1 -1
  19. package/dist/{dev-CerMd0mW.js → dev-Dc4cpmRl.js} +2741 -2233
  20. package/dist/doctorCommand-BYffQc0s.js +2 -0
  21. package/dist/{doctorCommand-CnDXQxfa.js → doctorCommand-CNFtt3nR.js} +76 -73
  22. package/dist/{dormancyCommand-Dszo57d6.js → dormancyCommand-6F6NsJKf.js} +1 -1
  23. package/dist/{embeddingsCommand-C0sKVRo1.js → embeddingsCommand-DRRdneJD.js} +1 -1
  24. package/dist/{envCommand-DPgdV1Bq.js → envCommand-TZzcyqZ-.js} +2 -2
  25. package/dist/{evolveCommand-DHpkgjgH.js → evolveCommand-iU35TPjT.js} +2 -2
  26. package/dist/frameworkTableAssembly-YyVe32Cb.js +2 -0
  27. package/dist/frameworkTableAssembly-oMPBKqlE.js +511 -0
  28. package/dist/{generateCommand-oibemh97.js → generateCommand-DbgcUpGw.js} +1 -1
  29. package/dist/index.js +1 -1
  30. package/dist/{infoCommand-BJw9nLUR.js → infoCommand-unqisJGp.js} +1 -1
  31. package/dist/{inspect-CBqFtAKA.js → inspect-CjTYzAs_.js} +32 -2
  32. package/dist/inspect-P4pxoMaV.js +2 -0
  33. package/dist/{inspectCmd-Bppy-GGw.js → inspectCmd-EHFZ9yYu.js} +1 -1
  34. package/dist/{inspectFetch-Cm8_wVvp.js → inspectFetch-EMuhTG_9.js} +1 -1
  35. package/dist/{logsCmd-CCca3KRZ.js → logsCmd-D36xK7Zu.js} +1 -1
  36. package/dist/manifestBuild-COkJoyAr.js +2 -0
  37. package/dist/{manifestBuild-sxpwdKY1.js → manifestBuild-hpPLaGxV.js} +1 -1
  38. package/dist/{migrate-CBwOt_iV.js → migrate-BV7I-ZHZ.js} +3 -3
  39. package/dist/probeCommand-CZfaaUOZ.js +122 -0
  40. package/dist/{runtimeTrace-CRxalXTs.js → runtimeTrace-D5LJ_N55.js} +1 -1
  41. package/dist/scheduleCmd-DQRu6BZC.js +149 -0
  42. package/dist/{sdkgen-CYJscZC7.js → sdkgen-82xVuvbt.js} +1 -1
  43. package/dist/{seedRunner-TFHHiToI.js → seedRunner-ZmLSqNe2.js} +74 -70
  44. package/dist/serveCommand-CEBVP36A.js +2 -0
  45. package/dist/serveCommand-VVGcIMIw.js +1766 -0
  46. package/dist/serveEntry.js +1 -1
  47. package/dist/{start-B-9Nsp-S.js → start-BgN62boB.js} +1 -1
  48. package/dist/{start-9LiUOfES.js → start-T4VesWiM.js} +2 -2
  49. package/dist/startEntry.js +1 -1
  50. package/dist/{tracesCmd-CkEZQrtt.js → tracesCmd-DStmCJPi.js} +1 -1
  51. package/dist/updateCommand-CSBXVsYq.js +2 -0
  52. package/dist/{updateCommand-Bkptutss.js → updateCommand-CwnUK_mf.js} +1 -1
  53. package/dist/webDev-BcykISYQ2.js +2 -0
  54. package/dist/{webDev-CBYvPqQr.js → webDev-Dybxew86.js} +14 -2
  55. package/dist/{webhooksCommand-CID96Rga.js → webhooksCommand-di1CJVzu.js} +1 -1
  56. package/dist/{workflowsCmd-D1VTmLMY.js → workflowsCmd-BGF-mRZ5.js} +1 -1
  57. package/package.json +53 -17
  58. package/templates/AGENTS.md +1 -1
  59. package/templates/agent-docs/_index.md +1 -1
  60. package/templates/agent-docs/_manifest.json +1 -1
  61. package/templates/agent-docs/authentication.md +55 -7
  62. package/templates/agent-docs/cli.md +81 -0
  63. package/templates/agent-docs/data.md +59 -2
  64. package/templates/agent-docs/database/migrations.md +50 -1
  65. package/templates/agent-docs/database/misc.md +33 -0
  66. package/templates/agent-docs/deployment.md +214 -21
  67. package/templates/agent-docs/introduction.md +1 -1
  68. package/templates/agent-docs/multi-tenancy.md +93 -22
  69. package/templates/agent-docs/plugins/ai-flows.md +86 -0
  70. package/templates/agent-docs/plugins/billing.md +1 -1
  71. package/templates/agent-docs/plugins/clickhouse.md +31 -0
  72. package/templates/agent-docs/plugins/search.md +6 -3
  73. package/templates/agent-docs/plugins/storage.md +11 -0
  74. package/templates/agent-docs/plugins.md +3 -1
  75. package/templates/agent-docs/scheduling.md +17 -0
  76. package/templates/agent-docs/security.md +2 -2
  77. package/templates/agent-docs/whats-new.md +31 -1764
  78. package/templates/agent-docs/workflows.md +101 -0
  79. package/templates/apps/api-ai/package.json +7 -7
  80. package/templates/apps/api-auth/package.json +8 -8
  81. package/templates/apps/api-backend/package.json +7 -7
  82. package/templates/apps/api-backend-deactivation/package.json +7 -7
  83. package/templates/apps/api-backend-mail/package.json +8 -8
  84. package/templates/apps/api-backend-mariadb/package.json +9 -9
  85. package/templates/apps/api-backend-sqlite/package.json +8 -8
  86. package/templates/apps/api-backend-storage/package.json +8 -8
  87. package/templates/apps/api-cms/package.json +10 -10
  88. package/templates/apps/api-collab/package.json +8 -8
  89. package/templates/apps/api-data-advanced/package.json +8 -8
  90. package/templates/apps/api-durable/package.json +8 -8
  91. package/templates/apps/api-feature-flags/package.json +9 -9
  92. package/templates/apps/api-governance/package.json +8 -8
  93. package/templates/apps/api-kv/package.json +8 -8
  94. package/templates/apps/api-moderation/package.json +8 -8
  95. package/templates/apps/api-observability/package.json +8 -8
  96. package/templates/apps/api-ratelimit/package.json +8 -8
  97. package/templates/apps/api-rbac/package.json +8 -8
  98. package/templates/apps/api-rest/package.json +7 -7
  99. package/templates/apps/api-saas/package.json +11 -11
  100. package/templates/apps/api-saas-starter/package.json +10 -10
  101. package/templates/apps/api-search/package.json +8 -8
  102. package/templates/apps/api-status/package.json +8 -8
  103. package/templates/apps/api-versioning/package.json +8 -8
  104. package/templates/apps/api-webhooks/package.json +9 -9
  105. package/templates/apps/changelog/package.json +6 -6
  106. package/templates/apps/edge-functions/package.json +2 -2
  107. package/templates/apps/frontend-admin/package.json +8 -8
  108. package/templates/apps/frontend-app/package.json +9 -9
  109. package/templates/apps/frontend-auth/package.json +8 -8
  110. package/templates/apps/frontend-blank/package.json +7 -7
  111. package/templates/apps/frontend-cms/package.json +9 -9
  112. package/templates/apps/frontend-collab/package.json +10 -10
  113. package/templates/apps/frontend-contact/package.json +7 -7
  114. package/templates/apps/frontend-dashboard/package.json +7 -7
  115. package/templates/apps/frontend-docs/package.json +7 -7
  116. package/templates/apps/frontend-i18n/package.json +6 -6
  117. package/templates/apps/frontend-landing/package.json +7 -7
  118. package/templates/apps/frontend-portal/package.json +8 -8
  119. package/templates/apps/frontend-saas/package.json +8 -8
  120. package/templates/apps/frontend-spa/package.json +7 -7
  121. package/templates/apps/frontend-ssr/package.json +7 -7
  122. package/templates/apps/frontend-ssr-api/package.json +8 -8
  123. package/templates/apps/frontend-static-blog/package.json +6 -6
  124. package/templates/apps/frontend-status/package.json +8 -8
  125. package/templates/apps/mobile-app/package.json +3 -3
  126. package/dist/apiBuild-BICVGnEC.js +0 -2
  127. package/dist/appGraph-CvQCte0z.js +0 -2
  128. package/dist/dbCommand-CpdKLeQq.js +0 -2
  129. package/dist/doctorCommand-BvqGBwNG.js +0 -2
  130. package/dist/frameworkTableAssembly-BGHmck-x.js +0 -2
  131. package/dist/frameworkTableAssembly-DkkP6BgC.js +0 -674
  132. package/dist/inspect-C_T_WGvl.js +0 -2
  133. package/dist/manifestBuild-ChsKAhmn.js +0 -2
  134. package/dist/scheduleCmd--jksTrf6.js +0 -69
  135. package/dist/serveCommand-B_isw7q4.js +0 -1647
  136. package/dist/serveCommand-DOvbgRnQ.js +0 -2
  137. package/dist/updateCommand-us1_hdIC.js +0 -2
  138. package/dist/webDev-Cg-fFiyd2.js +0 -2
@@ -0,0 +1,2 @@
1
+ import { v as e, y as t } from "./doctorCommand-CNFtt3nR.js";
2
+ export { e as runDoctorCommand, t as runServePreflight };
@@ -1,8 +1,8 @@
1
- import { Ft as e, Nt as t, Pt as n } from "./dev-CerMd0mW.js";
2
- import { $ as r, Q as i, X as a, Z as o, s, t as c, y as l } from "./webDev-CBYvPqQr.js";
3
- import { w as u } from "./frameworkTableAssembly-DkkP6BgC.js";
1
+ import { Bt as e, Rt as t, zt as n } from "./dev-Dc4cpmRl.js";
2
+ import { $ as r, Q as i, X as a, Z as o, s, t as c, y as l } from "./webDev-Dybxew86.js";
3
+ import { w as u } from "./frameworkTableAssembly-oMPBKqlE.js";
4
4
  import { n as d } from "./pageConvention-cEiRxdab.js";
5
- import { r as f, u as p } from "./apiBuild-DZF_f0_I.js";
5
+ import { r as f, u as p } from "./apiBuild-DiE9zcj6.js";
6
6
  import { n as m, r as h, t as g } from "./cliOutput-D1tSBoRM.js";
7
7
  import { n as ee, t as te } from "./tsconfigPaths-BWXBWgcl.js";
8
8
  import { n as ne, r as re } from "./fileTaxonomy-CJfgOllU.js";
@@ -672,7 +672,7 @@ var le = /* @__PURE__ */ new Set([
672
672
  r !== void 0 && o.push(r);
673
673
  }
674
674
  return o;
675
- }, s = /* @__PURE__ */ new Set(), c = e.filter((e) => st.test(v(n, e))), l = new Set(c);
675
+ }, s = /* @__PURE__ */ new Set(), c = e.filter((e) => ct.test(v(n, e))), l = new Set(c);
676
676
  for (; c.length > 0;) {
677
677
  let e = c.shift();
678
678
  if (!s.has(e)) {
@@ -685,11 +685,11 @@ var le = /* @__PURE__ */ new Set([
685
685
  let d = /* @__PURE__ */ new Set();
686
686
  for (let e of s) l.has(e) || u.has(e) || d.add(e);
687
687
  return d;
688
- }, F = (e) => e.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/[^\n]*/g, "$1").replace(/'(?:[^'\\\n]|\\.)*'/g, "''").replace(/"(?:[^"\\\n]|\\.)*"/g, "\"\""), rt = (e, t) => (e.match(t) ?? []).length, I = (e, t) => e.getDescendantsOfKind(D.CallExpression).filter((e) => t.test(e.getExpression().getText())).length, it = (e, t) => {
688
+ }, rt = (e) => e.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/(^|[^:])\/\/[^\n]*/g, "$1").replace(/'(?:[^'\\\n]|\\.)*'/g, "''").replace(/"(?:[^"\\\n]|\\.)*"/g, "\"\""), it = (e, t) => (e.match(t) ?? []).length, F = (e, t) => e.getDescendantsOfKind(D.CallExpression).filter((e) => t.test(e.getExpression().getText())).length, at = (e, t) => {
689
689
  if (e.src.includes(t)) return !0;
690
690
  let n = t.replace(/^@voltro\/plugin-/, "");
691
- return n !== t && I(e.file, RegExp(`^${n}Plugin$`)) > 0;
692
- }, at = (e, t) => {
691
+ return n !== t && F(e.file, RegExp(`^${n}Plugin$`)) > 0;
692
+ }, ot = (e, t) => {
693
693
  let n = [], r = RegExp(`\\b${t}\\s*(?:<[^()]*>)?\\s*\\(`, "g"), i;
694
694
  for (; (i = r.exec(e)) !== null;) {
695
695
  let t = i.index + i[0].length, r = 1, a = t;
@@ -697,10 +697,10 @@ var le = /* @__PURE__ */ new Set([
697
697
  n.push(e.slice(t, a - 1));
698
698
  }
699
699
  return n;
700
- }, ot = (e, t) => {
700
+ }, st = (e, t) => {
701
701
  let n = t.getSymbol()?.getDeclarations()?.[0];
702
702
  return n === void 0 ? [] : e.getDescendantsOfKind(D.Identifier).filter((e) => e.getSymbol()?.getDeclarations()?.[0] === n);
703
- }, st = /\.(server|cron|workflow\.server|subscribe|reaction|outbox|startup|trigger|webhook|migration|seed)\.tsx?$/, ct = /\.(query|mutation|action|stream)\.server\.tsx?$/, lt = [
703
+ }, ct = /\.(server|cron|workflow\.server|subscribe|reaction|outbox|startup|trigger|webhook|migration|seed)\.tsx?$/, lt = /\.(query|mutation|action|stream)\.server\.tsx?$/, ut = [
704
704
  "Id",
705
705
  "ID",
706
706
  "Hash",
@@ -726,7 +726,7 @@ var le = /* @__PURE__ */ new Set([
726
726
  "Comment",
727
727
  "Provider",
728
728
  "Format"
729
- ], ut = RegExp(`(?:${lt.join("|")})$|_(?:${lt.map((e) => e.toLowerCase()).join("|")})$`), dt = [
729
+ ], dt = RegExp(`(?:${ut.join("|")})$|_(?:${ut.map((e) => e.toLowerCase()).join("|")})$`), ft = [
730
730
  {
731
731
  id: "hardcoded-framework-cookie",
732
732
  scope: "client",
@@ -739,7 +739,7 @@ var le = /* @__PURE__ */ new Set([
739
739
  scope: "server",
740
740
  smell: "an executor that never names its own descriptor — its input type is hand-written, so it can drift from the contract it implements",
741
741
  use: "import the descriptor and type the input as `ExecutorInput<typeof descriptor>`, so the wire contract and the handler cannot disagree",
742
- match: ({ src: e, path: t }) => ct.test(t) && !/\bimport\s[^;]*\bfrom\s*['"][^'"]*['"]/.test((e.match(/^\s*import\s[^;]*from\s*['"]\.[^'"]*['"]/gm) ?? []).join("\n"))
742
+ match: ({ src: e, path: t }) => lt.test(t) && !/\bimport\s[^;]*\bfrom\s*['"][^'"]*['"]/.test((e.match(/^\s*import\s[^;]*from\s*['"]\.[^'"]*['"]/gm) ?? []).join("\n"))
743
743
  },
744
744
  {
745
745
  id: "subject-write-no-guard",
@@ -747,8 +747,8 @@ var le = /* @__PURE__ */ new Set([
747
747
  smell: "writes ctx.request.subject.id into the database with no guard on the descriptor — an anonymous caller reaches the write and gets a raw statement failure instead of a typed refusal",
748
748
  use: "add a guard (e.g. `.guard(requireScope('…'))`) or an explicit auth check, so an unauthenticated caller is refused BEFORE the write",
749
749
  match: ({ src: e, path: t }) => {
750
- if (!ct.test(t)) return !1;
751
- let n = F(e);
750
+ if (!lt.test(t)) return !1;
751
+ let n = rt(e);
752
752
  return /\bsubject\s*\.\s*id\b/.test(n) && /\b(?:insert|update|upsert|insertMany|updateMany|insertRow|upsertRow|updateManyRow)\s*\(/.test(n) && !/\b(?:guard|guards|requireScope|requireAnyScope|assertCan|assertScope|requireAuth|Unauthenticated)\b/.test(n);
753
753
  }
754
754
  },
@@ -757,14 +757,14 @@ var le = /* @__PURE__ */ new Set([
757
757
  scope: "server",
758
758
  smell: "raw fetch() for outbound HTTP on the server (no traceparent, no retry, and no SSRF guard where the URL is not a constant)",
759
759
  use: "yield* HttpClient — the framework client. It injects traceparent, retries, and honours `http.allowHosts`. Where the URL is built from anything a caller supplied it ALSO blocks loopback / RFC-1918 / link-local targets (incl. 169.254.169.254) on the initial request AND every redirect hop — for a hard-coded host that half is redundant, and the first three are still the reason to switch",
760
- match: ({ file: e, path: t, serverOnly: n }) => (st.test(t) || n) && I(e, /^(?:globalThis\.|window\.|self\.)?fetch$/) > 0
760
+ match: ({ file: e, path: t, serverOnly: n }) => (ct.test(t) || n) && F(e, /^(?:globalThis\.|window\.|self\.)?fetch$/) > 0
761
761
  },
762
762
  {
763
763
  id: "form",
764
764
  scope: "client",
765
765
  smell: "per-field useState + a submit flag (hand-rolled form)",
766
766
  use: "useFormBinding — fields + validation from the mutation input Schema; server ValidationError({ field }) routes to the field",
767
- match: ({ src: e, file: t }) => I(t, /^useState$/) >= 4 && /onSubmit|handleSubmit|isSubmitting/.test(e)
767
+ match: ({ src: e, file: t }) => F(t, /^useState$/) >= 4 && /onSubmit|handleSubmit|isSubmitting/.test(e)
768
768
  },
769
769
  {
770
770
  id: "table",
@@ -792,7 +792,7 @@ var le = /* @__PURE__ */ new Set([
792
792
  scope: "client",
793
793
  smell: "useMemo fanning in multiple subscriptions (hand-maintained dep array)",
794
794
  use: "useDerived — dependency-tracked, referentially stable",
795
- match: ({ src: e }) => rt(e, /\buseSubscription\s*[(<]/g) >= 3 && rt(e, /\buseMemo\s*\(/g) >= 3
795
+ match: ({ src: e }) => it(e, /\buseSubscription\s*[(<]/g) >= 3 && it(e, /\buseMemo\s*\(/g) >= 3
796
796
  },
797
797
  {
798
798
  id: "next-shim",
@@ -817,7 +817,7 @@ var le = /* @__PURE__ */ new Set([
817
817
  match: ({ file: e }) => e.getDescendantsOfKind(D.CallExpression).filter((e) => /(^|\.)useSubscription$/.test(e.getExpression().getText())).flatMap((e) => {
818
818
  let t = e.getFirstAncestorByKind(D.VariableDeclaration)?.getNameNode();
819
819
  return t === void 0 ? [] : T.isObjectBindingPattern(t) ? t.getElements().filter((e) => (e.getPropertyNameNode() ?? e.getNameNode()).getText() === "data").map((e) => e.getNameNode()) : [];
820
- }).some((t) => ot(e, t).some((e) => {
820
+ }).some((t) => st(e, t).some((e) => {
821
821
  let t = e.getParent();
822
822
  if (T.isBinaryExpression(t)) {
823
823
  let n = t.getOperatorToken().getText(), r = t.getLeft() === e ? t.getRight() : t.getLeft();
@@ -845,7 +845,7 @@ var le = /* @__PURE__ */ new Set([
845
845
  scope: "server",
846
846
  smell: "several sequential store reads assembling related data (an N+1 you are writing by hand)",
847
847
  use: "reads are a parent→child walk on ONE key → relations() in a *.relations.ts + .with({ … }) (ONE JSON-aggregate query, every dialect); reads collect ids from SEVERAL sources → keep the assembly and run the independent leading reads under Effect.all (same queries, same results, only concurrent — zero parity risk)",
848
- match: (e) => I(e.file, /\bstore\.query$/) >= 3 || I(e.file, /\bstore\.query$/) >= 2 && /\bnew Map\s*\(/.test(e.src)
848
+ match: (e) => F(e.file, /\bstore\.query$/) >= 3 || F(e.file, /\bstore\.query$/) >= 2 && /\bnew Map\s*\(/.test(e.src)
849
849
  },
850
850
  {
851
851
  id: "store-effect-lift",
@@ -868,7 +868,7 @@ var le = /* @__PURE__ */ new Set([
868
868
  use: ".encrypted() on the column — boot fails loudly if no cipher is configured, so it can never silently persist plaintext (a *Hash column and a vault* handle are NOT plaintext secrets: the hash IS the protection — often a unique lookup key — and the handle only names a secret held elsewhere, so both are skipped)",
869
869
  match: ({ src: e }) => e.split("\n").some((e) => [...e.matchAll(/\b([A-Za-z_$][\w$]*)\s*:\s*(?:text|varchar|string|longtext)\s*\(/g)].some((t) => {
870
870
  let n = t[1];
871
- return !/token|secret|credential|password|apikey|accesskey/i.test(n) || ut.test(n) || /^vault/i.test(n) || /\.unique\s*\(/.test(e) ? !1 : !/\.encrypted\s*\(/.test(e);
871
+ return !/token|secret|credential|password|apikey|accesskey/i.test(n) || dt.test(n) || /^vault/i.test(n) || /\.unique\s*\(/.test(e) ? !1 : !/\.encrypted\s*\(/.test(e);
872
872
  }))
873
873
  },
874
874
  {
@@ -878,7 +878,7 @@ var le = /* @__PURE__ */ new Set([
878
878
  use: "you cannot look a value up by equality AND encrypt it non-deterministically — `.encrypted()` would make this column unfindable. Store the HASH as the unique lookup key and keep the secret itself either `.encrypted()` in a second column or nowhere (the framework's own `_voltro_api_keys.hashedKey` is the shape: the presented value is hashed and compared, never read back). A deterministic cipher is the other option and buys equality lookup at the cost of leaking which rows share a value",
879
879
  match: ({ src: e }) => e.split("\n").some((e) => [...e.matchAll(/\b([A-Za-z_$][\w$]*)\s*:\s*(?:text|varchar|string|longtext)\s*\(/g)].some((t) => {
880
880
  let n = t[1];
881
- return !/token|secret|credential|password|apikey|accesskey/i.test(n) || ut.test(n) || /^vault/i.test(n) ? !1 : /\.unique\s*\(/.test(e) && !/\.encrypted\s*\(/.test(e);
881
+ return !/token|secret|credential|password|apikey|accesskey/i.test(n) || dt.test(n) || /^vault/i.test(n) ? !1 : /\.unique\s*\(/.test(e) && !/\.encrypted\s*\(/.test(e);
882
882
  }))
883
883
  },
884
884
  {
@@ -942,9 +942,9 @@ var le = /* @__PURE__ */ new Set([
942
942
  scope: "server",
943
943
  smell: "setRowFilter is registered, but no test passes `rowFilter:` to makeTestContext",
944
944
  use: "wire the filter into at least one test (`makeTestContext({ subject, store, rowFilter })`) and sabotage the predicate once to watch it go red — an untested row filter is a visibility rule nothing verifies",
945
- match: ({ file: e, testSources: t }) => I(e, /^setRowFilter$/) > 0 && ![...t.values()].some((e) => {
946
- let t = F(e);
947
- return at(t, "makeTestContext").length > 0 && /\browFilter\b/.test(t);
945
+ match: ({ file: e, testSources: t }) => F(e, /^setRowFilter$/) > 0 && ![...t.values()].some((e) => {
946
+ let t = rt(e);
947
+ return ot(t, "makeTestContext").length > 0 && /\browFilter\b/.test(t);
948
948
  })
949
949
  },
950
950
  {
@@ -954,14 +954,14 @@ var le = /* @__PURE__ */ new Set([
954
954
  use: "timestampMs / timestampMsOrNull from @voltro/database/wire in the descriptor's output struct — `output` IS the serializer (it is the rpc success schema), so a Date field declared as timestampMs crosses as epoch ms on its own; declaring Schema.Number describes the WIRE type and leaves nothing to convert",
955
955
  match: ({ src: e }) => /\.(getTime|toISOString)\s*\(\s*\)/.test(e) && /\.map\s*\(|=>\s*\(\{/.test(e) && /\bexport\s+default\b/.test(e)
956
956
  }
957
- ], ft = (e) => R(e), pt = (e, t) => {
957
+ ], pt = (e) => R(e), mt = (e, t) => {
958
958
  let n = /* @__PURE__ */ new Set();
959
959
  for (let r of t) {
960
960
  let t = v(e, r), i = t.split(/[\\/]/)[0];
961
961
  n.add(i !== void 0 && i !== t ? i : ".");
962
962
  }
963
963
  return [...n].sort();
964
- }, mt = /\.(tsx?|jsx?)$/, L = /(^|\/)(node_modules|dist|build|\.framework|\.next|coverage)(\/|$)/, ht = /(^|[\\/])[^\\/]*\.generated\.[cm]?[jt]sx?$|\.d\.[cm]?ts$/, gt = (e, t = [], n = 0) => {
964
+ }, I = /\.(tsx?|jsx?)$/, L = /(^|\/)(node_modules|dist|build|\.framework|\.next|coverage)(\/|$)/, ht = /(^|[\\/])[^\\/]*\.generated\.[cm]?[jt]sx?$|\.d\.[cm]?ts$/, gt = (e, t = [], n = 0) => {
965
965
  if (n > 12 || L.test(e)) return t;
966
966
  let r;
967
967
  try {
@@ -992,7 +992,7 @@ var le = /* @__PURE__ */ new Set([
992
992
  } catch {
993
993
  continue;
994
994
  }
995
- a.isDirectory() ? R(r, t, n + 1) : mt.test(i) && !/\.(test|spec)\./.test(i) && !ht.test(i) && t.push(r);
995
+ a.isDirectory() ? R(r, t, n + 1) : I.test(i) && !/\.(test|spec)\./.test(i) && !ht.test(i) && t.push(r);
996
996
  }
997
997
  return t;
998
998
  }, _t = (e, t = [], n = 0) => {
@@ -1010,17 +1010,17 @@ var le = /* @__PURE__ */ new Set([
1010
1010
  } catch {
1011
1011
  continue;
1012
1012
  }
1013
- a.isDirectory() ? _t(r, t, n + 1) : mt.test(i) && /\.(test|spec)\./.test(i) && t.push(r);
1013
+ a.isDirectory() ? _t(r, t, n + 1) : I.test(i) && /\.(test|spec)\./.test(i) && t.push(r);
1014
1014
  }
1015
1015
  return t;
1016
1016
  }, vt = (e) => {
1017
- let t = ft(e);
1017
+ let t = pt(e);
1018
1018
  return {
1019
- dirs: pt(e, t),
1019
+ dirs: mt(e, t),
1020
1020
  fileCount: t.length
1021
1021
  };
1022
1022
  }, yt = (e) => {
1023
- let t = ft(e);
1023
+ let t = pt(e);
1024
1024
  if (t.length === 0) return [];
1025
1025
  let n = new E({
1026
1026
  useInMemoryFileSystem: !0,
@@ -1048,13 +1048,13 @@ var le = /* @__PURE__ */ new Set([
1048
1048
  } catch {
1049
1049
  continue;
1050
1050
  }
1051
- for (let t of dt) {
1052
- if (t.plugin !== void 0 && it(c, t.plugin) || !t.match(c)) continue;
1051
+ for (let t of ft) {
1052
+ if (t.plugin !== void 0 && at(c, t.plugin) || !t.match(c)) continue;
1053
1053
  let n = r.get(t.id) ?? [];
1054
1054
  n.push(v(e, s)), r.set(t.id, n);
1055
1055
  }
1056
1056
  }
1057
- return dt.filter((e) => r.has(e.id)).map((e) => ({
1057
+ return ft.filter((e) => r.has(e.id)).map((e) => ({
1058
1058
  rule: e,
1059
1059
  files: r.get(e.id)
1060
1060
  })).sort((e, t) => t.files.length - e.files.length || e.rule.id.localeCompare(t.rule.id));
@@ -1245,7 +1245,7 @@ var le = /* @__PURE__ */ new Set([
1245
1245
  let t = zt.get(e);
1246
1246
  if (t !== void 0) return t;
1247
1247
  let n = (async () => {
1248
- let { walk: t, loadDiscovered: n } = await import("./dev-CoG-ZPx8.js"), r = await t(e);
1248
+ let { walk: t, loadDiscovered: n } = await import("./dev-BSFTgCQ5.js"), r = await t(e);
1249
1249
  return {
1250
1250
  files: r,
1251
1251
  discovered: await n(r)
@@ -1333,11 +1333,12 @@ var le = /* @__PURE__ */ new Set([
1333
1333
  }
1334
1334
  }, J = async (r) => {
1335
1335
  try {
1336
- let { loadApiConfig: i } = await import("./dev-CoG-ZPx8.js"), { discovered: a } = await U(r), o = n(await i(r)), s = {
1336
+ let { loadApiConfig: i } = await import("./dev-BSFTgCQ5.js"), { discovered: a } = await U(r), o = n(await i(r)), s = {
1337
1337
  queries: a.queries,
1338
1338
  mutations: a.mutations,
1339
1339
  actions: a.actions,
1340
- streams: a.streams
1340
+ streams: a.streams,
1341
+ events: a.events
1341
1342
  };
1342
1343
  return {
1343
1344
  checked: !0,
@@ -1362,7 +1363,9 @@ var le = /* @__PURE__ */ new Set([
1362
1363
  if (t.undecided.length === 0) return !1;
1363
1364
  console.log("");
1364
1365
  for (let e of t.undecided) console.log(` ✗ ${e.tag} (${e.kind})${e.file === void 0 ? "" : `\n ${e.file}`}`);
1365
- return console.log(""), t.defaultDeny ? (console.log(" `voltro dev` and `voltro serve` REFUSE to boot on these. Give each a decision:"), console.log(" `guards: [{ scope: '…' }]`, or `openAccess: '<why anyone may call it>'`."), !0) : (console.log(" This app sets `security: { defaultDeny: false }`, so these BOOT — and each one is"), console.log(" callable by any authenticated session. Advisory here for that reason only."), !1);
1366
+ return console.log(""), t.defaultDeny ? (console.log(" `voltro dev` and `voltro serve` REFUSE to boot on these. Give each a decision:"), Gt(), !0) : (console.log(" This app sets `security: { defaultDeny: false }`, so these BOOT — and each one is"), console.log(" callable by any authenticated session. Advisory here for that reason only."), Gt(), !1);
1367
+ }, Gt = () => {
1368
+ console.log(" `guards: [{ scope: '…' }]` authority the SUBJECT holds globally"), console.log(" `guards: [{ action, resourceType, resource }]` authority per ROW / per resource"), console.log(" — backed by `defineResourcePolicy` + a tuple source you register. If your"), console.log(" relationships already live in your own tables (a `teamMembers` row), register"), console.log(" a tuple source over them; nothing is copied. Fail-closed without a resolver."), console.log(" Docs: Authentication → Authorization."), console.log(" `openAccess: '<why anyone may call it>'` deliberately unauthenticated");
1366
1369
  }, Y = async (e) => {
1367
1370
  try {
1368
1371
  let { files: t } = await U(e), { WEBHOOK_PATTERN: n, loadWebhookFiles: r } = await import("./webhookDiscovery-CrGAfhIG.js"), { incomingWebhookVerification: i } = await import("@voltro/plugin-webhooks"), a = t.filter((e) => n.test(ie(e)));
@@ -1398,7 +1401,7 @@ var le = /* @__PURE__ */ new Set([
1398
1401
  verified: 0
1399
1402
  };
1400
1403
  }
1401
- }, Gt = async (e) => {
1404
+ }, Kt = async (e) => {
1402
1405
  let t = await Y(e);
1403
1406
  if (!t.checked) return console.log(""), console.log("• webhook verification: NOT CHECKED — the app's webhooks could not be loaded (not a pass)"), console.log(` reason: ${t.reason ?? "unknown"}`), !1;
1404
1407
  if (t.verified + t.open.length + t.unverified.length === 0) return !1;
@@ -1408,13 +1411,13 @@ var le = /* @__PURE__ */ new Set([
1408
1411
  console.log("");
1409
1412
  for (let e of t.unverified) console.log(` ✗ ${e.id}\n ${e.file}`);
1410
1413
  return console.log(""), console.log(" These are public POSTs that run your application code, and `voltro dev` /"), console.log(" `voltro serve` REFUSE to mount them. Declare one of: `provider:` (a preset),"), console.log(" `signature:` (your own HMAC scheme), `verification: 'provider'` (your handler"), console.log(" verifies), or `verification: 'none'` (deliberately public)."), !0;
1411
- }, Kt = async (e) => {
1414
+ }, qt = async (e) => {
1412
1415
  let { status: t, message: n } = await q(e);
1413
1416
  return t.checked ? n === void 0 ? !1 : (console.log(""), console.log(`✗ [serverOnly] ${n}`), !0) : (console.log(""), console.log("• serverOnly: NOT CHECKED — the app's descriptors could not be loaded (not a pass)"), console.log(` reason: ${t.reason ?? "unknown"}`), console.log(" This audit is the automated check that a hash or a token cannot reach the wire, so"), console.log(" an app that leans on `.serverOnly()` should treat a persistent skip as a failure."), console.log(" `voltro doctor --json` reports it as `serverOnly.checked: false` for a CI gate."), !1);
1414
- }, qt = async (e) => Xe({
1417
+ }, Jt = async (e) => Xe({
1415
1418
  hasWorkflows: async () => (await U(e)).discovered.workflows.length > 0,
1416
1419
  openStore: async () => {
1417
- let { loadApiConfig: t, buildStore: n } = await import("./dev-CoG-ZPx8.js"), r = await t(e);
1420
+ let { loadApiConfig: t, buildStore: n } = await import("./dev-BSFTgCQ5.js"), r = await t(e);
1418
1421
  if (r === null) throw Error("no app.config.ts in this directory");
1419
1422
  let i = await n(r, void 0);
1420
1423
  return {
@@ -1428,10 +1431,10 @@ var le = /* @__PURE__ */ new Set([
1428
1431
  let { sweepStalledRuns: t } = await import("@voltro/workflow");
1429
1432
  return t({ store: e });
1430
1433
  }
1431
- }), Jt = async (e) => {
1432
- let t = Qe(await qt(e));
1434
+ }), Yt = async (e) => {
1435
+ let t = Qe(await Jt(e));
1433
1436
  t !== null && (console.log(""), console.log(t));
1434
- }, Yt = async (e) => {
1437
+ }, Xt = async (e) => {
1435
1438
  let t;
1436
1439
  try {
1437
1440
  let { payloadPropertyNames: n } = await import("@voltro/runtime"), { files: r, discovered: i } = await U(e);
@@ -1454,13 +1457,13 @@ var le = /* @__PURE__ */ new Set([
1454
1457
  console.log("");
1455
1458
  let r = t.issues.length > 0 ? "✗" : t.unchecked.length > 0 ? "•" : "✓";
1456
1459
  console.log(`${r} ${n}`);
1457
- }, X = "voltro-authz-allowlist.txt", Xt = (e, t = (e) => {
1460
+ }, X = "voltro-authz-allowlist.txt", Zt = (e, t = (e) => {
1458
1461
  try {
1459
1462
  return S(e, "utf8");
1460
1463
  } catch {
1461
1464
  return "";
1462
1465
  }
1463
- }) => /* @__PURE__ */ new Set([...j, ...Ie(R(e).map(t))]), Zt = (e, t) => {
1466
+ }) => /* @__PURE__ */ new Set([...j, ...Ie(R(e).map(t))]), Qt = (e, t) => {
1464
1467
  let n = t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1465
1468
  return new RegExp(String.raw`(?:export\s+)?const\s+([A-Za-z_$][\w$]*)\s*=\s*define[A-Za-z]*Event\s*\(\s*\{[^}]*?name\s*:\s*['"\`]${n}['"\`]`, "s").exec(e)?.[1];
1466
1469
  }, Z = async (e) => {
@@ -1479,22 +1482,22 @@ var le = /* @__PURE__ */ new Set([
1479
1482
  }, a = R(e).filter((e) => !r.has(e)).map(i).join("\n");
1480
1483
  return n.filter(({ name: e, file: t }) => {
1481
1484
  if (a.includes(e)) return !1;
1482
- let n = Zt(i(t), e);
1485
+ let n = Qt(i(t), e);
1483
1486
  return n === void 0 || !new RegExp(String.raw`\b${n}\b`).test(a);
1484
1487
  }).map((e) => e.name).sort();
1485
1488
  } catch {
1486
1489
  return [];
1487
1490
  }
1488
- }, Qt = async (e) => {
1491
+ }, $t = async (e) => {
1489
1492
  let t = await Z(e);
1490
1493
  if (t.length !== 0) {
1491
1494
  console.log(""), console.log(`• ${t.length} declared event(s) with no emit call site found:`);
1492
1495
  for (let e of t) console.log(` ${e}`);
1493
1496
  console.log(""), console.log(" An event you declare is an event partners can subscribe to. One that"), console.log(" never fires is indistinguishable, from their side, from a broken"), console.log(" endpoint of their own — so they debug your contract instead of"), console.log(" reading it."), console.log(" ADVISORY: this looks for the event name AND the identifier its"), console.log(" declaration binds it to, so `emit(ctx, apiKeyCreated, …)` counts. An"), console.log(" emit through an ASSEMBLED name still reads as missing here.");
1494
1497
  }
1495
- }, $t = async (e) => {
1498
+ }, en = async (e) => {
1496
1499
  try {
1497
- let { loadApiConfig: t } = await import("./dev-CoG-ZPx8.js"), n = (await t(e))?.doctor?.scopeVocabulary;
1500
+ let { loadApiConfig: t } = await import("./dev-BSFTgCQ5.js"), n = (await t(e))?.doctor?.scopeVocabulary;
1498
1501
  if (typeof n != "string") return [];
1499
1502
  let [r, i] = n.split("#");
1500
1503
  if (r === void 0 || i === void 0) return [];
@@ -1510,7 +1513,7 @@ var le = /* @__PURE__ */ new Set([
1510
1513
  findings: []
1511
1514
  };
1512
1515
  try {
1513
- let { offlineManifest: n, toInput: r } = await import("./checkCommand-YZDmkAGd.js"), { buildAppGraph: i, checkAppGraph: a } = await import("./appGraph-CvQCte0z.js"), o = await n(e), s = r(o.manifest, o.tables), c = await $t(e), l = [.../* @__PURE__ */ new Set([...s.scopes ?? [], ...c])];
1516
+ let { offlineManifest: n, toInput: r } = await import("./checkCommand-BTA6P3Yr.js"), { buildAppGraph: i, checkAppGraph: a } = await import("./appGraph-zuMGKVYX.js"), o = await n(e), s = r(o.manifest, o.tables), c = await en(e), l = [.../* @__PURE__ */ new Set([...s.scopes ?? [], ...c])];
1514
1517
  if (l.length === 0) return t;
1515
1518
  let u = i({
1516
1519
  ...s,
@@ -1529,7 +1532,7 @@ var le = /* @__PURE__ */ new Set([
1529
1532
  } catch {
1530
1533
  return t;
1531
1534
  }
1532
- }, en = async (e) => {
1535
+ }, tn = async (e) => {
1533
1536
  let { findings: t, evaluated: n } = await Q(e);
1534
1537
  if (!n) {
1535
1538
  console.log(""), console.log("• scope vocabulary: none found — the unknown-scope rule did NOT run."), console.log(" It compares each procedure's required scopes against the scopes your"), console.log(" roles actually grant, and needs somewhere to read that set from."), console.log(" `@voltro/plugin-rbac` publishes it from its `roles` map; an app doing"), console.log(" RBAC without the plugin can point at its own:"), console.log(""), console.log(" // app.config.ts"), console.log(" doctor: { scopeVocabulary: './lib/teamRoles.ts#ALL_TEAM_SCOPES' }"), console.log(""), console.log(" Until then this section is NOT a clean bill of health — a procedure"), console.log(" requiring a scope no role grants is uncallable by everyone, and"), console.log(" nothing here would have told you.");
@@ -1540,7 +1543,7 @@ var le = /* @__PURE__ */ new Set([
1540
1543
  for (let e of t) console.log(` ${e.node}${e.file === void 0 ? "" : ` ${e.file}`}`), console.log(` ${e.detail}`);
1541
1544
  console.log(""), console.log(" Each of these is uncallable by every user in every role — not"), console.log(" misconfigured, DEAD — and nothing fails at boot to say so. The"), console.log(" usual cause is a typo or a rename that moved one side only."), console.log(` ${t[0].fix}`);
1542
1545
  }
1543
- }, tn = async (e) => {
1546
+ }, nn = async (e) => {
1544
1547
  let t = ["src/locales", "locales"], n, r = [];
1545
1548
  for (let i of t) {
1546
1549
  let t = _(e, i);
@@ -1552,7 +1555,7 @@ var le = /* @__PURE__ */ new Set([
1552
1555
  if (n === void 0 || r.length === 0) return;
1553
1556
  let i = [];
1554
1557
  try {
1555
- let { loadApiConfig: t } = await import("./dev-CoG-ZPx8.js");
1558
+ let { loadApiConfig: t } = await import("./dev-BSFTgCQ5.js");
1556
1559
  i = (await t(e))?.locales ?? [];
1557
1560
  } catch {
1558
1561
  return;
@@ -1565,10 +1568,10 @@ var le = /* @__PURE__ */ new Set([
1565
1568
  console.log("");
1566
1569
  for (let e of Fe(a, n)) console.log(e);
1567
1570
  }
1568
- }, nn = async (e) => {
1571
+ }, rn = async (e) => {
1569
1572
  let { discovered: t } = await U(e), n = [];
1570
1573
  try {
1571
- let { loadApiConfig: t } = await import("./dev-CoG-ZPx8.js");
1574
+ let { loadApiConfig: t } = await import("./dev-BSFTgCQ5.js");
1572
1575
  n = ((await t(e))?.plugins ?? []).map((e) => {
1573
1576
  let t = (e.extendSchema?.tables ?? []).map((e) => {
1574
1577
  let t = e;
@@ -1581,8 +1584,8 @@ var le = /* @__PURE__ */ new Set([
1581
1584
  plugin: e.name,
1582
1585
  tables: t,
1583
1586
  rpcTags: n,
1584
- canDisableTables: rn.has(r),
1585
- canAlias: an.has(r)
1587
+ canDisableTables: an.has(r),
1588
+ canAlias: on.has(r)
1586
1589
  };
1587
1590
  });
1588
1591
  } catch {
@@ -1600,12 +1603,12 @@ var le = /* @__PURE__ */ new Set([
1600
1603
  });
1601
1604
  console.log();
1602
1605
  for (let e of Ye(n, i)) console.log(e);
1603
- }, rn = /* @__PURE__ */ new Set([
1606
+ }, an = /* @__PURE__ */ new Set([
1604
1607
  "@voltro/plugin-rbac",
1605
1608
  "@voltro/plugin-audit",
1606
1609
  "@voltro/plugin-notifications",
1607
1610
  "aiFlows"
1608
- ]), an = /* @__PURE__ */ new Set([
1611
+ ]), on = /* @__PURE__ */ new Set([
1609
1612
  "aiFlows",
1610
1613
  "@voltro/plugin-audit",
1611
1614
  "@voltro/plugin-billing",
@@ -1622,8 +1625,8 @@ var le = /* @__PURE__ */ new Set([
1622
1625
  "@voltro/plugin-sso-saml",
1623
1626
  "@voltro/plugin-storage",
1624
1627
  "@voltro/plugin-versioning"
1625
- ]), $ = 20, on = async (e) => {
1626
- let t = await sn(e), n = new Set(t.reviewed.map((e) => e.tag)), r = t.result.findings.filter((e) => e.verdict.kind === "allowlisted" && !n.has(e.tag)).length;
1628
+ ]), $ = 20, sn = async (e) => {
1629
+ let t = await cn(e), n = new Set(t.reviewed.map((e) => e.tag)), r = t.result.findings.filter((e) => e.verdict.kind === "allowlisted" && !n.has(e.tag)).length;
1627
1630
  return {
1628
1631
  executors: t.executorCount,
1629
1632
  guardVocabulary: [...t.vocabulary].sort(),
@@ -1635,7 +1638,7 @@ var le = /* @__PURE__ */ new Set([
1635
1638
  },
1636
1639
  unchecked: t.result.unchecked
1637
1640
  };
1638
- }, sn = async (e) => {
1641
+ }, cn = async (e) => {
1639
1642
  let { discovered: t } = await U(e), n = /* @__PURE__ */ new Map(), r = (e) => {
1640
1643
  if (!n.has(e)) try {
1641
1644
  n.set(e, S(e, "utf8"));
@@ -1643,7 +1646,7 @@ var le = /* @__PURE__ */ new Set([
1643
1646
  n.set(e, "");
1644
1647
  }
1645
1648
  return n.get(e);
1646
- }, i = Xt(e, r), a = /* @__PURE__ */ new Set();
1649
+ }, i = Zt(e, r), a = /* @__PURE__ */ new Set();
1647
1650
  for (let e of t.tables) for (let t of Object.values(e.fields ?? {})) try {
1648
1651
  let e = t.references?.();
1649
1652
  e && a.add(e.tableName);
@@ -1697,8 +1700,8 @@ var le = /* @__PURE__ */ new Set([
1697
1700
  executorCount: o.length,
1698
1701
  allowPath: s
1699
1702
  };
1700
- }, cn = async (e, t) => {
1701
- let { result: n, vocabulary: r, existing: i, reviewed: a, executorCount: o, allowPath: s, rowFilterRegistered: c } = await sn(e), l = n.counts;
1703
+ }, ln = async (e, t) => {
1704
+ let { result: n, vocabulary: r, existing: i, reviewed: a, executorCount: o, allowPath: s, rowFilterRegistered: c } = await cn(e), l = n.counts;
1702
1705
  console.log(`\nauthz scan · ${o} executor(s)`);
1703
1706
  let u = [...r].filter((e) => !j.has(e)).sort();
1704
1707
  console.log(u.length === 0 ? " guard vocabulary: framework names only — no exported require*/assert* found in this app" : ` guard vocabulary: ${u.length} from your source (${u.slice(0, 6).join(", ")}${u.length > 6 ? ", …" : ""})`), console.log(` ✗ no access check ${String(l.unchecked).padStart(4)}`), console.log(` ⚠ inline ownership check, no named guard${String(l.inlineOwnership).padStart(4)} (informational)`), console.log(` ✓ guards: on the descriptor ${String(l.declaredGuard).padStart(4)}`), console.log(` ✓ calls a guard from the vocabulary ${String(l.vocabularyGuard).padStart(4)}`);
@@ -1711,7 +1714,7 @@ var le = /* @__PURE__ */ new Set([
1711
1714
  console.log("");
1712
1715
  for (let e of n.unchecked.slice(0, $)) console.log(` ✗ ${e.tag} — ${e.why}\n ${e.path}`);
1713
1716
  return n.unchecked.length > $ && console.log(` … and ${n.unchecked.length - $} more — \`voltro doctor --json\` prints every one (\`authz.unchecked\`).`), i === void 0 ? (console.log(`\nNo ${X} yet, so this run is advisory. To start the ratchet:`), console.log("\n voltro doctor --write-authz-allowlist\n"), console.log("That records today's unchecked handlers as DEBT and fails every run after on"), console.log("anything NEW. Fix a handler and its line stops mattering — the scan reports it as"), console.log("guarded whether or not the line is still there."), !1) : (console.log(`\n${n.unchecked.length} executor(s) with no access check are not in ${X}.`), console.log("Add a guard, or add the tag to that file if it is genuinely open."), console.log("\nBefore hand-rolling another check: `guards: [{ action, resourceType, resource }]`"), console.log("answers \"may this subject act on THIS row\" declaratively, and an app whose"), console.log("relationships live in its own tables registers its own tuple source rather than"), console.log("copying data into a framework table. See the authorization docs."), !0);
1714
- }, ln = async (e) => {
1717
+ }, un = async (e) => {
1715
1718
  if (e.includes("--help") || e.includes("-h")) return console.log(Rt), 0;
1716
1719
  let t = e.includes("--strict"), n = y(e.find((e) => !e.startsWith("-")) ?? process.cwd());
1717
1720
  if (h(e)) return g(), m({
@@ -1726,17 +1729,17 @@ var le = /* @__PURE__ */ new Set([
1726
1729
  serverOnly: (await q(n)).status,
1727
1730
  accessDecisions: await J(n),
1728
1731
  webhookVerification: await Y(n),
1729
- authz: await on(n),
1732
+ authz: await sn(n),
1730
1733
  ungrantedScopes: await Q(n),
1731
1734
  neverEmittedEvents: await Z(n),
1732
- stalledRuns: await qt(n)
1735
+ stalledRuns: await Jt(n)
1733
1736
  }), 0;
1734
1737
  let s = tt(n, t);
1735
- Tt(n), wt(n), Lt(n), ne(n), await jt(n), await Yt(n), await Jt(n), await Bt(n), await Ht(n), await Ut(n), await nn(n), await en(n), await Qt(n), await tn(n);
1736
- let c = await Kt(n), l = await cn(n, e.includes("--write-authz-allowlist")), u = await Wt(n), d = await Gt(n), f = r(o(n));
1738
+ Tt(n), wt(n), Lt(n), ne(n), await jt(n), await Xt(n), await Yt(n), await Bt(n), await Ht(n), await Ut(n), await rn(n), await tn(n), await $t(n), await nn(n);
1739
+ let c = await qt(n), l = await ln(n, e.includes("--write-authz-allowlist")), u = await Wt(n), d = await Kt(n), f = r(o(n));
1737
1740
  f !== void 0 && (console.log(""), console.log(f));
1738
1741
  let p = i(a(n));
1739
1742
  return p !== void 0 && console.log(`\n${p}`), c || l || u || d ? Math.max(s, 1) : s;
1740
1743
  };
1741
1744
  //#endregion
1742
- export { q as C, B as S, Y as T, jt as _, on as a, yt as b, G as c, vt as d, P as f, Lt as g, Tt as h, J as i, Xt as l, wt as m, et as n, Z as o, W as p, Et as r, Zt as s, Rt as t, z as u, ln as v, Q as w, V as x, tt as y };
1745
+ export { q as C, B as S, Y as T, jt as _, sn as a, yt as b, G as c, vt as d, P as f, Lt as g, Tt as h, J as i, Zt as l, wt as m, et as n, Z as o, W as p, Et as r, Qt as s, Rt as t, z as u, un as v, Q as w, V as x, tt as y };
@@ -1,4 +1,4 @@
1
- import { c as e, i as t } from "./dev-CerMd0mW.js";
1
+ import { c as e, i as t } from "./dev-Dc4cpmRl.js";
2
2
  import { n, t as r } from "./cliArgs-D4p8n7EE.js";
3
3
  import { r as i } from "./appPort-B_HpJ_ck.js";
4
4
  import { resolve as a } from "node:path";
@@ -1,4 +1,4 @@
1
- import { c as e, i as t } from "./dev-CerMd0mW.js";
1
+ import { c as e, i as t } from "./dev-Dc4cpmRl.js";
2
2
  import { Effect as n } from "effect";
3
3
  import { embedMany as r } from "@voltro/ai";
4
4
  //#region src/embeddingsBackfill.ts
@@ -1,5 +1,5 @@
1
- import { c as e } from "./dev-CerMd0mW.js";
2
- import { at as t, ct as n, lt as r, ot as i } from "./webDev-CBYvPqQr.js";
1
+ import { c as e } from "./dev-Dc4cpmRl.js";
2
+ import { at as t, ct as n, lt as r, ot as i } from "./webDev-Dybxew86.js";
3
3
  import { join as a } from "node:path";
4
4
  import { promises as o } from "node:fs";
5
5
  import { createLogger as s } from "@voltro/logger";
@@ -1,6 +1,6 @@
1
1
  import { n as e } from "./cliOutput-D1tSBoRM.js";
2
- import { t } from "./checkCommand-Dv8r9tGO.js";
3
- import { i as n, n as r } from "./codemodRunner-DRRqXR74.js";
2
+ import { t } from "./checkCommand-BhG0gmUD.js";
3
+ import { i as n, n as r } from "./codemodRunner-DjQGrdmg.js";
4
4
  import { basename as i, join as a, resolve as o } from "node:path";
5
5
  import { branchNamespaceName as s, planBranchProvision as c } from "@voltro/database";
6
6
  import { readFile as l } from "node:fs/promises";
@@ -0,0 +1,2 @@
1
+ import { n as e } from "./frameworkTableAssembly-oMPBKqlE.js";
2
+ export { e as assembleFrameworkTables };