@voltro/cli 0.38.0 → 0.39.1

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 +276 -0
  2. package/THIRD-PARTY-NOTICES.md +80 -45
  3. package/dist/{addCommand-BNeoeSxe.js → addCommand-C05L9tZh.js} +2 -2
  4. package/dist/addCommand-C3MdJG-a.js +2 -0
  5. package/dist/{agentsMd-mhQMF1bx.js → agentsMd-7zI2h5l9.js} +3 -3
  6. package/dist/agentsMd-BFCXh2gl.js +2 -0
  7. package/dist/apiBuild-BmR_bIxN.js +2 -0
  8. package/dist/{apiBuild-CvacV4zA.js → apiBuild-D9FB13_2.js} +3 -3
  9. package/dist/baselineCommand-CXv680Dc.js +2 -0
  10. package/dist/{baselineCommand-C6NMt-oa.js → baselineCommand-Ck2Xm8M7.js} +18 -18
  11. package/dist/bin.js +1 -1
  12. package/dist/{build-_LoTC1s0.js → build-DORV5mLM.js} +107 -100
  13. package/dist/{capabilitiesCommand-nq_pz5xd.js → capabilitiesCommand-D5gucwYa.js} +8 -8
  14. package/dist/{checkCommand-Pjk5sBl2.js → checkCommand-Bf6oMao4.js} +35 -35
  15. package/dist/{checkCommand-wibtQx-N.js → checkCommand-D9qK_gtA.js} +1 -1
  16. package/dist/{cloudCmd-NQSwe_Qk.js → cloudCmd-C42gaO8s.js} +16 -16
  17. package/dist/{clusterCmd-D5wsCmA_.js → clusterCmd-DrVFCzSj.js} +8 -4
  18. package/dist/{codegen-GYYcdpCg.js → codegen-CbpGCWLG.js} +1 -1
  19. package/dist/codegen-i8QGcHsi.js +2 -0
  20. package/dist/codegenCommand-CxOyKmc1.js +129 -0
  21. package/dist/{codemodRunner-CXgQ-ecJ.js → codemodRunner-D-jTyvWo.js} +622 -551
  22. package/dist/{commands-DaZVi9wi.js → commands-D6aW_6AR.js} +48 -48
  23. package/dist/{connectionConfig-UFlIEiys.js → connectionConfig-Bk9IC7D0.js} +1 -1
  24. package/dist/{dashboardCommand-Dxy_kmoW.js → dashboardCommand-CwTZh-XZ.js} +3 -3
  25. package/dist/{dataCommand-D6-Ha2lf.js → dataCommand-Cc9RiLQZ.js} +14 -11
  26. package/dist/{dbCommand-C4UW8cVN.js → dbCommand-DSwGv9wS.js} +50 -49
  27. package/dist/dbCommand-DcqEyxju.js +2 -0
  28. package/dist/{dev-E7Eo5GHc.js → dev-3mgc8c-H.js} +2260 -2184
  29. package/dist/dev-CjJAasDs.js +3 -0
  30. package/dist/{dialectDriver-CgXnDfec.js → dialectDriver-czCHYpeH.js} +2 -1
  31. package/dist/doctorCommand-Cghssndo.js +2 -0
  32. package/dist/{doctorCommand-gmDyALFL.js → doctorCommand-oLuzc-aC.js} +261 -244
  33. package/dist/{dormancyCommand-CE6wG8lj.js → dormancyCommand-Bxe4WtHU.js} +1 -1
  34. package/dist/{e2eCmd-BRabZww-.js → e2eCmd-uFHig1hV.js} +8 -2
  35. package/dist/{embeddingsCommand-C3uAuf6N.js → embeddingsCommand-CyNQkFIc.js} +6 -6
  36. package/dist/{envCommand-DzuWh8ya.js → envCommand-CAkSgBbh.js} +19 -19
  37. package/dist/{evolveCommand-DPLqcYb2.js → evolveCommand-CWhBoe_P.js} +6 -8
  38. package/dist/frameworkTableAssembly-DgylYh9_.js +2 -0
  39. package/dist/{generateCommand-DbgcUpGw.js → generateCommand-CcyvH2ve.js} +1 -1
  40. package/dist/index.js +1 -1
  41. package/dist/{infoCommand-CmczGj_l.js → infoCommand-CTo8Jnhq.js} +7 -7
  42. package/dist/inspect-B7U7Cl_Z.js +1192 -0
  43. package/dist/inspect-DUze25t0.js +2 -0
  44. package/dist/{inspectCmd-EHFZ9yYu.js → inspectCmd-niF97fAq.js} +5 -5
  45. package/dist/inspectGateHint-BjnFubmH.js +7 -0
  46. package/dist/{logFileSink-C_D2wRN1.js → logFileSink-B4uP8pvf.js} +1 -1
  47. package/dist/{logsCmd-D36xK7Zu.js → logsCmd-B6oNsfaZ.js} +10 -7
  48. package/dist/{manifestBuild-hpPLaGxV.js → manifestBuild-BK42hu0k.js} +1 -1
  49. package/dist/manifestBuild-j0n109tt.js +2 -0
  50. package/dist/{metaCommands-CIoQNlaQ.js → metaCommands-DUYR--Ts.js} +1 -1
  51. package/dist/{migrate-RwgUWXfc.js → migrate-BnPw2zC8.js} +7 -4
  52. package/dist/{packageCommand-Cug_3Ogl.js → packageCommand-9SVyvsSo.js} +3 -2
  53. package/dist/{probeCommand-BPEpwT32.js → probeCommand-C9gazU0H.js} +35 -24
  54. package/dist/{projectScaffold-CxgtJvlb.js → projectScaffold-BEhhHjPr.js} +1 -1
  55. package/dist/{projectScaffold-DDgWbNLe.js → projectScaffold-BvhLOrLq.js} +17 -15
  56. package/dist/{runtimeTrace-6jfznSzr.js → runtimeTrace-gNXeLf6H.js} +1 -1
  57. package/dist/{scheduleManifestCmd-D2x0CTTY.js → scheduleManifestCmd-kmWzrO_w.js} +6 -9
  58. package/dist/{sdkgen-CEJZZQUA.js → sdkgen-C8zz10-X.js} +4 -4
  59. package/dist/{seedRunner-ZmLSqNe2.js → seedRunner-IdHEprqf.js} +1 -4
  60. package/dist/serveCommand-BpK8-m1N.js +1770 -0
  61. package/dist/serveCommand-CW-goXvh.js +2 -0
  62. package/dist/serveEntry.js +2 -2
  63. package/dist/{serverlessCommand-CfJZy6dS.js → serverlessCommand-DbJ7Plg9.js} +3 -3
  64. package/dist/{start-CidwCcjl.js → start-BNuTWdRd.js} +1 -1
  65. package/dist/{start-RCh6qKFe.js → start-ft_KzFTd.js} +257 -254
  66. package/dist/startEntry.js +1 -1
  67. package/dist/{test-DIQ0jlkQ.js → test-CLYXrZ2F.js} +1 -1
  68. package/dist/{tracesCmd-DStmCJPi.js → tracesCmd-DgtgOUdi.js} +7 -4
  69. package/dist/{typecheckCommand-BlsWiCNq.js → typecheckCommand-BuCtT92o.js} +7 -7
  70. package/dist/updateCommand-6FMU2klq.js +2 -0
  71. package/dist/{updateCommand-CmksX7m_.js → updateCommand-CHBmCB17.js} +5 -3
  72. package/dist/{webDev-BKdD7c_a.js → webDev-CTpSY-e_.js} +813 -775
  73. package/dist/webDev-id3I5PvG.js +2 -0
  74. package/dist/{webhookDiscovery-D7VaeMlz.js → webhookDiscovery-CphsQe59.js} +4 -6
  75. package/dist/{webhookDiscovery-CrGAfhIG.js → webhookDiscovery-il9ti-HE.js} +1 -1
  76. package/dist/{webhooksCommand-BHeaF1ZJ.js → webhooksCommand-EccPZQZ4.js} +1 -1
  77. package/package.json +27 -21
  78. package/templates/AGENTS.md +2 -2
  79. package/templates/agent-docs/_index.md +2 -2
  80. package/templates/agent-docs/_manifest.json +2 -2
  81. package/templates/agent-docs/authentication.md +43 -4
  82. package/templates/agent-docs/cli.md +17 -13
  83. package/templates/agent-docs/data.md +44 -1
  84. package/templates/agent-docs/database/migrations.md +2 -2
  85. package/templates/agent-docs/database/seedsdialects.md +2 -2
  86. package/templates/agent-docs/deployment.md +21 -7
  87. package/templates/agent-docs/internationalization.md +10 -3
  88. package/templates/agent-docs/local-first-mobile.md +141 -20
  89. package/templates/agent-docs/plugins/mail.md +1 -1
  90. package/templates/agent-docs/plugins/ratelimit.md +1 -1
  91. package/templates/agent-docs/plugins.md +3 -1
  92. package/templates/agent-docs/releases.md +130 -1
  93. package/templates/agent-docs/routing.md +34 -2
  94. package/templates/agent-docs/templates/apibackends.md +1 -1
  95. package/templates/agent-docs/templates/mobile.md +1 -1
  96. package/templates/agent-docs/whats-new.md +26 -66
  97. package/templates/apps/api-ai/package.json +7 -7
  98. package/templates/apps/api-auth/package.json +8 -8
  99. package/templates/apps/api-backend/package.json +7 -7
  100. package/templates/apps/api-backend-deactivation/package.json +7 -7
  101. package/templates/apps/api-backend-mail/package.json +8 -8
  102. package/templates/apps/api-backend-mariadb/package.json +9 -9
  103. package/templates/apps/api-backend-sqlite/package.json +8 -8
  104. package/templates/apps/api-backend-storage/package.json +8 -8
  105. package/templates/apps/api-cms/package.json +10 -10
  106. package/templates/apps/api-collab/package.json +8 -8
  107. package/templates/apps/api-data-advanced/package.json +8 -8
  108. package/templates/apps/api-durable/package.json +8 -8
  109. package/templates/apps/api-durable/startup/warm.startup.tsx +16 -2
  110. package/templates/apps/api-feature-flags/package.json +9 -9
  111. package/templates/apps/api-governance/package.json +8 -8
  112. package/templates/apps/api-kv/package.json +8 -8
  113. package/templates/apps/api-moderation/package.json +8 -8
  114. package/templates/apps/api-observability/package.json +8 -8
  115. package/templates/apps/api-ratelimit/package.json +8 -8
  116. package/templates/apps/api-rbac/authz.ts +16 -1
  117. package/templates/apps/api-rbac/package.json +8 -8
  118. package/templates/apps/api-rest/package.json +7 -7
  119. package/templates/apps/api-saas/package.json +11 -11
  120. package/templates/apps/api-saas-starter/package.json +10 -10
  121. package/templates/apps/api-search/package.json +8 -8
  122. package/templates/apps/api-status/package.json +8 -8
  123. package/templates/apps/api-versioning/package.json +8 -8
  124. package/templates/apps/api-webhooks/package.json +9 -9
  125. package/templates/apps/changelog/package.json +6 -6
  126. package/templates/apps/edge-functions/package.json +2 -2
  127. package/templates/apps/frontend-admin/package.json +8 -8
  128. package/templates/apps/frontend-app/package.json +9 -9
  129. package/templates/apps/frontend-auth/package.json +8 -8
  130. package/templates/apps/frontend-blank/package.json +7 -7
  131. package/templates/apps/frontend-cms/package.json +9 -9
  132. package/templates/apps/frontend-collab/package.json +10 -10
  133. package/templates/apps/frontend-contact/package.json +7 -7
  134. package/templates/apps/frontend-dashboard/package.json +7 -7
  135. package/templates/apps/frontend-docs/package.json +7 -7
  136. package/templates/apps/frontend-i18n/package.json +6 -6
  137. package/templates/apps/frontend-landing/package.json +7 -7
  138. package/templates/apps/frontend-portal/package.json +8 -8
  139. package/templates/apps/frontend-saas/package.json +8 -8
  140. package/templates/apps/frontend-spa/package.json +7 -7
  141. package/templates/apps/frontend-ssr/package.json +7 -7
  142. package/templates/apps/frontend-ssr-api/package.json +8 -8
  143. package/templates/apps/frontend-static-blog/package.json +6 -6
  144. package/templates/apps/frontend-status/package.json +8 -8
  145. package/templates/apps/mobile-app/README.md +41 -17
  146. package/templates/apps/mobile-app/app.config.ts +1 -1
  147. package/templates/apps/mobile-app/package.json +15 -11
  148. package/templates/apps/mobile-app/src/app/_layout.tsx +44 -13
  149. package/templates/apps/mobile-app/src/app/index.tsx +1 -1
  150. package/templates/apps/mobile-app/src/app/settings.tsx +4 -1
  151. package/templates/apps/mobile-app/src/client.ts +74 -57
  152. package/templates/apps/mobile-app/src/lib/api.ts +4 -4
  153. package/templates/apps/mobile-app/src/lib/deeplinks.ts +6 -6
  154. package/templates/apps/mobile-app/src/persistence.ts +24 -3
  155. package/templates/apps/mobile-app/tsconfig.json +17 -3
  156. package/dist/addCommand-aXSQveak.js +0 -2
  157. package/dist/agentsMd-BTchIZku.js +0 -2
  158. package/dist/apiBuild-ttSDDOGp.js +0 -2
  159. package/dist/baselineCommand-Cfw2Afwm.js +0 -2
  160. package/dist/codegen-uYrrDzQv.js +0 -2
  161. package/dist/codegenCommand-C60m_LCp.js +0 -30
  162. package/dist/dbCommand-CC-qNzpz.js +0 -2
  163. package/dist/dev-CAOoXOkc.js +0 -3
  164. package/dist/doctorCommand-Cjl8Yii8.js +0 -2
  165. package/dist/frameworkTableAssembly-YyVe32Cb.js +0 -2
  166. package/dist/inspect-CjTYzAs_.js +0 -1190
  167. package/dist/inspect-P4pxoMaV.js +0 -2
  168. package/dist/inspectGateHint-BF6608UT.js +0 -4
  169. package/dist/manifestBuild-COkJoyAr.js +0 -2
  170. package/dist/serveCommand-DNRF2nDI.js +0 -2
  171. package/dist/serveCommand-DnY4VS3D.js +0 -1767
  172. package/dist/updateCommand-B0J_T9Vs.js +0 -2
  173. package/dist/webDev-CcJfdSjl2.js +0 -2
