@voltro/cli 0.51.0 → 0.53.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 (233) hide show
  1. package/CHANGELOG.md +356 -0
  2. package/THIRD-PARTY-NOTICES.md +8311 -3318
  3. package/dist/{agentsMd-D6yD7IQv.js → agentsMd-0l980yhL.js} +4 -1
  4. package/dist/agentsMd-SDDSkyl4.js +2 -0
  5. package/dist/{apiBuild-CPDHXF72.js → apiBuild-CaPfoWku.js} +11 -5
  6. package/dist/apiBuild-DHtLXYx9.js +2 -0
  7. package/dist/bin.js +1 -1
  8. package/dist/build-D-OnvNMf.js +843 -0
  9. package/dist/{checkCommand-DNuPiWMc.js → checkCommand-C5elt0tW.js} +92 -46
  10. package/dist/checkCommand-D2ZduVlh.js +2 -0
  11. package/dist/{cloudCmd-F4YJeqM3.js → cloudCmd-QUXh-b5w.js} +1 -1
  12. package/dist/codegen-BWpt3VgF.js +2 -0
  13. package/dist/{codegen-CrMXs4hb.js → codegen-FEk8AZHb.js} +2 -2
  14. package/dist/{codegenCommand-BNBHcNNj.js → codegenCommand-BOiWQ5hz.js} +12 -12
  15. package/dist/{codemodRunner-BDVixlSw.js → codemodRunner-BjtB2lq6.js} +691 -545
  16. package/dist/{commands-B1OiS9bX.js → commands-DyxAmhP0.js} +36 -36
  17. package/dist/{dashboardCommand-C-vvPY1B.js → dashboardCommand-BdKTyT13.js} +3 -3
  18. package/dist/{dataCommand-C1GxXW5q.js → dataCommand-Bab9X7s8.js} +27 -27
  19. package/dist/{dbCommand-If4Y1xQ-.js → dbCommand-06O2finM.js} +277 -236
  20. package/dist/dbCommand-B1EXBC6f.js +2 -0
  21. package/dist/{dev-kdAg9Q7l.js → dev-C6LGF4iY.js} +2998 -2379
  22. package/dist/dev-GjJWAYo2.js +3 -0
  23. package/dist/doctorCommand-B0hX0tdz.js +2 -0
  24. package/dist/{doctorCommand-nKmeW78u.js → doctorCommand-etMkflRc.js} +332 -220
  25. package/dist/{dormancyCommand-CY3wa_SW.js → dormancyCommand-UwZ1AZzB.js} +1 -1
  26. package/dist/{embeddingsCommand-BDLIgje_.js → embeddingsCommand-C70zWHwo.js} +1 -1
  27. package/dist/{envCommand-C6V_xVlT.js → envCommand-dSyKvRkM.js} +15 -15
  28. package/dist/{evolveCommand-D3c4DSfN.js → evolveCommand-CG0_ebO5.js} +2 -2
  29. package/dist/fileConventions-DASGEmj-.js +35 -0
  30. package/dist/{fileTaxonomy-CJfgOllU.js → fileTaxonomy-B7uxipWS.js} +55 -55
  31. package/dist/fontPipeline-LxIHa1vo.js +2 -0
  32. package/dist/fontPipeline-Tsh8kZfA.js +152 -0
  33. package/dist/frameworkTableAssembly-C_7Z-rMs.js +2 -0
  34. package/dist/{frameworkTableAssembly-BwJVEKLr.js → frameworkTableAssembly-DKx3ba3S.js} +5 -5
  35. package/dist/imagePipeline-B_GVJgm6.js +2 -0
  36. package/dist/imagePipeline-CBZmjT4i.js +127 -0
  37. package/dist/index.js +1 -1
  38. package/dist/{infoCommand-BnRFEF1o.js → infoCommand-_53iOc_j.js} +1 -1
  39. package/dist/{inspect-CtL_xTbu.js → inspect-Bd8-9wsi.js} +1 -1
  40. package/dist/inspect-CuoDInfZ.js +2 -0
  41. package/dist/{inspectGateHint-BjnFubmH.js → inspectGateHint-4LxkNtrz.js} +1 -1
  42. package/dist/inspectMetrics-CGF94puw.js +143 -0
  43. package/dist/manifestBuild-C4-J1-m_.js +2 -0
  44. package/dist/{manifestBuild-CuU1VrSm.js → manifestBuild-Cqgsx2bM.js} +1 -1
  45. package/dist/{metaCommands-CfRLra0s.js → metaCommands-Cn2oboG4.js} +9 -3
  46. package/dist/{migrate-DehuBakM.js → migrate-Cko9rswM.js} +2 -2
  47. package/dist/{pageConvention-cEiRxdab.js → pageConvention-C938S8oC.js} +1 -1
  48. package/dist/{privacyCommand-XejDMvmu.js → privacyCommand-DWTQMC6R.js} +2 -2
  49. package/dist/{probeCommand-C9gazU0H.js → probeCommand-DkGGLknv.js} +83 -24
  50. package/dist/{projectScaffold-mIX_DpSe.js → projectScaffold-B4dmTlwT.js} +1 -1
  51. package/dist/{projectScaffold-BIl97_E6.js → projectScaffold-EzlErR4E.js} +1 -1
  52. package/dist/{renderModeScan-D7J1B7Kw.js → renderModeScan-CUbOeOAg.js} +28 -11
  53. package/dist/{renderProfile-1OWWAAtx.js → renderProfile-CskIgAfn.js} +2 -2
  54. package/dist/{runtimeTrace-ZsBU7Tkx.js → runtimeTrace-c0APJz7E.js} +1 -1
  55. package/dist/{sdkgen-O4XqWOjM.js → sdkgen-BiQCgIEr.js} +1 -1
  56. package/dist/serveCommand-CueKQgzl.js +2443 -0
  57. package/dist/serveCommand-DsnrVN3U.js +2 -0
  58. package/dist/serveEntry.js +1 -1
  59. package/dist/start-BJzZLbt8.js +3 -0
  60. package/dist/start-ekPan8BT.js +1510 -0
  61. package/dist/startEntry.js +1 -1
  62. package/dist/{staticCommand-Dr2M6tpU.js → staticCommand-xlSL-IWk.js} +1 -1
  63. package/dist/{test-rXFq4S76.js → test-BWPQcRoB.js} +1 -1
  64. package/dist/updateCommand-Bqql_rsQ.js +2 -0
  65. package/dist/{updateCommand-Bs322Q78.js → updateCommand-C_8I8Rzo.js} +139 -115
  66. package/dist/webDev-C7jWJ5dX.js +2 -0
  67. package/dist/{webDev-B-ubQEMX.js → webDev-oczpugbx.js} +1767 -913
  68. package/dist/{webhooksCommand-FLYY9IXh.js → webhooksCommand-4SVPDjKg.js} +1 -1
  69. package/package.json +72 -18
  70. package/templates/AGENTS.core.md +11 -0
  71. package/templates/AGENTS.md +19 -6
  72. package/templates/agent-docs/_index.md +8 -6
  73. package/templates/agent-docs/_manifest.json +31 -15
  74. package/templates/agent-docs/ai.md +2 -2
  75. package/templates/agent-docs/authentication.md +1 -1
  76. package/templates/agent-docs/cli.md +97 -15
  77. package/templates/agent-docs/configuration.md +17 -0
  78. package/templates/agent-docs/data.md +680 -33
  79. package/templates/agent-docs/database/advancedqueries.md +7 -7
  80. package/templates/agent-docs/database/columntypes.md +2 -2
  81. package/templates/agent-docs/database/querying.md +1 -1
  82. package/templates/agent-docs/database/schema.md +2 -2
  83. package/templates/agent-docs/database/seedsdialects.md +2 -2
  84. package/templates/agent-docs/database/transactions.md +3 -3
  85. package/templates/agent-docs/deployment.md +30 -3
  86. package/templates/agent-docs/internationalization.md +2 -2
  87. package/templates/agent-docs/introduction.md +52 -0
  88. package/templates/agent-docs/local-first-mobile.md +132 -7
  89. package/templates/agent-docs/observability.md +2 -0
  90. package/templates/agent-docs/plugins/ai-flows.md +1 -1
  91. package/templates/agent-docs/plugins/audit.md +5 -5
  92. package/templates/agent-docs/plugins/auth.md +1 -1
  93. package/templates/agent-docs/plugins/cdc-out.md +2 -2
  94. package/templates/agent-docs/plugins/comments.md +142 -0
  95. package/templates/agent-docs/plugins/notifications.md +47 -4
  96. package/templates/agent-docs/plugins/presence.md +16 -3
  97. package/templates/agent-docs/plugins/prometheus.md +1 -1
  98. package/templates/agent-docs/plugins/queue.md +129 -0
  99. package/templates/agent-docs/plugins/{versioning.md → row-history.md} +22 -22
  100. package/templates/agent-docs/plugins/storage.md +2 -2
  101. package/templates/agent-docs/plugins.md +38 -12
  102. package/templates/agent-docs/reference.md +54 -5
  103. package/templates/agent-docs/routing.md +868 -50
  104. package/templates/agent-docs/schema-driven-ui.md +292 -5
  105. package/templates/agent-docs/security.md +125 -8
  106. package/templates/agent-docs/templates/apibackends.md +14 -14
  107. package/templates/agent-docs/templates/overview.md +1 -1
  108. package/templates/agent-docs/whats-new.md +171 -54
  109. package/templates/apps/api-ai/package.json +6 -7
  110. package/templates/apps/api-ai/tests/summarize.test.ts +1 -1
  111. package/templates/apps/api-auth/package.json +8 -8
  112. package/templates/apps/api-backend/package.json +7 -7
  113. package/templates/apps/api-backend-deactivation/package.json +7 -7
  114. package/templates/apps/api-backend-mail/package.json +8 -8
  115. package/templates/apps/api-backend-mariadb/package.json +9 -9
  116. package/templates/apps/api-backend-sqlite/package.json +8 -8
  117. package/templates/apps/api-backend-storage/package.json +8 -8
  118. package/templates/apps/api-cms/package.json +9 -10
  119. package/templates/apps/api-collab/package.json +8 -8
  120. package/templates/apps/api-data-advanced/package.json +8 -8
  121. package/templates/apps/api-durable/package.json +8 -8
  122. package/templates/apps/api-feature-flags/package.json +9 -9
  123. package/templates/apps/api-governance/package.json +8 -8
  124. package/templates/apps/api-kv/package.json +8 -8
  125. package/templates/apps/api-moderation/package.json +8 -8
  126. package/templates/apps/api-observability/package.json +8 -8
  127. package/templates/apps/api-ratelimit/package.json +8 -8
  128. package/templates/apps/api-rbac/package.json +8 -8
  129. package/templates/apps/api-rest/package.json +7 -7
  130. package/templates/apps/{api-versioning → api-row-history}/README.md +3 -3
  131. package/templates/apps/{api-versioning → api-row-history}/actions/documents.asOf.action.server.ts +1 -1
  132. package/templates/apps/{api-versioning → api-row-history}/actions/documents.history.action.server.ts +1 -1
  133. package/templates/apps/{api-versioning → api-row-history}/app.config.ts +3 -3
  134. package/templates/apps/{api-versioning → api-row-history}/database/schema.ts +1 -1
  135. package/templates/apps/{api-versioning → api-row-history}/mutations/documents.create.mutation.server.ts +1 -1
  136. package/templates/apps/{api-versioning → api-row-history}/mutations/documents.create.mutation.ts +1 -1
  137. package/templates/apps/{api-versioning → api-row-history}/mutations/documents.update.mutation.ts +1 -1
  138. package/templates/apps/{api-versioning → api-row-history}/package.json +8 -8
  139. package/templates/apps/api-row-history/template.json +6 -0
  140. package/templates/apps/{api-versioning → api-row-history}/tests/documents.create.test.ts +1 -1
  141. package/templates/apps/api-saas/app.config.ts +1 -0
  142. package/templates/apps/api-saas/package.json +10 -11
  143. package/templates/apps/api-saas-starter/package.json +10 -10
  144. package/templates/apps/api-search/package.json +8 -8
  145. package/templates/apps/api-status/package.json +8 -8
  146. package/templates/apps/api-webhooks/package.json +9 -9
  147. package/templates/apps/changelog/app.config.ts +26 -2
  148. package/templates/apps/changelog/content/releases/{0.1.0.mdx → v0-1-0.mdx} +0 -1
  149. package/templates/apps/changelog/content/releases/{0.2.0.mdx → v0-2-0.mdx} +0 -1
  150. package/templates/apps/changelog/package.json +8 -8
  151. package/templates/apps/changelog/src/collections/releases.collection.ts +48 -0
  152. package/templates/apps/changelog/src/globals.d.ts +1 -1
  153. package/templates/apps/changelog/src/locales/de.ts +1 -1
  154. package/templates/apps/changelog/src/locales/en.ts +1 -1
  155. package/templates/apps/changelog/src/pages/[locale]/[slug]/page.tsx +7 -4
  156. package/templates/apps/changelog/src/pages/[locale]/mirrors.test.tsx +13 -41
  157. package/templates/apps/changelog/src/pages/[slug]/page.test.tsx +26 -51
  158. package/templates/apps/changelog/src/pages/[slug]/page.tsx +21 -19
  159. package/templates/apps/changelog/src/pages/page.test.tsx +14 -37
  160. package/templates/apps/changelog/src/pages/page.tsx +18 -12
  161. package/templates/apps/edge-functions/package.json +2 -2
  162. package/templates/apps/frontend-admin/package.json +8 -8
  163. package/templates/apps/frontend-app/package.json +9 -9
  164. package/templates/apps/frontend-auth/package.json +8 -8
  165. package/templates/apps/frontend-blank/package.json +7 -7
  166. package/templates/apps/frontend-cms/package.json +9 -9
  167. package/templates/apps/frontend-collab/package.json +10 -10
  168. package/templates/apps/frontend-collab/src/pages/page.test.tsx +10 -9
  169. package/templates/apps/frontend-collab/src/pages/page.tsx +42 -65
  170. package/templates/apps/frontend-contact/package.json +7 -7
  171. package/templates/apps/frontend-dashboard/package.json +7 -7
  172. package/templates/apps/frontend-docs/content/docs/de/guides/first-page.md +4 -0
  173. package/templates/apps/frontend-docs/content/docs/de/intro/getting-started.md +4 -0
  174. package/templates/apps/frontend-docs/content/docs/en/guides/first-page.md +4 -0
  175. package/templates/apps/frontend-docs/content/docs/en/intro/getting-started.md +4 -0
  176. package/templates/apps/frontend-docs/package.json +8 -7
  177. package/templates/apps/frontend-docs/src/collections/docs.collection.ts +21 -0
  178. package/templates/apps/frontend-docs/src/locales/de.ts +0 -5
  179. package/templates/apps/frontend-docs/src/locales/en.ts +0 -5
  180. package/templates/apps/frontend-docs/src/pages/[locale]/docs/[...slug]/page.tsx +17 -9
  181. package/templates/apps/frontend-docs/src/pages/[locale]/mirrors.test.tsx +10 -5
  182. package/templates/apps/frontend-docs/src/pages/[locale]/page.tsx +8 -0
  183. package/templates/apps/frontend-docs/src/pages/docs/[...slug]/page.test.tsx +53 -15
  184. package/templates/apps/frontend-docs/src/pages/docs/[...slug]/page.tsx +27 -33
  185. package/templates/apps/frontend-docs/src/pages/page.test.tsx +17 -3
  186. package/templates/apps/frontend-docs/src/pages/page.tsx +16 -12
  187. package/templates/apps/frontend-i18n/package.json +6 -6
  188. package/templates/apps/frontend-landing/package.json +6 -7
  189. package/templates/apps/frontend-portal/package.json +8 -8
  190. package/templates/apps/frontend-saas/package.json +8 -8
  191. package/templates/apps/frontend-spa/package.json +7 -7
  192. package/templates/apps/frontend-ssr/package.json +7 -7
  193. package/templates/apps/frontend-ssr-api/package.json +8 -8
  194. package/templates/apps/frontend-static-blog/content/posts/cms-to-ssg.md +12 -0
  195. package/templates/apps/frontend-static-blog/content/posts/hello-static.md +12 -0
  196. package/templates/apps/frontend-static-blog/content/posts/islands-not-hydration.md +14 -0
  197. package/templates/apps/frontend-static-blog/package.json +8 -6
  198. package/templates/apps/frontend-static-blog/src/collections/posts.collection.ts +27 -0
  199. package/templates/apps/frontend-static-blog/src/pages/[locale]/blog/[slug]/page.tsx +7 -4
  200. package/templates/apps/frontend-static-blog/src/pages/[locale]/mirrors.test.tsx +7 -1
  201. package/templates/apps/frontend-static-blog/src/pages/blog/[slug]/page.test.tsx +19 -9
  202. package/templates/apps/frontend-static-blog/src/pages/blog/[slug]/page.tsx +19 -21
  203. package/templates/apps/frontend-static-blog/src/pages/page.test.tsx +18 -5
  204. package/templates/apps/frontend-static-blog/src/pages/page.tsx +21 -14
  205. package/templates/apps/frontend-status/package.json +8 -8
  206. package/templates/apps/mobile-app/package.json +4 -4
  207. package/dist/agentsMd-Bu_XQgVf.js +0 -2
  208. package/dist/apiBuild-GDKuGOMV.js +0 -2
  209. package/dist/build-DETLZAFt.js +0 -752
  210. package/dist/checkCommand-CWcnDArJ.js +0 -2
  211. package/dist/codegen-DiMn2KkZ.js +0 -2
  212. package/dist/dbCommand-C27HIsGE.js +0 -2
  213. package/dist/dev-CK522MV5.js +0 -3
  214. package/dist/doctorCommand-BK4l18eG.js +0 -2
  215. package/dist/fileConventions-Cof68_BL.js +0 -33
  216. package/dist/frameworkTableAssembly-CVDB2hCq.js +0 -2
  217. package/dist/inspect-CuGDYES0.js +0 -2
  218. package/dist/inspectMetrics-CfdKLh6t.js +0 -72
  219. package/dist/manifestBuild-CPjhvM62.js +0 -2
  220. package/dist/serveCommand-BRnPCxVd.js +0 -2
  221. package/dist/serveCommand-DdiYNBBu.js +0 -2362
  222. package/dist/start-BLNmWkLa.js +0 -1154
  223. package/dist/start-Dzicuyw8.js +0 -3
  224. package/dist/updateCommand-eXB35SEv.js +0 -2
  225. package/dist/webDev-DposiF3j.js +0 -2
  226. package/templates/apps/api-versioning/template.json +0 -6
  227. package/templates/apps/changelog/scripts/generate-rss.mjs +0 -38
  228. package/templates/apps/changelog/src/lib/releases.ts +0 -21
  229. package/templates/apps/frontend-static-blog/src/content/posts.ts +0 -64
  230. /package/templates/apps/{api-versioning → api-row-history}/actions/documents.asOf.action.ts +0 -0
  231. /package/templates/apps/{api-versioning → api-row-history}/actions/documents.history.action.ts +0 -0
  232. /package/templates/apps/{api-versioning → api-row-history}/mutations/documents.update.mutation.server.ts +0 -0
  233. /package/templates/apps/{api-versioning → api-row-history}/tsconfig.json +0 -0
