@voltro/runtime 0.62.1 → 0.62.3

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.
package/CHANGELOG.md CHANGED
@@ -39,6 +39,35 @@ _Changes staged for the next release accumulate here (rolled up from
39
39
 
40
40
  ---
41
41
 
42
+ ## [0.62.3] — 2026-09-03
43
+
44
+ ### Added
45
+
46
+ - **@voltro/runtime** — `EffectStore` now exposes the complete Promise-store mutation surface plus transactions that roll back while preserving an inner Effect Cause. `defineSubscriber` accepts `eachReplica: true` so local per-replica work can state its topology explicitly; it cannot be combined with `once`.
47
+
48
+ ### Fixed
49
+
50
+ - **@voltro/cli** — `voltro build` no longer starts Vite's HMR WebSocket while pre-rendering. A `RedirectError` from a static loader is now emitted as redirect metadata and served by `voltro start` with its exact status and `Location`; unrelated loader errors still fail the build.
51
+ - **@voltro/cli, @voltro/database, @voltro/plugin-storage** — `voltro doctor` now resolves grouped event bindings and narrows its hand-roll, junction, ownership, nullable-write, singleton-read, and UI reachability checks to evidence they can actually prove. Ids owned by external systems can be declared with `.externalId()`; plugin references and non-FK asset references carry that metadata automatically.
52
+
53
+ ---
54
+
55
+ ## [0.62.2] — 2026-09-03
56
+
57
+ ### Added
58
+
59
+ - **@voltro/client, @voltro/web, @voltro/runtime, @voltro/cli, @voltro/devtools, @voltro/workflow** — Reconnect incidents now have one bounded, payload-free evidence path: browser diagnostics retain runtime/socket/protocol/subscription transitions across a reload, the subscriptions panel exposes recovery progress and stuck re-issues, and `voltro support collect` joins that export to inspect snapshots and exact browser-to-replica socket ids. The opt-in browser fault harness can reproduce a bounded transport cut without a proxy; logs and traces remain excluded from the support bundle unless explicitly requested.
60
+
61
+ Workflow admission rows now retain queue-time app/schema provenance. `voltro workflows flow validate` checks queued payloads against the current release without returning them, while `flow retry <intentId>` re-arms one retained dead letter after its fix. Support bundles also inventory project `conflictColumns` callsites, and `voltro support sentry <eventId>` delegates source-map resolution diagnosis to Sentry's own CLI.
62
+ - **@voltro/runtime** — Successful rpc WebSocket upgrades now emit structured open and close records carrying the serving `replicaId` and a stable per-socket `connectionId`, so connection cuts can be correlated to an api replica without debug traffic.
63
+
64
+ ### Fixed
65
+
66
+ - **@voltro/client, @voltro/web, @voltro/react-native** — Subscription recovery now re-issues transport-failed active subscriptions only after the rpc protocol has cleared the previous socket error. A longer outage could previously reopen the WebSocket, immediately reject every re-issued subscription against the stale error, and leave the screen degraded until a reload.
67
+ - **@voltro/workflow, @voltro/cli, @voltro/devtools-ui** — Queued workflow starts whose stored payload no longer decodes now signal `onFailure` once and remain visible as dead-letter intents instead of retrying forever. Inspect or remove them with `voltro workflows flow` and `voltro workflows flow discard <intentId>`; a valid later debounce arrival for the same key replaces the obsolete payload and resumes normal draining.
68
+
69
+ ---
70
+
42
71
  ## [0.62.1] — 2026-09-02
43
72
 
44
73
  ### Fixed
@@ -46,6 +75,11 @@ _Changes staged for the next release accumulate here (rolled up from
46
75
  - **@voltro/client, @voltro/web, @voltro/react-native** — `useSubscriptionHealth` now clears failures when replacement subscriptions succeed after a reconnect; each api keeps one error bus across transport, auth-refresh, and subject-reconnect generations.
47
76
  - **@voltro/client, @voltro/web, @voltro/react-native** — Active subscriptions whose fibers ended in a transport failure are now re-issued when the rpc socket opens again, preserving their last rows and resume revision; `useConnectionStatus` stays degraded until every affected subscription delivers a later snapshot or delta.
48
77
 
78
+ **Correction:** In 0.62.1 that reissue runs on the raw WebSocket `open`, before
79
+ the rpc protocol clears the previous socket error. After a longer outage the
80
+ reissued fibers can therefore fail immediately and remain terminal. The next
81
+ patch moves recovery behind the protocol-ready `onOpen` effect.
82
+
49
83
  ### Internal (no consumer-facing effect)
50
84
 
51
85
  - **@voltro/local-first** — Release dependency floors now exclude the vulnerable `fast-uri` and `@xmldom/xmldom` ranges, and the local-first test toolchain uses the patched Tiptap release.
package/dist/index.d.ts CHANGED
@@ -3605,10 +3605,29 @@ export declare interface EffectStoreOps {
3605
3605
  * hand-built descriptor. */
3606
3606
  readonly query: <R = Row>(descriptor: QueryDescriptor<R>) => Effect.Effect<ReadonlyArray<R>, StoreError>;
3607
3607
  readonly insert: (table: string, row: Row) => Effect.Effect<Row, StoreError>;
3608
+ readonly insertMany: (table: string, rows: ReadonlyArray<Row>) => Effect.Effect<ReadonlyArray<Row>, StoreError>;
3609
+ readonly patchJson: (table: string, primaryKey: string, path: string, value: unknown) => Effect.Effect<Row | null, StoreError>;
3608
3610
  readonly update: (table: string, primaryKey: string, patch: Readonly<Record<string, unknown>>) => Effect.Effect<Row | null, StoreError>;
3611
+ readonly updateMany: (table: string, patch: Readonly<Record<string, unknown>>, options: {
3612
+ readonly where: Predicate;
3613
+ }) => Effect.Effect<number, StoreError>;
3609
3614
  readonly delete: (table: string, primaryKey: string) => Effect.Effect<boolean, StoreError>;
3615
+ readonly deleteMany: (table: string, options: {
3616
+ readonly where: Predicate;
3617
+ }) => Effect.Effect<number, StoreError>;
3618
+ readonly upsert: (table: string, row: Row, options: {
3619
+ readonly conflictColumns: ReadonlyArray<string>;
3620
+ readonly update?: ReadonlyArray<string> | ((existing: Row) => Readonly<Record<string, unknown>>);
3621
+ }) => Effect.Effect<Row, StoreError>;
3622
+ readonly insertIgnore: (table: string, row: Row, options: {
3623
+ readonly conflictColumns: ReadonlyArray<string>;
3624
+ }) => Effect.Effect<Row, StoreError>;
3610
3625
  /** Bypass soft-delete. See `MutationStore.hardDelete`. */
3611
3626
  readonly hardDelete: (table: string, primaryKey: string) => Effect.Effect<boolean, StoreError>;
3627
+ /** Run one Effect program atomically against the transaction-scoped store.
3628
+ * The inner Effect's typed failures and defects are preserved; database /
3629
+ * store failures join the error channel as `StoreError`. */
3630
+ readonly transactional: <A, E, R>(work: (transaction: EffectStoreOps) => Effect.Effect<A, E, R>) => Effect.Effect<A, E | StoreError, R>;
3612
3631
  }
3613
3632
 
3614
3633
  /** Empty registry — handy for tests + the rare bootstrap path with no
@@ -8779,6 +8798,10 @@ export declare interface RpcServerOptions<Rpcs extends Rpc.Any> {
8779
8798
  */
8780
8799
  readonly host?: string;
8781
8800
  readonly path?: `/${string}`;
8801
+ /** Non-sensitive fleet identity written on the rpc WebSocket open/close
8802
+ * records. Defaults to the process identity resolver (POD_NAME/HOSTNAME).
8803
+ * Embedders may state it explicitly when they own process identity. */
8804
+ readonly replicaId?: string;
8782
8805
  /** Optional tracer layer (`buildTracingLayer().layer`). Merged into the
8783
8806
  * server's layer scope so every `Effect.withSpan` on the handler path
8784
8807
  * — query/mutation/action/stream/workflow handlers — emits real OTel spans
@@ -10238,6 +10261,15 @@ export declare interface SubscriberDefinition {
10238
10261
  * from a `*.reaction.tsx`, where the durability is the primitive's job.
10239
10262
  */
10240
10263
  readonly once?: true | ((event: SubscribeEvent) => string);
10264
+ /**
10265
+ * State explicitly that this handler must run on every replica.
10266
+ *
10267
+ * This is the executable counterpart to omitting `once`: it documents that
10268
+ * multiplication is intentional and lets `voltro doctor` distinguish an
10269
+ * unmade fleet decision from a cache/index refresh that genuinely belongs on
10270
+ * every process.
10271
+ */
10272
+ readonly eachReplica?: true;
10241
10273
  readonly handler: SubscribeHandler;
10242
10274
  }
10243
10275