@@ -1,4 +1,4 @@
1
- # What's new in 0.38.0
1
+ # What's new in 0.39.1
2
2
 
3
3
  Read this FIRST when a task touches an area you have not worked in recently.
4
4
  It is the cheapest way to notice that the framework grew the thing you were
@@ -7,90 +7,50 @@ workaround for something that shipped two versions ago.
7
7
 
8
8
  BREAKING entries name a codemod; run `voltro update` to apply it.
9
9
 
10
- ### ⚠ BREAKING
11
-
12
- - **@voltro/plugin-audit, @voltro/protocol, @voltro/plugin-auth** — An audit row now says when an action was taken through an IMPERSONATED session, on the default settings, and no redactor can take that away.
13
-
14
- `AuditEvent` gained `impersonation`, and the datastore sink a nullable json column of the same name. The mark is lifted out of `subject.metadata` BEFORE the redaction chain runs, so `redactSubject` — including a custom function that erases the subject wholesale — never gets a say.
15
-
16
- **The defect it closes.** `@voltro/plugin-auth` mints the mark into `subject.metadata`, and `auditPlugin`'s default `redactSubject: 'metadata'` replaces that whole bag. That default is right: the bag is where a per-user provider credential lands, and an audit table is the last place a live PAT should be. The consequence was that on defaults an impersonated action was recorded indistinguishably from the user's own — the one distinction an audit trail exists to make. The documented mitigation (`redactSubject: impersonationAuditRedactor()`) worked and was opt-in, and an audit property that depends on somebody wiring it is not a property.
17
-
18
- The alternative fix — a keep-these-keys option on `redactSubject` — was rejected for the same reason: it leaves the default wrong, and "who really did this" is not the app's metadata to configure away. It is a property of the event, so it is now a field of the event.
19
-
20
- **BREAKING: `IMPERSONATION_METADATA_KEY` moved from `@voltro/plugin-auth` to `@voltro/protocol`.** It names the one reserved key in `Subject.metadata`, and `Subject` is protocol's type. Two packages need it — plugin-auth writes the mark, plugin-audit reads it — and a plugin must not depend on another plugin, so spelling the string in both would have made it a second definition no guard is watching. Everything else stays: plugin-auth still exports `impersonationOf`, `isImpersonated`, `ImpersonationMark` and `impersonationAuditRedactor`. The codemod repoints the import, preserving an alias and the type-only form.
21
-
22
- The redactor keeps working and is no longer load-bearing. Set `redactSubject: 'none'` or a custom function for your own reasons; the impersonation mark is recorded either way.
23
-
24
- No migration is needed for the new column — a `_voltro_*` change rides the declarative differ on `voltro db apply` and on a `voltro dev` boot, on every dialect.
25
- - **@voltro/cli** — A `*.startup.ts` that fails now refuses the boot. It used to warn and let the server come up.
26
-
27
- Measured, on a real `voltro dev` against postgres, while building the row-filter integration test in this same release. A startup reached for `ctx.store.select(...)` — a builder that lives on the request-scoped `MutationStore`, not on the `DataStore` a startup receives — and threw on its first line. The boot printed:
28
-
29
- ```
30
- warn startup: function rejected
31
- info startup: registered <- next line, same file
32
- ```
33
-
34
- and then served every request with no row filter registered. Two lines contradicting each other, the second asserting exactly the thing that had just failed, and an app that looked healthy while its access control was absent.
10
+ ### Fixed
35
11
 
