@voltro/runtime 0.52.0 → 0.54.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.
- package/CHANGELOG.md +424 -0
- package/THIRD-PARTY-NOTICES.md +29 -1
- package/dist/index.d.ts +481 -29
- package/dist/index.js +2633 -2079
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -69,6 +69,7 @@ import { RetentionSource } from '@voltro/database';
|
|
|
69
69
|
import { RetentionSpec } from '@voltro/database';
|
|
70
70
|
import { retentionTtlMsFromEnv } from '@voltro/database';
|
|
71
71
|
import { Row } from '@voltro/database';
|
|
72
|
+
import { RowPatch } from '@voltro/protocol';
|
|
72
73
|
import { Rpc } from '@effect/rpc';
|
|
73
74
|
import { RpcGroup } from '@effect/rpc';
|
|
74
75
|
import { RpcInterceptor } from '@voltro/protocol';
|
|
@@ -97,6 +98,8 @@ import { TenantRowNotFound } from '@voltro/protocol';
|
|
|
97
98
|
import { TenantScopeViolation } from '@voltro/protocol';
|
|
98
99
|
import { Tracer } from 'effect';
|
|
99
100
|
import { Unauthenticated } from '@voltro/protocol';
|
|
101
|
+
import { ValidationError } from '@voltro/protocol';
|
|
102
|
+
import { ValidationErrors } from '@voltro/protocol';
|
|
100
103
|
import { WebSocketGatewayRoute } from '@voltro/protocol';
|
|
101
104
|
import { WorkflowParentClosePolicy } from '@voltro/protocol';
|
|
102
105
|
import { WorkflowRunHandle } from '@voltro/protocol';
|
|
@@ -151,6 +154,28 @@ export declare interface ActivitySignals {
|
|
|
151
154
|
readonly activeWorkflowExecutions: () => number;
|
|
152
155
|
}
|
|
153
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Adopt a detached subscription for a resuming client at `fromRevision`.
|
|
159
|
+
* Undefined — identity unknown, entry dead (an error/revocation while
|
|
160
|
+
* offline), or the revision does not chain — means: subscribe fresh, send a
|
|
161
|
+
* snapshot. A failed adoption EXPIRES the entry: its ring cannot serve this
|
|
162
|
+
* client and keeping a half-dead entry around only risks a second caller
|
|
163
|
+
* adopting state the first one invalidated.
|
|
164
|
+
*/
|
|
165
|
+
export declare const adoptDetached: (identity: ResumeIdentity, fromRevision: number, now?: number, tunables?: ResumeTunables) => AdoptedSubscription | undefined;
|
|
166
|
+
|
|
167
|
+
export declare interface AdoptedSubscription {
|
|
168
|
+
/** The deltas the client missed, in order — replay before going live. */
|
|
169
|
+
readonly deltas: ReadonlyArray<{
|
|
170
|
+
readonly revision: number;
|
|
171
|
+
readonly emittedAt: number;
|
|
172
|
+
readonly patch: RowPatch;
|
|
173
|
+
}>;
|
|
174
|
+
/** Redirect this to the new stream to go live on the SAME revision line. */
|
|
175
|
+
readonly sink: ResumeSink;
|
|
176
|
+
readonly unsubscribe: () => void;
|
|
177
|
+
}
|
|
178
|
+
|
|
154
179
|
export declare interface AggregateContext {
|
|
155
180
|
/** Read-side store for source queries. Note: the build function
|
|
156
181
|
* runs OUTSIDE any per-request subject, so the auto-stamping a
|
|
@@ -808,6 +833,15 @@ export declare interface AnalyticsTopEntry {
|
|
|
808
833
|
readonly value: number;
|
|
809
834
|
}
|
|
810
835
|
|
|
836
|
+
/**
|
|
837
|
+
* Answer a `resumeFrom` for this identity. `fromRevision` is the last
|
|
838
|
+
* revision the CLIENT materialised. Only revisions inside
|
|
839
|
+
* [baseRevision, headRevision] chain; everything else — unknown key, aged
|
|
840
|
+
* ring, a revision the ring no longer covers, a revision AHEAD of the head
|
|
841
|
+
* (a client from a different life) — is a snapshot.
|
|
842
|
+
*/
|
|
843
|
+
export declare const answerResume: (identity: ResumeIdentity, fromRevision: number, now?: number, tunables?: ResumeTunables) => ResumeAnswer;
|
|
844
|
+
|
|
811
845
|
declare type AnyRow = Record<string, unknown>;
|
|
812
846
|
|
|
813
847
|
declare type AnyRow_2 = Record<string, unknown>;
|
|
@@ -990,6 +1024,10 @@ export declare interface AppContext {
|
|
|
990
1024
|
* `ctx.access.has(scope)` / `yield* ctx.access.require(scope)` instead of
|
|
991
1025
|
* reaching into `ctx.request.subject.scopes`. Always present. */
|
|
992
1026
|
readonly access: AppAccess;
|
|
1027
|
+
/** Typed server-side field validation — `yield* ctx.validation.fail('email',
|
|
1028
|
+
* 'validation.emailTaken')` routes to the form field that submitted it.
|
|
1029
|
+
* Always present. */
|
|
1030
|
+
readonly validation: AppValidation;
|
|
993
1031
|
/** Cache — always present (memory backend by default). Use
|
|
994
1032
|
* `ctx.cache.wrap(key, { ttlMs, tags }, () => expensive())` to cache
|
|
995
1033
|
* derived work; tagged entries auto-invalidate when a mutation writes a
|
|
@@ -1074,6 +1112,28 @@ export declare interface AppContext {
|
|
|
1074
1112
|
*/
|
|
1075
1113
|
export declare const applyConnectionCredential: (clientId: number, headers: Record<string, string | undefined>) => Record<string, string | undefined>;
|
|
1076
1114
|
|
|
1115
|
+
/**
|
|
1116
|
+
* Reconcile a mutation target's declared junction `relations:` against the
|
|
1117
|
+
* input — INSIDE the mutation's transaction, through `ctx.store`, so the
|
|
1118
|
+
* links ride the same undo capture, rule evaluation and rollback as the
|
|
1119
|
+
* mutation's own writes.
|
|
1120
|
+
*
|
|
1121
|
+
* Semantics that must not drift:
|
|
1122
|
+
* - an ABSENT input field touches nothing (absent ≠ empty);
|
|
1123
|
+
* - an empty array is the explicit clear;
|
|
1124
|
+
* - a non-array value is a refusal naming the field — silently ignoring it
|
|
1125
|
+
* would read as "saved" while the links stayed stale;
|
|
1126
|
+
* - the row id is `output.id`, else `input.id`; with neither the declaration
|
|
1127
|
+
* is unusable and says so.
|
|
1128
|
+
*/
|
|
1129
|
+
export declare const applyDeclaredRelations: (params: {
|
|
1130
|
+
readonly store: RelationLinksStore;
|
|
1131
|
+
readonly target: MutationLike["descriptor"]["target"];
|
|
1132
|
+
readonly procedure: string;
|
|
1133
|
+
readonly input: unknown;
|
|
1134
|
+
readonly output: unknown;
|
|
1135
|
+
}) => Promise<void>;
|
|
1136
|
+
|
|
1077
1137
|
/**
|
|
1078
1138
|
* Pure helper backing `ctx.store.applyDefined`. Picks the listed keys from
|
|
1079
1139
|
* `input` whose value is not `undefined`, so a PATCH sets exactly the fields
|
|
@@ -1220,6 +1280,35 @@ export declare interface AppSupervisor {
|
|
|
1220
1280
|
stop: () => Promise<void>;
|
|
1221
1281
|
}
|
|
1222
1282
|
|
|
1283
|
+
/** Typed server-side FIELD validation — the executor half of form error
|
|
1284
|
+
* routing. Each helper fails the procedure with a wire `ValidationError`
|
|
1285
|
+
* (auto-merged into every mutation's and action's error union), which the
|
|
1286
|
+
* form binding routes to `errors[field]` instead of `submitError`. */
|
|
1287
|
+
export declare interface AppValidation {
|
|
1288
|
+
/** Fail with ONE field error. `message` is a message id
|
|
1289
|
+
* (`'validation.emailTaken'`) resolved by the client's validation catalog.
|
|
1290
|
+
*
|
|
1291
|
+
* if (await emailTaken(input.email)) {
|
|
1292
|
+
* return yield* ctx.validation.fail('email', 'validation.emailTaken')
|
|
1293
|
+
* }
|
|
1294
|
+
*/
|
|
1295
|
+
readonly fail: (field: string, message: string, params?: Record<string, unknown>) => Effect.Effect<never, ValidationError>;
|
|
1296
|
+
/** Fail with several field errors in one round trip. Refuses an empty
|
|
1297
|
+
* list — a failure with nothing to show is a bug at the call site. */
|
|
1298
|
+
readonly failAll: (issues: ReadonlyArray<{
|
|
1299
|
+
readonly field: string;
|
|
1300
|
+
readonly message: string;
|
|
1301
|
+
readonly params?: Record<string, unknown>;
|
|
1302
|
+
}>) => Effect.Effect<never, ValidationErrors>;
|
|
1303
|
+
/** Guard form: succeed when `condition` holds, else fail the field. */
|
|
1304
|
+
readonly require: (condition: boolean, field: string, message: string, params?: Record<string, unknown>) => Effect.Effect<void, ValidationError>;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
/** The ONE `ctx.validation` value. Pure and subject-free, so a single shared
|
|
1308
|
+
* instance serves every context — request, schedule, workflow, test — and
|
|
1309
|
+
* the builders cannot each assemble a drifting copy. */
|
|
1310
|
+
export declare const appValidation: AppValidation;
|
|
1311
|
+
|
|
1223
1312
|
/** Effect-style guard for handlers — throws the typed {@link AccessDenied} on a
|
|
1224
1313
|
* deny so it surfaces to the client typed. */
|
|
1225
1314
|
export declare const assertCan: (subject: RebacSubject, action: string, resource: RebacResource, deps: CanDeps) => void;
|
|
@@ -1623,7 +1712,14 @@ reauthorize?: (subject: Subject) => () => Promise<unknown>,
|
|
|
1623
1712
|
*/
|
|
1624
1713
|
refilter?: (subject: Subject) => () => Promise<RowFilterScope>) => Stream.Stream<SubscriptionEvent<T>, never, SubjectService | ConnectionInfo>;
|
|
1625
1714
|
|
|
1626
|
-
export declare const bindSubscriptionUntyped: (descriptor: QueryDescriptor, dispatcher: Dispatcher, context: RuntimeContext, indexHint: MatcherIndexHint | undefined, label: string, cacheBinding: SnapshotCacheBinding | undefined, reauthorize: (() => Promise<unknown>) | undefined, refilter?: (() => Promise<RowFilterScope>) | undefined
|
|
1715
|
+
export declare const bindSubscriptionUntyped: (descriptor: QueryDescriptor, dispatcher: Dispatcher, context: RuntimeContext, indexHint: MatcherIndexHint | undefined, label: string, cacheBinding: SnapshotCacheBinding | undefined, reauthorize: (() => Promise<unknown>) | undefined, refilter?: (() => Promise<RowFilterScope>) | undefined, backpressure?: {
|
|
1716
|
+
readonly maxBufferedBytes: number;
|
|
1717
|
+
readonly overrunAfterMs: number;
|
|
1718
|
+
readonly oversizedEventBytes: number;
|
|
1719
|
+
}, resume?: {
|
|
1720
|
+
readonly input: unknown;
|
|
1721
|
+
readonly fromRevision?: number;
|
|
1722
|
+
}) => Stream.Stream<SubscriptionEvent<ReadonlyArray<Row>>, never, never>;
|
|
1627
1723
|
|
|
1628
1724
|
export declare interface BrandedScheduleDefinition extends ScheduleDefinition {
|
|
1629
1725
|
readonly [SCHEDULE_BRAND]: true;
|
|
@@ -1760,6 +1856,8 @@ export declare interface CandidateShape {
|
|
|
1760
1856
|
readonly windowed?: boolean;
|
|
1761
1857
|
}
|
|
1762
1858
|
|
|
1859
|
+
export declare const canonicalInputKey: (input: unknown) => string;
|
|
1860
|
+
|
|
1763
1861
|
/* Excluded from this release type: canonicalize */
|
|
1764
1862
|
|
|
1765
1863
|
/**
|
|
@@ -2542,6 +2640,8 @@ export declare const counter: (name: string, description?: string) => Metric.Met
|
|
|
2542
2640
|
*/
|
|
2543
2641
|
export declare const countRunningWorkflows: (store: DataStore) => Promise<number>;
|
|
2544
2642
|
|
|
2643
|
+
export declare const crdtCompactMaxBytes: () => number;
|
|
2644
|
+
|
|
2545
2645
|
/**
|
|
2546
2646
|
* Every firing instant of `def` in `(from, to]`, oldest first, bounded by
|
|
2547
2647
|
* `cap + 1` entries.
|
|
@@ -2819,6 +2919,8 @@ export declare const DEFAULT_CLAIM_BUCKET_MS = 60000;
|
|
|
2819
2919
|
|
|
2820
2920
|
export declare const DEFAULT_COMPRESSION_MIN_BYTES = 1024;
|
|
2821
2921
|
|
|
2922
|
+
export declare const DEFAULT_CRDT_COMPACT_MAX_BYTES: number;
|
|
2923
|
+
|
|
2822
2924
|
/**
|
|
2823
2925
|
* How many subscribers one change event is delivered to CONCURRENTLY.
|
|
2824
2926
|
*
|
|
@@ -2857,6 +2959,10 @@ export declare const DEFAULT_RAW_READ_TRACKING_LIMIT = 32;
|
|
|
2857
2959
|
|
|
2858
2960
|
export declare const DEFAULT_REFRESH_SKEW_MS = 60000;
|
|
2859
2961
|
|
|
2962
|
+
export declare const DEFAULT_RESUME_MAX_DELTAS = 256;
|
|
2963
|
+
|
|
2964
|
+
export declare const DEFAULT_RESUME_WINDOW_MS = 60000;
|
|
2965
|
+
|
|
2860
2966
|
/**
|
|
2861
2967
|
* Retry policy applied to `load` when a filter does not specify one: three
|
|
2862
2968
|
* attempts total (the initial call plus two retries), backing off exponentially
|
|
@@ -2869,6 +2975,14 @@ export declare const DEFAULT_REFRESH_SKEW_MS = 60000;
|
|
|
2869
2975
|
*/
|
|
2870
2976
|
export declare const DEFAULT_ROW_FILTER_RETRY: Schedule.Schedule<unknown, unknown>;
|
|
2871
2977
|
|
|
2978
|
+
/** Defaults, overridable via `app.config.ts` `reactive.socket.*` (+ env) —
|
|
2979
|
+
* resolved by the boot paths' tunables resolver. */
|
|
2980
|
+
export declare const DEFAULT_SOCKET_MAX_BUFFERED_BYTES = 1048576;
|
|
2981
|
+
|
|
2982
|
+
export declare const DEFAULT_SOCKET_OVERRUN_AFTER_MS = 10000;
|
|
2983
|
+
|
|
2984
|
+
export declare const DEFAULT_SOCKET_OVERSIZED_EVENT_BYTES = 262144;
|
|
2985
|
+
|
|
2872
2986
|
/**
|
|
2873
2987
|
* The message of an UNDECLARED throw, bounded, with nothing else attached.
|
|
2874
2988
|
*
|
|
@@ -3074,6 +3188,17 @@ export declare const deliveredRowCount: (value: unknown) => number;
|
|
|
3074
3188
|
*/
|
|
3075
3189
|
export declare const deriveKey: (passphrase: string) => Buffer;
|
|
3076
3190
|
|
|
3191
|
+
/**
|
|
3192
|
+
* Detach a live subscription for possible resume. The sink is redirected to
|
|
3193
|
+
* ring-recording only; after the window the subscription is truly
|
|
3194
|
+
* unsubscribed. If an entry already sits under this identity (an older
|
|
3195
|
+
* incarnation), it is expired first — one identity, one detached entry.
|
|
3196
|
+
*/
|
|
3197
|
+
export declare const detachForResume: (identity: ResumeIdentity, handle: {
|
|
3198
|
+
readonly sink: ResumeSink;
|
|
3199
|
+
readonly unsubscribe: () => void;
|
|
3200
|
+
}, tunables?: ResumeTunables, now?: () => number) => void;
|
|
3201
|
+
|
|
3077
3202
|
export { DialectReplicationAdapter }
|
|
3078
3203
|
|
|
3079
3204
|
/** Field-level diff for one change. Insert → every field `undefined→value`;
|
|
@@ -3180,7 +3305,12 @@ export declare class Dispatcher {
|
|
|
3180
3305
|
/** Re-run the query's `guards:` before every delivery — see
|
|
3181
3306
|
* `ActiveSubscription.reauthorize`. Omitted for unguarded queries. */
|
|
3182
3307
|
reauthorize?: () => Promise<unknown>,
|
|
3183
|
-
/** Re-resolve row visibility per delivery — see `ActiveSubscription.refilter`.
|
|
3308
|
+
/** Re-resolve row visibility per delivery — see `ActiveSubscription.refilter`.
|
|
3309
|
+
*
|
|
3310
|
+
* Optional ONLY in the sense that an app with no registered row filter has
|
|
3311
|
+
* nothing to resolve; it is not the caller's choice. Omitting it while a
|
|
3312
|
+
* filter IS registered throws below, because the read would then ignore the
|
|
3313
|
+
* filter entirely. Build it with `makeDefaultRefilter(subject)`. */
|
|
3184
3314
|
refilter?: () => Promise<RowFilterScope>): Promise<() => void>;
|
|
3185
3315
|
/**
|
|
3186
3316
|
* Tear a subscription down because it can no longer be served CORRECTLY
|
|
@@ -3254,6 +3384,10 @@ export declare class Dispatcher {
|
|
|
3254
3384
|
|
|
3255
3385
|
export declare interface DispatcherDependencies {
|
|
3256
3386
|
readonly store: DataStore;
|
|
3387
|
+
/** CRDT columns per table (schemaRegistry.crdtColumns). Feeds the
|
|
3388
|
+
* downstream lane: crdt cells diff as incremental mergeCells ops.
|
|
3389
|
+
* Absent → no crdt tables (tests, embedders) — plain full-value diffs. */
|
|
3390
|
+
readonly crdtColumnsOf?: (table: string) => ReadonlySet<string>;
|
|
3257
3391
|
/** Optional sink for per-delivery timing. `voltro dev` wires this into
|
|
3258
3392
|
* the trace buffer so the dashboards show each data transfer's latency.
|
|
3259
3393
|
* No-op when absent (tests, embedders that don't trace). */
|
|
@@ -3489,6 +3623,8 @@ export declare const evaluateTouchedRules: (params: {
|
|
|
3489
3623
|
readonly subject: unknown;
|
|
3490
3624
|
}) => Promise<void>;
|
|
3491
3625
|
|
|
3626
|
+
declare type Event_2 = SubscriptionEvent<ReadonlyArray<Row>>;
|
|
3627
|
+
|
|
3492
3628
|
/**
|
|
3493
3629
|
* How many deliveries one client may fall behind before the oldest are dropped.
|
|
3494
3630
|
*
|
|
@@ -4411,6 +4547,14 @@ export declare interface FluentStore extends Omit<MutationStore, 'update' | 'del
|
|
|
4411
4547
|
* await ctx.store.links('post_tags', { postId: post.id }).set(tagIds)
|
|
4412
4548
|
*/
|
|
4413
4549
|
links(junctionTable: string, anchor: Readonly<Record<string, string>>): JunctionLinks;
|
|
4550
|
+
/**
|
|
4551
|
+
* `links(...)` with the anchor COLUMN derived from the anchored TABLE: the
|
|
4552
|
+
* junction's reference column that points at `anchorTable` becomes the
|
|
4553
|
+
* source. Exactly one column may qualify — a self-junction (both columns
|
|
4554
|
+
* referencing the same table) is refused with the fix, never guessed.
|
|
4555
|
+
* This is what a mutation target's declared `relations:` resolves through.
|
|
4556
|
+
*/
|
|
4557
|
+
relationLinks(junctionTable: string, anchorTable: string, anchorId: string): JunctionLinks;
|
|
4414
4558
|
/**
|
|
4415
4559
|
* Execute a query descriptor and return the matching rows — TYPED.
|
|
4416
4560
|
*
|
|
@@ -5417,6 +5561,25 @@ export declare const makeCoordinatedScheduler: (deps: CoordinatedScheduleDeps) =
|
|
|
5417
5561
|
*/
|
|
5418
5562
|
export declare const makeDataLoader: (deps: LoaderDeps) => DataLoader;
|
|
5419
5563
|
|
|
5564
|
+
/**
|
|
5565
|
+
* The per-delivery refilter EVERY subscribing transport must hand the
|
|
5566
|
+
* dispatcher — the one that re-resolves this subject's visibility before each
|
|
5567
|
+
* delivery instead of freezing it at subscribe.
|
|
5568
|
+
*
|
|
5569
|
+
* It lives here, beside the registration it reads, because it was a private
|
|
5570
|
+
* helper of the WebSocket entrypoint and the transports that did not import it
|
|
5571
|
+
* did not filter at all. `dispatcher.subscribe` resolves visibility itself and
|
|
5572
|
+
* treats an absent refilter as "this app has no filter", so a transport that
|
|
5573
|
+
* simply omitted the argument read the UNFILTERED descriptor — on the initial
|
|
5574
|
+
* snapshot and on every delta. The SSE and gRPC projections omitted it.
|
|
5575
|
+
*
|
|
5576
|
+
* Returning `undefined` when no filter is registered is the fast path, not an
|
|
5577
|
+
* opt-out: it is what keeps a filterless app free of a per-delivery await, and
|
|
5578
|
+
* `dispatcher.subscribe` refuses the ambiguous case (nothing passed WHILE a
|
|
5579
|
+
* filter is registered) rather than reading it as this one.
|
|
5580
|
+
*/
|
|
5581
|
+
export declare const makeDefaultRefilter: (subject: Subject, onError?: (error: unknown) => void) => (() => Promise<RowFilterScope>) | undefined;
|
|
5582
|
+
|
|
5420
5583
|
/** `__voltro.connections.disconnect` — forget the caller's credential. */
|
|
5421
5584
|
export declare const makeDisconnectConnectionExecutor: (deps: ConnectionBuiltinDeps) => (input: {
|
|
5422
5585
|
readonly connectionId: string;
|
|
@@ -5626,6 +5789,8 @@ export declare const makeSubmitTokenExecutor: (deps: ConnectionBuiltinDeps) => (
|
|
|
5626
5789
|
readonly ok: boolean;
|
|
5627
5790
|
}>;
|
|
5628
5791
|
|
|
5792
|
+
export declare const makeSubscriptionOutbox: (options: SubscriptionBackpressureOptions) => SubscriptionOutbox;
|
|
5793
|
+
|
|
5629
5794
|
/**
|
|
5630
5795
|
* The factory the serve entrypoints inject into `makeMutationRunner`'s
|
|
5631
5796
|
* `undoCapture` dep. Collects changes from the wrapped tx; `persist` writes ONE
|
|
@@ -5633,7 +5798,7 @@ export declare const makeSubmitTokenExecutor: (deps: ConnectionBuiltinDeps) => (
|
|
|
5633
5798
|
* mutation's transaction. The changes are JSON-serialized into a TEXT column —
|
|
5634
5799
|
* dialect-uniform, no json codec on the path.
|
|
5635
5800
|
*/
|
|
5636
|
-
export declare const makeUndoCapture: (rawTx: DataStore) => {
|
|
5801
|
+
export declare const makeUndoCapture: (rawTx: DataStore, crdtColumnsOf?: (table: string) => ReadonlySet<string>) => {
|
|
5637
5802
|
tx: DataStore;
|
|
5638
5803
|
persist: (store: unknown, meta: {
|
|
5639
5804
|
readonly tag: string;
|
|
@@ -5922,8 +6087,10 @@ export declare interface MutationLike {
|
|
|
5922
6087
|
readonly requiresApproval?: AnyApprovalPolicy | undefined;
|
|
5923
6088
|
readonly target?: {
|
|
5924
6089
|
readonly table: string;
|
|
6090
|
+
readonly relations?: Readonly<Record<string, string>> | undefined;
|
|
5925
6091
|
} | ReadonlyArray<{
|
|
5926
6092
|
readonly table: string;
|
|
6093
|
+
readonly relations?: Readonly<Record<string, string>> | undefined;
|
|
5927
6094
|
}> | undefined;
|
|
5928
6095
|
};
|
|
5929
6096
|
executor(input: unknown, ctx: unknown): unknown;
|
|
@@ -6629,6 +6796,16 @@ export declare const publishEvent: <Name extends string, Key extends Schema.Sche
|
|
|
6629
6796
|
readonly deferred: boolean;
|
|
6630
6797
|
}, EventPublishError>;
|
|
6631
6798
|
|
|
6799
|
+
/**
|
|
6800
|
+
* A Layer that publishes whatever tracer is in scope when it is built.
|
|
6801
|
+
*
|
|
6802
|
+
* Provided immediately INSIDE the tracer layer at boot, so it captures the
|
|
6803
|
+
* configured tracer rather than the default one. With tracing off it captures
|
|
6804
|
+
* Effect's no-op tracer, which is the correct answer — detached work then
|
|
6805
|
+
* behaves exactly as in-request work does.
|
|
6806
|
+
*/
|
|
6807
|
+
export declare const publishServerTracerLayer: Layer.Layer<never, never, never>;
|
|
6808
|
+
|
|
6632
6809
|
/**
|
|
6633
6810
|
* The two scopes, composed once, for every path that finalises a descriptor.
|
|
6634
6811
|
*
|
|
@@ -6690,9 +6867,23 @@ export declare interface QueryProducerDeps<D> {
|
|
|
6690
6867
|
}
|
|
6691
6868
|
|
|
6692
6869
|
export declare interface QuerySubscriberDeps<D> extends QueryProducerDeps<D> {
|
|
6693
|
-
/**
|
|
6694
|
-
|
|
6695
|
-
|
|
6870
|
+
/**
|
|
6871
|
+
* Open a dispatcher subscription for a finalized descriptor.
|
|
6872
|
+
*
|
|
6873
|
+
* `reauthorize` and `refilter` are REQUIRED parameters of this callback, not
|
|
6874
|
+
* optional extras, and the requirement is the guard: they used to be
|
|
6875
|
+
* `dispatcher.subscribe`'s trailing optional arguments, this callback simply
|
|
6876
|
+
* did not pass them, and the dispatcher reads their absence as "this query is
|
|
6877
|
+
* unguarded and this app has no row filter". So the SSE and gRPC projections
|
|
6878
|
+
* re-ran no guard and read the UNFILTERED descriptor — initial snapshot and
|
|
6879
|
+
* every delta — while the WebSocket path (which goes through
|
|
6880
|
+
* `bindSubscription`) did both. Threading them through the signature makes the
|
|
6881
|
+
* next transport unable to repeat that by omission.
|
|
6882
|
+
*/
|
|
6883
|
+
readonly subscribeDescriptor: (descriptor: D, emit: (event: unknown) => void, context: ServeRequestContext, reauthorize: (() => Promise<unknown>) | undefined, refilter: (() => Promise<RowFilterScope>) | undefined) => Promise<() => void>;
|
|
6884
|
+
/** Open a dispatcher subscription for a COMPUTED query (re-runs on source change).
|
|
6885
|
+
* A computed query re-runs its HANDLER per change, so guards and the row
|
|
6886
|
+
* filter are re-applied by that re-run — it needs no separate pair. */
|
|
6696
6887
|
readonly subscribeComputed: (computed: ComputedQuery, emit: (event: unknown) => void, context: ServeRequestContext) => Promise<() => void>;
|
|
6697
6888
|
}
|
|
6698
6889
|
|
|
@@ -6869,6 +7060,25 @@ export declare interface ReactiveConfigInput {
|
|
|
6869
7060
|
* warning to name a later one.
|
|
6870
7061
|
*/
|
|
6871
7062
|
readonly rawReadTrackingLimit?: number;
|
|
7063
|
+
/**
|
|
7064
|
+
* Subscription socket backpressure (plan 01 P1). A slow or dead consumer no
|
|
7065
|
+
* longer retains every event: updates COALESCE onto the newest state while
|
|
7066
|
+
* the socket is blocked, and a consumer persistently over the buffer
|
|
7067
|
+
* threshold is closed with a typed `SubscriptionOverrun` (it re-subscribes
|
|
7068
|
+
* for a fresh snapshot). Resolved by the CLI's `reactiveTunables.ts`; env
|
|
7069
|
+
* overrides win: `VOLTRO_REACTIVE_MAX_BUFFERED_BYTES` /
|
|
7070
|
+
* `VOLTRO_REACTIVE_OVERRUN_AFTER_MS` / `VOLTRO_REACTIVE_OVERSIZED_EVENT_BYTES`.
|
|
7071
|
+
*/
|
|
7072
|
+
readonly socket?: {
|
|
7073
|
+
/** Estimated pending bytes per subscription above which a persistently
|
|
7074
|
+
* blocked consumer is overrun-closed. Default 1 MiB. */
|
|
7075
|
+
readonly maxBufferedBytes?: number;
|
|
7076
|
+
/** How long the pending state must stay over the threshold before the
|
|
7077
|
+
* terminal close. Default 10_000 ms. */
|
|
7078
|
+
readonly overrunAfterMs?: number;
|
|
7079
|
+
/** Per-event WARN threshold (telemetry, NOT a cap). Default 256 KiB. */
|
|
7080
|
+
readonly oversizedEventBytes?: number;
|
|
7081
|
+
};
|
|
6872
7082
|
}
|
|
6873
7083
|
|
|
6874
7084
|
export declare interface ReactiveEnv {
|
|
@@ -6884,6 +7094,16 @@ export declare type ReactiveReturn<D extends ExecutorDescriptor> = D extends {
|
|
|
6884
7094
|
readonly descriptor: QueryDescriptor;
|
|
6885
7095
|
} : never;
|
|
6886
7096
|
|
|
7097
|
+
export declare interface ReactiveSocketTunables {
|
|
7098
|
+
readonly maxBufferedBytes: number;
|
|
7099
|
+
readonly overrunAfterMs: number;
|
|
7100
|
+
readonly oversizedEventBytes: number;
|
|
7101
|
+
}
|
|
7102
|
+
|
|
7103
|
+
/** The resolved tunables, or the defaults when no boot path has set any
|
|
7104
|
+
* (unit tests, a bare library use). */
|
|
7105
|
+
export declare const reactiveSocketTunables: () => ReactiveSocketTunables;
|
|
7106
|
+
|
|
6887
7107
|
export declare interface ReadClassification {
|
|
6888
7108
|
/** Tables whose ROWS can reach the caller: the queried table and its joins. */
|
|
6889
7109
|
readonly composed: ReadonlySet<string>;
|
|
@@ -6970,6 +7190,8 @@ export declare interface RebacSubject {
|
|
|
6970
7190
|
readonly scopes?: ReadonlyArray<string>;
|
|
6971
7191
|
}
|
|
6972
7192
|
|
|
7193
|
+
export declare const recordCoalesced: (label: string, collapsed: number) => void;
|
|
7194
|
+
|
|
6973
7195
|
export declare const recordCredentialExpiry: (clientId: number, exp: number | undefined) => void;
|
|
6974
7196
|
|
|
6975
7197
|
/** What the framework emit-seams (servePipeline / rpcServer / plugin wrappers)
|
|
@@ -6996,6 +7218,15 @@ export declare const recordEventPublished: (event: string) => void;
|
|
|
6996
7218
|
/** Subscriber attached (+1) or detached (-1). */
|
|
6997
7219
|
export declare const recordEventSubscribers: (event: string, delta: number) => void;
|
|
6998
7220
|
|
|
7221
|
+
/**
|
|
7222
|
+
* Record one emitted event into the identity's ring. Snapshots RESET the ring
|
|
7223
|
+
* (the snapshot's revision becomes the new replay base — a client holding an
|
|
7224
|
+
* older revision is outside the chain); deltas append. An error event drops
|
|
7225
|
+
* the ring: whatever state the client holds, the safe answer after an error
|
|
7226
|
+
* is a fresh snapshot.
|
|
7227
|
+
*/
|
|
7228
|
+
export declare const recordForResume: (identity: ResumeIdentity, event: SubscriptionEvent<unknown>, now?: number, tunables?: ResumeTunables) => void;
|
|
7229
|
+
|
|
6999
7230
|
/**
|
|
7000
7231
|
* A store that notes every read and changes nothing else.
|
|
7001
7232
|
*
|
|
@@ -7006,6 +7237,10 @@ export declare const recordEventSubscribers: (event: string, delta: number) => v
|
|
|
7006
7237
|
*/
|
|
7007
7238
|
export declare const recordingStore: (store: DataStore) => DataStore;
|
|
7008
7239
|
|
|
7240
|
+
export declare const recordOverrun: (label: string) => void;
|
|
7241
|
+
|
|
7242
|
+
export declare const recordOversized: (label: string) => void;
|
|
7243
|
+
|
|
7009
7244
|
/**
|
|
7010
7245
|
* Record a raw read, opening a scope for the rest of this execution context if
|
|
7011
7246
|
* none is open yet.
|
|
@@ -7296,6 +7531,13 @@ export declare interface RegistryTableLike {
|
|
|
7296
7531
|
* request was. */
|
|
7297
7532
|
export declare const rehydrateGuards: (serialized: ReadonlyArray<SerializedGuard>) => ReadonlyArray<AnyGuardSpec>;
|
|
7298
7533
|
|
|
7534
|
+
/** The store slice `applyDeclaredRelations` needs. */
|
|
7535
|
+
declare interface RelationLinksStore {
|
|
7536
|
+
relationLinks(junctionTable: string, anchorTable: string, anchorId: string): {
|
|
7537
|
+
set(targetIds: ReadonlyArray<string>): Promise<unknown>;
|
|
7538
|
+
};
|
|
7539
|
+
}
|
|
7540
|
+
|
|
7299
7541
|
/** A relationship tuple — `subjectId` has `relation` on `<resourceType>:<resourceId>`.
|
|
7300
7542
|
* In practice these are rows in a relation table; the engine takes them as data. */
|
|
7301
7543
|
export declare interface RelationTuple {
|
|
@@ -7481,15 +7723,24 @@ export declare const resetComputedQueryCacheWarnings: () => void;
|
|
|
7481
7723
|
/** Test/dev-only — clear ALL per-connection state. Don't call from app code. */
|
|
7482
7724
|
export declare const _resetConnectionCredentialsForTest: () => void;
|
|
7483
7725
|
|
|
7726
|
+
/** Test seam — expire everything immediately. */
|
|
7727
|
+
export declare const resetDetachedForTest: () => void;
|
|
7728
|
+
|
|
7484
7729
|
/** Test seams for the tag-cache guard — the cache is module-private otherwise. */
|
|
7485
7730
|
export declare const resetEventMetricTagCacheForTests: () => void;
|
|
7486
7731
|
|
|
7487
7732
|
/** Drop everything recorded. For tests; not called by the runtime. */
|
|
7488
7733
|
export declare const resetObservedGraph: () => void;
|
|
7489
7734
|
|
|
7735
|
+
/** Test seam. */
|
|
7736
|
+
export declare const resetResumeRingsForTest: () => void;
|
|
7737
|
+
|
|
7490
7738
|
/** Reset to the env default (tests). */
|
|
7491
7739
|
export declare const resetSecretsBackend: () => void;
|
|
7492
7740
|
|
|
7741
|
+
/** Test seam. */
|
|
7742
|
+
export declare const resetSubscriptionSocketMetrics: () => void;
|
|
7743
|
+
|
|
7493
7744
|
/**
|
|
7494
7745
|
* The client address to rate-limit, geo-block and audit by.
|
|
7495
7746
|
*
|
|
@@ -7808,6 +8059,46 @@ export declare const restrictingReadsEffect: <A, E, R>(effect: Effect.Effect<A,
|
|
|
7808
8059
|
/** The full ordered list of result variants for a definition, holdout last. */
|
|
7809
8060
|
export declare const resultVariantNames: (def: ExperimentDefinition) => ReadonlyArray<string>;
|
|
7810
8061
|
|
|
8062
|
+
export declare type ResumeAnswer =
|
|
8063
|
+
/** The client's revision chains: replay these deltas in order. */
|
|
8064
|
+
{
|
|
8065
|
+
readonly kind: 'deltas';
|
|
8066
|
+
readonly deltas: ReadonlyArray<RingDelta>;
|
|
8067
|
+
}
|
|
8068
|
+
/** Outside the window / unknown identity / gap — send a snapshot,
|
|
8069
|
+
* `resumed: false`. */
|
|
8070
|
+
| {
|
|
8071
|
+
readonly kind: 'snapshot';
|
|
8072
|
+
};
|
|
8073
|
+
|
|
8074
|
+
/**
|
|
8075
|
+
* The identity a ring is recorded under — and the identity a resume must
|
|
8076
|
+
* present to read it back. `subjectId`/`tenantId` are part of the KEY, so a
|
|
8077
|
+
* login/logout/tenant-switch between disconnect and resume simply misses the
|
|
8078
|
+
* ring and falls back to a snapshot (`resumed: false`) — the blank-on-auth
|
|
8079
|
+
* doctrine, enforced structurally rather than checked.
|
|
8080
|
+
*/
|
|
8081
|
+
export declare interface ResumeIdentity {
|
|
8082
|
+
readonly label: string;
|
|
8083
|
+
/** Canonicalised query input (JSON with sorted keys). */
|
|
8084
|
+
readonly inputKey: string;
|
|
8085
|
+
readonly subjectId: string;
|
|
8086
|
+
readonly tenantId: string;
|
|
8087
|
+
}
|
|
8088
|
+
|
|
8089
|
+
export declare const resumeKeyOf: (identity: ResumeIdentity) => string;
|
|
8090
|
+
|
|
8091
|
+
export declare interface ResumeSink {
|
|
8092
|
+
current: (event: SubscriptionEvent<unknown>) => void;
|
|
8093
|
+
}
|
|
8094
|
+
|
|
8095
|
+
export declare interface ResumeTunables {
|
|
8096
|
+
readonly windowMs: number;
|
|
8097
|
+
readonly maxDeltas: number;
|
|
8098
|
+
}
|
|
8099
|
+
|
|
8100
|
+
export declare const resumeTunables: () => ResumeTunables;
|
|
8101
|
+
|
|
7811
8102
|
export { RetentionConflict }
|
|
7812
8103
|
|
|
7813
8104
|
export { RetentionSource }
|
|
@@ -7882,6 +8173,12 @@ export declare const revokedIds: (before: ReadonlyArray<{
|
|
|
7882
8173
|
readonly id: string;
|
|
7883
8174
|
}>) => ReadonlyArray<string>;
|
|
7884
8175
|
|
|
8176
|
+
declare interface RingDelta {
|
|
8177
|
+
readonly revision: number;
|
|
8178
|
+
readonly emittedAt: number;
|
|
8179
|
+
readonly patch: RowPatch;
|
|
8180
|
+
}
|
|
8181
|
+
|
|
7885
8182
|
/**
|
|
7886
8183
|
* Live traffic the router fronts — read by idle detection (the orchestrator
|
|
7887
8184
|
* can't see the app's HTTP/WS load directly when it's scaled to zero, but
|
|
@@ -7974,8 +8271,71 @@ export declare interface RowFilter<Ctx = unknown> {
|
|
|
7974
8271
|
* the handler still carries the check the filter was meant to replace.
|
|
7975
8272
|
*/
|
|
7976
8273
|
readonly onLoadError?: 'fail' | 'deny';
|
|
8274
|
+
/**
|
|
8275
|
+
* The ONLY tables this filter may narrow. Optional; declaring it buys
|
|
8276
|
+
* delta-resume back for every subscription whose source is not in the set.
|
|
8277
|
+
*
|
|
8278
|
+
* WHY IT EXISTS. A subscription whose row set is re-resolved per delivery
|
|
8279
|
+
* must not replay deltas on reconnect — the answer can change while the
|
|
8280
|
+
* socket is down (a membership ends) and a wrong replay leaks rows. But the
|
|
8281
|
+
* question the framework could ask was only "is a filter registered at
|
|
8282
|
+
* all?", so ONE registration disabled delta-resume for the whole process. A
|
|
8283
|
+
* deployment measured a filter narrowing 4 tables costing the feature on all
|
|
8284
|
+
* 173 of their query descriptors, 55 of whose source tables it never touches.
|
|
8285
|
+
*
|
|
8286
|
+
* WHY A DECLARATION RATHER THAN A PROBE. Resolving the scope at subscribe
|
|
8287
|
+
* and treating `predicate(ctx, source) === undefined` as safe is cheaper and
|
|
8288
|
+
* unsound: the predicate is a function of freshly loaded context, so a table
|
|
8289
|
+
* it does not narrow now may be narrowed on the next delivery — which is the
|
|
8290
|
+
* entire reason the refilter is per-delivery. A static list is a promise
|
|
8291
|
+
* about every future resolution.
|
|
8292
|
+
*
|
|
8293
|
+
* IT IS VERIFIED, not trusted. Returning a predicate for a table outside
|
|
8294
|
+
* this set raises {@link RowFilterDeclarationViolated} at the read that did
|
|
8295
|
+
* it — the request fails and a subscription is revoked, rather than serving
|
|
8296
|
+
* rows under a resume grant the declaration no longer earns. An undeclared
|
|
8297
|
+
* filter (this field absent) keeps the conservative behaviour: no resume
|
|
8298
|
+
* anywhere, no verification.
|
|
8299
|
+
*
|
|
8300
|
+
* setRowFilter({
|
|
8301
|
+
* load, predicate,
|
|
8302
|
+
* tables: ['bookmarks', 'recentSearches', 'todoSchedules', 'todoTags'],
|
|
8303
|
+
* })
|
|
8304
|
+
*/
|
|
8305
|
+
readonly tables?: ReadonlyArray<string>;
|
|
8306
|
+
}
|
|
8307
|
+
|
|
8308
|
+
/**
|
|
8309
|
+
* A row filter narrowed a table its `tables:` declaration does not list.
|
|
8310
|
+
*
|
|
8311
|
+
* Fail-closed by construction: the declaration is what the framework hands
|
|
8312
|
+
* delta-resume, so a filter that quietly narrows beyond it would have rings
|
|
8313
|
+
* recorded for a table whose visibility CAN change — the leak the exclusion
|
|
8314
|
+
* exists to prevent. Raised at the read that violated it, naming the table and
|
|
8315
|
+
* the fix, rather than degrading to an unfiltered or empty answer.
|
|
8316
|
+
*/
|
|
8317
|
+
export declare class RowFilterDeclarationViolated extends RowFilterDeclarationViolated_base {
|
|
7977
8318
|
}
|
|
7978
8319
|
|
|
8320
|
+
declare const RowFilterDeclarationViolated_base: Schema.TaggedErrorClass<RowFilterDeclarationViolated, "RowFilterDeclarationViolated", {
|
|
8321
|
+
readonly _tag: Schema.tag<"RowFilterDeclarationViolated">;
|
|
8322
|
+
} & {
|
|
8323
|
+
/** The table the predicate narrowed. */
|
|
8324
|
+
table: typeof Schema.String;
|
|
8325
|
+
/** The declared set, for the message. */
|
|
8326
|
+
declared: Schema.Array$<typeof Schema.String>;
|
|
8327
|
+
}>;
|
|
8328
|
+
|
|
8329
|
+
/**
|
|
8330
|
+
* Could the registered filter narrow ANY of `tables`?
|
|
8331
|
+
*
|
|
8332
|
+
* The question delta-resume asks before recording a ring. Answers `true`
|
|
8333
|
+
* whenever it cannot prove otherwise — no declaration means the framework does
|
|
8334
|
+
* not know which tables the predicate may reach, and "unknown" must read as
|
|
8335
|
+
* "yes" or the exclusion stops protecting anything.
|
|
8336
|
+
*/
|
|
8337
|
+
export declare const rowFilterMayNarrow: (tables: ReadonlyArray<string>) => boolean;
|
|
8338
|
+
|
|
7979
8339
|
/**
|
|
7980
8340
|
* Is a row filter registered right now — asked by a path about to serve an
|
|
7981
8341
|
* UNFILTERED read.
|
|
@@ -8097,9 +8457,16 @@ export declare interface RpcServerOptions<Rpcs extends Rpc.Any> {
|
|
|
8097
8457
|
* http app, so it fires on EVERY request — inspect, webhooks, AND the
|
|
8098
8458
|
* rpc websocket upgrade — before auth/routing. A non-null return
|
|
8099
8459
|
* short-circuits with that response (e.g. a rate-limit 429 / geo-block
|
|
8100
|
-
* 451). Absent → no wrapper.
|
|
8101
|
-
*
|
|
8102
|
-
*
|
|
8460
|
+
* 451). Absent → no wrapper.
|
|
8461
|
+
*
|
|
8462
|
+
* FAIL-CLOSED: a throwing interceptor answers 500 and logs, it does NOT
|
|
8463
|
+
* let the request through. The composed chain is where security gates
|
|
8464
|
+
* live (an IP shield, a tenant fence — anything a plugin mounts
|
|
8465
|
+
* pre-auth), and a gate that crashes open has silently stopped
|
|
8466
|
+
* guarding while still reading as installed. An interceptor that must
|
|
8467
|
+
* not take the listener down with its own dependency owns that
|
|
8468
|
+
* decision itself — plugin-ratelimit's httpShield catches its store
|
|
8469
|
+
* failure and degrades to "unlimited, loudly" rather than throwing.
|
|
8103
8470
|
*/
|
|
8104
8471
|
readonly pluginHttpInterceptor?: HttpRequestInterceptor;
|
|
8105
8472
|
/**
|
|
@@ -8968,6 +9335,12 @@ export declare interface ServeRequestContext {
|
|
|
8968
9335
|
readonly subject: unknown;
|
|
8969
9336
|
readonly traceId: string;
|
|
8970
9337
|
readonly spanId?: string;
|
|
9338
|
+
/**
|
|
9339
|
+
* Caller-side cancellation (the gRPC deadline / client-cancel path).
|
|
9340
|
+
* Honoured at the ONE place the executor effect runs to a promise, so an
|
|
9341
|
+
* exceeded deadline INTERRUPTS the server work — not merely the response.
|
|
9342
|
+
*/
|
|
9343
|
+
readonly signal?: AbortSignal;
|
|
8971
9344
|
/**
|
|
8972
9345
|
* Row-level visibility for this request, resolved by `withRowFilter` and read
|
|
8973
9346
|
* by the context builder when it wraps the store.
|
|
@@ -9025,13 +9398,26 @@ export declare type ServeRpcInterceptor = (base: Effect.Effect<unknown, unknown,
|
|
|
9025
9398
|
readonly target?: ReadonlyArray<string>;
|
|
9026
9399
|
}) => Effect.Effect<unknown, unknown, never>;
|
|
9027
9400
|
|
|
9401
|
+
/** The published tracer, or `undefined` when tracing is off / no server booted. */
|
|
9402
|
+
export declare const serverTracer: () => Tracer.Tracer | undefined;
|
|
9403
|
+
|
|
9404
|
+
export declare const setBufferedBytes: (label: string, bytes: number) => void;
|
|
9405
|
+
|
|
9028
9406
|
/** Register the process-wide connection resolver (or clear with `undefined`).
|
|
9029
9407
|
* Called by the CLI at boot; tests call it directly. */
|
|
9030
9408
|
export declare const setConnectionResolver: (resolver: ConnectionResolver | undefined) => void;
|
|
9031
9409
|
|
|
9410
|
+
/** Boot/test override — the slot `wireCrdtTunables` writes. `null` restores
|
|
9411
|
+
* env/default resolution. */
|
|
9412
|
+
export declare const setCrdtCompactMaxBytes: (maxBytes: number | null) => void;
|
|
9413
|
+
|
|
9032
9414
|
/** Register the field cipher (or clear with `undefined`). */
|
|
9033
9415
|
export declare const setFieldCipher: (cipher: FieldCipher | undefined) => void;
|
|
9034
9416
|
|
|
9417
|
+
export declare const setReactiveSocketTunables: (tunables: ReactiveSocketTunables | null) => void;
|
|
9418
|
+
|
|
9419
|
+
export declare const setResumeTunables: (tunables: ResumeTunables | null) => void;
|
|
9420
|
+
|
|
9035
9421
|
/**
|
|
9036
9422
|
* Boot-path wiring. `null` clears (shutdown). Registering `null` vs never
|
|
9037
9423
|
* registering are deliberately the SAME state — a call before boot wiring and
|
|
@@ -9048,6 +9434,9 @@ export declare const setRowFilter: <Ctx>(filter: RowFilter<Ctx> | undefined) =>
|
|
|
9048
9434
|
/** Install the process-wide secrets backend (called once at boot). */
|
|
9049
9435
|
export declare const setSecretsBackend: (backend: SecretsBackend) => void;
|
|
9050
9436
|
|
|
9437
|
+
/** Publish the server's tracer. Called once, from inside the provided scope. */
|
|
9438
|
+
export declare const setServerTracer: (tracer: Tracer.Tracer | undefined) => void;
|
|
9439
|
+
|
|
9051
9440
|
/** Install the finding sink. `undefined` turns recording back off. */
|
|
9052
9441
|
export declare const setSourceGapSink: (fn: ((finding: string) => void) | undefined) => void;
|
|
9053
9442
|
|
|
@@ -9160,7 +9549,10 @@ export declare interface SnapshotCacheBinding {
|
|
|
9160
9549
|
readonly swrMs: number | undefined;
|
|
9161
9550
|
}
|
|
9162
9551
|
|
|
9163
|
-
/** Snapshot the whole registry, normalized to `MetricSample[]
|
|
9552
|
+
/** Snapshot the whole registry, normalized to `MetricSample[]` — plus the
|
|
9553
|
+
* socket-backpressure counters (`subscriptionSocketMetrics.ts`), appended
|
|
9554
|
+
* HERE so every reader (Prometheus exporter, inspect Metrics panel) sees
|
|
9555
|
+
* one derivation and the two cannot diverge. */
|
|
9164
9556
|
export declare const snapshotMetrics: Effect.Effect<ReadonlyArray<MetricSample>>;
|
|
9165
9557
|
|
|
9166
9558
|
/** Eager snapshot for sync callers (the inspect endpoint). */
|
|
@@ -9425,6 +9817,22 @@ export declare interface SubscriberDefinition {
|
|
|
9425
9817
|
readonly handler: SubscribeHandler;
|
|
9426
9818
|
}
|
|
9427
9819
|
|
|
9820
|
+
export declare interface SubscriptionBackpressureOptions {
|
|
9821
|
+
/** Estimated pending bytes above which a persistently-blocked consumer is
|
|
9822
|
+
* overrun-closed. `reactive.socket.maxBufferedBytes` / env override. */
|
|
9823
|
+
readonly maxBufferedBytes: number;
|
|
9824
|
+
/** How long the pending state must stay over the threshold (with the pump
|
|
9825
|
+
* blocked) before the terminal close. */
|
|
9826
|
+
readonly overrunAfterMs: number;
|
|
9827
|
+
/** Per-event WARN threshold — telemetry for oversized snapshots/deltas.
|
|
9828
|
+
* Deliberately NOT a cap: measurability is the goal. */
|
|
9829
|
+
readonly oversizedEventBytes: number;
|
|
9830
|
+
/** Query tag for logs + metrics. */
|
|
9831
|
+
readonly label: string;
|
|
9832
|
+
readonly now?: () => number;
|
|
9833
|
+
readonly warn?: (message: string, fields: Record<string, unknown>) => void;
|
|
9834
|
+
}
|
|
9835
|
+
|
|
9428
9836
|
/**
|
|
9429
9837
|
* Timing of ONE subscription delivery (the initial snapshot, or a delta
|
|
9430
9838
|
* pushed on a change). The duration is the real produce→push latency:
|
|
@@ -9460,6 +9868,29 @@ export declare interface SubscriptionDeliveryRecord {
|
|
|
9460
9868
|
readonly rowCount: number;
|
|
9461
9869
|
}
|
|
9462
9870
|
|
|
9871
|
+
export declare interface SubscriptionOutbox {
|
|
9872
|
+
/** SYNC push from the dispatcher's emit callback. */
|
|
9873
|
+
readonly push: (event: Event_2) => void;
|
|
9874
|
+
/** Pump side: resolves with the next event to hand into the stream —
|
|
9875
|
+
* coalesced when more than one push landed since the last take — or null
|
|
9876
|
+
* once the outbox is closed and drained. */
|
|
9877
|
+
readonly take: () => Promise<Event_2 | null>;
|
|
9878
|
+
/** True once the overrun policy fired (the error event has been queued;
|
|
9879
|
+
* the stream ends after it drains). */
|
|
9880
|
+
readonly overrun: () => boolean;
|
|
9881
|
+
readonly close: () => void;
|
|
9882
|
+
}
|
|
9883
|
+
|
|
9884
|
+
/** The wire shape of the terminal overrun error — documented in
|
|
9885
|
+
* wire-protocol.md. The client surfaces it as the entry's `error` and
|
|
9886
|
+
* re-subscribes for a fresh snapshot. */
|
|
9887
|
+
export declare interface SubscriptionOverrunError {
|
|
9888
|
+
readonly _tag: 'SubscriptionOverrun';
|
|
9889
|
+
readonly message: string;
|
|
9890
|
+
readonly bufferedBytes: number;
|
|
9891
|
+
readonly maxBufferedBytes: number;
|
|
9892
|
+
}
|
|
9893
|
+
|
|
9463
9894
|
export declare type SubscriptionRecord = {
|
|
9464
9895
|
readonly id: string;
|
|
9465
9896
|
readonly table: string;
|
|
@@ -9520,6 +9951,35 @@ export declare interface SubscriptionSnapshot {
|
|
|
9520
9951
|
readonly subscriberCount: number;
|
|
9521
9952
|
}
|
|
9522
9953
|
|
|
9954
|
+
/**
|
|
9955
|
+
* The counters as `MetricSample`s — appended by `snapshotMetrics`
|
|
9956
|
+
* (metrics.ts), which is the ONE derivation both the Prometheus exporter and
|
|
9957
|
+
* the inspect Metrics panel read. Same input → the two cannot diverge.
|
|
9958
|
+
*/
|
|
9959
|
+
export declare const subscriptionSocketMetricSamples: () => ReadonlyArray< MetricSample>;
|
|
9960
|
+
|
|
9961
|
+
export declare interface SubscriptionSocketMetricsSnapshot {
|
|
9962
|
+
/** Sum + per-label current pending bytes across live subscriptions. */
|
|
9963
|
+
readonly bufferedBytes: {
|
|
9964
|
+
readonly total: number;
|
|
9965
|
+
readonly byLabel: Readonly<Record<string, number>>;
|
|
9966
|
+
};
|
|
9967
|
+
readonly coalescedTotal: {
|
|
9968
|
+
readonly total: number;
|
|
9969
|
+
readonly byLabel: Readonly<Record<string, number>>;
|
|
9970
|
+
};
|
|
9971
|
+
readonly overrunTotal: {
|
|
9972
|
+
readonly total: number;
|
|
9973
|
+
readonly byLabel: Readonly<Record<string, number>>;
|
|
9974
|
+
};
|
|
9975
|
+
readonly oversizedTotal: {
|
|
9976
|
+
readonly total: number;
|
|
9977
|
+
readonly byLabel: Readonly<Record<string, number>>;
|
|
9978
|
+
};
|
|
9979
|
+
}
|
|
9980
|
+
|
|
9981
|
+
export declare const subscriptionSocketMetricsSnapshot: () => SubscriptionSocketMetricsSnapshot;
|
|
9982
|
+
|
|
9523
9983
|
/** Drop handshake grants past their TTL. Wired into the boot retention sweep;
|
|
9524
9984
|
* a grant is worthless the moment it expires and keeping them turns a hot
|
|
9525
9985
|
* table into an audit liability. */
|
|
@@ -10390,24 +10850,6 @@ export declare const webhookVerificationOf: (handle: unknown) => WebhookVerifica
|
|
|
10390
10850
|
*/
|
|
10391
10851
|
export declare type WhereOp = '=' | '!=' | '<>' | '>' | '>=' | '<' | '<=' | 'in' | 'contains' | 'startsWith' | 'fts';
|
|
10392
10852
|
|
|
10393
|
-
/**
|
|
10394
|
-
* Resolve this request's row-filter scope. A no-op (same object back) when the
|
|
10395
|
-
* app registered no filter, so an app that uses none pays nothing.
|
|
10396
|
-
*
|
|
10397
|
-
* Every runner calls this before building a context. A read path that skipped
|
|
10398
|
-
* it would have no row-level security and would look exactly like one that
|
|
10399
|
-
* does — which is why it lives in the shared spine rather than in each
|
|
10400
|
-
* entrypoint.
|
|
10401
|
-
*
|
|
10402
|
-
* REJECTS with the raw `RowFilterUnavailable` (via `runProvidedEffect`, not
|
|
10403
|
-
* `Effect.runPromise`) when the filter's `onLoadError` is the default `'fail'`
|
|
10404
|
-
* and `load` failed every retry. Raw, so the rpc encoder matches it against the
|
|
10405
|
-
* descriptor's `error:` schema and the client gets the tag instead of an opaque
|
|
10406
|
-
* defect — the same treatment `enforceGuards` gives a `ScopeError`. Proceeding
|
|
10407
|
-
* with an unresolved filter is not an option here: the context builder would
|
|
10408
|
-
* receive `rowFilter: undefined`, which means "this app registered no filter"
|
|
10409
|
-
* and would silently serve the request UNFILTERED.
|
|
10410
|
-
*/
|
|
10411
10853
|
export declare const withRowFilter: <R extends ServeRequestContext>(request: R) => Promise<R>;
|
|
10412
10854
|
|
|
10413
10855
|
/**
|
|
@@ -10432,6 +10874,16 @@ export declare const withRowFilter: <R extends ServeRequestContext>(request: R)
|
|
|
10432
10874
|
*/
|
|
10433
10875
|
export declare const withScopedRequest: <R extends ServeRequestContext, A>(requestContext: R, body: (scoped: R) => A | Effect.Effect<A, unknown, never>) => A | Effect.Effect<A, unknown, never>;
|
|
10434
10876
|
|
|
10877
|
+
/**
|
|
10878
|
+
* Run detached work under the server's tracer, so a span it opens is exported
|
|
10879
|
+
* rather than created and dropped.
|
|
10880
|
+
*
|
|
10881
|
+
* A no-op when nothing is published (a unit test, an embedder, a process with no
|
|
10882
|
+
* rpc server) — never a second tracer, never a throw. The alternative to this
|
|
10883
|
+
* function is not "a different tracer", it is silence.
|
|
10884
|
+
*/
|
|
10885
|
+
export declare const withServerTracer: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
10886
|
+
|
|
10435
10887
|
/**
|
|
10436
10888
|
* What the gate decided. `passthrough` is the common case — no controls
|
|
10437
10889
|
* declared — and is distinct from `start` so the facade can skip the commit
|
|
@@ -10937,7 +11389,7 @@ export declare interface WorkflowWaitOptions {
|
|
|
10937
11389
|
* calls (incl. multi-table within one mutation) are. A mutation that writes via
|
|
10938
11390
|
* a bulk helper simply produces no undo entry (documented).
|
|
10939
11391
|
*/
|
|
10940
|
-
export declare const wrapCaptureStore: (tx: DataStore, collect: (c: ForwardChange) => void) => DataStore;
|
|
11392
|
+
export declare const wrapCaptureStore: (tx: DataStore, collect: (c: ForwardChange) => void, crdtColumnsOf?: (table: string) => ReadonlySet<string>) => DataStore;
|
|
10941
11393
|
|
|
10942
11394
|
/**
|
|
10943
11395
|
* Wrap a raw `DataStore` with the storage codec only — `.encrypted()` columns
|