@voltro/protocol 0.86.0 → 0.88.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 +5484 -0
- package/THIRD-PARTY-NOTICES.md +3 -227
- package/dist/apiRoleEndpoints.js +107 -0
- package/dist/apiRoleObservation.js +67 -0
- package/dist/apikey.d.ts +10 -0
- package/dist/apikey.js +1 -2
- package/dist/approval.js +1 -2
- package/dist/approvalDescriptors.js +1 -2
- package/dist/auth.js +40 -21
- package/dist/boundedRing.js +1 -2
- package/dist/businessRule.js +1 -2
- package/dist/canonicalJson.js +13 -0
- package/dist/connection.js +1 -2
- package/dist/devActivity.js +1 -2
- package/dist/errorSchema.js +23 -0
- package/dist/errorValue.js +1 -2
- package/dist/event.js +52 -47
- package/dist/formCapture.js +11 -0
- package/dist/httpStreamMaxDuration.js +8 -0
- package/dist/idempotency.js +89 -35
- package/dist/idempotencyInput.js +122 -0
- package/dist/identity.js +1 -2
- package/dist/index.d.ts +876 -124
- package/dist/index.js +51 -40
- package/dist/inspect.d.ts +1 -1
- package/dist/inspect.js +1 -2
- package/dist/inspectBackfill.js +1 -2
- package/dist/inspectCommandRejection.js +1 -2
- package/dist/inspectProjection.js +1 -2
- package/dist/inspectStorageProjection.js +1 -2
- package/dist/inspectValueIdentity.js +1 -2
- package/dist/inspectWorkflowExecution.js +1 -2
- package/dist/inspectWorkflowQueuedStart.js +1 -2
- package/dist/jsonSchema.js +1 -2
- package/dist/jwt.d.ts +10 -0
- package/dist/jwt.js +2 -3
- package/dist/outbox.js +1 -2
- package/dist/pairing.js +1 -2
- package/dist/plugin.js +44 -19
- package/dist/pluginAccountMerge.js +87 -0
- package/dist/pluginNaming.js +1 -2
- package/dist/pluginPrivacy.js +165 -0
- package/dist/procedure.js +115 -98
- package/dist/publicApi.js +191 -211
- package/dist/queryOptionalSources.js +13 -0
- package/dist/reactivityChannel.js +1 -2
- package/dist/rest.d.ts +227 -64
- package/dist/rest.js +296 -194
- package/dist/restFormat.js +1 -2
- package/dist/restReceipt.js +42 -0
- package/dist/revalidate.js +12 -0
- package/dist/rowEquality.js +1 -2
- package/dist/rowPatch.js +1 -2
- package/dist/schemaShape.js +1 -2
- package/dist/scopes.js +72 -40
- package/dist/secretWindows.js +70 -0
- package/dist/serverErrorBus.js +1 -2
- package/dist/serviceCall.js +1 -2
- package/dist/session.d.ts +89 -6
- package/dist/session.js +56 -56
- package/dist/sessionHeader.js +1 -2
- package/dist/ssrfPolicy.js +29 -0
- package/dist/storageAccess.js +1 -2
- package/dist/storeErrors.js +1 -2
- package/dist/storeScreenshots.js +1 -2
- package/dist/strictInput.js +1 -2
- package/dist/subscriptionEvent.js +1 -2
- package/dist/tenantSelection.js +1 -2
- package/dist/time.js +1 -2
- package/dist/undo.js +1 -2
- package/dist/validation.js +1 -2
- package/dist/webSocketGateway.js +8 -3
- package/dist/workflow.js +1 -2
- package/dist/workflowAccess.js +1 -2
- package/dist/workflowRestart.js +1 -2
- package/dist/workflowRetry.js +1 -2
- package/dist/workflowStartOutcome.js +1 -2
- package/package.json +7 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
|
+
import { ConnectionKind as ConnectionKind_2 } from '@voltro/kv/connection';
|
|
2
|
+
import { ConnectionRef } from '@voltro/kv/connection';
|
|
3
|
+
import { ConnectionRegistryShape } from '@voltro/kv/connection';
|
|
4
|
+
import { ConnectionUnavailablePolicy } from '@voltro/kv/connection';
|
|
1
5
|
import { Context } from 'effect';
|
|
2
6
|
import { DataStore } from '@voltro/database';
|
|
3
7
|
import { Effect } from 'effect';
|
|
8
|
+
import { HotStoreShape } from '@voltro/kv/hot/contract';
|
|
4
9
|
import { Layer } from 'effect';
|
|
5
10
|
import { Option } from 'effect';
|
|
6
11
|
import { Rpc } from 'effect/rpc';
|
|
7
12
|
import { RpcMiddleware } from 'effect/rpc';
|
|
8
13
|
import { Schema } from 'effect';
|
|
9
14
|
import { SchemaAST } from 'effect';
|
|
15
|
+
import { Scope } from 'effect';
|
|
10
16
|
import { SqlClient } from 'effect/sql';
|
|
17
|
+
import { StorageAddress } from '@voltro/kv/storage';
|
|
18
|
+
import { StorageDestinationRouter } from '@voltro/kv/storage';
|
|
19
|
+
import { StorageError } from '@voltro/kv/storage';
|
|
20
|
+
import { StorageProvider } from '@voltro/kv/storage';
|
|
11
21
|
import { Stream } from 'effect/rpc/RpcSchema';
|
|
12
22
|
import { VersionConflict } from '@voltro/database/wire';
|
|
13
23
|
import { YieldableError } from 'effect/Cause';
|
|
@@ -137,7 +147,7 @@ export declare interface AnyApprovalPolicy {
|
|
|
137
147
|
|
|
138
148
|
/** A guard entry is a scope check, a relationship check, an identity check, a
|
|
139
149
|
* declared no-check-needed decision, or a service-only decision. */
|
|
140
|
-
export declare type AnyCheckSpec = GuardCheckSpec | PolicyCheckSpec | AuthenticatedCheckSpec | OpenAccessSpec | ServiceAccessSpec;
|
|
150
|
+
export declare type AnyCheckSpec = GuardCheckSpec | PolicyCheckSpec | AuthenticatedCheckSpec | UpgradedCheckSpec | OpenAccessSpec | ServiceAccessSpec;
|
|
141
151
|
|
|
142
152
|
/** Any declared event, with the generics erased — for registries and audits. */
|
|
143
153
|
/** The erased descriptor every registry holds. `guards` reads the key type
|
|
@@ -147,7 +157,10 @@ export declare type AnyCheckSpec = GuardCheckSpec | PolicyCheckSpec | Authentica
|
|
|
147
157
|
export declare type AnyEventDescriptor = EventDescriptor<string, Schema.Top, Schema.Top, DeclaredAccess<never>>;
|
|
148
158
|
|
|
149
159
|
/** A guard is a scope check, a relationship check, or an identity check. */
|
|
150
|
-
export declare type AnyGuardSpec<Input = unknown> = GuardSpec<Input> | PolicyGuardSpec<Input> | AuthenticatedGuardSpec;
|
|
160
|
+
export declare type AnyGuardSpec<Input = unknown> = GuardSpec<Input> | PolicyGuardSpec<Input> | AuthenticatedGuardSpec | UpgradedGuardSpec;
|
|
161
|
+
|
|
162
|
+
/** Work performed by an API process; schema and descriptor loading is separate. */
|
|
163
|
+
export declare const API_WORKLOADS: readonly ["rpc", "subscriptions", "events", "presence", "workflows", "schedules", "directors", "drainers", "reapers", "retention", "rest", "webhooks", "inspect", "cdc"];
|
|
151
164
|
|
|
152
165
|
export declare const APIKEY_ISSUE_ORG_SCOPE = "apikeys:issue:org";
|
|
153
166
|
|
|
@@ -180,6 +193,118 @@ export declare const APIKEY_ISSUE_OTHER_SCOPE = "apikeys:issue:other";
|
|
|
180
193
|
*/
|
|
181
194
|
export declare const APIKEY_ISSUE_SELF_SCOPE = "apikeys:issue:self";
|
|
182
195
|
|
|
196
|
+
export declare interface ApiRoleEndpoint {
|
|
197
|
+
readonly role: string;
|
|
198
|
+
readonly routes: ReadonlyArray<string> | null;
|
|
199
|
+
readonly workloads: ReadonlyArray<string>;
|
|
200
|
+
readonly httpPath: string | null;
|
|
201
|
+
readonly webSocketPath: string;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export declare interface ApiRoleEndpoints {
|
|
205
|
+
readonly version: 1;
|
|
206
|
+
readonly transport: 'compose-nginx' | 'kubernetes-nginx';
|
|
207
|
+
readonly roles: ReadonlyArray<ApiRoleEndpoint>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export declare const apiRoleEndpointUrl: (baseUrl: string, endpoint: ApiRoleEndpoint, transport: "http" | "websocket") => string;
|
|
211
|
+
|
|
212
|
+
export declare interface ApiRoleObservationReport {
|
|
213
|
+
readonly replicaId: string;
|
|
214
|
+
readonly startedAt: number;
|
|
215
|
+
readonly role: string;
|
|
216
|
+
readonly workloads: ReadonlyArray<ApiWorkload>;
|
|
217
|
+
readonly capturedAt: number;
|
|
218
|
+
readonly publisher: {
|
|
219
|
+
readonly ready: boolean;
|
|
220
|
+
readonly stopped: boolean;
|
|
221
|
+
readonly pendingBuckets: number;
|
|
222
|
+
readonly droppedBuckets: number;
|
|
223
|
+
readonly rejectedSegments: number;
|
|
224
|
+
readonly writeFailures: number;
|
|
225
|
+
readonly observationErrors: number;
|
|
226
|
+
};
|
|
227
|
+
readonly currentMeasuredSeconds: ReadonlyArray<{
|
|
228
|
+
readonly role: string;
|
|
229
|
+
readonly workload: ApiWorkload;
|
|
230
|
+
readonly seconds: number;
|
|
231
|
+
}>;
|
|
232
|
+
readonly history: {
|
|
233
|
+
readonly state: 'pending' | 'available' | 'unavailable';
|
|
234
|
+
readonly assessment: ApiRoleWindowAssessment | null;
|
|
235
|
+
/** Measured portions only; no share is inferred from incomplete coverage. */
|
|
236
|
+
readonly measuredSeconds: ReadonlyArray<{
|
|
237
|
+
readonly workload: ApiWorkload;
|
|
238
|
+
readonly seconds: number;
|
|
239
|
+
}>;
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Browser-safe wire contract; no runtime or database imports. */
|
|
244
|
+
export declare const ApiRoleObservationSchema: Schema.Struct<{
|
|
245
|
+
readonly replicaId: Schema.NonEmptyString;
|
|
246
|
+
readonly startedAt: Schema.Number;
|
|
247
|
+
readonly role: Schema.NonEmptyString;
|
|
248
|
+
readonly workloads: Schema.$Array<Schema.Literals<readonly ["rpc", "subscriptions", "events", "presence", "workflows", "schedules", "directors", "drainers", "reapers", "retention", "rest", "webhooks", "inspect", "cdc"]>>;
|
|
249
|
+
readonly capturedAt: Schema.Number;
|
|
250
|
+
readonly publisher: Schema.Struct<{
|
|
251
|
+
readonly ready: Schema.Boolean;
|
|
252
|
+
readonly stopped: Schema.Boolean;
|
|
253
|
+
readonly pendingBuckets: Schema.Number;
|
|
254
|
+
readonly droppedBuckets: Schema.Number;
|
|
255
|
+
readonly rejectedSegments: Schema.Number;
|
|
256
|
+
readonly writeFailures: Schema.Number;
|
|
257
|
+
readonly observationErrors: Schema.Number;
|
|
258
|
+
}>;
|
|
259
|
+
readonly currentMeasuredSeconds: Schema.$Array<Schema.Struct<{
|
|
260
|
+
readonly role: Schema.NonEmptyString;
|
|
261
|
+
readonly workload: Schema.Literals<readonly ["rpc", "subscriptions", "events", "presence", "workflows", "schedules", "directors", "drainers", "reapers", "retention", "rest", "webhooks", "inspect", "cdc"]>;
|
|
262
|
+
readonly seconds: Schema.Number;
|
|
263
|
+
}>>;
|
|
264
|
+
readonly history: Schema.Struct<{
|
|
265
|
+
readonly state: Schema.Literals<readonly ["pending", "available", "unavailable"]>;
|
|
266
|
+
readonly measuredSeconds: Schema.$Array<Schema.Struct<{
|
|
267
|
+
readonly workload: Schema.Literals<readonly ["rpc", "subscriptions", "events", "presence", "workflows", "schedules", "directors", "drainers", "reapers", "retention", "rest", "webhooks", "inspect", "cdc"]>;
|
|
268
|
+
readonly seconds: Schema.Number;
|
|
269
|
+
}>>;
|
|
270
|
+
readonly assessment: Schema.NullOr<Schema.Struct<{
|
|
271
|
+
readonly from: Schema.Number;
|
|
272
|
+
readonly until: Schema.Number;
|
|
273
|
+
readonly complete: Schema.Boolean;
|
|
274
|
+
readonly missingBuckets: Schema.Number;
|
|
275
|
+
readonly incompleteWorkloads: Schema.$Array<Schema.Literals<readonly ["rpc", "subscriptions", "events", "presence", "workflows", "schedules", "directors", "drainers", "reapers", "retention", "rest", "webhooks", "inspect", "cdc"]>>;
|
|
276
|
+
readonly reason: Schema.Literals<readonly ["invalid-observation", "incomplete", "idle", "observed"]>;
|
|
277
|
+
readonly totals: Schema.$Array<Schema.Struct<{
|
|
278
|
+
readonly workload: Schema.Literals<readonly ["rpc", "subscriptions", "events", "presence", "workflows", "schedules", "directors", "drainers", "reapers", "retention", "rest", "webhooks", "inspect", "cdc"]>;
|
|
279
|
+
readonly seconds: Schema.Number;
|
|
280
|
+
readonly share: Schema.Number;
|
|
281
|
+
}>>;
|
|
282
|
+
readonly splitCandidates: Schema.$Array<Schema.Literals<readonly ["rpc", "subscriptions", "events", "presence", "workflows", "schedules", "directors", "drainers", "reapers", "retention", "rest", "webhooks", "inspect", "cdc"]>>;
|
|
283
|
+
}>>;
|
|
284
|
+
}>;
|
|
285
|
+
}>;
|
|
286
|
+
|
|
287
|
+
/** Reserved web proxy base; the API name isolates identical role names. */
|
|
288
|
+
export declare const apiRoleProxyBasePath: (apiName: string) => string;
|
|
289
|
+
|
|
290
|
+
export declare type ApiRoleRpcWorkload = 'rpc' | 'subscriptions' | 'events';
|
|
291
|
+
|
|
292
|
+
export declare interface ApiRoleWindowAssessment {
|
|
293
|
+
readonly from: number;
|
|
294
|
+
readonly until: number;
|
|
295
|
+
readonly complete: boolean;
|
|
296
|
+
readonly missingBuckets: number;
|
|
297
|
+
readonly incompleteWorkloads: ReadonlyArray<ApiWorkload>;
|
|
298
|
+
readonly reason: 'invalid-observation' | 'incomplete' | 'idle' | 'observed';
|
|
299
|
+
readonly totals: ReadonlyArray<{
|
|
300
|
+
readonly workload: ApiWorkload;
|
|
301
|
+
readonly seconds: number;
|
|
302
|
+
readonly share: number;
|
|
303
|
+
}>;
|
|
304
|
+
/** Advisory evidence only: no topology mutation and no acceptance claim. */
|
|
305
|
+
readonly splitCandidates: ReadonlyArray<ApiWorkload>;
|
|
306
|
+
}
|
|
307
|
+
|
|
183
308
|
export declare class ApiUnavailable extends ApiUnavailable_base {
|
|
184
309
|
}
|
|
185
310
|
|
|
@@ -193,6 +318,8 @@ declare const ApiUnavailable_base: Schema.Class<ApiUnavailable, Schema.TaggedStr
|
|
|
193
318
|
readonly message: Schema.String;
|
|
194
319
|
}>, YieldableError>;
|
|
195
320
|
|
|
321
|
+
export declare type ApiWorkload = typeof API_WORKLOADS[number];
|
|
322
|
+
|
|
196
323
|
/** The subject a decision produces, plus what the decision took away. `removed`
|
|
197
324
|
* is never non-empty for a `grant`. */
|
|
198
325
|
export declare interface AppliedScopes {
|
|
@@ -625,6 +752,13 @@ export declare interface AuthStrategy {
|
|
|
625
752
|
export declare interface AuthStrategyInput {
|
|
626
753
|
readonly headers: Readonly<Record<string, string | undefined>>;
|
|
627
754
|
readonly clientId: number;
|
|
755
|
+
/** HTTP request target, supplied by REST transports. Request selectors may
|
|
756
|
+
* read an explicit tenant hint here; it is never authentication or authority.
|
|
757
|
+
* Absent for connection transports and non-HTTP callers. */
|
|
758
|
+
readonly http?: {
|
|
759
|
+
readonly path: string;
|
|
760
|
+
readonly query: string;
|
|
761
|
+
};
|
|
628
762
|
/**
|
|
629
763
|
* The app's DataStore, for a strategy that must READ to identify the caller.
|
|
630
764
|
*
|
|
@@ -673,8 +807,9 @@ export declare interface AuthStrategyWithCallback extends AuthStrategy {
|
|
|
673
807
|
export declare type AuthSubjectGuard = (subject: Subject, ctx: AuthSubjectGuardContext) => Promise<AuthSubjectGuardVerdict> | AuthSubjectGuardVerdict;
|
|
674
808
|
|
|
675
809
|
export declare interface AuthSubjectGuardContext {
|
|
676
|
-
/** `'request'` for a live call, `'workflow'` for a durable run being executed
|
|
677
|
-
|
|
810
|
+
/** `'request'` for a live call, `'workflow'` for a durable run being executed,
|
|
811
|
+
* `'room'` for a Room seat redeemed on a Room host (no request headers). */
|
|
812
|
+
readonly origin: 'request' | 'workflow' | 'room';
|
|
678
813
|
/** The request's headers. EMPTY for `origin: 'workflow'`. */
|
|
679
814
|
readonly headers: Readonly<Record<string, string | undefined>>;
|
|
680
815
|
/** `undefined` for `origin: 'workflow'` and for transports with no connection. */
|
|
@@ -724,7 +859,7 @@ export declare type AuthSubjectGuardVerdict = {
|
|
|
724
859
|
* `fresh` the caller runs the handler then calls `finish`/`fail`; on
|
|
725
860
|
* `replay`/`conflict` it returns immediately without touching the handler.
|
|
726
861
|
*/
|
|
727
|
-
export declare const beginIdempotent: (store: IdempotencyStore, scope: string, key: string, ttlMs: number, now: number, inFlightLeaseMs?: number) => Promise<IdempotencyOutcome>;
|
|
862
|
+
export declare const beginIdempotent: (store: IdempotencyStore, scope: string, key: string, inputHash: string, ttlMs: number, now: number, inFlightLeaseMs?: number) => Promise<IdempotencyOutcome>;
|
|
728
863
|
|
|
729
864
|
/** Bind a process-local authority refresh to an independent subject snapshot.
|
|
730
865
|
* Neither the resolver nor its credentials become serializable subject fields.
|
|
@@ -776,6 +911,24 @@ export declare interface CachedScopeDecision {
|
|
|
776
911
|
readonly fresh: boolean;
|
|
777
912
|
}
|
|
778
913
|
|
|
914
|
+
/**
|
|
915
|
+
* Canonical JSON — object keys sorted recursively, so two structurally equal
|
|
916
|
+
* inputs that differ only in key order digest identically. A retry from a
|
|
917
|
+
* different client build must not mint a second approval.
|
|
918
|
+
* Preserve own JSON fields such as `__proto__`; a prototype setter must never
|
|
919
|
+
* discard part of the content that an approval identity binds.
|
|
920
|
+
*
|
|
921
|
+
* Lives here, not in `@voltro/runtime`, so identity digests in modules that
|
|
922
|
+
* must not load the server runtime (storage metadata, browser-safe code) use
|
|
923
|
+
* the same encoding.
|
|
924
|
+
*/
|
|
925
|
+
export declare const canonicalJson: (value: unknown) => string;
|
|
926
|
+
|
|
927
|
+
export declare const captureApiRoleEndpoints: (value: unknown) => ApiRoleEndpoints;
|
|
928
|
+
|
|
929
|
+
/** Capture optional integration observations without changing reactive triggers. */
|
|
930
|
+
export declare const captureOptionalQuerySources: (name: string, source: string | ReadonlyArray<string> | undefined, optional: unknown) => ReadonlyArray<string> | undefined;
|
|
931
|
+
|
|
779
932
|
/**
|
|
780
933
|
* Validate `plugin.framework` (npm-semver range) against the running
|
|
781
934
|
* voltro version. Returns either `{ ok: true }` or
|
|
@@ -850,6 +1003,9 @@ export declare interface ClientDescriptor {
|
|
|
850
1003
|
* (`<DataTable>` derives its columns from it) + the capability map can
|
|
851
1004
|
* introspect it. Same browser-safety rationale as `input`. */
|
|
852
1005
|
readonly output?: Schema.Top | undefined;
|
|
1006
|
+
/** The procedure's own declared error schema, by reference like input/output.
|
|
1007
|
+
* This is not the widened framework/plugin wire error union. */
|
|
1008
|
+
readonly error?: Schema.Top | undefined;
|
|
853
1009
|
}
|
|
854
1010
|
|
|
855
1011
|
/**
|
|
@@ -1020,6 +1176,8 @@ export declare const composeAuthStrategies: (strategies: ReadonlyArray<AuthStrat
|
|
|
1020
1176
|
readonly getStore?: () => unknown;
|
|
1021
1177
|
}) => ((input: AuthStrategyInput) => Promise<SubjectResolution>);
|
|
1022
1178
|
|
|
1179
|
+
export declare const composeReplayAuthorityBindings: (plugins: ReadonlyArray<unknown>) => RpcReplayAuthorityBinding | undefined;
|
|
1180
|
+
|
|
1023
1181
|
/**
|
|
1024
1182
|
* Compose a list of Effect-native interceptors into ONE function the
|
|
1025
1183
|
* runtime calls. Reduces right-to-left so the array order reads
|
|
@@ -1090,6 +1248,11 @@ export declare class ConnectionInfoMiddleware extends ConnectionInfoMiddleware_b
|
|
|
1090
1248
|
declare const ConnectionInfoMiddleware_base: RpcMiddleware.ServiceClass<ConnectionInfoMiddleware, "@voltro/ConnectionInfoMiddleware", ConnectionInfo, Schema.Never, never, never, false>;
|
|
1091
1249
|
|
|
1092
1250
|
export declare interface ConnectionInfoValue {
|
|
1251
|
+
/** The effective per-call Cookie header, including current connection
|
|
1252
|
+
* credential patches. Server-only input for app-specific signed-cookie
|
|
1253
|
+
* verification; not a verified identity. Never serialize it into responses
|
|
1254
|
+
* or public page state. Absent when the caller presented no cookies. */
|
|
1255
|
+
readonly cookieHeader?: string;
|
|
1093
1256
|
/** Per-connection identifier assigned by the rpc transport. Stable for the
|
|
1094
1257
|
* lifetime of the underlying WebSocket connection; reused as the key for
|
|
1095
1258
|
* the per-connection subject override map. */
|
|
@@ -1353,8 +1516,9 @@ declare const ConstraintViolation_base: Schema.Class<ConstraintViolation, Schema
|
|
|
1353
1516
|
* plugin wants to cancel EARLY (before shutdown).
|
|
1354
1517
|
*/
|
|
1355
1518
|
export declare interface CoordinatedScheduleHandle {
|
|
1356
|
-
/** Stop
|
|
1357
|
-
|
|
1519
|
+
/** Stop future admission immediately; await completion before releasing the
|
|
1520
|
+
* task dependencies. Idempotent; synchronous handles finish immediately. */
|
|
1521
|
+
readonly stop: () => void | Promise<void>;
|
|
1358
1522
|
/** The task name (for logging / dedup diagnostics). */
|
|
1359
1523
|
readonly name: string;
|
|
1360
1524
|
/**
|
|
@@ -1413,6 +1577,13 @@ export declare interface CoordinatedTickOutcome {
|
|
|
1413
1577
|
readonly nextDueInMs?: number | null;
|
|
1414
1578
|
}
|
|
1415
1579
|
|
|
1580
|
+
/** Capture the complete participant list once. Undeclared SQL tables refuse
|
|
1581
|
+
* before any hook; erasure and merge are distinct policies and never substitute. */
|
|
1582
|
+
export declare const createPluginAccountMergeRegistry: (plugins: ReadonlyArray<VoltroPlugin>) => PluginAccountMergeRegistry;
|
|
1583
|
+
|
|
1584
|
+
/** Captures hooks once. Does not read a store, schedule work, retry or grant authority. */
|
|
1585
|
+
export declare const createPluginPrivacyRegistry: (plugins: ReadonlyArray<VoltroPlugin>) => PluginPrivacyRegistry;
|
|
1586
|
+
|
|
1416
1587
|
/** Index reuse for one subscription's immutable snapshots and returned rows.
|
|
1417
1588
|
* Arbitrary mutable input must use applyRowPatch. A different base rebuilds
|
|
1418
1589
|
* the index; reset releases it on snapshot replacement or owner disposal. */
|
|
@@ -1436,6 +1607,9 @@ export declare const currentSubjectAuthority: (subject: Subject) => Subject;
|
|
|
1436
1607
|
*/
|
|
1437
1608
|
export declare type DeclaredAccess<Input = unknown> = ReadonlyArray<AnyGuardSpec<Input> | OpenAccessSpec | ServiceAccessSpec>;
|
|
1438
1609
|
|
|
1610
|
+
/** The `_tag` literals a descriptor's `error:` union declares (empty for none). */
|
|
1611
|
+
export declare const declaredErrorTags: (error: Schema.Top | undefined) => ReadonlySet<string>;
|
|
1612
|
+
|
|
1439
1613
|
/** Every channel declared in this process, by routing key. */
|
|
1440
1614
|
export declare const declaredReactivityChannelKeys: () => ReadonlySet<string>;
|
|
1441
1615
|
|
|
@@ -1608,10 +1782,9 @@ export declare const defineEvent: <const Name extends string, Key extends Schema
|
|
|
1608
1782
|
* resource-scoped rule ("may this terminal watch this arena") stays
|
|
1609
1783
|
* declarative. `ScopeError` is merged into the wire error union automatically.
|
|
1610
1784
|
*
|
|
1611
|
-
*
|
|
1612
|
-
*
|
|
1613
|
-
*
|
|
1614
|
-
* makes throughput scale with the audience instead of the publish rate.
|
|
1785
|
+
* Checked before subscription and each delivery. Resource resolvers can observe
|
|
1786
|
+
* live revocation; captured subject scopes remain bounded by credential expiry.
|
|
1787
|
+
* Additional private payload filtering uses the app-owned clientPolicy.
|
|
1615
1788
|
*/
|
|
1616
1789
|
readonly guards?: Guards<Schema.Schema.Type<Key>>;
|
|
1617
1790
|
/**
|
|
@@ -1672,6 +1845,8 @@ export declare const defineEvent: <const Name extends string, Key extends Schema
|
|
|
1672
1845
|
* to miss one?" — not "is this event frequent?".
|
|
1673
1846
|
*/
|
|
1674
1847
|
readonly delivery?: EventDeliverySemantics;
|
|
1848
|
+
/** Required private-client policy ID, resolved from the installing app. */
|
|
1849
|
+
readonly clientPolicy?: string;
|
|
1675
1850
|
}) => EventDescriptor<Name, Key, Payload>;
|
|
1676
1851
|
|
|
1677
1852
|
export declare const defineMutation: <const Name extends string, Input extends Schema.Top, Output extends Schema.Top, Error extends Schema.Top = typeof Schema.Never>(options: {
|
|
@@ -1704,6 +1879,13 @@ export declare const defineMutation: <const Name extends string, Input extends S
|
|
|
1704
1879
|
* same way. Not a durable outbox, a distributed lock or a cross-tab merge.
|
|
1705
1880
|
*/
|
|
1706
1881
|
readonly serialize?: MutationSerialization<Schema.Schema.Type<Input>>;
|
|
1882
|
+
/** Exclude mutations without a valid row-image inverse (for example a
|
|
1883
|
+
* derived-index rebuild) from automatic undo. Omitted means the normal
|
|
1884
|
+
* environment-controlled capture. Transactions, guards and audit still run. */
|
|
1885
|
+
readonly undo?: {
|
|
1886
|
+
readonly capture: false;
|
|
1887
|
+
readonly reason: string;
|
|
1888
|
+
};
|
|
1707
1889
|
/** Optional declarative target(s) — drives auto-optimistic. */
|
|
1708
1890
|
readonly target?: Target<Schema.Schema.Type<Input>, Schema.Schema.Type<Output>>;
|
|
1709
1891
|
/** Declarative authorization guard(s) — the caller must hold the named
|
|
@@ -1857,6 +2039,9 @@ export declare const defineQuery: <const Name extends string, Input extends Sche
|
|
|
1857
2039
|
* import edge is what makes a channel `source:` impossible to leave stale,
|
|
1858
2040
|
* which a table name (a bare string) can always be. */
|
|
1859
2041
|
readonly source?: ReactivitySource | ReadonlyArray<ReactivitySource>;
|
|
2042
|
+
/** Names in source that observe an optional integration. These remain in
|
|
2043
|
+
* the complete trigger set; unavailable optional tables warn in check. */
|
|
2044
|
+
readonly optionalSource?: ReadonlyArray<string>;
|
|
1860
2045
|
/** Opt into server-side snapshot caching with auto-invalidation. */
|
|
1861
2046
|
readonly cache?: QueryCacheConfig;
|
|
1862
2047
|
/** Declarative authorization guard(s) — the caller must hold the named
|
|
@@ -2091,6 +2276,8 @@ export declare const effectiveScopes: (subject: Subject) => ReadonlyArray<string
|
|
|
2091
2276
|
*/
|
|
2092
2277
|
export declare const encodeEventKey: (key: unknown) => string;
|
|
2093
2278
|
|
|
2279
|
+
export declare const encodeNativeFormCapture: (selector: string, presentationDigest: string) => string;
|
|
2280
|
+
|
|
2094
2281
|
/** Encode a failure under `format`: the tagged body the desugar always wrote
|
|
2095
2282
|
* (`{ error, …fields }`), Problem Details, or the format's own encoder. */
|
|
2096
2283
|
export declare const encodeRestError: (format: RestFormat, error: RestFormatError, ctx: RestFormatContext) => RestFormatResponse;
|
|
@@ -2109,6 +2296,10 @@ export declare interface EnqueueOptions {
|
|
|
2109
2296
|
readonly delayMs?: number;
|
|
2110
2297
|
}
|
|
2111
2298
|
|
|
2299
|
+
/** The member of an error union that declares `tag`, as a schema of its own —
|
|
2300
|
+
* for the spec's per-status responses. */
|
|
2301
|
+
export declare const errorMemberSchema: (error: Schema.Top | undefined, tag: string) => Schema.Top | undefined;
|
|
2302
|
+
|
|
2112
2303
|
/**
|
|
2113
2304
|
* The text to SHOW for a failure value — its `message`, else its `_tag`, else
|
|
2114
2305
|
* `String(value)`.
|
|
@@ -2169,6 +2360,34 @@ export declare const eventAttached: Schema.Struct<{
|
|
|
2169
2360
|
readonly _tag: Schema.Literal<"attached">;
|
|
2170
2361
|
}>;
|
|
2171
2362
|
|
|
2363
|
+
/** App-owned, server-only callbacks. Descriptors carry only the policy ID. */
|
|
2364
|
+
export declare interface EventClientPolicy {
|
|
2365
|
+
readonly id: string;
|
|
2366
|
+
/** Before bus subscription, including reattachment/resume. Only true admits. */
|
|
2367
|
+
readonly admit: (input: {
|
|
2368
|
+
readonly subject: Subject;
|
|
2369
|
+
readonly event: string;
|
|
2370
|
+
readonly key: unknown;
|
|
2371
|
+
}) => Effect.Effect<boolean, unknown>;
|
|
2372
|
+
/** Recheck current membership AND payload visibility. Deny ends the stream;
|
|
2373
|
+
* drop withholds this payload but keeps the subscription. No client filtering. */
|
|
2374
|
+
/** Register revocation before initial admission. The returned effect ends when
|
|
2375
|
+
* access may have changed; completion or failure ends the client stream.
|
|
2376
|
+
* Acquire resources in the supplied Scope; no detached background owner. */
|
|
2377
|
+
readonly monitor?: (input: {
|
|
2378
|
+
readonly subject: Subject;
|
|
2379
|
+
readonly event: string;
|
|
2380
|
+
readonly key: unknown;
|
|
2381
|
+
}) => Effect.Effect<Effect.Effect<void, unknown>, unknown, Scope.Scope>;
|
|
2382
|
+
readonly deliver: (input: {
|
|
2383
|
+
readonly subject: Subject;
|
|
2384
|
+
readonly event: string;
|
|
2385
|
+
readonly key: unknown;
|
|
2386
|
+
readonly payload: unknown;
|
|
2387
|
+
readonly emittedAt: number;
|
|
2388
|
+
}) => Effect.Effect<'allow' | 'drop' | 'deny', unknown>;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2172
2391
|
/**
|
|
2173
2392
|
* What it means for a subscriber to fall behind.
|
|
2174
2393
|
*
|
|
@@ -2205,9 +2424,8 @@ export declare interface EventDescriptor<Name extends string, Key extends Schema
|
|
|
2205
2424
|
readonly key: Key;
|
|
2206
2425
|
readonly payload: Payload;
|
|
2207
2426
|
/** Who may LISTEN — the author's guards, or the erased form of their
|
|
2208
|
-
* `openAccess:` decision, never both (see `DeclaredAccess`).
|
|
2209
|
-
*
|
|
2210
|
-
* why that distinction is deliberate. */
|
|
2427
|
+
* `openAccess:` decision, never both (see `DeclaredAccess`). Resource guards are checked before subscription and delivery; credential
|
|
2428
|
+
* expiry bounds captured subject authority. */
|
|
2211
2429
|
readonly guards: Guards | undefined;
|
|
2212
2430
|
/** The declared `openAccess:` reason, when there is one — what the boot gate
|
|
2213
2431
|
* and `voltro doctor` read. The enforcement paths read `guards`. */
|
|
@@ -2218,6 +2436,8 @@ export declare interface EventDescriptor<Name extends string, Key extends Schema
|
|
|
2218
2436
|
readonly delivery: EventDeliverySemantics | undefined;
|
|
2219
2437
|
/** Opt this event into outbound HTTP delivery. See `EventWebhookSpec`. */
|
|
2220
2438
|
readonly webhook: EventWebhookSpec | undefined;
|
|
2439
|
+
/** Required app-owned server policy, in addition to guards. No server imports in descriptors. */
|
|
2440
|
+
readonly clientPolicy?: string;
|
|
2221
2441
|
}
|
|
2222
2442
|
|
|
2223
2443
|
/**
|
|
@@ -2298,6 +2518,9 @@ export declare const eventResumePoint: Schema.Struct<{
|
|
|
2298
2518
|
|
|
2299
2519
|
export declare const eventRoute: (tenantId: string | null, event: string, key: unknown) => string;
|
|
2300
2520
|
|
|
2521
|
+
/** Browser-safe execution ownership marker; wire schemas remain unchanged. */
|
|
2522
|
+
export declare const EventRpcWorkload: Context.Service<true, true>;
|
|
2523
|
+
|
|
2301
2524
|
export declare type EventStreamEvent<P> = {
|
|
2302
2525
|
readonly _tag: 'attached';
|
|
2303
2526
|
} | {
|
|
@@ -2353,15 +2576,6 @@ export declare const eventSubscribeInput: <K extends Schema.Top>(key: K) => Sche
|
|
|
2353
2576
|
}>>>;
|
|
2354
2577
|
}>;
|
|
2355
2578
|
|
|
2356
|
-
/**
|
|
2357
|
-
* Lift an event descriptor into its rpc.
|
|
2358
|
-
*
|
|
2359
|
-
* A `stream: true` rpc, like a query — the framework's push transport is the
|
|
2360
|
-
* WebSocket a subscription already holds open, and reusing it is why `useEvent`
|
|
2361
|
-
* shares one connection lifecycle, one reconnect policy and one devtools view
|
|
2362
|
-
* with `useSubscription` instead of being a second realtime concept in the same
|
|
2363
|
-
* app.
|
|
2364
|
-
*/
|
|
2365
2579
|
export declare const eventToRpc: <Name extends string, Key extends Schema.Top, Payload extends Schema.Top>(descriptor: EventDescriptor<Name, Key, Payload, ReadonlyArray<unknown>>, extraErrors?: ReadonlyArray<Schema.Top>) => Rpc.Rpc<Name, Schema.Struct<{
|
|
2366
2580
|
readonly key: Key;
|
|
2367
2581
|
readonly resume: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
@@ -2444,8 +2658,8 @@ export declare interface ExposeAsToolSpec {
|
|
|
2444
2658
|
*/
|
|
2445
2659
|
export declare type ExtraErrors = ReadonlyArray<Schema.Top>;
|
|
2446
2660
|
|
|
2447
|
-
/** Release
|
|
2448
|
-
export declare const failIdempotent: (store: IdempotencyStore,
|
|
2661
|
+
/** Release this failed execution's running claim without deleting a successor. */
|
|
2662
|
+
export declare const failIdempotent: (store: IdempotencyStore, claim: IdempotencyClaim) => Promise<boolean>;
|
|
2449
2663
|
|
|
2450
2664
|
/**
|
|
2451
2665
|
* The field-addressed issues carried by a wire error, or `[]` when the error
|
|
@@ -2483,8 +2697,8 @@ export declare const findAdvisoryResourceGuards: (procedures: ReadonlyArray<{
|
|
|
2483
2697
|
readonly guards?: ReadonlyArray<AnyCheckSpec>;
|
|
2484
2698
|
}>) => ReadonlyArray<string>;
|
|
2485
2699
|
|
|
2486
|
-
/** Record a
|
|
2487
|
-
export declare const finishIdempotent: (store: IdempotencyStore,
|
|
2700
|
+
/** Record a response only while this original execution owns the claim. */
|
|
2701
|
+
export declare const finishIdempotent: (store: IdempotencyStore, claim: IdempotencyClaim, response: IdempotencyResponse, now: number) => Promise<boolean>;
|
|
2488
2702
|
|
|
2489
2703
|
/**
|
|
2490
2704
|
* The schema as the generator should see it: every `Number` node checked
|
|
@@ -2516,9 +2730,16 @@ export declare const finiteNumberView: (ast: SchemaAST.AST, memo?: Map<SchemaAST
|
|
|
2516
2730
|
*/
|
|
2517
2731
|
export declare const firstEventValue: (tag: string, value: unknown, label: string) => unknown;
|
|
2518
2732
|
|
|
2733
|
+
export declare const FORM_CAPTURE_FIELD = "__voltro_capture";
|
|
2734
|
+
|
|
2735
|
+
export declare const FORM_CAPTURE_META_NAME = "voltro:form-source";
|
|
2736
|
+
|
|
2519
2737
|
/** A route rendered for humans — logs, the inspect surface, the dashboard. */
|
|
2520
2738
|
export declare const formatEventRoute: (route: string) => string;
|
|
2521
2739
|
|
|
2740
|
+
/** Build selector (snapshot/input/execution) followed by its public class digest. */
|
|
2741
|
+
export declare const formCaptureSource: (value: unknown) => string | undefined;
|
|
2742
|
+
|
|
2522
2743
|
/**
|
|
2523
2744
|
* The framework errors EVERY procedure of a kind carries on its wire union —
|
|
2524
2745
|
* the unconditional members `wireErrorUnion` adds. The conditional ones (a
|
|
@@ -2533,8 +2754,8 @@ export declare const formatEventRoute: (route: string) => string;
|
|
|
2533
2754
|
export declare const FRAMEWORK_WIRE_ERRORS: {
|
|
2534
2755
|
readonly query: readonly [typeof ScopeError, typeof Unauthenticated, typeof RequestedTenantRefused];
|
|
2535
2756
|
readonly stream: readonly [typeof ScopeError, typeof Unauthenticated, typeof RequestedTenantRefused];
|
|
2536
|
-
readonly action: readonly [typeof ScopeError, typeof Unauthenticated, typeof RequestedTenantRefused, typeof ValidationError, typeof ValidationErrors];
|
|
2537
|
-
readonly mutation: readonly [typeof ScopeError, typeof Unauthenticated, typeof RequestedTenantRefused, typeof BusinessRuleViolation, typeof MutationInFlight, typeof VersionConflict, typeof ValidationError, typeof ValidationErrors];
|
|
2757
|
+
readonly action: readonly [typeof ScopeError, typeof Unauthenticated, typeof RequestedTenantRefused, typeof MutationInFlight, typeof MutationIdempotencyRefused, typeof ValidationError, typeof ValidationErrors];
|
|
2758
|
+
readonly mutation: readonly [typeof ScopeError, typeof Unauthenticated, typeof RequestedTenantRefused, typeof BusinessRuleViolation, typeof MutationInFlight, typeof MutationIdempotencyRefused, typeof VersionConflict, typeof ValidationError, typeof ValidationErrors];
|
|
2538
2759
|
};
|
|
2539
2760
|
|
|
2540
2761
|
/** The error values {@link FRAMEWORK_WIRE_ERRORS} admits for `Kind`. */
|
|
@@ -2619,35 +2840,17 @@ export declare interface GuardSpec<Input = unknown> {
|
|
|
2619
2840
|
/** How an array of scopes combines. `'all'` (default) = AND (hold every
|
|
2620
2841
|
* scope); `'any'` = OR (hold at least one). Ignored for a single scope. */
|
|
2621
2842
|
readonly mode?: 'all' | 'any';
|
|
2622
|
-
/**
|
|
2623
|
-
*
|
|
2624
|
-
*
|
|
2625
|
-
*
|
|
2626
|
-
*
|
|
2627
|
-
*
|
|
2628
|
-
*
|
|
2629
|
-
* carried for logging and for a future subject-scope resolver that narrows by
|
|
2630
|
-
* resource. It does not, on its own, make the check per-resource.
|
|
2631
|
-
*
|
|
2632
|
-
* **If your authority is per-resource, you want {@link PolicyGuardSpec}, not
|
|
2633
|
-
* this field** — `guards: [{ action, resourceType, resource }]`, backed by
|
|
2634
|
-
* `defineResourcePolicy` + a tuple source you register. That is built, wired
|
|
2635
|
-
* on both boot paths, fail-closed without a resolver, and documented under
|
|
2636
|
-
* *Authentication → Authorization*. An app whose relationships already live
|
|
2637
|
-
* in its own tables (a `teamMembers` row, say) registers its own tuple source
|
|
2638
|
-
* rather than copying data across; see `policyGuardResolver.ts`.
|
|
2639
|
-
*
|
|
2640
|
-
* That paragraph is here because its absence cost a deployment their access
|
|
2641
|
-
* gate. This comment used to describe the resolver as "a future ReBAC /
|
|
2642
|
-
* `accessPolicy()` resolver" — written before the ReBAC path shipped and
|
|
2643
|
-
* never updated. They read the type, quoted the sentence, concluded there was
|
|
2644
|
-
* "nothing in between" declaring an untruth and turning the gate off, and set
|
|
2645
|
-
* `security: { defaultDeny: false }` on an app with 565 undecided procedures.
|
|
2646
|
-
* The capability they needed was two fields away. A doc comment that says
|
|
2647
|
-
* "future" about something shipped is not a small inaccuracy: it is the only
|
|
2648
|
-
* thing a careful reader has, and it argued them out of a feature.
|
|
2649
|
-
*/
|
|
2843
|
+
/** Pure browser-safe input → target resource id selector. With a registered
|
|
2844
|
+
* setResourceScopeResolver, scopes can be checked on this resource. Without
|
|
2845
|
+
* resourceOnly, an existing global scope or admin:full may satisfy the guard
|
|
2846
|
+
* without consulting that resolver. For per-resource authority over relationships use
|
|
2847
|
+
* PolicyGuardSpec: `defineResourcePolicy` plus a registered tuple source. That is built, wired
|
|
2848
|
+
* on both boot paths and fail-closed without a resolver — an earlier comment called it "future"
|
|
2849
|
+
* and argued a deployment out of its access gate. */
|
|
2650
2850
|
readonly resource?: (input: Input) => string | undefined;
|
|
2851
|
+
/** Require an explicit current resource verdict, including for globally held
|
|
2852
|
+
* scopes or admin:full. Missing resolver/resource refuses access. */
|
|
2853
|
+
readonly resourceOnly?: boolean;
|
|
2651
2854
|
}
|
|
2652
2855
|
|
|
2653
2856
|
/** Does this descriptor declare an access decision — a guard, or a deliberate
|
|
@@ -2677,8 +2880,9 @@ export declare const hasEnforcedGuard: (guards: DeclaredAccess | undefined) => b
|
|
|
2677
2880
|
* the RAW subject scopes — use `hasEffectiveScope` to include rbac roles. */
|
|
2678
2881
|
export declare const hasScope: (subject: Subject, scope: string) => boolean;
|
|
2679
2882
|
|
|
2680
|
-
/** Renew
|
|
2681
|
-
|
|
2883
|
+
/** Renew only the captured execution identity; ownership loss stops renewal.
|
|
2884
|
+
* Stopping this timer never proves a remote business operation has stopped. */
|
|
2885
|
+
export declare const holdIdempotentClaim: (store: IdempotencyStore, claim: IdempotencyClaim, inFlightLeaseMs?: number, now?: () => number) => (() => void);
|
|
2682
2886
|
|
|
2683
2887
|
/**
|
|
2684
2888
|
* Short-circuit response shape. Returning a `HttpInterceptResponse`
|
|
@@ -2749,11 +2953,35 @@ export declare type HttpRequestInterceptor = (next: () => Promise<HttpInterceptR
|
|
|
2749
2953
|
/** Fire-and-forget observer of plugin HTTP route calls — see {@link PluginHttpRouteEvent}. */
|
|
2750
2954
|
export declare type HttpRouteObserver = (event: PluginHttpRouteEvent) => void;
|
|
2751
2955
|
|
|
2956
|
+
/** Identity of one acquired execution, never reused when a key is reclaimed.
|
|
2957
|
+
* This is receipt ownership, not authority to perform a business side effect. */
|
|
2958
|
+
export declare interface IdempotencyClaim {
|
|
2959
|
+
readonly scope: string;
|
|
2960
|
+
readonly key: string;
|
|
2961
|
+
readonly id: string;
|
|
2962
|
+
readonly inputHash: string;
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
export declare type IdempotencyClaimResult = {
|
|
2966
|
+
readonly kind: 'claimed';
|
|
2967
|
+
readonly claim: IdempotencyClaim;
|
|
2968
|
+
} | {
|
|
2969
|
+
readonly kind: 'existing';
|
|
2970
|
+
readonly record: IdempotencyRecord;
|
|
2971
|
+
} | {
|
|
2972
|
+
readonly kind: 'conflict';
|
|
2973
|
+
};
|
|
2974
|
+
|
|
2752
2975
|
export declare type IdempotencyOutcome = {
|
|
2753
2976
|
readonly kind: 'fresh';
|
|
2977
|
+
readonly claim: IdempotencyClaim;
|
|
2754
2978
|
} | {
|
|
2755
2979
|
readonly kind: 'replay';
|
|
2756
2980
|
readonly response: IdempotencyResponse;
|
|
2981
|
+
} | {
|
|
2982
|
+
readonly kind: 'input-conflict';
|
|
2983
|
+
} | {
|
|
2984
|
+
readonly kind: 'input-unbound';
|
|
2757
2985
|
} | {
|
|
2758
2986
|
readonly kind: 'conflict';
|
|
2759
2987
|
};
|
|
@@ -2761,6 +2989,8 @@ export declare type IdempotencyOutcome = {
|
|
|
2761
2989
|
export declare interface IdempotencyRecord {
|
|
2762
2990
|
readonly scope: string;
|
|
2763
2991
|
readonly key: string;
|
|
2992
|
+
/** Null means a retained receipt predates declared-input binding. */
|
|
2993
|
+
readonly inputHash: string | null;
|
|
2764
2994
|
readonly status: 'in_flight' | 'completed';
|
|
2765
2995
|
readonly response: IdempotencyResponse | null;
|
|
2766
2996
|
/** epoch ms */
|
|
@@ -2770,38 +3000,41 @@ export declare interface IdempotencyRecord {
|
|
|
2770
3000
|
export declare interface IdempotencyResponse {
|
|
2771
3001
|
readonly status: number;
|
|
2772
3002
|
readonly body: unknown;
|
|
3003
|
+
/** Framework-owned REST qualification metadata. Custom stores preserve it
|
|
3004
|
+
* unchanged, separately from the arbitrary application output in body. */
|
|
3005
|
+
readonly rest?: unknown;
|
|
2773
3006
|
}
|
|
2774
3007
|
|
|
2775
3008
|
/** Build the scope key — keep keys from colliding across tenants + endpoints. */
|
|
2776
3009
|
export declare const idempotencyScope: (tenantId: string | null | undefined, method: string, path: string) => string;
|
|
2777
3010
|
|
|
2778
3011
|
export declare interface IdempotencyStore {
|
|
2779
|
-
/** Current record for (scope, key), or null. Read-side (inspect/dashboard). */
|
|
2780
3012
|
readonly get: (scope: string, key: string) => Promise<IdempotencyRecord | null>;
|
|
2781
|
-
/**
|
|
2782
|
-
*
|
|
2783
|
-
*
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
*
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
readonly
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
readonly
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
readonly
|
|
2804
|
-
|
|
3013
|
+
/** Atomically acquire an absent/stale key with a new, never-reused identity.
|
|
3014
|
+
* Otherwise return the existing receipt, or conflict if contention prevents
|
|
3015
|
+
* observing a stable record. Expiry does not prove an old executor stopped. */
|
|
3016
|
+
readonly claim: (scope: string, key: string, inputHash: string, now: number, ttlMs: number, inFlightLeaseMs: number) => Promise<IdempotencyClaimResult>;
|
|
3017
|
+
/** Atomically match original scope/key/id AND in_flight status. False means
|
|
3018
|
+
* this execution no longer owns a running receipt; never touch its successor. */
|
|
3019
|
+
readonly renew: (claim: IdempotencyClaim, now: number) => Promise<boolean>;
|
|
3020
|
+
/** Complete only the original running claim and start its replay window now. */
|
|
3021
|
+
readonly complete: (claim: IdempotencyClaim, response: IdempotencyResponse, now: number) => Promise<boolean>;
|
|
3022
|
+
/** Release only the original running claim. Completed receipts are retained. */
|
|
3023
|
+
readonly release: (claim: IdempotencyClaim) => Promise<boolean>;
|
|
3024
|
+
}
|
|
3025
|
+
|
|
3026
|
+
/** What an identity's authority resolved to: the subject to run as, or why not. */
|
|
3027
|
+
export declare type IdentityAuthorityOutcome = {
|
|
3028
|
+
readonly kind: 'resolved';
|
|
3029
|
+
readonly subject: Subject;
|
|
3030
|
+
} | {
|
|
3031
|
+
readonly kind: 'unavailable';
|
|
3032
|
+
readonly reason: string;
|
|
3033
|
+
} | {
|
|
3034
|
+
readonly kind: 'vetoed';
|
|
3035
|
+
readonly code: string;
|
|
3036
|
+
readonly message: string;
|
|
3037
|
+
};
|
|
2805
3038
|
|
|
2806
3039
|
/** `/<id>` — the op path for a row id. Ids are JSON-pointer-escaped
|
|
2807
3040
|
* (`~` → `~0`, `/` → `~1`) so a slash or tilde inside a string id can't
|
|
@@ -2947,6 +3180,10 @@ export declare const isSystemSubject: (subject: Subject) => boolean;
|
|
|
2947
3180
|
|
|
2948
3181
|
export declare const isTenantSelectable: (subject: Subject) => subject is TenantSelectableSubject;
|
|
2949
3182
|
|
|
3183
|
+
export declare const isUpgradedCheck: (g: AnyCheckSpec) => g is UpgradedCheckSpec;
|
|
3184
|
+
|
|
3185
|
+
export declare const isUpgradedGuard: <I>(g: AnyGuardSpec<I>) => g is UpgradedGuardSpec;
|
|
3186
|
+
|
|
2950
3187
|
/**
|
|
2951
3188
|
* Is this descriptor allowed on the wire at all?
|
|
2952
3189
|
*
|
|
@@ -3024,7 +3261,7 @@ export declare interface Membership {
|
|
|
3024
3261
|
* project from wherever it keeps them. `input.store` is the app's DataStore. */
|
|
3025
3262
|
export declare type MembershipsSource = (subject: Subject, input: AuthStrategyInput) => Promise<ReadonlyArray<Membership>> | ReadonlyArray<Membership>;
|
|
3026
3263
|
|
|
3027
|
-
/** In-memory store —
|
|
3264
|
+
/** In-memory store — one process only, with unique ownership per acquisition. */
|
|
3028
3265
|
export declare const memoryIdempotencyStore: () => IdempotencyStore;
|
|
3029
3266
|
|
|
3030
3267
|
/** The refusal a missing access decision produces. Exported so the boot gate
|
|
@@ -3065,6 +3302,18 @@ declare const MutationConnectionRequired_base: Schema.Class<MutationConnectionRe
|
|
|
3065
3302
|
readonly traceId: Schema.String;
|
|
3066
3303
|
}>, YieldableError>;
|
|
3067
3304
|
|
|
3305
|
+
/** Input refusal is terminal for this key, not an in-flight retry invitation.
|
|
3306
|
+
* No stored hash, input or response is disclosed. Check the original operation
|
|
3307
|
+
* before deliberately starting another business action. */
|
|
3308
|
+
export declare class MutationIdempotencyRefused extends MutationIdempotencyRefused_base {
|
|
3309
|
+
get message(): string;
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
declare const MutationIdempotencyRefused_base: Schema.Class<MutationIdempotencyRefused, Schema.TaggedStruct<"MutationIdempotencyRefused", {
|
|
3313
|
+
readonly traceId: Schema.String;
|
|
3314
|
+
readonly reason: Schema.Literals<readonly ["input-conflict", "input-unbound", "input-unavailable"]>;
|
|
3315
|
+
}>, YieldableError>;
|
|
3316
|
+
|
|
3068
3317
|
/** Ordinary writes deduplicate across reconnects. A connection-side effect
|
|
3069
3318
|
* (for example joining a room) must execute once for EACH native connection. */
|
|
3070
3319
|
export declare type MutationIdempotencyScope = 'subject' | 'connection';
|
|
@@ -3092,6 +3341,12 @@ export declare interface MutationProcedureDescriptor<Name extends string, Input
|
|
|
3092
3341
|
readonly idempotencyScope?: MutationIdempotencyScope | undefined;
|
|
3093
3342
|
/** Same-key calls run in invocation order on the client — see `defineMutation`. */
|
|
3094
3343
|
readonly serialize?: MutationSerialization<Schema.Schema.Type<Input>> | undefined;
|
|
3344
|
+
/** Exclude this invocation from automatic row-image undo capture, with an
|
|
3345
|
+
* explicit domain reason. Does not disable transactions, guards or audit. */
|
|
3346
|
+
readonly undo?: {
|
|
3347
|
+
readonly capture: false;
|
|
3348
|
+
readonly reason: string;
|
|
3349
|
+
} | undefined;
|
|
3095
3350
|
/** Declarative target(s) — drives auto-optimistic on the client AND
|
|
3096
3351
|
* surfaces which tables this mutation touches (debug, future
|
|
3097
3352
|
* query-invalidation analytics). Mutations without a target run
|
|
@@ -3153,6 +3408,12 @@ export declare interface MutationSerialization<Input = unknown> {
|
|
|
3153
3408
|
|
|
3154
3409
|
export declare const mutationToRpc: <Name extends string, Input extends Schema.Top, Output extends Schema.Top, Err extends Schema.Top>(descriptor: MutationProcedureDescriptor<Name, Input, Output, Err>, extraErrors?: ExtraErrors) => Rpc.Rpc<Name, Input extends Schema.Struct.Fields ? Schema.Struct<Input> : Input, Output, Schema.Top, never, never>;
|
|
3155
3410
|
|
|
3411
|
+
export declare interface NativeFormCaptureDocument {
|
|
3412
|
+
readonly querySelectorAll: (selector: string) => ArrayLike<{
|
|
3413
|
+
readonly getAttribute: (name: string) => string | null;
|
|
3414
|
+
}>;
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3156
3417
|
export declare interface NestedTargetFields<Input = unknown> {
|
|
3157
3418
|
/** Dot-path to the nested array within the query VALUE to patch (e.g.
|
|
3158
3419
|
* `'snapshot.projects'`). Absent → patch the top-level row array (default). */
|
|
@@ -3390,6 +3651,21 @@ export declare const parseEventRoute: (route: string) => {
|
|
|
3390
3651
|
/** The record from a link, or `null` for anything that is not a pairing link. */
|
|
3391
3652
|
export declare const parsePairingLink: (url: string) => Pairing | null;
|
|
3392
3653
|
|
|
3654
|
+
/**
|
|
3655
|
+
* Parse a `revalidate` page export into a duration in milliseconds.
|
|
3656
|
+
*
|
|
3657
|
+
* Accepted shapes:
|
|
3658
|
+
* - number → seconds (Next.js compatibility)
|
|
3659
|
+
* - '<N> seconds' / 's'
|
|
3660
|
+
* - '<N> minutes' / 'm'
|
|
3661
|
+
* - '<N> hours' / 'h'
|
|
3662
|
+
* - '<N> days' / 'd'
|
|
3663
|
+
*
|
|
3664
|
+
* Returns null if the value is missing or unrecognised — caller treats
|
|
3665
|
+
* `null` as "don't cache" (every request re-renders, same as plain SSR).
|
|
3666
|
+
*/
|
|
3667
|
+
export declare const parseRevalidateMs: (value: unknown) => number | null;
|
|
3668
|
+
|
|
3393
3669
|
export declare const patchCellSchema: Schema.decodeTo<Schema.Unknown, Schema.Unknown, never, never>;
|
|
3394
3670
|
|
|
3395
3671
|
/** A single row in a subscription result. Must carry an `id`; everything
|
|
@@ -3435,6 +3711,49 @@ export declare type PendingApproval = Schema.Schema.Type<typeof PendingApproval>
|
|
|
3435
3711
|
/** The normalisation above, applied to any JSON Schema fragment. */
|
|
3436
3712
|
export declare const plainJsonSchema: (value: unknown) => unknown;
|
|
3437
3713
|
|
|
3714
|
+
export declare interface PluginAccountMergeContext extends PluginAccountMergeRequest {
|
|
3715
|
+
/** Borrow the coordinator's existing transaction. No external I/O, separate
|
|
3716
|
+
* pool, nested transaction or session grant belongs in a data hook. */
|
|
3717
|
+
readonly store: DataStore;
|
|
3718
|
+
}
|
|
3719
|
+
|
|
3720
|
+
export declare interface PluginAccountMergeCoverage {
|
|
3721
|
+
readonly participants: ReadonlyArray<{
|
|
3722
|
+
readonly name: string;
|
|
3723
|
+
readonly tables: ReadonlyArray<string>;
|
|
3724
|
+
}>;
|
|
3725
|
+
readonly missing: ReadonlyArray<string>;
|
|
3726
|
+
}
|
|
3727
|
+
|
|
3728
|
+
export declare class PluginAccountMergeFailure extends PluginAccountMergeFailure_base {
|
|
3729
|
+
}
|
|
3730
|
+
|
|
3731
|
+
declare const PluginAccountMergeFailure_base: Schema.Class<PluginAccountMergeFailure, Schema.TaggedStruct<"PluginAccountMergeFailure", {
|
|
3732
|
+
readonly code: Schema.Literals<readonly ["invalid_request", "coverage_missing", "hook_failed"]>;
|
|
3733
|
+
readonly requestId: Schema.String;
|
|
3734
|
+
readonly plugin: Schema.NullOr<Schema.String>;
|
|
3735
|
+
/** Hooks that returned before failure; never evidence of SQL commit. */
|
|
3736
|
+
readonly returned: Schema.$Array<Schema.String>;
|
|
3737
|
+
readonly missing: Schema.$Array<Schema.String>;
|
|
3738
|
+
}>, YieldableError>;
|
|
3739
|
+
|
|
3740
|
+
export declare type PluginAccountMergeHook = (context: PluginAccountMergeContext) => Effect.Effect<void, unknown>;
|
|
3741
|
+
|
|
3742
|
+
export declare interface PluginAccountMergeRegistry {
|
|
3743
|
+
readonly coverage: (kind: 'user' | 'guest') => PluginAccountMergeCoverage;
|
|
3744
|
+
/** The caller owns both-account authorization, confirmation, the transaction
|
|
3745
|
+
* and durable receipt. This registry neither commits nor withdraws identity. */
|
|
3746
|
+
readonly mergeInTransaction: (context: PluginAccountMergeContext) => Effect.Effect<ReadonlyArray<string>, PluginAccountMergeFailure>;
|
|
3747
|
+
}
|
|
3748
|
+
|
|
3749
|
+
export declare interface PluginAccountMergeRequest {
|
|
3750
|
+
readonly requestId: string;
|
|
3751
|
+
readonly tenantId: string;
|
|
3752
|
+
readonly sourceId: string;
|
|
3753
|
+
readonly sourceKind: 'user' | 'guest';
|
|
3754
|
+
readonly targetId: string;
|
|
3755
|
+
}
|
|
3756
|
+
|
|
3438
3757
|
/**
|
|
3439
3758
|
* Called once at app boot, after `voltro dev` resolves the plugin
|
|
3440
3759
|
* list and before the rpc server starts accepting connections. Use
|
|
@@ -3457,6 +3776,37 @@ export declare type PluginActivateHook = (ctx: PluginLifecycleContext) => Effect
|
|
|
3457
3776
|
export declare const pluginAlias: (pluginName: string) => string;
|
|
3458
3777
|
|
|
3459
3778
|
export declare interface PluginBindContext {
|
|
3779
|
+
/** Selected API work; absent custom-host selection means all workloads. */
|
|
3780
|
+
readonly workloads?: ReadonlyArray<ApiWorkload>;
|
|
3781
|
+
/** Starts the app's workflows from server work that has no request, such as
|
|
3782
|
+
* Room results. Present when the app declares workflows. */
|
|
3783
|
+
readonly workflows?: PluginWorkflowStarter;
|
|
3784
|
+
/** Execute an already-provided Effect, preserving typed failures as rejection
|
|
3785
|
+
* values. This does not inject request identity, app services or a new scope. */
|
|
3786
|
+
readonly runEffect?: <A, E>(effect: Effect.Effect<A, E>) => Promise<A>;
|
|
3787
|
+
/** Execute server work with the actual shared app services, including user
|
|
3788
|
+
* Layer overrides, in a scope owned by this call. Available after the host
|
|
3789
|
+
* assembles its service layer, never during store binding or shutdown. No
|
|
3790
|
+
* request Subject, request-local store or transaction is injected. Consume
|
|
3791
|
+
* borrowed services inside the Effect; do not return them beyond its scope.
|
|
3792
|
+
* The host drains admitted calls before plugin/pool teardown. */
|
|
3793
|
+
readonly runWithAppServices?: <A, E, R>(effect: Effect.Effect<A, E, R>) => Promise<A>;
|
|
3794
|
+
/** App-owned subject hook registry. The server caller owns authorization and withdrawal. */
|
|
3795
|
+
readonly privacyRegistry?: PluginPrivacyRegistry;
|
|
3796
|
+
/** App-owned plugin namespace; tenant acquisition remains explicit and isolated. */
|
|
3797
|
+
readonly hotStore?: (context?: {
|
|
3798
|
+
readonly tenantId: string;
|
|
3799
|
+
}) => Promise<HotStoreShape>;
|
|
3800
|
+
/** Same borrowed registry as lifecycle hooks; the API host owns its pools. */
|
|
3801
|
+
readonly connectionRegistry?: ConnectionRegistryShape;
|
|
3802
|
+
readonly connectionReference?: PluginConnectionReference;
|
|
3803
|
+
readonly connectionAvailability?: PluginConnectionAvailability;
|
|
3804
|
+
/** Resolve the registered owner's retained destination for physical reference
|
|
3805
|
+
* protection. Borrowed app wiring; never substitutes the caller's provider. */
|
|
3806
|
+
readonly storageReferenceProvider?: (input: {
|
|
3807
|
+
readonly storageInstance: string;
|
|
3808
|
+
readonly address: StorageAddress;
|
|
3809
|
+
}) => Effect.Effect<StorageProvider, StorageError>;
|
|
3460
3810
|
/**
|
|
3461
3811
|
* This process's replica identity — the same value the event bus stamps as
|
|
3462
3812
|
* its publish `origin` and the membership registry announces under.
|
|
@@ -3476,6 +3826,16 @@ export declare interface PluginBindContext {
|
|
|
3476
3826
|
* who is on the channel, and an instance that dies simply goes quiet.
|
|
3477
3827
|
*/
|
|
3478
3828
|
readonly membership?: {
|
|
3829
|
+
/** Current receiver-observed members from the same app-owned registry.
|
|
3830
|
+
* Optional for custom hosts providing only change notifications. Borrowed:
|
|
3831
|
+
* plugins must not start, stop or replace the membership owner. */
|
|
3832
|
+
readonly list?: () => ReadonlyArray<{
|
|
3833
|
+
readonly instanceId: string;
|
|
3834
|
+
readonly startedAt: number;
|
|
3835
|
+
readonly meta: Readonly<Record<string, string | number>> | undefined;
|
|
3836
|
+
readonly lastHeardAt: number;
|
|
3837
|
+
readonly self: boolean;
|
|
3838
|
+
}>;
|
|
3479
3839
|
readonly onChange: (listener: (event: {
|
|
3480
3840
|
readonly kind: 'joined' | 'left' | 'restarted';
|
|
3481
3841
|
readonly instanceId: string;
|
|
@@ -3583,6 +3943,14 @@ export declare interface PluginCacheHandle {
|
|
|
3583
3943
|
|
|
3584
3944
|
export declare interface PluginCapabilities {
|
|
3585
3945
|
readonly mediaPersist?: PluginMediaPersistCapability;
|
|
3946
|
+
/** Borrow this app instance's bound object transport; the caller owns no pools. */
|
|
3947
|
+
readonly storageProvider?: () => StorageProvider;
|
|
3948
|
+
/** Address-aware object ownership; request tenant resolution is never global. */
|
|
3949
|
+
readonly storageDestinations?: {
|
|
3950
|
+
readonly router: StorageDestinationRouter;
|
|
3951
|
+
readonly directDestination: string | undefined;
|
|
3952
|
+
readonly registry: () => ConnectionRegistryShape | undefined;
|
|
3953
|
+
};
|
|
3586
3954
|
}
|
|
3587
3955
|
|
|
3588
3956
|
/**
|
|
@@ -3704,6 +4072,36 @@ export declare interface PluginCodegenContext {
|
|
|
3704
4072
|
}>;
|
|
3705
4073
|
}
|
|
3706
4074
|
|
|
4075
|
+
/** Resolves only this plugin's admitted role; omitted policy means fail. */
|
|
4076
|
+
export declare type PluginConnectionAvailability = (role: string) => ConnectionUnavailablePolicy;
|
|
4077
|
+
|
|
4078
|
+
export declare interface PluginConnectionNeed {
|
|
4079
|
+
readonly onUnavailable?: ConnectionUnavailablePolicy;
|
|
4080
|
+
readonly kind: ConnectionKind_2;
|
|
4081
|
+
readonly role: string;
|
|
4082
|
+
readonly crossNode?: boolean;
|
|
4083
|
+
/** Use the plugin's direct transport only when no declaration or binding selects this role. */
|
|
4084
|
+
readonly optional?: boolean;
|
|
4085
|
+
}
|
|
4086
|
+
|
|
4087
|
+
/**
|
|
4088
|
+
* Per-app context handed to lifecycle hooks. The shape is intentionally
|
|
4089
|
+
* thin — the framework's deeper services (DataStore, Logger, etc.) are
|
|
4090
|
+
* available via the per-request `AppContext` plugins see in their rpc
|
|
4091
|
+
* interceptors. Lifecycle hooks run OUTSIDE any request, so they
|
|
4092
|
+
* receive a minimal slice:
|
|
4093
|
+
*
|
|
4094
|
+
* - `app`: the resolved app-config metadata
|
|
4095
|
+
* (`{ name, type, voltroVersion }`).
|
|
4096
|
+
* - `logger`: a scoped `@voltro/logger` instance keyed to the
|
|
4097
|
+
* plugin's `name`, so log lines are attributable.
|
|
4098
|
+
* - `env`: the process env (alias of `process.env` for typing).
|
|
4099
|
+
* - `config`: the plugin's own validated config (if `configSchema`
|
|
4100
|
+
* declared) — already decoded against the plugin's Schema, ready
|
|
4101
|
+
* for the hook to consume. Unknown otherwise.
|
|
4102
|
+
*/
|
|
4103
|
+
export declare type PluginConnectionReference = <K extends ConnectionKind_2>(role: string, kind: K) => ConnectionRef<K> | '';
|
|
4104
|
+
|
|
3707
4105
|
/**
|
|
3708
4106
|
* A remote-mounted dashboard surface a plugin contributes. The
|
|
3709
4107
|
* dashboard-host (voltro-cloud / voltro-devtools) renders the mount
|
|
@@ -3814,6 +4212,8 @@ export declare interface PluginEnvVar {
|
|
|
3814
4212
|
readonly generate?: 'base64url' | 'hex' | 'p256';
|
|
3815
4213
|
}
|
|
3816
4214
|
|
|
4215
|
+
export declare type PluginEraseHook = (subjectId: string, context: PluginPrivacyHookContext) => Effect.Effect<void, unknown>;
|
|
4216
|
+
|
|
3817
4217
|
/**
|
|
3818
4218
|
* A cross-cutting error schema a plugin merges into EVERY procedure's
|
|
3819
4219
|
* wire error union. Use when a plugin interceptor can fail with a typed
|
|
@@ -3852,8 +4252,26 @@ export declare interface PluginErrorSchema {
|
|
|
3852
4252
|
};
|
|
3853
4253
|
}
|
|
3854
4254
|
|
|
4255
|
+
/**
|
|
4256
|
+
* Per-call context handed to a plugin-contributed rpc route's
|
|
4257
|
+
* executor. Mirror of the user-handler `AppContext` shape but typed
|
|
4258
|
+
* loosely so the plugin doesn't need to depend on `@voltro/runtime`.
|
|
4259
|
+
*/
|
|
4260
|
+
/** Structural view of the existing request-scoped typed publisher. No runtime import. */
|
|
4261
|
+
export declare interface PluginEventPublisher {
|
|
4262
|
+
publish<Name extends string, Key extends Schema.Top, Payload extends Schema.Top>(descriptor: EventDescriptor<Name, Key, Payload>, key: Schema.Schema.Type<Key>, payload: Schema.Schema.Type<Payload>): Effect.Effect<unknown, unknown>;
|
|
4263
|
+
}
|
|
4264
|
+
|
|
4265
|
+
export declare type PluginExportHook = (subjectId: string, context: PluginPrivacyHookContext) => Effect.Effect<unknown, unknown>;
|
|
4266
|
+
|
|
3855
4267
|
/** A public raw-HTTP route a plugin serves on the framework listener. */
|
|
3856
4268
|
export declare interface PluginHttpRoute {
|
|
4269
|
+
/** Executable API workload owning this route. Omitted means `rpc`.
|
|
4270
|
+
* Discovery and descriptor generation remain independent of role selection. */
|
|
4271
|
+
readonly workload?: ApiWorkload;
|
|
4272
|
+
/** The already-mounted REST projection, retained for SDK/schema inspection.
|
|
4273
|
+
* Do not remount it through generic REST auth or idempotency bindings. */
|
|
4274
|
+
readonly restContract?: RestRouteDescriptor<any, any>;
|
|
3857
4275
|
/** HTTP method, or `'*'` for any (the handler decides). The server mounts the
|
|
3858
4276
|
* path for exactly the methods its routes declare; `'*'` mounts it for every
|
|
3859
4277
|
* method the router knows (34), so keep that for a route that really serves
|
|
@@ -3882,6 +4300,13 @@ export declare interface PluginHttpRoute {
|
|
|
3882
4300
|
*/
|
|
3883
4301
|
readonly match?: 'prefix' | 'exact';
|
|
3884
4302
|
readonly handle: (req: PluginHttpRouteRequest) => Promise<PluginHttpRouteResult>;
|
|
4303
|
+
/** Lazy, backpressured input instead of a buffered rawBody on real HTTP.
|
|
4304
|
+
* Requires match: 'exact' and exclusive ownership of the router-equivalent
|
|
4305
|
+
* path (including other methods). The required handle remains the buffered
|
|
4306
|
+
* in-process entry. Both entries must apply the same authorization/codec.
|
|
4307
|
+
* maxBodyBytes counts consumed bytes; overflow overrides the handler's
|
|
4308
|
+
* response with 413 even when the handler catches the read error. */
|
|
4309
|
+
readonly handleStream?: (req: PluginHttpRouteStreamRequest) => Promise<PluginHttpRouteResult>;
|
|
3885
4310
|
/** Per-route body cap override (bytes) — wins over the listener's shared
|
|
3886
4311
|
* `maxBodyBytes`. NOTE: routes SHARING a path share one body read, so the
|
|
3887
4312
|
* widest override on the path's group applies to the whole group. */
|
|
@@ -4108,11 +4533,23 @@ export declare interface PluginHttpRouteResult {
|
|
|
4108
4533
|
*/
|
|
4109
4534
|
export declare interface PluginHttpRouteStream {
|
|
4110
4535
|
readonly subscribe: (emit: (chunk: string) => void) => () => void;
|
|
4536
|
+
/** Per-connection lifetime in milliseconds (1..2147483647). Ending the
|
|
4537
|
+
* response releases the subscription and keep-alive timer. Absent: no cap. */
|
|
4538
|
+
readonly maxDurationMs?: number;
|
|
4111
4539
|
/** Keep-alive comment interval in ms (default 15000; `0` disables). Without
|
|
4112
4540
|
* it an idle SSE connection is dropped by proxies after ~30–60s. */
|
|
4113
4541
|
readonly keepAliveMs?: number;
|
|
4114
4542
|
}
|
|
4115
4543
|
|
|
4544
|
+
/** A lazy binary request on the framework listener. No body bytes are read
|
|
4545
|
+
* before the handler runs. Consume once, through EOF, before accepting an
|
|
4546
|
+
* upload; returning early drains the unread body without validating it.
|
|
4547
|
+
* The signal ends on disconnect, interruption or handler completion. */
|
|
4548
|
+
export declare interface PluginHttpRouteStreamRequest extends Omit<PluginHttpRouteRequest, 'rawBody'> {
|
|
4549
|
+
readonly body: AsyncIterable<Uint8Array>;
|
|
4550
|
+
readonly signal: AbortSignal;
|
|
4551
|
+
}
|
|
4552
|
+
|
|
4116
4553
|
export declare interface PluginInspectEndpoint {
|
|
4117
4554
|
/** HTTP method. */
|
|
4118
4555
|
readonly method: 'GET' | 'POST' | 'DELETE';
|
|
@@ -4241,23 +4678,9 @@ export declare const pluginInstanceName: (args: {
|
|
|
4241
4678
|
readonly instance?: string | undefined;
|
|
4242
4679
|
}) => string;
|
|
4243
4680
|
|
|
4244
|
-
/**
|
|
4245
|
-
* Per-app context handed to lifecycle hooks. The shape is intentionally
|
|
4246
|
-
* thin — the framework's deeper services (DataStore, Logger, etc.) are
|
|
4247
|
-
* available via the per-request `AppContext` plugins see in their rpc
|
|
4248
|
-
* interceptors. Lifecycle hooks run OUTSIDE any request, so they
|
|
4249
|
-
* receive a minimal slice:
|
|
4250
|
-
*
|
|
4251
|
-
* - `app`: the resolved app-config metadata
|
|
4252
|
-
* (`{ name, type, voltroVersion }`).
|
|
4253
|
-
* - `logger`: a scoped `@voltro/logger` instance keyed to the
|
|
4254
|
-
* plugin's `name`, so log lines are attributable.
|
|
4255
|
-
* - `env`: the process env (alias of `process.env` for typing).
|
|
4256
|
-
* - `config`: the plugin's own validated config (if `configSchema`
|
|
4257
|
-
* declared) — already decoded against the plugin's Schema, ready
|
|
4258
|
-
* for the hook to consume. Unknown otherwise.
|
|
4259
|
-
*/
|
|
4260
4681
|
export declare interface PluginLifecycleContext {
|
|
4682
|
+
/** Selected API work; absent custom-host selection means all workloads. */
|
|
4683
|
+
readonly workloads?: ReadonlyArray<ApiWorkload>;
|
|
4261
4684
|
readonly app: {
|
|
4262
4685
|
readonly name: string;
|
|
4263
4686
|
readonly type: 'api' | 'web';
|
|
@@ -4272,6 +4695,11 @@ export declare interface PluginLifecycleContext {
|
|
|
4272
4695
|
readonly env: NodeJS.ProcessEnv;
|
|
4273
4696
|
/** Validated plugin config (if `configSchema` was declared). */
|
|
4274
4697
|
readonly config: unknown;
|
|
4698
|
+
/** App-owned command registry, available before API plugin activation. Never dispose it. */
|
|
4699
|
+
readonly connectionRegistry?: ConnectionRegistryShape;
|
|
4700
|
+
/** Resolve only this plugin's declared role through the app's binding/default. */
|
|
4701
|
+
readonly connectionReference?: PluginConnectionReference;
|
|
4702
|
+
readonly connectionAvailability?: PluginConnectionAvailability;
|
|
4275
4703
|
}
|
|
4276
4704
|
|
|
4277
4705
|
/** Where the offloaded-inference dispatcher puts a media artifact a provider
|
|
@@ -4356,7 +4784,13 @@ export declare type PluginMigrationSqlClient = SqlClient.SqlClient;
|
|
|
4356
4784
|
* boot log + `/_voltro/inspect/plugins` so operators audit what each
|
|
4357
4785
|
* plugin asks for before installing.
|
|
4358
4786
|
*/
|
|
4359
|
-
export declare type PluginPermission = 'rpc:intercept:mutation' | 'rpc:intercept:query' | 'rpc:intercept:action' | 'rpc:intercept:workflow' | 'schedule:fire' | 'schedule:read' | 'workflow:step' | 'http:intercept' | 'inspect:read' | 'inspect:write' | 'dashboard:mount' | 'outbox:handle' | 'store:write' | 'migration:run' | 'store:changes:read' | `secrets:read:${string}` | `network:outbound:${string}` | `plugin:hook:${string}`;
|
|
4787
|
+
export declare type PluginPermission = 'rpc:authority:replay' | 'rpc:intercept:mutation' | 'rpc:intercept:query' | 'rpc:intercept:action' | 'rpc:intercept:workflow' | 'rpc:intercept:stream' | 'schedule:fire' | 'schedule:read' | 'workflow:step' | 'http:intercept' | 'inspect:read' | 'inspect:write' | 'dashboard:mount' | 'outbox:handle' | 'store:write' | 'migration:run' | 'store:changes:read' | `secrets:read:${string}` | `network:outbound:${string}` | `plugin:hook:${string}`;
|
|
4788
|
+
|
|
4789
|
+
export declare interface PluginPrivacyCoverage {
|
|
4790
|
+
readonly participants: ReadonlyArray<PluginPrivacyParticipant>;
|
|
4791
|
+
/** Plugin declarations only. App-owned tables require their own declared hooks. */
|
|
4792
|
+
readonly missing: ReadonlyArray<string>;
|
|
4793
|
+
}
|
|
4360
4794
|
|
|
4361
4795
|
/** What a plugin collects and uses — folded by `voltro compliance generate`
|
|
4362
4796
|
* into PrivacyInfo.xcprivacy and the Play Data-safety answers. A plugin that
|
|
@@ -4366,12 +4800,76 @@ export declare interface PluginPrivacyDeclaration {
|
|
|
4366
4800
|
readonly requiredReasonApis?: ReadonlyArray<PrivacyRequiredReasonApi>;
|
|
4367
4801
|
}
|
|
4368
4802
|
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4803
|
+
export declare type PluginPrivacyErasePhase = typeof PluginPrivacyErasePhaseSchema.Type;
|
|
4804
|
+
|
|
4805
|
+
/** Resource/actor withdrawal must finish before destructive data hooks. */
|
|
4806
|
+
export declare const PluginPrivacyErasePhaseSchema: Schema.Literals<readonly ["prepare", "data", "identity", "finalize"]>;
|
|
4807
|
+
|
|
4808
|
+
export declare interface PluginPrivacyErasure {
|
|
4809
|
+
readonly requestId: string;
|
|
4810
|
+
readonly target: PluginPrivacyTarget;
|
|
4811
|
+
readonly completed: ReadonlyArray<string>;
|
|
4812
|
+
}
|
|
4813
|
+
|
|
4814
|
+
export declare interface PluginPrivacyExport {
|
|
4815
|
+
readonly requestId: string;
|
|
4816
|
+
readonly target: PluginPrivacyTarget;
|
|
4817
|
+
readonly plugins: ReadonlyArray<{
|
|
4818
|
+
readonly name: string;
|
|
4819
|
+
readonly data: unknown;
|
|
4820
|
+
}>;
|
|
4821
|
+
}
|
|
4822
|
+
|
|
4823
|
+
/** Never carries a driver's error, credentials, exported rows or the hook's cause. */
|
|
4824
|
+
export declare class PluginPrivacyFailure extends PluginPrivacyFailure_base {
|
|
4825
|
+
}
|
|
4826
|
+
|
|
4827
|
+
declare const PluginPrivacyFailure_base: Schema.Class<PluginPrivacyFailure, Schema.TaggedStruct<"PluginPrivacyFailure", {
|
|
4828
|
+
readonly code: Schema.Literals<readonly ["invalid_request", "coverage_missing", "hook_failed", "unavailable"]>;
|
|
4829
|
+
readonly operation: Schema.Literals<readonly ["export", "erase"]>;
|
|
4830
|
+
readonly requestId: Schema.String;
|
|
4831
|
+
readonly plugin: Schema.NullOr<Schema.String>;
|
|
4832
|
+
readonly completed: Schema.$Array<Schema.String>;
|
|
4833
|
+
readonly missing: Schema.$Array<Schema.String>;
|
|
4834
|
+
}>, YieldableError>;
|
|
4835
|
+
|
|
4836
|
+
export declare interface PluginPrivacyHookContext {
|
|
4837
|
+
readonly requestId: string;
|
|
4838
|
+
readonly tenantId: string | null;
|
|
4839
|
+
readonly kind: 'user' | 'guest';
|
|
4840
|
+
/** Only the finalizer receives these immutable, successfully completed hook names. */
|
|
4841
|
+
readonly completed?: ReadonlyArray<string>;
|
|
4842
|
+
}
|
|
4843
|
+
|
|
4844
|
+
export declare interface PluginPrivacyParticipant {
|
|
4845
|
+
readonly name: string;
|
|
4846
|
+
readonly tables: ReadonlyArray<string>;
|
|
4847
|
+
readonly erasePhase: PluginPrivacyErasePhase;
|
|
4848
|
+
}
|
|
4849
|
+
|
|
4850
|
+
/** Borrowed app-owned hook port. Authorization and durable withdrawal belong to the caller. */
|
|
4851
|
+
export declare interface PluginPrivacyRegistry {
|
|
4852
|
+
readonly coverage: (kind: PluginPrivacyTarget['kind']) => PluginPrivacyCoverage;
|
|
4853
|
+
readonly exportSubject: (request: PluginPrivacyRequest) => Effect.Effect<PluginPrivacyExport, PluginPrivacyFailure>;
|
|
4854
|
+
readonly eraseSubject: (request: PluginPrivacyRequest) => Effect.Effect<PluginPrivacyErasure, PluginPrivacyFailure>;
|
|
4855
|
+
}
|
|
4856
|
+
|
|
4857
|
+
/** Reuse the request identity on recovery; hooks must be idempotent. */
|
|
4858
|
+
export declare interface PluginPrivacyRequest {
|
|
4859
|
+
readonly requestId: string;
|
|
4860
|
+
readonly target: PluginPrivacyTarget;
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
/** A server-authorized subject, never an identity accepted from a client body. */
|
|
4864
|
+
export declare interface PluginPrivacyTarget {
|
|
4865
|
+
readonly subjectId: string;
|
|
4866
|
+
readonly tenantId: string | null;
|
|
4867
|
+
readonly kind: 'user' | 'guest';
|
|
4868
|
+
}
|
|
4869
|
+
|
|
4374
4870
|
export declare interface PluginRouteContext {
|
|
4871
|
+
/** Borrows the host request publisher, preserving tenant and transaction ownership. */
|
|
4872
|
+
readonly events?: PluginEventPublisher;
|
|
4375
4873
|
/** Request-scoped transaction for mutation routes. Reuse it instead of opening
|
|
4376
4874
|
* a transaction on the plugin's bound root store. Absent on direct calls. */
|
|
4377
4875
|
readonly mutationStore?: DataStore;
|
|
@@ -4474,6 +4972,8 @@ export declare interface PluginRpcRoute {
|
|
|
4474
4972
|
* checking.
|
|
4475
4973
|
*/
|
|
4476
4974
|
readonly source?: ReactivitySourceValue | ReadonlyArray<ReactivitySourceValue> | undefined;
|
|
4975
|
+
/** Optional integration observers; each name must also occur in source. */
|
|
4976
|
+
readonly optionalSource?: ReadonlyArray<string> | undefined;
|
|
4477
4977
|
/**
|
|
4478
4978
|
* The route's ACCESS DECISION — the same two-field vocabulary user
|
|
4479
4979
|
* procedures carry, because a plugin route is dispatched through the exact
|
|
@@ -4540,6 +5040,23 @@ export declare interface PluginSchemaContribution {
|
|
|
4540
5040
|
*/
|
|
4541
5041
|
export declare const pluginSlug: (pluginName: string) => string;
|
|
4542
5042
|
|
|
5043
|
+
export declare interface PluginSubjectMerge {
|
|
5044
|
+
readonly tables: ReadonlyArray<string>;
|
|
5045
|
+
/** Source kinds whose data this implementation can reconcile. */
|
|
5046
|
+
readonly kinds: ReadonlyArray<'user' | 'guest'>;
|
|
5047
|
+
}
|
|
5048
|
+
|
|
5049
|
+
/** SQL tables owned by this hook pair. External resources belong in the hooks too. */
|
|
5050
|
+
export declare interface PluginSubjectPrivacy {
|
|
5051
|
+
readonly tables: ReadonlyArray<string>;
|
|
5052
|
+
readonly kinds: ReadonlyArray<PluginPrivacyTarget['kind']>;
|
|
5053
|
+
/** Preparation withdraws active work before data hooks. Identity/session
|
|
5054
|
+
* deletion follows every data hook, regardless of plugin order. */
|
|
5055
|
+
/** Terminal request bookkeeping follows every data and identity hook.
|
|
5056
|
+
* At most one finalizer may own completion for each subject kind. */
|
|
5057
|
+
readonly erasePhase?: PluginPrivacyErasePhase;
|
|
5058
|
+
}
|
|
5059
|
+
|
|
4543
5060
|
/**
|
|
4544
5061
|
* The wire tag a plugin's own client code must call for one of its routes.
|
|
4545
5062
|
*
|
|
@@ -4622,6 +5139,20 @@ export declare interface PluginTemplate {
|
|
|
4622
5139
|
*/
|
|
4623
5140
|
export declare type PluginUninstallHook = (ctx: PluginLifecycleContext) => Effect.Effect<void, unknown> | Promise<void> | void;
|
|
4624
5141
|
|
|
5142
|
+
/** Starts app workflows from plugin server work outside a request. */
|
|
5143
|
+
export declare interface PluginWorkflowStarter {
|
|
5144
|
+
/** Resolves once the run is accepted. Runs as the plugin's system subject
|
|
5145
|
+
* (`plugin:<name>`); rejects while the host's workflow runtime is not ready. */
|
|
5146
|
+
start(workflowName: string, payload: unknown): Promise<unknown>;
|
|
5147
|
+
}
|
|
5148
|
+
|
|
5149
|
+
export declare type PluginWorkloadHook = (context: PluginLifecycleContext) => Effect.Effect<PluginWorkloadResource, unknown> | Promise<PluginWorkloadResource> | PluginWorkloadResource;
|
|
5150
|
+
|
|
5151
|
+
export declare interface PluginWorkloadResource {
|
|
5152
|
+
/** Await drainage; rejection retains ownership and must be retryable. */
|
|
5153
|
+
stop(): Effect.Effect<void, unknown> | Promise<void> | void;
|
|
5154
|
+
}
|
|
5155
|
+
|
|
4625
5156
|
/** The runtime-erased form of `PolicyGuardSpec` — a relationship check. */
|
|
4626
5157
|
export declare interface PolicyCheckSpec {
|
|
4627
5158
|
readonly action: string | ((input: unknown) => string);
|
|
@@ -4678,6 +5209,17 @@ export declare interface PolicyGuardSpec<Input = unknown> {
|
|
|
4678
5209
|
readonly resource: (input: Input) => string | undefined;
|
|
4679
5210
|
}
|
|
4680
5211
|
|
|
5212
|
+
export declare interface PreparedIdempotentInput {
|
|
5213
|
+
readonly input: unknown;
|
|
5214
|
+
readonly fingerprint: string;
|
|
5215
|
+
}
|
|
5216
|
+
|
|
5217
|
+
/** Capture the declared schema's wire input before waiting for a receipt.
|
|
5218
|
+
* Decode an independent snapshot for execution and require an equal round trip.
|
|
5219
|
+
* The principal comes from server authentication, never a client digest/header.
|
|
5220
|
+
* This binds identity and input, not current permissions or a business lease. */
|
|
5221
|
+
export declare const prepareIdempotentInput: (schema: Schema.Top, offered: unknown, subject: Subject, transportInput?: unknown) => Promise<PreparedIdempotentInput>;
|
|
5222
|
+
|
|
4681
5223
|
/**
|
|
4682
5224
|
* An environment variable a plugin reads. DECLARATION ONLY — metadata, not a
|
|
4683
5225
|
* read path: the plugin still reads the value itself (typically
|
|
@@ -4772,6 +5314,9 @@ export declare interface PublicApiClientConfig {
|
|
|
4772
5314
|
readonly baseUrl?: string;
|
|
4773
5315
|
}
|
|
4774
5316
|
|
|
5317
|
+
/** A descriptor kind that can be projected to REST (streams are not, in v1). */
|
|
5318
|
+
declare type PublicApiDescriptor = QueryProcedureDescriptor<string, Schema.Top, Schema.Top, Schema.Top> | MutationProcedureDescriptor<string, Schema.Top, Schema.Top, Schema.Top> | ActionProcedureDescriptor<string, Schema.Top, Schema.Top, Schema.Top>;
|
|
5319
|
+
|
|
4775
5320
|
/** The `publicApi:` block of an api `app.config.ts`, and the shape of a
|
|
4776
5321
|
* descriptor's `publicApi.format` override (every field optional there). */
|
|
4777
5322
|
export declare interface PublicApiProfileConfig {
|
|
@@ -4848,6 +5393,10 @@ export declare interface PublicApiSpec {
|
|
|
4848
5393
|
/** Streaming queries over request/response: 'snapshot' (default — first
|
|
4849
5394
|
* snapshot, like POST /rpc) | 'sse' (Server-Sent Events of snapshot+deltas). */
|
|
4850
5395
|
readonly stream?: 'snapshot' | 'sse';
|
|
5396
|
+
/** Per-connection SSE lifetime in milliseconds (1..2147483647). Requires
|
|
5397
|
+
* an SSE query projection. Clients may reconnect for a freshly authorized
|
|
5398
|
+
* snapshot; expiry does not cancel a domain operation. */
|
|
5399
|
+
readonly streamMaxDurationMs?: number;
|
|
4851
5400
|
/**
|
|
4852
5401
|
* HTTP status per DECLARED typed error tag, for the projection. A typed
|
|
4853
5402
|
* error the handler fails with — one of the descriptor's `error:` union —
|
|
@@ -4859,6 +5408,11 @@ export declare interface PublicApiSpec {
|
|
|
4859
5408
|
* publicApi: { errorStatus: { AccessDeniedError: 403, NotFoundError: 404 } }
|
|
4860
5409
|
*/
|
|
4861
5410
|
readonly errorStatus?: Readonly<Record<string, number>>;
|
|
5411
|
+
/** Additional HTTP failure statuses for the same declared error schema.
|
|
5412
|
+
* Documents dedicated handlers that choose a status from the error's fields;
|
|
5413
|
+
* does not change `errorStatus` or the generic projection's runtime mapping.
|
|
5414
|
+
* Values must be integer HTTP error statuses (400–599); duplicates are omitted. */
|
|
5415
|
+
readonly additionalErrorStatuses?: Readonly<Record<string, ReadonlyArray<number>>>;
|
|
4862
5416
|
/**
|
|
4863
5417
|
* The spec's tag group(s) for this operation. Default: the rpc tag's prefix
|
|
4864
5418
|
* (`teams.list` → `teams`) — the first path segment, what a consumer looks
|
|
@@ -4960,6 +5514,16 @@ export declare interface QueryCacheConfig {
|
|
|
4960
5514
|
* cardinality of a cache the author sized per org.
|
|
4961
5515
|
*/
|
|
4962
5516
|
readonly scope: 'subject' | 'tenant' | 'global';
|
|
5517
|
+
/**
|
|
5518
|
+
* The handler's result also depends on something no table write
|
|
5519
|
+
* invalidates — the clock, randomness, `ctx.connections`, an outgoing HTTP
|
|
5520
|
+
* call, `ctx.kv`. Applies to a COMPUTED query (a handler that returns a
|
|
5521
|
+
* value): without it such a result is computed but NOT kept, and the dev log
|
|
5522
|
+
* names what was used. With it, `ttl` is the bound on how stale that part may
|
|
5523
|
+
* be. `Date.now()`, `Math.random()` and a `fetch` outside the framework's
|
|
5524
|
+
* HTTP client are not observable — a handler that uses them must say so here.
|
|
5525
|
+
*/
|
|
5526
|
+
readonly volatile?: boolean | undefined;
|
|
4963
5527
|
}
|
|
4964
5528
|
|
|
4965
5529
|
export declare interface QueryProcedureDescriptor<Name extends string, Input extends Schema.Top, Output extends Schema.Top, Error extends Schema.Top> {
|
|
@@ -4974,6 +5538,9 @@ export declare interface QueryProcedureDescriptor<Name extends string, Input ext
|
|
|
4974
5538
|
* listed table changes (pass an array to depend on several). Optional:
|
|
4975
5539
|
* queries without a source never receive auto-patches (joins, aggregates). */
|
|
4976
5540
|
readonly source: string | ReadonlyArray<string> | undefined;
|
|
5541
|
+
/** Optional integration observers, all also present in source. They keep
|
|
5542
|
+
* invalidation active when installed; absence is a visible graph warning. */
|
|
5543
|
+
readonly optionalSource?: ReadonlyArray<string>;
|
|
4977
5544
|
/** Server-side snapshot cache config. Absent → never cached (the
|
|
4978
5545
|
* default; the dispatcher already keeps live subscriptions fresh). */
|
|
4979
5546
|
readonly cache: QueryCacheConfig | undefined;
|
|
@@ -5128,6 +5695,8 @@ export declare type ReactivitySource = TableName | ReactivityChannel;
|
|
|
5128
5695
|
*/
|
|
5129
5696
|
export declare type ReactivitySourceValue = string | ReactivityChannel;
|
|
5130
5697
|
|
|
5698
|
+
export declare const readFormCaptureSource: (document?: NativeFormCaptureDocument | undefined) => string | undefined;
|
|
5699
|
+
|
|
5131
5700
|
export declare const readPairing: (storage: PairingStorage) => Promise<Pairing | null>;
|
|
5132
5701
|
|
|
5133
5702
|
/**
|
|
@@ -5199,9 +5768,25 @@ export declare type RequestedTenantSource = (subject: Subject, input: AuthStrate
|
|
|
5199
5768
|
* Checks the EFFECTIVE set so role-derived scopes count. */
|
|
5200
5769
|
export declare const requireScope: (subject: Subject, scope: string) => Effect.Effect<void, ScopeError>;
|
|
5201
5770
|
|
|
5771
|
+
/** Browser-safe descriptor guard for capabilities that require registration. */
|
|
5772
|
+
export declare const requireUpgraded: () => UpgradedGuardSpec;
|
|
5773
|
+
|
|
5202
5774
|
/** Drop every registration. Tests only — production registers once at module load. */
|
|
5203
5775
|
export declare const resetPluginAliases: () => void;
|
|
5204
5776
|
|
|
5777
|
+
/**
|
|
5778
|
+
* Put authority back onto an IDENTITY that arrived without it — a resumed
|
|
5779
|
+
* durable run, a redeemed Room seat — through the app's own `resolveScopes`
|
|
5780
|
+
* and `subjectGuards`, the same seam a request uses. Credentials never carry
|
|
5781
|
+
* scopes (`subjectIdentity`), so every non-request consumer resolves here
|
|
5782
|
+
* rather than trusting authority frozen at mint time. With no resolver the
|
|
5783
|
+
* identity keeps what it carries (nothing), the fail-closed default.
|
|
5784
|
+
*/
|
|
5785
|
+
export declare const resolveIdentityAuthority: (identity: Subject, ctx: AuthSubjectGuardContext, authority: {
|
|
5786
|
+
readonly resolveScopes?: ((subject: Subject, ctx: AuthSubjectGuardContext) => Promise<ScopeResolverResult> | ScopeResolverResult) | undefined;
|
|
5787
|
+
readonly subjectGuards?: ReadonlyArray<AuthSubjectGuard> | undefined;
|
|
5788
|
+
} | undefined) => Promise<IdentityAuthorityOutcome>;
|
|
5789
|
+
|
|
5205
5790
|
/** Resolve the input-selected action once. Invalid selectors deny rather than
|
|
5206
5791
|
* widening to any action the subject happens to hold. Also used when an
|
|
5207
5792
|
* approval persists the resolved guard for its later recheck. */
|
|
@@ -5398,7 +5983,7 @@ export declare interface RestFormatResponse {
|
|
|
5398
5983
|
readonly contentType?: string;
|
|
5399
5984
|
}
|
|
5400
5985
|
|
|
5401
|
-
declare type RestGuard = (ctx: RestRouteContext) => RestGuardRejection | undefined | Promise<RestGuardRejection | undefined>;
|
|
5986
|
+
declare type RestGuard = (ctx: RestRouteContext, request?: RestGuardRequest) => RestGuardRejection | undefined | Promise<RestGuardRejection | undefined>;
|
|
5402
5987
|
|
|
5403
5988
|
/**
|
|
5404
5989
|
* A guard runs after input decode + ctx resolution, before the handler.
|
|
@@ -5410,6 +5995,13 @@ declare interface RestGuardRejection {
|
|
|
5410
5995
|
readonly message: string;
|
|
5411
5996
|
}
|
|
5412
5997
|
|
|
5998
|
+
/** Guard input is the decoded execution snapshot. Guards are read-only
|
|
5999
|
+
* admission checks and may run again after awaited admission/storage work. */
|
|
6000
|
+
declare interface RestGuardRequest {
|
|
6001
|
+
readonly input: unknown;
|
|
6002
|
+
readonly defaultDeny: boolean;
|
|
6003
|
+
}
|
|
6004
|
+
|
|
5413
6005
|
/** What a REST handler may return: the decoded output, a `response(...)` with
|
|
5414
6006
|
* its own status and headers, an `sse(...)` stream, or `bytes(...)` for a
|
|
5415
6007
|
* non-JSON body (a file, an export, an XML document). */
|
|
@@ -5449,6 +6041,8 @@ declare interface RestResponse<O> {
|
|
|
5449
6041
|
* stays free of the database dep).
|
|
5450
6042
|
*/
|
|
5451
6043
|
declare interface RestRouteContext {
|
|
6044
|
+
/** Server-owned invocation trace, stable through readmission and projection. */
|
|
6045
|
+
readonly traceId: string;
|
|
5452
6046
|
readonly subject: Subject;
|
|
5453
6047
|
readonly headers: Readonly<Record<string, string>>;
|
|
5454
6048
|
/** Request metadata and the byte-exact body as received by the HTTP
|
|
@@ -5473,6 +6067,9 @@ declare interface RestRouteContext {
|
|
|
5473
6067
|
}
|
|
5474
6068
|
|
|
5475
6069
|
declare interface RestRouteDescriptor<I, O> {
|
|
6070
|
+
/** Original schemas for client generation. Metadata only: never mounts a
|
|
6071
|
+
* second handler or selects authentication/idempotency bindings. */
|
|
6072
|
+
readonly publicApiDescriptor?: PublicApiDescriptor;
|
|
5476
6073
|
readonly method: RestMethod;
|
|
5477
6074
|
/** Absolute path, e.g. `/v1/customers`. Matches that path exactly. */
|
|
5478
6075
|
readonly path: string;
|
|
@@ -5486,6 +6083,12 @@ declare interface RestRouteDescriptor<I, O> {
|
|
|
5486
6083
|
* encodes it to JSON for the `200` response. */
|
|
5487
6084
|
readonly output: Schema.Codec<O, any, never, never>;
|
|
5488
6085
|
readonly handler: (input: I, ctx: RestRouteContext) => Promise<RestHandlerResult<O>> | RestHandlerResult<O>;
|
|
6086
|
+
/** Pure synchronous normalization of thrown admission/handler failures.
|
|
6087
|
+
* Return a mapped thrown value (for example RestRouteError), not an HTTP
|
|
6088
|
+
* response; undefined keeps the original failure. Available before authentication,
|
|
6089
|
+
* so only request metadata is given.
|
|
6090
|
+
* Public projections supply their existing typed/profile error mapper here. */
|
|
6091
|
+
readonly mapFailure?: (error: unknown, request: Pick<PluginHttpRouteRequest, 'method' | 'path' | 'query'>) => unknown;
|
|
5489
6092
|
readonly summary?: string;
|
|
5490
6093
|
readonly description?: string;
|
|
5491
6094
|
readonly example?: RestRouteExample;
|
|
@@ -5595,14 +6198,23 @@ declare interface RestRouteProjection {
|
|
|
5595
6198
|
* auth subject + the bound DataStore.
|
|
5596
6199
|
*/
|
|
5597
6200
|
declare interface RestServeBindings {
|
|
6201
|
+
/** Pure scope-refresher registration, shared with native RPC admission. */
|
|
6202
|
+
readonly bindReplayAuthority?: RpcReplayAuthorityBinding;
|
|
6203
|
+
/** Actual host policy for projected procedure guards; raw routes own guards. */
|
|
6204
|
+
readonly defaultDeny?: boolean;
|
|
6205
|
+
/** Full runtime hosts supply their existing trace generator. */
|
|
6206
|
+
readonly traceId?: () => string;
|
|
5598
6207
|
/** Bound once from the app's mounted rate-limit plugin. */
|
|
5599
6208
|
readonly rateLimit?: (policy: RestRateLimit, ctx: RestRouteContext, route: RestRouteDescriptor<any, any>) => Effect.Effect<void, unknown>;
|
|
5600
|
-
/** Resolve the calling subject
|
|
5601
|
-
readonly resolveSubject?: (headers: Readonly<Record<string, string
|
|
6209
|
+
/** Resolve the calling subject and request-local selection before guards. */
|
|
6210
|
+
readonly resolveSubject?: (headers: Readonly<Record<string, string>>, request: {
|
|
6211
|
+
readonly path: string;
|
|
6212
|
+
readonly query: string;
|
|
6213
|
+
}) => Subject | Promise<Subject>;
|
|
5602
6214
|
/** The bound framework DataStore. */
|
|
5603
6215
|
readonly store?: unknown;
|
|
5604
6216
|
/** Build the full per-request app context after authentication. */
|
|
5605
|
-
readonly buildContext?: (subject: Subject, headers: Readonly<Record<string, string
|
|
6217
|
+
readonly buildContext?: (subject: Subject, headers: Readonly<Record<string, string>>, request: Pick<RestRouteContext, 'traceId' | 'remoteAddr'>) => unknown | Promise<unknown>;
|
|
5606
6218
|
/**
|
|
5607
6219
|
* HTTP idempotency — when set, a mutating request (POST/PUT/PATCH/DELETE)
|
|
5608
6220
|
* carrying the `header` is deduplicated: the first call runs + caches its
|
|
@@ -5772,7 +6384,7 @@ export declare interface RpcInterceptorContext {
|
|
|
5772
6384
|
readonly enqueueOutcome?: OutboxEnqueueFacade['enqueue'];
|
|
5773
6385
|
/** Procedure tag, e.g. `todos.create`. */
|
|
5774
6386
|
readonly tag: string;
|
|
5775
|
-
/**
|
|
6387
|
+
/** Procedure kind, including finite stream admission. */
|
|
5776
6388
|
readonly kind: RpcKind;
|
|
5777
6389
|
/** The validated input the executor is about to (or already did) receive. */
|
|
5778
6390
|
readonly input: unknown;
|
|
@@ -5808,10 +6420,20 @@ export declare interface RpcInterceptorContext {
|
|
|
5808
6420
|
* Which kind of rpc the interceptor is wrapping. The runtime passes
|
|
5809
6421
|
* `kind: 'mutation'` to interceptors registered as `interceptMutation`,
|
|
5810
6422
|
* `kind: 'query'` to `interceptQuery`, `kind: 'action'` to
|
|
5811
|
-
* `interceptAction`,
|
|
6423
|
+
* `interceptAction`, `kind: 'workflow'` to `interceptWorkflow`, and
|
|
6424
|
+
* `kind: 'stream'` to `interceptStream` — one
|
|
5812
6425
|
* plugin can implement any combination.
|
|
5813
6426
|
*/
|
|
5814
|
-
export declare type RpcKind = 'mutation' | 'query' | 'action' | 'workflow';
|
|
6427
|
+
export declare type RpcKind = 'mutation' | 'query' | 'action' | 'workflow' | 'stream';
|
|
6428
|
+
|
|
6429
|
+
export declare type RpcReplayAuthorityBinding = (context: RpcReplayAuthorityContext) => undefined;
|
|
6430
|
+
|
|
6431
|
+
/** Pure synchronous authority-refresher binding for RPC and REST admission.
|
|
6432
|
+
* No business work, I/O, grants or side effects belong in this hook. The host
|
|
6433
|
+
* calls the existing guard rechecker after every binding. */
|
|
6434
|
+
export declare interface RpcReplayAuthorityContext extends Pick<RpcInterceptorContext, 'tag' | 'input' | 'subject' | 'traceId' | 'surface' | 'publicApi' | 'remoteAddr'> {
|
|
6435
|
+
readonly kind: RpcKind | 'rest';
|
|
6436
|
+
}
|
|
5815
6437
|
|
|
5816
6438
|
/**
|
|
5817
6439
|
* Per-firing context passed to schedule-fire interceptors. Shape
|
|
@@ -5960,6 +6582,10 @@ declare const ScopeError_base: Schema.Class<ScopeError, Schema.TaggedStruct<"Sco
|
|
|
5960
6582
|
* resolver already has. */
|
|
5961
6583
|
export declare type ScopeResolverResult = ReadonlyArray<string> | ScopeDecision;
|
|
5962
6584
|
|
|
6585
|
+
/** Exact tags outrank namespace filters; deeper namespaces outrank broader ones.
|
|
6586
|
+
* Equal specificity is an ambiguity, never an implicit failover/credential hop. */
|
|
6587
|
+
export declare const selectApiRoleEndpoint: (endpoints: ApiRoleEndpoints, tag: string, workload: ApiRoleRpcWorkload) => ApiRoleEndpoint;
|
|
6588
|
+
|
|
5963
6589
|
/**
|
|
5964
6590
|
* The subject with `tenantId` selected — or a refusal.
|
|
5965
6591
|
*
|
|
@@ -6196,6 +6822,33 @@ export declare const shapeDigest: (text: string) => string;
|
|
|
6196
6822
|
*/
|
|
6197
6823
|
export declare const sourceKeys: (source: ReactivitySourceValue | ReadonlyArray<ReactivitySourceValue> | undefined) => ReadonlyArray<string>;
|
|
6198
6824
|
|
|
6825
|
+
export declare interface SsrfPolicy {
|
|
6826
|
+
/**
|
|
6827
|
+
* Hosts that bypass the guard. An entry may be an exact hostname
|
|
6828
|
+
* (`billing.internal`), a suffix wildcard (`*.svc.cluster.local`), or a
|
|
6829
|
+
* host:port (`127.0.0.1:8787`) when only one port should be reachable.
|
|
6830
|
+
*
|
|
6831
|
+
* This is the one escape hatch, and it is deliberately per-HOST rather than a
|
|
6832
|
+
* boolean: "we call one internal service" and "we do not check URLs" are very
|
|
6833
|
+
* different postures, and a boolean cannot tell them apart six months later.
|
|
6834
|
+
*/
|
|
6835
|
+
readonly allowHosts?: ReadonlyArray<string>;
|
|
6836
|
+
/** Max redirect hops to follow. Each one is revalidated. Default 5. */
|
|
6837
|
+
readonly maxRedirects?: number;
|
|
6838
|
+
}
|
|
6839
|
+
|
|
6840
|
+
/**
|
|
6841
|
+
* Decide whether a URL may be fetched. Returns `null` when allowed, else the
|
|
6842
|
+
* reason. Fails CLOSED: a URL that will not parse is blocked.
|
|
6843
|
+
*
|
|
6844
|
+
* DNS is deliberately NOT resolved — this is a synchronous check on the literal
|
|
6845
|
+
* target, so a hostname that RESOLVES to a private address (DNS rebinding) is not
|
|
6846
|
+
* caught here. Blocking the direct-IP vector is the high-severity, cheap half;
|
|
6847
|
+
* rebinding needs network-layer egress control and is called out in the docs
|
|
6848
|
+
* rather than silently implied.
|
|
6849
|
+
*/
|
|
6850
|
+
export declare const ssrfReason: (rawUrl: string, policy?: SsrfPolicy) => string | null;
|
|
6851
|
+
|
|
6199
6852
|
export declare type StorageAccessPolicy = typeof StorageAccessPolicySchema.Type;
|
|
6200
6853
|
|
|
6201
6854
|
export declare const StorageAccessPolicySchema: Schema.$Array<Schema.Struct<{
|
|
@@ -6374,6 +7027,9 @@ export declare const strictInput: <S extends Schema.Top>(input: S, procedure?: s
|
|
|
6374
7027
|
|
|
6375
7028
|
export declare const Subject: Schema.Union<readonly [Schema.Struct<{
|
|
6376
7029
|
readonly type: Schema.Literal<"user">;
|
|
7030
|
+
/** A guest has a stable identity but has not linked a registered account.
|
|
7031
|
+
* This identity mark survives session signing; it never grants authority. */
|
|
7032
|
+
readonly kind: Schema.optional<Schema.Literal<"guest">>;
|
|
6377
7033
|
readonly id: Schema.String;
|
|
6378
7034
|
readonly tenantId: Schema.String;
|
|
6379
7035
|
readonly scopes: Schema.optional<Schema.$Array<Schema.String>>;
|
|
@@ -6440,6 +7096,7 @@ export declare const subjectAuditActorId: (subject: Subject) => string | null;
|
|
|
6440
7096
|
export declare const SubjectIdentity: Schema.Union<readonly [Schema.Struct<{
|
|
6441
7097
|
readonly type: Schema.Literal<"user">;
|
|
6442
7098
|
readonly id: Schema.String;
|
|
7099
|
+
readonly kind: Schema.optional<Schema.Literal<"guest">>;
|
|
6443
7100
|
readonly tenantId: Schema.String;
|
|
6444
7101
|
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
6445
7102
|
}>, Schema.Struct<{
|
|
@@ -6482,9 +7139,9 @@ export declare const SubjectIdentity: Schema.Union<readonly [Schema.Struct<{
|
|
|
6482
7139
|
}>, Schema.Struct<{
|
|
6483
7140
|
readonly type: Schema.Literal<"service">;
|
|
6484
7141
|
readonly id: Schema.String;
|
|
7142
|
+
readonly service: Schema.String;
|
|
6485
7143
|
readonly tenantId: Schema.Null;
|
|
6486
7144
|
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
6487
|
-
readonly service: Schema.String;
|
|
6488
7145
|
}>]>;
|
|
6489
7146
|
|
|
6490
7147
|
export declare type SubjectIdentity = typeof SubjectIdentity.Type;
|
|
@@ -6523,6 +7180,7 @@ declare const SubjectService_base: Context.ServiceClass<SubjectService, "@voltro
|
|
|
6523
7180
|
readonly type: "user";
|
|
6524
7181
|
readonly id: string;
|
|
6525
7182
|
readonly tenantId: string;
|
|
7183
|
+
readonly kind?: "guest" | undefined;
|
|
6526
7184
|
readonly scopes?: readonly string[] | undefined;
|
|
6527
7185
|
readonly metadata?: {
|
|
6528
7186
|
readonly [x: string]: unknown;
|
|
@@ -6560,8 +7218,8 @@ declare const SubjectService_base: Context.ServiceClass<SubjectService, "@voltro
|
|
|
6560
7218
|
} | {
|
|
6561
7219
|
readonly type: "service";
|
|
6562
7220
|
readonly id: string;
|
|
6563
|
-
readonly tenantId: null;
|
|
6564
7221
|
readonly service: string;
|
|
7222
|
+
readonly tenantId: null;
|
|
6565
7223
|
readonly scopes?: readonly string[] | undefined;
|
|
6566
7224
|
readonly metadata?: {
|
|
6567
7225
|
readonly [x: string]: unknown;
|
|
@@ -7054,6 +7712,26 @@ export declare interface UpdateTarget<Input = unknown, Row = unknown, Item = Rec
|
|
|
7054
7712
|
readonly shapeItem?: ((input: Input, current: Item) => Item) | undefined;
|
|
7055
7713
|
}
|
|
7056
7714
|
|
|
7715
|
+
/** Runtime form of the registered-human identity requirement. */
|
|
7716
|
+
export declare interface UpgradedCheckSpec {
|
|
7717
|
+
readonly upgraded: true;
|
|
7718
|
+
}
|
|
7719
|
+
|
|
7720
|
+
/** Reject an upgraded marker combined with another guard variant in one entry.
|
|
7721
|
+
* Structural guard unions allow such objects to compile. Keep independent
|
|
7722
|
+
* requirements in separate entries so dispatch and persistence retain both. */
|
|
7723
|
+
export declare const upgradedGuardShapeError: (guard: unknown) => ScopeError | null;
|
|
7724
|
+
|
|
7725
|
+
/** Require a registered human identity. Guest and machine credentials cannot
|
|
7726
|
+
* satisfy this requirement, including credentials holding admin scopes. */
|
|
7727
|
+
export declare interface UpgradedGuardSpec {
|
|
7728
|
+
readonly upgraded: true;
|
|
7729
|
+
}
|
|
7730
|
+
|
|
7731
|
+
/** Validate an optional per-connection SSE lifetime before acquiring resources.
|
|
7732
|
+
* The timer ceiling also prevents millisecond overflow becoming a 1ms timer. */
|
|
7733
|
+
export declare const validateHttpStreamMaxDuration: (value: unknown) => number | undefined;
|
|
7734
|
+
|
|
7057
7735
|
/** Refuse malformed runtime contributions before starting a worker. */
|
|
7058
7736
|
export declare function validateOutboxHandlerDefinition(value: unknown, owner: string): asserts value is OutboxHandlerDefinition<unknown>;
|
|
7059
7737
|
|
|
@@ -7100,6 +7778,26 @@ export declare const ValidationIssue: Schema.Struct<{
|
|
|
7100
7778
|
export declare type ValidationIssueShape = Schema.Schema.Type<typeof ValidationIssue>;
|
|
7101
7779
|
|
|
7102
7780
|
export declare interface VoltroPlugin {
|
|
7781
|
+
/** Server callbacks for explicitly policy-bound event client streams. */
|
|
7782
|
+
readonly eventClientPolicies?: ReadonlyArray<EventClientPolicy>;
|
|
7783
|
+
/** Declared background/listener work. Omitted means rpc-only for role admission.
|
|
7784
|
+
* Metadata alone does not suppress hooks; hosts must apply the role plan. */
|
|
7785
|
+
readonly workloads?: ReadonlyArray<ApiWorkload>;
|
|
7786
|
+
/** Separately owned API work, started after shared activation. A failed start
|
|
7787
|
+
* must release partial acquisitions before rejecting. Returned resources drain
|
|
7788
|
+
* before shared deactivation; stop failures retain them for retry. */
|
|
7789
|
+
readonly workloadHooks?: Readonly<Partial<Record<ApiWorkload, PluginWorkloadHook>>>;
|
|
7790
|
+
/** App-supplied connection references for this configured plugin instance.
|
|
7791
|
+
* Registry bindings override these selections. Library plugins must not set
|
|
7792
|
+
* topology defaults here; populate only from explicit app options. */
|
|
7793
|
+
readonly connectionBindings?: Readonly<Record<string, ConnectionRef>>;
|
|
7794
|
+
/** Backend-independent requirements. Cross-node HotStore requires Redis; broker roles require their native transport. */
|
|
7795
|
+
readonly needs?: {
|
|
7796
|
+
readonly hot?: 'local' | 'crossNode';
|
|
7797
|
+
readonly connections?: ReadonlyArray<PluginConnectionNeed>;
|
|
7798
|
+
readonly pubsub?: boolean;
|
|
7799
|
+
readonly atomicMulti?: boolean;
|
|
7800
|
+
};
|
|
7103
7801
|
/**
|
|
7104
7802
|
* Plugin identifier — printed in `voltro dev` boot logs + surfaced in
|
|
7105
7803
|
* the inspect manifest. Use a stable string scoped to the package
|
|
@@ -7198,6 +7896,16 @@ export declare interface VoltroPlugin {
|
|
|
7198
7896
|
readonly declaredEnv?: ReadonlyArray<PluginEnvVar>;
|
|
7199
7897
|
/** What this plugin collects and uses — see `PluginPrivacyDeclaration`. */
|
|
7200
7898
|
readonly privacy?: PluginPrivacyDeclaration;
|
|
7899
|
+
/** Subject-data ownership; distinct from the platform privacy disclosure above. */
|
|
7900
|
+
readonly subjectPrivacy?: PluginSubjectPrivacy;
|
|
7901
|
+
/** Idempotent server hook. Identity hooks run after all declared data hooks. */
|
|
7902
|
+
readonly onErase?: PluginEraseHook;
|
|
7903
|
+
/** Server-authorized JSON export. Omit credentials, hashes and session tokens. */
|
|
7904
|
+
readonly onExport?: PluginExportHook;
|
|
7905
|
+
/** Transactional account-data reconciliation; distinct from privacy erasure. */
|
|
7906
|
+
readonly subjectMerge?: PluginSubjectMerge;
|
|
7907
|
+
/** Trusted coordinator must authenticate both accounts and confirmation. */
|
|
7908
|
+
readonly onMergeAccounts?: PluginAccountMergeHook;
|
|
7201
7909
|
/** Where this plugin sends data outside the installation — see `PluginEgressDeclaration`. Omit when it sends nothing. */
|
|
7202
7910
|
readonly egress?: ReadonlyArray<PluginEgressDeclaration>;
|
|
7203
7911
|
/**
|
|
@@ -7239,6 +7947,10 @@ export declare interface VoltroPlugin {
|
|
|
7239
7947
|
* Absent → the plugin contributes nothing at the mutation boundary
|
|
7240
7948
|
* (schema-only / lifecycle-only plugins are fine).
|
|
7241
7949
|
*/
|
|
7950
|
+
/** Register pure authority refreshers for native and REST admission,
|
|
7951
|
+
* including queries and raw REST routes, before/after receipt waits. Requires rpc:authority:replay; never run the executor
|
|
7952
|
+
* or normal interceptors to reconstruct an authorization decision. */
|
|
7953
|
+
readonly bindReplayAuthority?: RpcReplayAuthorityBinding;
|
|
7242
7954
|
readonly interceptMutation?: RpcInterceptor;
|
|
7243
7955
|
/** Runs after successful executor and business-rule evaluation, before the
|
|
7244
7956
|
* transaction commits. Use only the supplied store for required records or
|
|
@@ -7280,6 +7992,11 @@ export declare interface VoltroPlugin {
|
|
|
7280
7992
|
* plugins carry a parity test that fails when one does.
|
|
7281
7993
|
*/
|
|
7282
7994
|
readonly interceptWorkflow?: RpcInterceptor;
|
|
7995
|
+
/** Wraps finite stream admission and construction, once per subscription,
|
|
7996
|
+
* before guards and executor side effects. The successful value is the
|
|
7997
|
+
* Stream itself; element delivery retains ordinary live guard rechecks.
|
|
7998
|
+
* Requires rpc:intercept:stream. */
|
|
7999
|
+
readonly interceptStream?: RpcInterceptor;
|
|
7283
8000
|
/**
|
|
7284
8001
|
* Effect Layer that contributes services into the per-request
|
|
7285
8002
|
* context. Anything declared here is yieldable from any handler in
|
|
@@ -7460,7 +8177,7 @@ export declare interface VoltroPlugin {
|
|
|
7460
8177
|
*/
|
|
7461
8178
|
readonly extendSchema?: PluginSchemaContribution;
|
|
7462
8179
|
/**
|
|
7463
|
-
*
|
|
8180
|
+
* An absolute directory or named directories of APP-SHAPED primitives this plugin brings with it — the same
|
|
7464
8181
|
* file conventions an app uses (`*.query.ts` + `.server.ts`, `*.mutation.ts`,
|
|
7465
8182
|
* `*.workflow.tsx`, `*.cron.tsx`, `*.subscribe.ts`, `*.reaction.ts`,
|
|
7466
8183
|
* `schema.ts` / `*.entity.ts`, …).
|
|
@@ -7479,9 +8196,12 @@ export declare interface VoltroPlugin {
|
|
|
7479
8196
|
*
|
|
7480
8197
|
* The block's procedures keep the names their descriptors declare; a name
|
|
7481
8198
|
* that collides with the app's own is refused at codegen, as any collision is.
|
|
7482
|
-
*
|
|
8199
|
+
* A directory or a plain named map of directories. Named roots use stable
|
|
8200
|
+
* per-plugin module identities independent of declaration order; choose names
|
|
8201
|
+
* explicitly when optional subsystems contribute separate folders. Each value
|
|
8202
|
+
* must be an absolute existing directory; missing/overlapping roots refuse boot.
|
|
7483
8203
|
*/
|
|
7484
|
-
readonly sources?: string
|
|
8204
|
+
readonly sources?: string | Readonly<Record<string, string>>;
|
|
7485
8205
|
/**
|
|
7486
8206
|
* Cross-cutting error schemas merged into every procedure's wire error
|
|
7487
8207
|
* union. Lets a plugin interceptor fail with a typed error (e.g.
|
|
@@ -7620,15 +8340,17 @@ export declare interface WebSocketGatewayConnection {
|
|
|
7620
8340
|
readonly send: (data: string | Uint8Array) => void;
|
|
7621
8341
|
/** Await the local transport write, NOT peer receipt. Rejects on close or
|
|
7622
8342
|
* overflow. Await each send to propagate backpressure to the producer. */
|
|
7623
|
-
readonly sendAsync: (data: string | Uint8Array) => Promise<
|
|
8343
|
+
readonly sendAsync: (data: string | Uint8Array) => Promise<WebSocketGatewaySendResult>;
|
|
8344
|
+
/** Active plus queued frame bytes, excluding WebSocket framing overhead. */
|
|
8345
|
+
readonly queuedBytes: number;
|
|
7624
8346
|
/** Aborted on close, expiry, shutdown or setup failure, including while
|
|
7625
8347
|
* onConnection is still awaiting an upstream connection. */
|
|
7626
8348
|
readonly signal: AbortSignal;
|
|
7627
8349
|
/** Close the connection (application close codes 4000-4999 are yours). */
|
|
7628
8350
|
readonly close: (code?: number, reason?: string) => void;
|
|
7629
8351
|
/** Register a message listener (binary-safe; text arrives as bytes). */
|
|
7630
|
-
readonly onMessage: (listener: (data: Uint8Array) => void) => void;
|
|
7631
|
-
/** The
|
|
8352
|
+
readonly onMessage: (listener: (data: Uint8Array, receivedAt: number) => void) => void;
|
|
8353
|
+
/** The verified subject — `null` only on an `auth: 'public'` route. */
|
|
7632
8354
|
readonly subject: Subject | null;
|
|
7633
8355
|
/** Lowercased request headers of the upgrade. */
|
|
7634
8356
|
readonly headers: Readonly<Record<string, string>>;
|
|
@@ -7649,11 +8371,27 @@ export declare interface WebSocketGatewayRoute {
|
|
|
7649
8371
|
* expires.
|
|
7650
8372
|
* - `'public'` — deliberately unauthenticated (a device fleet with its own
|
|
7651
8373
|
* protocol-level auth). A decision somebody wrote down, not a default.
|
|
7652
|
-
|
|
7653
|
-
|
|
8374
|
+
* - `'token'` — upgrades after the origin check, then verifies the first
|
|
8375
|
+
* assembled frame before starting onConnection. The credential frame
|
|
8376
|
+
* never reaches message listeners. Clients wait for an application
|
|
8377
|
+
* acknowledgement before sending more frames; early frames close 1008.
|
|
8378
|
+
*/
|
|
8379
|
+
readonly auth: 'subject' | 'public' | 'token';
|
|
8380
|
+
/** Required only for auth: 'token'. Return null to refuse (1008), or the
|
|
8381
|
+
* verified SubjectResolution (credentialExpiresAt is Unix SECONDS).
|
|
8382
|
+
* Throw/rejection closes 1011 with a generic reason. Respect context.signal:
|
|
8383
|
+
* timeout, disconnect and shutdown abort it, and late results are ignored. */
|
|
8384
|
+
readonly verify?: (firstFrame: Uint8Array, context: WebSocketGatewayVerificationContext) => SubjectResolution | null | Promise<SubjectResolution | null>;
|
|
8385
|
+
/** Only for auth: 'token'. Deadline from socket open, including waiting for
|
|
8386
|
+
* the first frame and verification; default 5000 ms, maximum 2147483647. */
|
|
8387
|
+
readonly verificationTimeoutMs?: number;
|
|
7654
8388
|
/** Per-connection bounds. Inbound size is checked before app dispatch,
|
|
7655
8389
|
* not before the platform assembles a WebSocket message. */
|
|
7656
8390
|
readonly limits?: {
|
|
8391
|
+
/** Optional per-connection token refill rate. Omitted means no rate limit. */
|
|
8392
|
+
readonly maxInboundMessagesPerSecond?: number;
|
|
8393
|
+
/** Initial and maximum token capacity; defaults to the configured rate. */
|
|
8394
|
+
readonly burst?: number;
|
|
7657
8395
|
/** Maximum inbound/outbound frame bytes; default 1 MiB. */
|
|
7658
8396
|
readonly maxMessageBytes?: number;
|
|
7659
8397
|
/** Active plus queued outbound bytes; default 4 MiB. */
|
|
@@ -7672,6 +8410,20 @@ export declare interface WebSocketGatewayRoute {
|
|
|
7672
8410
|
readonly onConnection: (connection: WebSocketGatewayConnection) => void | (() => void) | Promise<void | (() => void)>;
|
|
7673
8411
|
}
|
|
7674
8412
|
|
|
8413
|
+
/** Local queue pressure after the frame's transport write; not peer receipt. */
|
|
8414
|
+
export declare interface WebSocketGatewaySendResult {
|
|
8415
|
+
readonly queuedBytes: number;
|
|
8416
|
+
}
|
|
8417
|
+
|
|
8418
|
+
/** Cancellation and upgrade metadata for first-frame credential verification. */
|
|
8419
|
+
export declare interface WebSocketGatewayVerificationContext {
|
|
8420
|
+
readonly signal: AbortSignal;
|
|
8421
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
8422
|
+
readonly path: string;
|
|
8423
|
+
/** Process-monotonic reception time in milliseconds, not a Unix timestamp. */
|
|
8424
|
+
readonly receivedAt: number;
|
|
8425
|
+
}
|
|
8426
|
+
|
|
7675
8427
|
/**
|
|
7676
8428
|
* Who may call a procedure over the wire: the app's own clients, or only other
|
|
7677
8429
|
* apps of the project.
|