36
- **The rule this overturns was right when it was written.** The header of `startupRunner.ts` read "Errors are logged but never fatal a failing startup MUST NOT block the rest of the app", and for the startups it was written for — an SSE bridge, a sync loop, a metric aggregator — that is the correct call. It stopped being right when a startup became the documented seam for REGISTRATION: `setRowFilter` is installed from one.
12
+ - **@voltro/runtime, @voltro/cli**An app-registered tuple source is no longer replaced by the framework default.
37
13
 
38
- The runner cannot tell a registration from a background loop, and the two failures are not symmetric. "The app refuses to boot" is fixed in seconds and is visible to everyone; "the app serves without its access control" is visible to nobody. So the default is the recoverable one, and an app that genuinely wants best-effort writes the `try`/`catch` inside its own startup — one line, at the site where somebody decided the failure was acceptable, where a reviewer can see it. Deliberately not a flag: a flag moves that decision away from the startup it applies to and makes it one setting for all of them.
14
+ Both boot paths carried this comment, verbatim:
39
15
 
40
- **Two sibling silences went with it**, because fixing only the rejection would have left two more ways to reach the identical state — the per-seam shape this repo keeps paying for. A startup file that cannot be imported, and one with no default-exported function, used to warn and skip. Both refuse now. The second matters more than it sounds: the convention is a DEFAULT-exported function, a named export is discovered and never runs, and that is indistinguishable from a startup that ran and did nothing.
16
+ > An app whose relationships live in its own tables overrides with > `setTupleSource`.
41
17
 