@@ -29,7 +29,7 @@ The dispatcher routes `voltro <command> [args]` to the matching subcommand and p
29
29
  | [Data transfer](/docs/cli/data) | `data` (`export` / `import` / `unpack` / `inspect` / `backup` / `restore`) — directory + single-file `.vbundle` bundles, streaming assets, masking, at-rest encryption |
30
30
  | Ops / infra | `cache` (`status` / `flush` / `invalidate`), `add` (`redis`), `baseline` (`list` / `status` / `set`), `schedule` (`run <name>` — fire a registered schedule on demand; `--process` / `--trigger manual\|external` / `--url`), `schedule-manifest`, [`storage`](/docs/plugins/storage) (`doctor` / `cors`) |
31
31
  | AI / data | `embeddings backfill <table> --text <field> --vector <field>` — (re)embed rows the `vectorEmbedding()` mixin missed (pre-existing rows / a model change); `--dry-run` to preview; [`eval`](/docs/ai/agents#evaluating-recorded-runs-voltro-eval) — replay recorded agent runs against golden cases + judge, exit 1 on regression (a deploy gate; `--json` / `--branch` / `--threshold`) |
32
- | Integrate | [`webhooks`](/docs/plugins/webhooks#voltro-webhooks-consumer--the-package-your-subscribers-install) (`consumer` / `events`) — generate the ZERO-dependency Standard-Webhooks verification package your subscribers install, from your own declared events (`--out` / `--name`); list the events a subscriber can register for (`--json`) |
32
+ | Integrate | [`webhooks`](/docs/plugins/webhooks#voltro-webhooks-consumer-the-package-your-subscribers-install) (`consumer` / `events`) — generate the ZERO-dependency Standard-Webhooks verification package your subscribers install, from your own declared events (`--out` / `--name`); list the events a subscriber can register for (`--json`) |
33
33
  | [Inspect & debug](/docs/cli/inspect) | `inspect`, `logs`, `traces`, `workflows`, `cluster`, `check` |
34
34
  | [Health & surface](/docs/cli/build-and-start) | [`doctor`](/docs/cli/build-and-start) — serve preflight + the hand-roll detector (names the shipped primitive at the spot you're rebuilding it); [`capabilities`](/docs/cli/build-and-start) (`--json`) — the export surface read from your installed `@voltro/*`, so it can be verified instead of recalled; `info` (`--json`) — CLI / node / package-manager / dialect + every installed `@voltro/*` version, flagging lockstep skew (exits 1 on skew) |
35
35
  | Harness | `test`, `e2e` |
@@ -142,6 +142,12 @@ config value always winning:
142
142
  | `VOLTRO_CSP_HTML` | CSP for HTML responses (under `strict` it defaults to the same policy as `VOLTRO_CSP`). `off` drops just this one. |
143
143
  | `VOLTRO_HSTS` | `Strict-Transport-Security` value. `off` drops just this one. |
144
144
  | `VOLTRO_MAX_RPC_BODY_BYTES` | Cap on the buffered `POST /rpc` JSON body (default 8 MiB) — an oversized body is refused `413` and never buffered past the cap. File uploads ride plugin routes with their own limits. |
145
+ | `VOLTRO_MAX_BODY_BYTES` | Cap on every OTHER body read — plugin HTTP routes, REST routes, incoming webhooks (default 8 MiB, matching the rpc cap). The config-file spelling is `http.maxBodyBytes` in `app.config.ts`; per-route overrides (`defineRestRoute({ maxBodyBytes })`, a webhook handler's `maxBodyBytes`) win over both. Oversize is `413` for `Content-Length` and chunked alike. |
146
+
147
+ Response compression for the buffered non-rpc surfaces (and `voltro start`'s
148
+ HTML) is configured in the same `http:` block — `http.compression.{enabled,minBytes}`
149
+ (default on, 1 KiB threshold; `POST /rpc` is never compressed). Details + the
150
+ BREACH reasoning: [Security → compression](/docs/security/overview#response-compression-and-where-breach-sits).
145
151
 
146
152
  Generate any of the secret vars above with `voltro secret generate <purpose>` (see [`secret`](#command-quick-reference)) — it picks the right length and format. A lower environment's secrets must always differ from production's.
147
153
 
@@ -317,36 +323,48 @@ fails to update.
317
323
 
318
324
  ```
319
325
  observed: 12/34 procedures exercised (35%)
326
+ 1 declared/observed mismatch among the 12 that ran
320
327
  mutation(orders.place) (api/orders/place.mutation.ts)
321
328
  writes 'inventory' (update) but declares no target for it
322
329
  subscriptions on that table are not invalidated by this mutation
323
330
  fix: add { table: 'inventory', op: 'update' } to this procedure's targets
324
- 22 unexercised — no recording, so nothing is claimed about them
331
+ 20 never ran — no observation exists, so nothing is claimed about them
332
+ 2 ran with no table access recorded — indistinguishable from touching nothing, so nothing is claimed about them either
325
333
  ```
326
334
 
327
- Three things about that output are deliberate:
335
+ Four things about that output are deliberate:
328
336
 
329
337
  - **Coverage comes first.** Three findings at 8% coverage and three at 95% are
330
338
  different claims. Hiding the denominator is how a check starts overstating
331
339
  what it knows.
332
- - **`unexercised` is a third state, not a finding.** A procedure no test and no
333
- dev session ever ran has *no observation* which is not the same as "touches
334
- nothing". It is counted and never reported as a problem.
340
+ - **Every result line carries the count it is a result about.** `1 mismatch
341
+ among the 12 that ran` never a bare verdict. A sentence that still reads as
342
+ a conclusion once it is cut out of this block will eventually be cut out of
343
+ it, and quoted as a clean bill of health for a surface nobody measured.
344
+ - **The counts partition the declared set — they add up to the total, always.**
345
+ There are two ways to say nothing about a procedure, and both get a line:
346
+ it never ran, or it ran and no table access was recorded for it. A procedure
347
+ that appeared in no line at all would be indistinguishable from a defect in
348
+ `check` itself, so the two kinds of blindness are named separately and never
349
+ folded into the findings.
335
350
  - **Observed diagnostics never fail the build.** An observation is evidence
336
351
  about the runs that happened, not a proof about the ones that didn't, and
337
352
  `check`'s exit code gates CI. They are always warnings.
338
353
 
339
- A fourth thing is not visible in that output and matters more than any of the
340
- three: **the recorder only knows what ran.** A boot is not a run. An idle dev
354
+ A fifth thing is not visible in that output and matters more than any of the
355
+ four: **the recorder only knows what ran.** A boot is not a run. An idle dev
341
356
  instance that started, served nothing and stopped produces
342
357
 
343
358
  ```
344
- observed: 0/2755 procedures exercised (0%)
345
- 2753 unexercisedno recording, so nothing is claimed about them
359
+ observed: 0/34 procedures exercised (0%)
360
+ nothing was compared a declaration is only checked against a procedure that RAN
361
+ 34 never ran — no observation exists, so nothing is claimed about them
346
362
  ```
347
363
 
348
- which is the honest answer and also a useless one the section says nothing
349
- about 99.9% of the surface. If you want this as a CI gate, the recording pass has
364
+ Note what that is NOT: it is not "no mismatches found". At zero coverage there
365
+ is no result to report, so the section reports the absence of the comparison
366
+ instead. The honest answer is also a useless one — it says nothing about any of
367
+ the surface. If you want this as a CI gate, the recording pass has
350
368
  to be a run that actually *calls* the procedures. `voltro e2e` is one: it spawns
351
369
  `voltro dev` for the api, which turns recording on, and then drives the specs. A
352
370
  harness of your own that boots the app in its own process needs
@@ -365,6 +383,29 @@ handlers: a static pass over code that reaches the store through shared helpers,
365
383
  behind conditionals, has a long tail of both false positives and false negatives
366
384
  — and a check that is *sometimes* wrong is one people stop reading.
367
385
 
386
+ #### Declared vs LIVE — against a running server
387
+
388
+ When `check` runs against a live api (a local `voltro dev`, or a deployed one
389
+ via `--url`), it also diffs the tags your source declares — plugin routes
390
+ included — against the server's actual rpc registry:
391
+
392
+ ```
393
+ declared vs live: 2 of 214 source-declared tags are NOT registered on the server
394
+ ⚠ presence.heartbeat — a generated client calls this and gets "Unknown request tag"
395
+ ⚠ presence.list — a generated client calls this and gets "Unknown request tag"
396
+ fix: if the server runs older code, redeploy; if it is current, plugin route registration was dropped — check the boot line "plugin routes registered"
397
+ ```
398
+
399
+ Only the source→live direction is a finding — a tag the server carries that your
400
+ source does not declare is normal runtime synthesis (agents, undo, approvals).
401
+ This exists because exactly that gap has shipped once: every
402
+ plugin-contributed procedure dead under `voltro serve`, with nothing anywhere
403
+ saying so — the only evidence was a `Defect` frame in the browser console of
404
+ whoever happened to look. (That registration defect is fixed; the diff is the
405
+ runtime backstop for the next one, e.g. a stale deploy.) The server now also
406
+ logs every `Defect` frame it sends (`rpc defect sent to client`), so an unknown
407
+ tag is an operator-visible event rather than a client-only one.
408
+
368
409
  The HTTP surface is reachable directly too — e.g. `curl -s localhost:4000/_voltro/inspect/rpc | jq` (there is no `/_voltro/inspect/queries` endpoint; it's `rpc` for procedures, `routes` for the web page tree, `subscriptions` for active subscribers).
369
410
 
370
411
  ## Where to read next
@@ -1364,7 +1405,7 @@ Point the Kubernetes liveness probe at `/internal/liveness` and the readiness pr
1364
1405
  For WebSocket connections to land on the same backend (required for in-process subscription state):
1365
1406
 
1366
1407
  - Reverse proxy: `lb_policy ip_hash` (Caddy) / `ip_hash` (nginx).
1367
- - Or use `@voltro/plugin-cluster` to share subscription state across instances any-load-balancer-works.
1408
+ - Cross-instance subscription invalidation is built in on Postgres (LISTEN/NOTIFY) and MySQL/MariaDB (binlog CDC); on any other dialect add [`@voltro/plugin-broadcast`](/docs/plugins/broadcast) (Redis/NATS). With that in place a reconnect may land on any replica and still sees every change — sticky sessions then only keep one live connection pinned, they are not a correctness requirement.
1368
1409
 
1369
1410
  ## `voltro build api --target <swift|kotlin>` — native SDK generation
1370
1411
 
@@ -1796,6 +1837,47 @@ matching rule lives inside the CLI, so you cannot re-derive the list with your
1796
1837
  own grep. `--json` prints the complete scan, nothing elided, with no preflight
1797
1838
  output mixed in:
1798
1839
 
1840
+ ### Unimported `@voltro/*` dependencies
1841
+
1842
+ A declared framework dependency nobody imports still gets installed, walked on
1843
+ every `voltro update`, and read as evidence the package is in use — its
1844
+ breaking-change notes included. The usual origin is a migration: the app moves
1845
+ off a framework package to a third-party one, and the `package.json` entry
1846
+ stays. `voltro doctor` checks every `@voltro/*` in `dependencies` and
1847
+ `devDependencies` for an import site:
1848
+
1849
+ ```
1850
+ unimported deps · 8 @voltro/* package(s) declared, 214 file(s) scanned
1851
+ ⚠ @voltro/i18n — declared in dependencies, imported nowhere
1852
+ a dependency nobody imports still gets installed, updated, and read as
1853
+ evidence the package is in use — its breaking-change notes included.
1854
+ Remove it, or if it IS imported through an assembled specifier the scan
1855
+ cannot see, keep it and ignore this line — the rule is advisory.
1856
+ · (2 loaded by the framework itself: @voltro/cli, @voltro/sql-postgres)
1857
+ ```
1858
+
1859
+ Scoped to `@voltro/*` deliberately: for third-party packages the same question
1860
+ has a long tail of legitimate no-import shapes, and a rule that is sometimes
1861
+ wrong is one people stop reading. Three states are distinguished, and each is
1862
+ printed:
1863
+
1864
+ - **Exempt, by name** — packages the framework loads on your declaration
1865
+ (`@voltro/cli` is the binary; `@voltro/devtools` is mounted by `voltro dev`;
1866
+ the `@voltro/sql-*` dialect drivers are loaded from your config). An
1867
+ exemption you cannot see is a finding you cannot question.
1868
+ - **Not measurable yet** — `@voltro/client` / `@voltro/web` are normally
1869
+ imported by *generated* code. On a tree where codegen has never run, their
1870
+ absence is a missing measurement, not a dead dependency; the section says so
1871
+ and tells you to run `voltro dev` once.
1872
+ - **Unimported** — advisory, never fatal. A mention in a comment or an error
1873
+ string does not count as an import (a commented-out import is exactly the
1874
+ residue this looks for), and an import assembled at runtime from string
1875
+ pieces is invisible to the scan — the finding text says both.
1876
+
1877
+ The full report is in `voltro doctor --json` under `unimportedDeps`
1878
+ (`null` when there is no `package.json` to read — "could not check" and
1879
+ "checked, clean" never print the same).
1880
+
1799
1881
  ### Duplicate package instances
1800
1882
 
1801
1883
  `voltro doctor` also reports any identity-sensitive package resolved at more than
@@ -2850,7 +2932,7 @@ Not every run can take it, and a run that cannot **says why** rather than quietl
2850
2932
  taking the slower path:
2851
2933
 
2852
2934
  - a store the framework cannot send DDL to (the in-memory store).
2853
- - a **write recorder** on any table in the set — `versioningPlugin({ timing:
2935
+ - a **write recorder** on any table in the set — `rowHistoryPlugin({ timing:
2854
2936
  'in-transaction' })` and friends. A recorder is keyed by table name, so a
2855
2937
  staged write would find none and the recorder would silently not run. Its
2856
2938
  promise is "if the change committed, the entry is there", so the run keeps the
@@ -2906,7 +2988,7 @@ ITSELF is not a cycle: one statement carries the whole table.
2906
2988
 
2907
2989
  ### A `replace` does not write per-row history
2908
2990
 
2909
- Write recorders — `versioningPlugin({ timing: 'in-transaction' })` and anything
2991
+ Write recorders — `rowHistoryPlugin({ timing: 'in-transaction' })` and anything
2910
2992
  else registered through the same seam — are **suspended for a `replace`**. A
2911
2993
  replace sets a state; it does not change rows, so a per-row history entry would
2912
2994
  describe something that did not happen. On a large bundle that is not a detail:
@@ -126,6 +126,11 @@ just as secret and just as required, but inventing one produces a value that
126
126
  merely *looks* right and authenticates nobody — better that the boot gate fails
127
127
  and a human fetches the real one.
128
128
 
129
+ Encodings: `base64url` and `hex` mint 32 random bytes; `p256` mints a valid
130
+ P-256 private scalar (what web push's `VOLTRO_VAPID_PRIVATE_KEY` needs — a
131
+ plugin can declare its own mintables the same way, which is how a configured
132
+ `webPushChannel()` gets its key without you declaring anything).
133
+
129
134
  Minting is **development only**. `voltro serve`, `build` and `start` never mint:
130
135
  in production a missing secret is a boot failure, which is the whole point.
131
136
  Generate deployment values with `voltro secret generate <purpose>`.
@@ -302,6 +307,18 @@ This updates what code that reads a secret **per use** sees: outbound API keys r
302
307
  `setSecretsBackend(backend)` installs a backend for a test; `resetSecretsBackend()` restores the env default. `resolveSecretsBackend(config)` is the pure resolver the boot path uses to turn the `secrets` config value into a backend.
303
308
 
304
309
 
310
+ ## `VOLTRO_OG_SECRET` — conditional, multi-replica only
311
+
312
+ The signed on-demand OG-image route (ssr pages exporting
313
+ [`ogImage`](/docs/routing/loaders-and-meta#og-images-from-a-template-ogimage))
314
+ signs its URLs with `VOLTRO_OG_SECRET`. The requirement is CONDITIONAL: a
315
+ single process mints a per-boot secret and is self-consistent — only a
316
+ multi-replica deploy needs the env var (the signing replica and the fetching
317
+ replica differ), and a deploy boot with ssr `ogImage` pages and no secret
318
+ refuses loudly rather than serving images that 403 on every other replica.
319
+ Any long random value; same on every replica; never a default.
320
+
321
+
305
322
 
306
323
  ---
307
324