42
- **And the 2-second race is gone, which is the half that made the rest reliable.** The old code did not wait for a startup to settle it raced it against 2000 ms and let the boot win. A startup slower than that was reported as fine, so a rejection arriving afterwards had nothing left to refuse. The runner now waits for the startup to SETTLE, so every failure is catchable however slow it is.
18
+ and then called `setTupleSource(default)` **unconditionally**. That call runs AFTER the app's startups `runBootLifecycle` at `dev.ts:3910` and `serveCommand.ts:869`, against the registration at `dev.ts:4065` and `serveApi.ts:937`and `setTupleSource` is last-write-wins. So the framework won every time: an app registering its own source in a `*.startup.tsx`, which is what the docs tell it to do, had it silently replaced.
43
19
 
44
- That race existed to protect one shape: a startup that never returns because it holds a fiber until shutdown. Counted before changing it, that shape appears in ZERO of the four startups this framework ships `warm.startup.tsx` (twice), `searchBackfill.startup.tsx` and the memory fixture's all return. So the race protected the shape we discourage and penalised the shape we teach, and the penalised one includes `searchBackfill`, our own example, which awaits a full-table query plus an index backfill and is the likeliest thing in the box to exceed two seconds. Slow AND failing put a consumer back in exactly the silent state this release removes.
20
+ The consequence is not subtle. Every relationship guard would then be answered from `_voltro_rebac_tuples`empty, for exactly the app that keeps its relations in its own tables so every guard DENIES, fail-closed, with a `no tuple source` warning that never fires because a source *is* registered: the wrong one.
45
21
 
46
- **So a startup that never returns now refuses the boot too**, after `VOLTRO_STARTUP_TIMEOUT_MS` (60s default), with a message naming the file and showing the `onShutdown` shape to use instead. That makes a previously-documented capability illegal "a fiber that resolves only on shutdown" — and it is the deliberate half of this change rather than a side effect. A startup that is merely SLOW is unaffected: it is waited for and registers when it finishes.
22
+ The comment was not wrong about the design; it described the design while the code removed it. Same shape as the `DORMANCY_WAKEUP_TENANT` scar equal by value at both call sites, so nothing could fail, and the comment was the only place the intent survived.
47
23
 
48
- `startup: registered` is written only when the function actually returned. The old code printed it for a failed startup and for one still running.
24
+ `registerDefaultTupleSource` fills the gap only when nobody else did, and returns whether it acted so the boot can say which source is live instead of leaving an operator to guess. `setTupleSource` itself is unchanged: an app calling it twice still gets the second one, because narrowing that would trade one silent surprise for another.
49
25
 
50
- Verified against a real process in every direction, not only in units: the reintroduced defect exits 1 and never listens; a never-returning startup exits 1 and never listens; a slow-but-successful one still registers; and the healthy fixture boots and serves all eight row-filter assertions. `startupRunner.test.ts` is new there were no tests on this runner at all, which is part of why the contradiction survived.
26
+ Found while re-checking a consumer's claim that a different item was still open. It was not but it sits beside this, and this is the one that would have bitten them. Pinned in both directions: a unit test for the registrar, and a source guard asserting neither boot path installs `loadResourceTuples` through `setTupleSource` again. Red-verified by restoring the original line.
27
+ - **@voltro/cli** — `voltro doctor` no longer reports "scope vocabulary: none found" when it could not read the config at all.
51
28
 
52
- **`voltro update` carries you across this** codemod `0.38.0/02_startup-failure-refuses-boot`.
29
+ A consumer HAD configured `doctor.scopeVocabulary` and still read `none found`. The cause was not their vocabulary: `app.config.ts` could not be imported outside their pod — an auth strategy demands its secret while the config is evaluated — so the vocabulary was never read. Inside the pod the message disappears and the rule runs.
53
30
 
54
- ### Fixed
31
+ "You have no vocabulary" and "I could not look" are different states, and only the first is a statement about their app. This section already made exactly that distinction one member earlier — its own comment reads **DORMANT AND CLEAN MUST NOT PRINT THE SAME** — and then collapsed the third.
55
32
 
56
- - **@voltro/cli** A table declared through `databaseHandle({ })` but not exported as a top-level table is now DISCOVEREDso its mixins apply.
33
+ The signal existed and was not connected. `offlineManifest` deliberately survives an unimportable config (a doctor run must not die on one), so the empty vocabulary arrived looking like a real absence, while the same failure was reported a hundred lines earlier under plugin tables. The consumer read the section about scopes and searched at the wrong end which is the correct way to read a report.
57
34
 
58
- Discovery kept whatever `isTable()` accepted out of a schema module's `Object.values`, which only ever sees tables the file exports DIRECTLY. A schema that builds its tables programmatically exports the builder's result:
35
+ The rule now probes importability before claiming an absence, and says so:
59
36
 
60
- ```ts
61
- export const blogEntities = contentTypeToEntities(blogPost) // { draft, published }
62
- export const database = databaseHandle({ …, blogPostDrafts: blogEntities.draft })
63
37
  ```
64
-
65
- `isTable({ draft, published })` is false, so those tables never entered the schema registry while `databaseHandle` had registered them for by-name lookup perfectly well.
66
-
67
- **Two registries with different populations, read by different things.** `getTable()` found the table, so insert validation knew `tenantId` was NOT NULL. The schema registry is what drives the mixins, so nothing stamped it. Measured against a real `voltro dev` boot of the scaffolded `api-cms` template, over real RPC:
68
-
38
+ • scope vocabulary: NOT EVALUATED — `app.config.ts` could not be imported.
39
+ This is not a statement about your scopes: the rule never got to read them.
40
+ … The same import failure is reported above for plugin tables; both sections
41
+ have this one cause.
69
42
  ```
70
- TableValidationFailed: { "table": "blogPost_drafts", "summary":
71
- "missing required column 'tenantId' — NOT NULL with no default and not auto-stamped" }
72
- ```
73
-
74
- Every `content.saveDraft` in that template, since it shipped. Its own unit test could not see it, because the test builds its schema registry by hand — the one step the running app does not perform.
75
-
76
- **The write failing was the lucky half.** Reads do not announce themselves: `makeQueryFinalizer` AND-merges `tenantId` from this same registry, so a table missing from it is a table nobody scopes. The visible symptom was a broken mutation; the invisible one was tenant isolation quietly not applied to those tables.
77
-
78
- The fix takes the by-name registry's DELTA across each schema module's import, so a handle-declared table is attributed to the file that declared it — rather than reading the whole global registry, which by then also holds framework tables that this set deliberately excludes. It lives in `loadDiscovered`, which `voltro dev` and `voltro serve` both call, so the two cannot disagree about it.
79
-
80
- No app change is needed; the idiomatic `databaseHandle` declaration now works as its documentation always said.
81
- - **@voltro/database, @voltro/cli** — A migration that fails because `DB_SCHEMA` names a schema that does not exist now says so.
82
43
 
83
- Postgres answers `3F000 no schema has been selected to create in`, and the only thing that puts a non-default schema on the connection's `search_path` here is `DB_SCHEMA`. The error mentions neither the variable nor the schema, so the FIRST `CREATE TABLE` of the boot fails with a message about SQL and the reader goes looking at the DDL — for a typo in an environment variable.
44
+ The dormant case keeps its own wording, so a quiet run on an app that genuinely publishes no vocabulary is not relabelled as a broken config.
84
45
 
85
- Found while building the row-filter integration test below: the boot aborted, the log named `_voltro_migrations` and a postgres routine, and nothing in it pointed at the one line of configuration that caused it. Same shape as a 403 that says nothing about `VOLTRO_INSPECT_TOKEN`, fixed in the same release.
46
+ ### Internal (no consumer-facing effect)
86
47
 
87
- The remedy also states what the framework will NOT do: Voltro creates tables, never the schema itself. That is a namespace decision, and inventing one from a typo puts a migration somewhere nobody is looking.
48
+ - **@voltro/cache, @voltro/kv** The RESP TTL tests in `@voltro/cache` and `@voltro/kv` stopped measuring the machine. Test-only; no product code changed.
88
49
 
89
- `remedyFor` is deliberately a one-entry map and the test asserts the empty case as well as the full one. A remedy is worth printing only where the mapping from driver code to cause is exact; a list of maybes is how a reader learns to skip the section.
50
+ Both wrote a key with `ttlMs: 150`, asserted it was still there, then slept 300 ms and asserted it was gone. The second half is fine — waiting LONGER only strengthens "it expired". The first half was a race: the write and the read are two round-trips, so on a loaded runner the key legitimately expired before the liveness assertion, and the test reported a defect that was not there. It failed exactly that way on a release gate, in the keydb engine, while passing locally with 24/24 green.
90
51
 
91
- **Alongside it: the row filter is now driven under `voltro dev` against a real postgres.** Both defects that reached consumers lived between layers that were each individually covered — a module-local `let` that split per instance, then a query producer that built its context from an unscoped request and three consumer documents carried "we have not run this against a real database" as an honest caveat. `rowFilterDevPostgres.integration.test.ts` boots the fixture twice: handlers with no predicate of their own, a filter registered from a `*.startup.tsx`, and a NEGATIVE CONTROL run with the registration skipped that asserts the same queries return BOTH owners. Without the control, "the caller saw one owner" is equally consistent with a database that only ever held one.
92
- - **@voltro/cli** — A shard that cannot be released no longer spins a fiber at full speed. Upstream `@effect/cluster` releases shards through `Effect.eventually` — retry until success, zero delay, logged at DEBUG — so a shard whose storage was unreachable retried as fast as the event loop allowed, in the one place nobody watches.
52
+ Now: a 2 s window, so liveness has real headroom rather than 150 ms of it, and the expiry is awaited as a CONDITION (`awaitGone` polls) rather than as a duration. Idle machines finish in about the TTL; loaded ones take as long as they need; a key that never expires still fails, because the ceiling is a failure mode and not a timing assumption.
93
53
 
94
- Our patch replaces it with `Effect.retry(Schedule.exponential(100) ∪ Schedule.spaced(5000))`. `union` takes the MINIMUM of the two delays, so the 5s spacing caps the backoff instead of compounding with it, and both schedules recur forever attempts stay unbounded, which is what the original intended. The persistence was always correct; only the missing delay was the defect.
54
+ Fixed in BOTH packages in one change. The two files carried the identical construction, and this repo's standing lesson is that a fix landing in one copy of a duplicated shape leaves the other one broken `@voltro/kv` had not failed yet, which is a statement about luck rather than about the test.
95
55
 
96
- This entry exists because the change would otherwise have shipped undocumented. The patch lives in `packages/cli/templates/patches/`, and the changelog gate requires an entry for `packages/*/src` — so nothing would have demanded one, even though the file is installed into every user project that runs cluster. A rule that cannot see a path is not the same as a path with nothing on it.
56
+ `@voltro/kv`'s header also pointed at `../cache/test/docker-compose.yml` for bringing the engines up. That path does not exist; there is one compose file, at the repo root.
@@ -12,16 +12,16 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.97.0",
14
14
  "@effect/rpc": "^0.76.0",
15
- "@voltro/ai": "0.38.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/protocol": "0.38.0",
20
- "@voltro/runtime": "0.38.0",
15
+ "@voltro/ai": "0.39.1",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/protocol": "0.39.1",
20
+ "@voltro/runtime": "0.39.1",
21
21
  "effect": "^3.22.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.38.0",
24
+ "@voltro/testing": "0.39.1",
25
25
  "typescript": "^6.0.3",
26
26
  "@vitest/coverage-v8": "^4.1.10",
27
27
  "vitest": "^4.1.10"
@@ -13,17 +13,17 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/plugin-auth": "0.38.0",
20
- "@voltro/protocol": "0.38.0",
21
- "@voltro/runtime": "0.38.0",
22
- "@voltro/sql-postgres": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/plugin-auth": "0.39.1",
20
+ "@voltro/protocol": "0.39.1",
21
+ "@voltro/runtime": "0.39.1",
22
+ "@voltro/sql-postgres": "0.39.1",
23
23
  "effect": "^3.22.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.38.0",
26
+ "@voltro/testing": "0.39.1",
27
27
  "typescript": "^6.0.3",
28
28
  "@vitest/coverage-v8": "^4.1.10",
29
29
  "vitest": "^4.1.10"
@@ -16,16 +16,16 @@
16
16
  "dependencies": {
17
17
  "@effect/platform": "^0.97.0",
18
18
  "@effect/rpc": "^0.76.0",
19
- "@voltro/cli": "0.38.0",
20
- "@voltro/database": "0.38.0",
21
- "@voltro/env": "0.38.0",
22
- "@voltro/plugin-multitenancy": "0.38.0",
23
- "@voltro/protocol": "0.38.0",
24
- "@voltro/runtime": "0.38.0",
19
+ "@voltro/cli": "0.39.1",
20
+ "@voltro/database": "0.39.1",
21
+ "@voltro/env": "0.39.1",
22
+ "@voltro/plugin-multitenancy": "0.39.1",
23
+ "@voltro/protocol": "0.39.1",
24
+ "@voltro/runtime": "0.39.1",
25
25
  "effect": "^3.22.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@voltro/testing": "0.38.0",
28
+ "@voltro/testing": "0.39.1",
29
29
  "typescript": "^6.0.3",
30
30
  "@vitest/coverage-v8": "^4.1.10",
31
31
  "vitest": "^4.1.10"
@@ -13,16 +13,16 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/plugin-deactivation": "0.38.0",
20
- "@voltro/protocol": "0.38.0",
21
- "@voltro/runtime": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/plugin-deactivation": "0.39.1",
20
+ "@voltro/protocol": "0.39.1",
21
+ "@voltro/runtime": "0.39.1",
22
22
  "effect": "^3.22.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.38.0",
25
+ "@voltro/testing": "0.39.1",
26
26
  "typescript": "^6.0.3",
27
27
  "@vitest/coverage-v8": "^4.1.10",
28
28
  "vitest": "^4.1.10"
@@ -13,18 +13,18 @@
13
13
  "dependencies": {
14
14
  "@react-email/components": "^1.0.12",
15
15
  "@react-email/render": "^1.4.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/plugin-mail": "0.38.0",
20
- "@voltro/plugin-multitenancy": "0.38.0",
21
- "@voltro/protocol": "0.38.0",
22
- "@voltro/runtime": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/plugin-mail": "0.39.1",
20
+ "@voltro/plugin-multitenancy": "0.39.1",
21
+ "@voltro/protocol": "0.39.1",
22
+ "@voltro/runtime": "0.39.1",
23
23
  "effect": "^3.22.0",
24
24
  "react": "^19.0.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@voltro/testing": "0.38.0",
27
+ "@voltro/testing": "0.39.1",
28
28
  "typescript": "^6.0.3",
29
29
  "@vitest/coverage-v8": "^4.1.10",
30
30
  "vitest": "^4.1.10"
@@ -13,18 +13,18 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/plugin-multitenancy": "0.38.0",
20
- "@voltro/plugin-storage": "0.38.0",
21
- "@voltro/protocol": "0.38.0",
22
- "@voltro/runtime": "0.38.0",
23
- "@voltro/sql-mysql": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/plugin-multitenancy": "0.39.1",
20
+ "@voltro/plugin-storage": "0.39.1",
21
+ "@voltro/protocol": "0.39.1",
22
+ "@voltro/runtime": "0.39.1",
23
+ "@voltro/sql-mysql": "0.39.1",
24
24
  "effect": "^3.22.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@voltro/testing": "0.38.0",
27
+ "@voltro/testing": "0.39.1",
28
28
  "typescript": "^6.0.3",
29
29
  "@vitest/coverage-v8": "^4.1.10",
30
30
  "vitest": "^4.1.10"
@@ -13,17 +13,17 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/plugin-multitenancy": "0.38.0",
20
- "@voltro/protocol": "0.38.0",
21
- "@voltro/runtime": "0.38.0",
22
- "@voltro/sql-sqlite": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/plugin-multitenancy": "0.39.1",
20
+ "@voltro/protocol": "0.39.1",
21
+ "@voltro/runtime": "0.39.1",
22
+ "@voltro/sql-sqlite": "0.39.1",
23
23
  "effect": "^3.22.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.38.0",
26
+ "@voltro/testing": "0.39.1",
27
27
  "typescript": "^6.0.3",
28
28
  "@vitest/coverage-v8": "^4.1.10",
29
29
  "vitest": "^4.1.10"
@@ -11,17 +11,17 @@
11
11
  "test": "voltro test"
12
12
  },
13
13
  "dependencies": {
14
- "@voltro/cli": "0.38.0",
15
- "@voltro/database": "0.38.0",
16
- "@voltro/env": "0.38.0",
17
- "@voltro/plugin-multitenancy": "0.38.0",
18
- "@voltro/plugin-storage": "0.38.0",
19
- "@voltro/protocol": "0.38.0",
20
- "@voltro/runtime": "0.38.0",
14
+ "@voltro/cli": "0.39.1",
15
+ "@voltro/database": "0.39.1",
16
+ "@voltro/env": "0.39.1",
17
+ "@voltro/plugin-multitenancy": "0.39.1",
18
+ "@voltro/plugin-storage": "0.39.1",
19
+ "@voltro/protocol": "0.39.1",
20
+ "@voltro/runtime": "0.39.1",
21
21
  "effect": "^3.22.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.38.0",
24
+ "@voltro/testing": "0.39.1",
25
25
  "typescript": "^6.0.3",
26
26
  "@vitest/coverage-v8": "^4.1.10",
27
27
  "vitest": "^4.1.10"
@@ -13,19 +13,19 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/cms": "0.38.0",
18
- "@voltro/database": "0.38.0",
19
- "@voltro/env": "0.38.0",
20
- "@voltro/plugin-auth": "0.38.0",
21
- "@voltro/plugin-multitenancy": "0.38.0",
22
- "@voltro/protocol": "0.38.0",
23
- "@voltro/runtime": "0.38.0",
24
- "@voltro/sql-postgres": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/cms": "0.39.1",
18
+ "@voltro/database": "0.39.1",
19
+ "@voltro/env": "0.39.1",
20
+ "@voltro/plugin-auth": "0.39.1",
21
+ "@voltro/plugin-multitenancy": "0.39.1",
22
+ "@voltro/protocol": "0.39.1",
23
+ "@voltro/runtime": "0.39.1",
24
+ "@voltro/sql-postgres": "0.39.1",
25
25
  "effect": "^3.22.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@voltro/testing": "0.38.0",
28
+ "@voltro/testing": "0.39.1",
29
29
  "typescript": "^6.0.3",
30
30
  "@vitest/coverage-v8": "^4.1.10",
31
31
  "vitest": "^4.1.10"
@@ -13,17 +13,17 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/local-first": "0.38.0",
20
- "@voltro/plugin-multitenancy": "0.38.0",
21
- "@voltro/protocol": "0.38.0",
22
- "@voltro/runtime": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/local-first": "0.39.1",
20
+ "@voltro/plugin-multitenancy": "0.39.1",
21
+ "@voltro/protocol": "0.39.1",
22
+ "@voltro/runtime": "0.39.1",
23
23
  "effect": "^3.22.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.38.0",
26
+ "@voltro/testing": "0.39.1",
27
27
  "typescript": "^6.0.3",
28
28
  "@vitest/coverage-v8": "^4.1.10",
29
29
  "vitest": "^4.1.10"
@@ -12,17 +12,17 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.97.0",
14
14
  "@effect/rpc": "^0.76.0",
15
- "@voltro/cli": "0.38.0",
16
- "@voltro/database": "0.38.0",
17
- "@voltro/env": "0.38.0",
18
- "@voltro/plugin-governance": "0.38.0",
19
- "@voltro/plugin-multitenancy": "0.38.0",
20
- "@voltro/protocol": "0.38.0",
21
- "@voltro/runtime": "0.38.0",
15
+ "@voltro/cli": "0.39.1",
16
+ "@voltro/database": "0.39.1",
17
+ "@voltro/env": "0.39.1",
18
+ "@voltro/plugin-governance": "0.39.1",
19
+ "@voltro/plugin-multitenancy": "0.39.1",
20
+ "@voltro/protocol": "0.39.1",
21
+ "@voltro/runtime": "0.39.1",
22
22
  "effect": "^3.22.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.38.0",
25
+ "@voltro/testing": "0.39.1",
26
26
  "typescript": "^6.0.3",
27
27
  "@vitest/coverage-v8": "^4.1.10",
28
28
  "vitest": "^4.1.10"
@@ -12,17 +12,17 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.97.0",
14
14
  "@effect/rpc": "^0.76.0",
15
- "@voltro/cli": "0.38.0",
16
- "@voltro/database": "0.38.0",
17
- "@voltro/env": "0.38.0",
18
- "@voltro/plugin-multitenancy": "0.38.0",
19
- "@voltro/protocol": "0.38.0",
20
- "@voltro/runtime": "0.38.0",
21
- "@voltro/workflow": "0.38.0",
15
+ "@voltro/cli": "0.39.1",
16
+ "@voltro/database": "0.39.1",
17
+ "@voltro/env": "0.39.1",
18
+ "@voltro/plugin-multitenancy": "0.39.1",
19
+ "@voltro/protocol": "0.39.1",
20
+ "@voltro/runtime": "0.39.1",
21
+ "@voltro/workflow": "0.39.1",
22
22
  "effect": "^3.22.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.38.0",
25
+ "@voltro/testing": "0.39.1",
26
26
  "typescript": "^6.0.3",
27
27
  "@vitest/coverage-v8": "^4.1.10",
28
28
  "vitest": "^4.1.10"
@@ -6,8 +6,22 @@
6
6
  // websocket, start a background interval, register a process singleton —
7
7
  // and register a teardown via `onShutdown`.
8
8
  //
9
- // A throw here does NOT block boot (it's logged; the rpc surface stays
10
- // up). Distinct from `*.seed.ts` (runs once and RETURNS) and `*.cron.tsx`
9
+ // A throw here REFUSES the boot, naming this file and the cause. A startup
10
+ // is where an app arms things the request path depends on, and "served
11
+ // without them" is the failure nobody sees — so the default is the
12
+ // recoverable one. If a failure is genuinely acceptable here (a cache warm
13
+ // is the usual case), catch it INSIDE this function, so the decision sits
14
+ // where somebody made it:
15
+ //
16
+ // try { await warm(store) }
17
+ // catch (err) { log.warn('cache warm failed; serving cold', {}, err) }
18
+ //
19
+ // The function must also RETURN. Start the work, hand back teardown via
20
+ // `onShutdown`, return — one that never returns refuses the boot after
21
+ // `VOLTRO_STARTUP_TIMEOUT_MS` (default 60s). A slow but successful startup
22
+ // is simply awaited.
23
+ //
24
+ // Distinct from `*.seed.ts` (runs once and RETURNS) and `*.cron.tsx`
11
25
  // (periodic) — a startup HOLDS a resource for the process lifetime.
12
26
  //
13
27
  // NOTE: `StartupContext` lives on the `@voltro/cli/startup` subpath (the
@@ -13,18 +13,18 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/plugin-flags": "0.38.0",
20
- "@voltro/plugin-multitenancy": "0.38.0",
21
- "@voltro/protocol": "0.38.0",
22
- "@voltro/runtime": "0.38.0",
23
- "@voltro/sql-postgres": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/plugin-flags": "0.39.1",
20
+ "@voltro/plugin-multitenancy": "0.39.1",
21
+ "@voltro/protocol": "0.39.1",
22
+ "@voltro/runtime": "0.39.1",
23
+ "@voltro/sql-postgres": "0.39.1",
24
24
  "effect": "^3.22.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@voltro/testing": "0.38.0",
27
+ "@voltro/testing": "0.39.1",
28
28
  "typescript": "^6.0.3",
29
29
  "@vitest/coverage-v8": "^4.1.10",
30
30
  "vitest": "^4.1.10"
@@ -13,17 +13,17 @@
13
13
  "dependencies": {
14
14
  "@effect/platform": "^0.97.0",
15
15
  "@effect/rpc": "^0.76.0",
16
- "@voltro/cli": "0.38.0",
17
- "@voltro/database": "0.38.0",
18
- "@voltro/env": "0.38.0",
19
- "@voltro/plugin-audit": "0.38.0",
20
- "@voltro/plugin-governance": "0.38.0",
21
- "@voltro/protocol": "0.38.0",
22
- "@voltro/runtime": "0.38.0",
16
+ "@voltro/cli": "0.39.1",
17
+ "@voltro/database": "0.39.1",
18
+ "@voltro/env": "0.39.1",
19
+ "@voltro/plugin-audit": "0.39.1",
20
+ "@voltro/plugin-governance": "0.39.1",
21
+ "@voltro/protocol": "0.39.1",
22
+ "@voltro/runtime": "0.39.1",
23
23
  "effect": "^3.22.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.38.0",
26
+ "@voltro/testing": "0.39.1",
27
27
  "typescript": "^6.0.3",
28
28
  "@vitest/coverage-v8": "^4.1.10",
29
29
  "vitest": "^4.1.10"
@@ -12,17 +12,17 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.97.0",
14
14
  "@effect/rpc": "^0.76.0",
15
- "@voltro/cli": "0.38.0",
16
- "@voltro/database": "0.38.0",
17
- "@voltro/env": "0.38.0",
18
- "@voltro/kv": "0.38.0",
19
- "@voltro/plugin-multitenancy": "0.38.0",
20
- "@voltro/protocol": "0.38.0",
21
- "@voltro/runtime": "0.38.0",
15
+ "@voltro/cli": "0.39.1",
16
+ "@voltro/database": "0.39.1",
17
+ "@voltro/env": "0.39.1",
18
+ "@voltro/kv": "0.39.1",
19
+ "@voltro/plugin-multitenancy": "0.39.1",
20
+ "@voltro/protocol": "0.39.1",
21
+ "@voltro/runtime": "0.39.1",
22
22
  "effect": "^3.22.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.38.0",
25
+ "@voltro/testing": "0.39.1",
26
26
  "typescript": "^6.0.3",
27
27
  "@vitest/coverage-v8": "^4.1.10",
28
28
  "vitest": "^4.1.10"