@voltro/protocol 0.80.0 → 0.82.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 +1610 -6
- package/dist/apikey.d.ts +10 -2
- package/dist/index.d.ts +949 -76
- package/dist/index.js +904 -634
- package/dist/inspect.d.ts +67 -1
- package/dist/inspect.js +95 -61
- package/dist/jwt.d.ts +9 -1
- package/dist/rest.d.ts +121 -19
- package/dist/rest.js +255 -214
- package/dist/{restFormat-ChSVyufA.js → restFormat-EZ8k9ZcQ.js} +77 -60
- package/dist/{scopes-BbIyym8y.js → scopes-Di756ENh.js} +153 -102
- package/dist/session.d.ts +31 -0
- package/dist/session.js +49 -48
- package/dist/sessionHeader-DriTZhmv.js +7 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { RpcMiddleware } from '@effect/rpc';
|
|
|
8
8
|
import { Schema } from 'effect';
|
|
9
9
|
import { SqlClient } from '@effect/sql';
|
|
10
10
|
import { Stream } from '@effect/rpc/RpcSchema';
|
|
11
|
+
import { VersionConflict } from '@voltro/database/wire';
|
|
11
12
|
|
|
12
13
|
export declare interface ActionProcedureDescriptor<Name extends string, Input extends Schema.Schema.Any, Output extends Schema.Schema.Any, Error extends Schema.Schema.All> {
|
|
13
14
|
readonly kind: 'action';
|
|
@@ -37,6 +38,9 @@ export declare interface ActionProcedureDescriptor<Name extends string, Input ex
|
|
|
37
38
|
* `openAccess: '<why>'`. Mutually exclusive with `guards`; together they are
|
|
38
39
|
* the only two shapes `security.defaultDeny` accepts. */
|
|
39
40
|
readonly openAccess: string | undefined;
|
|
41
|
+
/** Only these apps of the project may call this procedure — see `service` on
|
|
42
|
+
* the definer's options. Absent → the app's own clients call it. */
|
|
43
|
+
readonly service: ServiceSpec | undefined;
|
|
40
44
|
/** Opt this action into a public REST endpoint (innovation/11). */
|
|
41
45
|
readonly publicApi: PublicApiSpec | undefined;
|
|
42
46
|
/** Opt this action into the auto-synthesized agent toolset (innovation/07). */
|
|
@@ -80,6 +84,46 @@ export declare const ADMIN_SCOPE = "admin:full";
|
|
|
80
84
|
* so the wording lives beside the semantics it describes. */
|
|
81
85
|
export declare const advisoryResourceGuardWarning: (tags: ReadonlyArray<string>) => string;
|
|
82
86
|
|
|
87
|
+
/**
|
|
88
|
+
* What an UNAUTHENTICATED caller is — the app's decision, never the request's.
|
|
89
|
+
*
|
|
90
|
+
* A request that matches no auth strategy still resolves to a Subject, and
|
|
91
|
+
* that Subject's `tenantId` decides what every tenant-scoped table and every
|
|
92
|
+
* `openAccess` procedure answers. Left to the request, the `x-tenant` header
|
|
93
|
+
* would choose it: any client could read any tenant's public-per-tenant data,
|
|
94
|
+
* and a procedure that was `openAccess` for the tenant's MEMBERS would answer
|
|
95
|
+
* for whichever tenant the header named. So the policy is declared once, in
|
|
96
|
+
* `app.config.ts` (`auth.anonymous`), and `voltro serve` refuses to boot
|
|
97
|
+
* without it.
|
|
98
|
+
*
|
|
99
|
+
* - `'refuse'` — no unauthenticated callers at all: `Unauthenticated`.
|
|
100
|
+
* - `'no-tenant'` — the caller carries the empty tenant `''`: every
|
|
101
|
+
* tenant-scoped read is empty (fails closed), tables without `tenant()` and
|
|
102
|
+
* procedures that need no tenant answer. The default of the composer, and
|
|
103
|
+
* the right choice for an api whose public surface is token-shaped (an
|
|
104
|
+
* invite preview, a signed link).
|
|
105
|
+
* - `'header'` — the tenant is what the request's `x-tenant` header names; a
|
|
106
|
+
* request without it is refused. For public-per-tenant data (a marketing
|
|
107
|
+
* site per tenant, public listings by slug) — and ONLY that: every
|
|
108
|
+
* `openAccess` procedure and every table without `tenant()` is then public
|
|
109
|
+
* for a client-chosen tenant.
|
|
110
|
+
* - `{ tenantId }` — every unauthenticated caller is that ONE tenant, chosen
|
|
111
|
+
* here; the header is not consulted.
|
|
112
|
+
*
|
|
113
|
+
* NEVER `null`: a null tenant is a SYSTEM subject to the store and reads
|
|
114
|
+
* unscoped, across every tenant.
|
|
115
|
+
*/
|
|
116
|
+
export declare type AnonymousPolicy = 'refuse' | 'no-tenant' | 'header' | {
|
|
117
|
+
readonly tenantId: string;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/** The development boot's convenience, which no app config can name: the
|
|
121
|
+
* header's tenant, else the dev tenant. `voltro dev` runs an undecided app
|
|
122
|
+
* with it and says so; `voltro serve` refuses instead. */
|
|
123
|
+
export declare type AnonymousPolicyOrDevTenant = AnonymousPolicy | {
|
|
124
|
+
readonly headerOrTenant: string;
|
|
125
|
+
};
|
|
126
|
+
|
|
83
127
|
export declare const anonymousSubject: (tenantId: string | null, credentialRejected?: string) => Subject;
|
|
84
128
|
|
|
85
129
|
/** The erased policy a descriptor carries (input generic dropped). */
|
|
@@ -89,9 +133,9 @@ export declare interface AnyApprovalPolicy {
|
|
|
89
133
|
readonly reason?: string;
|
|
90
134
|
}
|
|
91
135
|
|
|
92
|
-
/** A guard entry is a scope check, a relationship check, an identity check,
|
|
93
|
-
*
|
|
94
|
-
export declare type AnyCheckSpec = GuardCheckSpec | PolicyCheckSpec | AuthenticatedCheckSpec | OpenAccessSpec;
|
|
136
|
+
/** A guard entry is a scope check, a relationship check, an identity check, a
|
|
137
|
+
* declared no-check-needed decision, or a service-only decision. */
|
|
138
|
+
export declare type AnyCheckSpec = GuardCheckSpec | PolicyCheckSpec | AuthenticatedCheckSpec | OpenAccessSpec | ServiceAccessSpec;
|
|
95
139
|
|
|
96
140
|
/** Any declared event, with the generics erased — for registries and audits. */
|
|
97
141
|
export declare type AnyEventDescriptor = EventDescriptor<string, Schema.Schema.Any, Schema.Schema.Any>;
|
|
@@ -130,6 +174,21 @@ export declare const APIKEY_ISSUE_OTHER_SCOPE = "apikeys:issue:other";
|
|
|
130
174
|
*/
|
|
131
175
|
export declare const APIKEY_ISSUE_SELF_SCOPE = "apikeys:issue:self";
|
|
132
176
|
|
|
177
|
+
export declare class ApiUnavailable extends ApiUnavailable_base {
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
declare const ApiUnavailable_base: Schema.TaggedErrorClass<ApiUnavailable, "ApiUnavailable", {
|
|
181
|
+
readonly _tag: Schema.tag<"ApiUnavailable">;
|
|
182
|
+
} & {
|
|
183
|
+
/** The binding name on the caller (`apis.<name>`). */
|
|
184
|
+
api: typeof Schema.String;
|
|
185
|
+
/** The rpc tag that was called. */
|
|
186
|
+
tag: typeof Schema.String;
|
|
187
|
+
/** Why no answer arrived. */
|
|
188
|
+
reason: Schema.Literal<["timeout", "transport", "closed"]>;
|
|
189
|
+
message: typeof Schema.String;
|
|
190
|
+
}>;
|
|
191
|
+
|
|
133
192
|
/** The subject a decision produces, plus what the decision took away. `removed`
|
|
134
193
|
* is never non-empty for a `grant`. */
|
|
135
194
|
export declare interface AppliedScopes {
|
|
@@ -137,6 +196,9 @@ export declare interface AppliedScopes {
|
|
|
137
196
|
readonly removed: ReadonlyArray<string>;
|
|
138
197
|
}
|
|
139
198
|
|
|
199
|
+
/** Keep a pairing for the next boot; the app reads it when it builds its api config. */
|
|
200
|
+
export declare const applyPairing: (storage: PairingStorage, pairing: Pairing) => Promise<void>;
|
|
201
|
+
|
|
140
202
|
export declare const applyRowPatch: (prev: ReadonlyArray<PatchRow>, patch: RowPatch, options?: ApplyRowPatchOptions) => ReadonlyArray<PatchRow>;
|
|
141
203
|
|
|
142
204
|
/**
|
|
@@ -556,7 +618,7 @@ export declare interface AuthStrategy {
|
|
|
556
618
|
readonly resolve: (input: AuthStrategyInput) => Promise<StrategyResolution> | StrategyResolution;
|
|
557
619
|
/**
|
|
558
620
|
* The bearer-token PREFIX this strategy claims, when it gates on one
|
|
559
|
-
* (`'sk_'`, `'
|
|
621
|
+
* (`'sk_'`, `'acme_'`). Declared so a collision is DETECTABLE.
|
|
560
622
|
*
|
|
561
623
|
* Two strategies claiming the same prefix is not a harmless duplicate: the
|
|
562
624
|
* chain is first-match-wins, so whichever runs first decides the Subject —
|
|
@@ -677,7 +739,7 @@ export declare type AuthSubjectGuardVerdict = {
|
|
|
677
739
|
* `fresh` the caller runs the handler then calls `finish`/`fail`; on
|
|
678
740
|
* `replay`/`conflict` it returns immediately without touching the handler.
|
|
679
741
|
*/
|
|
680
|
-
export declare const beginIdempotent: (store: IdempotencyStore, scope: string, key: string, ttlMs: number, now: number) => Promise<IdempotencyOutcome>;
|
|
742
|
+
export declare const beginIdempotent: (store: IdempotencyStore, scope: string, key: string, ttlMs: number, now: number, inFlightLeaseMs?: number) => Promise<IdempotencyOutcome>;
|
|
681
743
|
|
|
682
744
|
/**
|
|
683
745
|
* A cross-table business rule was violated inside a mutation's transaction; the
|
|
@@ -754,9 +816,14 @@ export declare const checkGuards: (subject: Subject, guards: ReadonlyArray<AnyCh
|
|
|
754
816
|
*
|
|
755
817
|
* Returns a typed `ScopeError` naming the first unmet scope, or `null` when
|
|
756
818
|
* every guard passes. The runtime calls this in the dispatch spine BEFORE the
|
|
757
|
-
* executor (mutations: before the transaction opens).
|
|
819
|
+
* executor (mutations: before the transaction opens). A resolver or tuple
|
|
820
|
+
* source that answers `'missing'` turns the refusal into `NoSuchResource` for
|
|
821
|
+
* a signed-in caller — the first failing guard decides, so a scope refusal
|
|
822
|
+
* ahead of it is never upgraded into a disclosure.
|
|
758
823
|
*/
|
|
759
|
-
export declare const checkGuardsEffect: (subject: Subject, guards: ReadonlyArray<AnyCheckSpec> | undefined, input: unknown, options?: GuardCheckOptions) => Effect.Effect<ScopeError | Unauthenticated | null>;
|
|
824
|
+
export declare const checkGuardsEffect: (subject: Subject, guards: ReadonlyArray<AnyCheckSpec> | undefined, input: unknown, options?: GuardCheckOptions) => Effect.Effect<ScopeError | Unauthenticated | NoSuchResource | null>;
|
|
825
|
+
|
|
826
|
+
export declare const clearPairing: (storage: PairingStorage) => Promise<void>;
|
|
760
827
|
|
|
761
828
|
export declare interface ClientDescriptor {
|
|
762
829
|
readonly kind: 'query' | 'mutation' | 'action' | 'stream' | 'workflow';
|
|
@@ -817,42 +884,17 @@ export declare interface ClientTarget {
|
|
|
817
884
|
export declare const compareSurfaces: (mine: Readonly<Record<string, string>>, theirs: Readonly<Record<string, string>>) => SurfaceMismatch;
|
|
818
885
|
|
|
819
886
|
export declare const composeAuthStrategies: (strategies: ReadonlyArray<AuthStrategy>, options?: {
|
|
820
|
-
/** Fallback when no strategy matched.
|
|
821
|
-
*
|
|
887
|
+
/** Fallback when no strategy matched. Replaces `anonymous` entirely: the
|
|
888
|
+
* function owns the anonymous subject AND the rejected-credential decision. */
|
|
822
889
|
readonly fallback?: (input: AuthStrategyInput) => Subject;
|
|
823
890
|
/** Hook for logging — called on every `failed` resolution. */
|
|
824
891
|
readonly onStrategyFailed?: (event: {
|
|
825
892
|
strategyId: string;
|
|
826
893
|
reason: string;
|
|
827
894
|
}) => void;
|
|
828
|
-
/**
|
|
829
|
-
*
|
|
830
|
-
|
|
831
|
-
* throws `Unauthenticated` instead of returning a null-tenant
|
|
832
|
-
* anonymous Subject. Use it on multi-tenant apps where every call —
|
|
833
|
-
* even an anonymous one — must be scoped to a tenant; without it a
|
|
834
|
-
* tenant-less anonymous Subject can read across the whole DB on
|
|
835
|
-
* tables that aren't `tenant()`-scoped. Ignored when a custom
|
|
836
|
-
* `fallback` is supplied (the fallback owns that decision).
|
|
837
|
-
*/
|
|
838
|
-
readonly anonymousTenantRequired?: boolean;
|
|
839
|
-
/**
|
|
840
|
-
* The ONE tenant every anonymous caller resolves to — chosen by the server,
|
|
841
|
-
* never by the request. When set, the `x-tenant` header is not consulted:
|
|
842
|
-
* a client naming its own tenant is exactly the thing a fixed anonymous
|
|
843
|
-
* tenant exists to rule out. Ignored when `fallback` is supplied (that
|
|
844
|
-
* function owns the anonymous subject).
|
|
845
|
-
*/
|
|
846
|
-
readonly anonymousTenantId?: string;
|
|
847
|
-
/**
|
|
848
|
-
* The tenant an anonymous caller resolves to when its request names none
|
|
849
|
-
* in `x-tenant`. The header still wins when present — this only replaces
|
|
850
|
-
* the `null` tenant. It exists so a boot path can supply a default tenant
|
|
851
|
-
* without a `fallback`: a `fallback` owns the rejected-credential decision,
|
|
852
|
-
* this does not, so a presented-and-rejected credential is still refused.
|
|
853
|
-
* Ignored when `anonymousTenantId` or `fallback` is set.
|
|
854
|
-
*/
|
|
855
|
-
readonly anonymousTenantDefault?: string;
|
|
895
|
+
/** What an unauthenticated caller is — see {@link AnonymousPolicy}.
|
|
896
|
+
* Default `'no-tenant'`. Ignored when `fallback` is supplied. */
|
|
897
|
+
readonly anonymous?: AnonymousPolicyOrDevTenant;
|
|
856
898
|
/**
|
|
857
899
|
* The subject's memberships — the ONE source, strategy-independent. Read
|
|
858
900
|
* only when a stored tenant selection exists for the subject and names a
|
|
@@ -1348,8 +1390,8 @@ export declare interface CoordinatedScheduleHandle {
|
|
|
1348
1390
|
*/
|
|
1349
1391
|
export declare interface CoordinatedTaskOptions {
|
|
1350
1392
|
/**
|
|
1351
|
-
* Stop ticking entirely on an idle tick
|
|
1352
|
-
* back only on `wake()`. Default `false`.
|
|
1393
|
+
* Stop ticking entirely on an idle tick that reports `nextDueInMs: null`
|
|
1394
|
+
* (nothing scheduled), and come back only on `wake()`. Default `false`.
|
|
1353
1395
|
*
|
|
1354
1396
|
* Pass `true` only when an arrival is GUARANTEED to call `wake()` — a change
|
|
1355
1397
|
* subscription on the table your task drains, on a deployment where remote
|
|
@@ -1363,10 +1405,17 @@ export declare interface CoordinatedTaskOptions {
|
|
|
1363
1405
|
export declare interface CoordinatedTickOutcome {
|
|
1364
1406
|
/** `true` when the tick found nothing to do. Only an idle tick backs off. */
|
|
1365
1407
|
readonly idle: boolean;
|
|
1366
|
-
/** Milliseconds until the earliest deadline this task already knows about
|
|
1367
|
-
*
|
|
1368
|
-
* 400 ms is armed for 400 ms rather
|
|
1369
|
-
|
|
1408
|
+
/** Milliseconds until the earliest deadline this task already knows about —
|
|
1409
|
+
* a retry, a re-poll, a lease running out. Caps the backoff, so a task that
|
|
1410
|
+
* is idle now but has something due in 400 ms is armed for 400 ms rather
|
|
1411
|
+
* than for the idle ceiling.
|
|
1412
|
+
*
|
|
1413
|
+
* `null` says "nothing is scheduled; new work can only arrive as a write",
|
|
1414
|
+
* and is the ONLY idle report that lets a `disarmWhenIdle` task stop
|
|
1415
|
+
* ticking. Leaving the field out backs off instead: work that comes due on
|
|
1416
|
+
* a clock writes nothing, so nothing would ever wake a task that disarmed
|
|
1417
|
+
* while holding it. */
|
|
1418
|
+
readonly nextDueInMs?: number | null;
|
|
1370
1419
|
}
|
|
1371
1420
|
|
|
1372
1421
|
/**
|
|
@@ -1379,11 +1428,33 @@ export declare interface CoordinatedTickOutcome {
|
|
|
1379
1428
|
* because that is where the normalised decision lands, and because every
|
|
1380
1429
|
* enforcement path reads the descriptor's array and nothing else.
|
|
1381
1430
|
*/
|
|
1382
|
-
export declare type DeclaredAccess<Input = unknown> = ReadonlyArray<AnyGuardSpec<Input> | OpenAccessSpec>;
|
|
1431
|
+
export declare type DeclaredAccess<Input = unknown> = ReadonlyArray<AnyGuardSpec<Input> | OpenAccessSpec | ServiceAccessSpec>;
|
|
1383
1432
|
|
|
1384
1433
|
/** Every channel declared in this process, by routing key. */
|
|
1385
1434
|
export declare const declaredReactivityChannelKeys: () => ReadonlySet<string>;
|
|
1386
1435
|
|
|
1436
|
+
/**
|
|
1437
|
+
* Does this guard list name a resource — a relationship guard, or a scope guard
|
|
1438
|
+
* with a `resource` extractor? Exactly the guards whose resolver may answer
|
|
1439
|
+
* `'missing'`, so exactly the procedures whose wire union carries
|
|
1440
|
+
* {@link NoSuchResource}.
|
|
1441
|
+
*/
|
|
1442
|
+
export declare const declaresResourceGuard: (guards: ReadonlyArray<AnyCheckSpec> | undefined) => boolean;
|
|
1443
|
+
|
|
1444
|
+
/**
|
|
1445
|
+
* How long a RUNNING claim holds without renewal.
|
|
1446
|
+
*
|
|
1447
|
+
* A claim used to go stale only after the replay window — 24 hours by default —
|
|
1448
|
+
* so a process that died inside a handler left its key `in_flight` for a day:
|
|
1449
|
+
* every retry was refused as "still in flight", including the retry of a
|
|
1450
|
+
* workflow step whose callee had simply restarted. A live handler renews its
|
|
1451
|
+
* claim every third of this (`holdIdempotentClaim`); a dead one stops, and the
|
|
1452
|
+
* next retry takes over after at most this long. A handler that blocks its event
|
|
1453
|
+
* loop longer than this can be taken over while still running — the same bound
|
|
1454
|
+
* every lease has.
|
|
1455
|
+
*/
|
|
1456
|
+
export declare const DEFAULT_IN_FLIGHT_LEASE_MS = 30000;
|
|
1457
|
+
|
|
1387
1458
|
/** Default cap on cached subjects before the cache sweeps + trims. */
|
|
1388
1459
|
export declare const DEFAULT_SCOPE_CACHE_MAX_ENTRIES = 10000;
|
|
1389
1460
|
|
|
@@ -1418,6 +1489,26 @@ export declare const defineAction: <const Name extends string, Input extends Sch
|
|
|
1418
1489
|
* openAccess: 'public pricing page — reads no caller data'
|
|
1419
1490
|
*/
|
|
1420
1491
|
readonly openAccess?: string;
|
|
1492
|
+
/**
|
|
1493
|
+
* Make this a SERVICE procedure: callable only by the listed apps of this
|
|
1494
|
+
* project, and by nobody else — no browser session, no API key, no admin.
|
|
1495
|
+
*
|
|
1496
|
+
* service: { callers: ['worker'] }
|
|
1497
|
+
*
|
|
1498
|
+
* The caller is another app that binds this one under `apis:` and calls it as
|
|
1499
|
+
* `ctx.apis.<name>.<tag>(input)`; it authenticates with the service credential
|
|
1500
|
+
* this app accepts under `serviceCallers`. It is its own access decision, so it
|
|
1501
|
+
* satisfies `security.defaultDeny` and cannot sit beside `guards:` or
|
|
1502
|
+
* `openAccess:`.
|
|
1503
|
+
*
|
|
1504
|
+
* The handler runs as the calling SERVICE: it reads across tenants and must
|
|
1505
|
+
* name a tenant to write into one — `ctx.storeForTenant(input.tenantId)` is the
|
|
1506
|
+
* shape for per-tenant work.
|
|
1507
|
+
*
|
|
1508
|
+
* Codegen emits it into `serviceGroup.generated.ts`, never into the browser's
|
|
1509
|
+
* `rpcGroup.generated.ts`.
|
|
1510
|
+
*/
|
|
1511
|
+
readonly service?: ServiceSpec;
|
|
1421
1512
|
/** Table(s) this action READS. Declaring it is what lets `voltro check` know
|
|
1422
1513
|
* the table is alive — without it, a table only an action touches reads as
|
|
1423
1514
|
* an orphan. See `ActionProcedureDescriptor.source`. */
|
|
@@ -1631,6 +1722,26 @@ export declare const defineMutation: <const Name extends string, Input extends S
|
|
|
1631
1722
|
* openAccess: 'public pricing page — reads no caller data'
|
|
1632
1723
|
*/
|
|
1633
1724
|
readonly openAccess?: string;
|
|
1725
|
+
/**
|
|
1726
|
+
* Make this a SERVICE procedure: callable only by the listed apps of this
|
|
1727
|
+
* project, and by nobody else — no browser session, no API key, no admin.
|
|
1728
|
+
*
|
|
1729
|
+
* service: { callers: ['worker'] }
|
|
1730
|
+
*
|
|
1731
|
+
* The caller is another app that binds this one under `apis:` and calls it as
|
|
1732
|
+
* `ctx.apis.<name>.<tag>(input)`; it authenticates with the service credential
|
|
1733
|
+
* this app accepts under `serviceCallers`. It is its own access decision, so it
|
|
1734
|
+
* satisfies `security.defaultDeny` and cannot sit beside `guards:` or
|
|
1735
|
+
* `openAccess:`.
|
|
1736
|
+
*
|
|
1737
|
+
* The handler runs as the calling SERVICE: it reads across tenants and must
|
|
1738
|
+
* name a tenant to write into one — `ctx.storeForTenant(input.tenantId)` is the
|
|
1739
|
+
* shape for per-tenant work.
|
|
1740
|
+
*
|
|
1741
|
+
* Codegen emits it into `serviceGroup.generated.ts`, never into the browser's
|
|
1742
|
+
* `rpcGroup.generated.ts`.
|
|
1743
|
+
*/
|
|
1744
|
+
readonly service?: ServiceSpec;
|
|
1634
1745
|
/** Project this mutation as a public REST endpoint (innovation/11). */
|
|
1635
1746
|
readonly publicApi?: PublicApiSpec;
|
|
1636
1747
|
/** Expose this mutation as an agent tool (innovation/07). */
|
|
@@ -1764,6 +1875,26 @@ export declare const defineQuery: <const Name extends string, Input extends Sche
|
|
|
1764
1875
|
* openAccess: 'public pricing page — reads no caller data'
|
|
1765
1876
|
*/
|
|
1766
1877
|
readonly openAccess?: string;
|
|
1878
|
+
/**
|
|
1879
|
+
* Make this a SERVICE procedure: callable only by the listed apps of this
|
|
1880
|
+
* project, and by nobody else — no browser session, no API key, no admin.
|
|
1881
|
+
*
|
|
1882
|
+
* service: { callers: ['worker'] }
|
|
1883
|
+
*
|
|
1884
|
+
* The caller is another app that binds this one under `apis:` and calls it as
|
|
1885
|
+
* `ctx.apis.<name>.<tag>(input)`; it authenticates with the service credential
|
|
1886
|
+
* this app accepts under `serviceCallers`. It is its own access decision, so it
|
|
1887
|
+
* satisfies `security.defaultDeny` and cannot sit beside `guards:` or
|
|
1888
|
+
* `openAccess:`.
|
|
1889
|
+
*
|
|
1890
|
+
* The handler runs as the calling SERVICE: it reads across tenants and must
|
|
1891
|
+
* name a tenant to write into one — `ctx.storeForTenant(input.tenantId)` is the
|
|
1892
|
+
* shape for per-tenant work.
|
|
1893
|
+
*
|
|
1894
|
+
* Codegen emits it into `serviceGroup.generated.ts`, never into the browser's
|
|
1895
|
+
* `rpcGroup.generated.ts`.
|
|
1896
|
+
*/
|
|
1897
|
+
readonly service?: ServiceSpec;
|
|
1767
1898
|
/** Project this query as a public REST endpoint (innovation/11). */
|
|
1768
1899
|
readonly publicApi?: PublicApiSpec;
|
|
1769
1900
|
/** Expose this query as an agent tool (innovation/07). */
|
|
@@ -1933,6 +2064,20 @@ export declare const encodeRestError: (format: RestFormat, error: RestFormatErro
|
|
|
1933
2064
|
*/
|
|
1934
2065
|
export declare const encodeRestSuccess: (format: RestFormat, value: unknown, ctx: RestFormatContext) => RestFormatResponse;
|
|
1935
2066
|
|
|
2067
|
+
/**
|
|
2068
|
+
* The text to SHOW for a failure value — its `message`, else its `_tag`, else
|
|
2069
|
+
* `String(value)`.
|
|
2070
|
+
*
|
|
2071
|
+
* Its partner above, for the same reason: every client surface hands over the
|
|
2072
|
+
* declared error as the plain `{ _tag, …fields, message }` object the wire
|
|
2073
|
+
* carries, and `String()` of a plain object is `[object Object]`. A
|
|
2074
|
+
* subscription used to hand over an Effect `Cause`, whose `String()` happened
|
|
2075
|
+
* to read, so `String(error)` in an error banner or an `error.tsx` looked right
|
|
2076
|
+
* until the value became what the docs always said it was. Works on an `Error`,
|
|
2077
|
+
* a `Schema.TaggedError` instance, the wire object and a bare string alike.
|
|
2078
|
+
*/
|
|
2079
|
+
export declare const errorMessage: (err: unknown) => string;
|
|
2080
|
+
|
|
1936
2081
|
/**
|
|
1937
2082
|
* Read the `_tag` off a thrown error value, or `undefined` when it has none.
|
|
1938
2083
|
*
|
|
@@ -2308,9 +2453,10 @@ export declare const finishIdempotent: (store: IdempotencyStore, scope: string,
|
|
|
2308
2453
|
*
|
|
2309
2454
|
* A query's success type is the three-member union above, and a one-shot read
|
|
2310
2455
|
* takes only its first event: a `snapshot` resolves to its `data`; an `error`
|
|
2311
|
-
* REJECTS
|
|
2312
|
-
*
|
|
2313
|
-
*
|
|
2456
|
+
* REJECTS with the typed error ITSELF — exactly as a failed exit does, and the
|
|
2457
|
+
* same value a live subscription's `error` and the api's error bus hand over,
|
|
2458
|
+
* so one `_tag` switch serves every surface; a `delta` cannot be first and says
|
|
2459
|
+
* so. Anything else is a mutation or action's own result and
|
|
2314
2460
|
* passes through, which may legitimately be a tagged object of the app's.
|
|
2315
2461
|
*
|
|
2316
2462
|
* Shared because there are two such reads — the server loader's `ctx.query`
|
|
@@ -2326,6 +2472,31 @@ export declare const firstEventValue: (tag: string, value: unknown, label: strin
|
|
|
2326
2472
|
/** A route rendered for humans — logs, the inspect surface, the dashboard. */
|
|
2327
2473
|
export declare const formatEventRoute: (route: string) => string;
|
|
2328
2474
|
|
|
2475
|
+
/**
|
|
2476
|
+
* The framework errors EVERY procedure of a kind carries on its wire union —
|
|
2477
|
+
* the unconditional members `wireErrorUnion` adds. The conditional ones (a
|
|
2478
|
+
* resource guard's `NoSuchResource`, `requiresApproval`'s refusals,
|
|
2479
|
+
* `MutationConnectionRequired`) are left out on purpose: a type that cannot see
|
|
2480
|
+
* the condition must not promise them.
|
|
2481
|
+
*
|
|
2482
|
+
* It exists for the TYPE-level reader, `defineExecutor`, which checks an
|
|
2483
|
+
* executor's failure channel against the union the server will judge it by. A
|
|
2484
|
+
* test pins it against `wireErrorUnion` per kind, so the two cannot drift.
|
|
2485
|
+
*/
|
|
2486
|
+
export declare const FRAMEWORK_WIRE_ERRORS: {
|
|
2487
|
+
readonly query: readonly [typeof ScopeError, typeof Unauthenticated];
|
|
2488
|
+
readonly stream: readonly [typeof ScopeError, typeof Unauthenticated];
|
|
2489
|
+
readonly action: readonly [typeof ScopeError, typeof Unauthenticated, typeof ValidationError, typeof ValidationErrors];
|
|
2490
|
+
readonly mutation: readonly [typeof ScopeError, typeof Unauthenticated, typeof BusinessRuleViolation, typeof MutationInFlight, typeof VersionConflict, typeof ValidationError, typeof ValidationErrors];
|
|
2491
|
+
};
|
|
2492
|
+
|
|
2493
|
+
/** The error values {@link FRAMEWORK_WIRE_ERRORS} admits for `Kind`. */
|
|
2494
|
+
export declare type FrameworkWireError<Kind extends WireProcedureKind> = Schema.Schema.Type<(typeof FRAMEWORK_WIRE_ERRORS)[Kind][number]>;
|
|
2495
|
+
|
|
2496
|
+
/** How long a record of this status stays fresh — the replay window for a
|
|
2497
|
+
* completed response, the lease for a running one (never longer than the window). */
|
|
2498
|
+
export declare const freshFor: (status: IdempotencyRecord["status"], ttlMs: number, inFlightLeaseMs: number) => number;
|
|
2499
|
+
|
|
2329
2500
|
/** Close code a gateway connection receives when its credential expires —
|
|
2330
2501
|
* the same session-expiry contract the rpc socket has (SEC-16), spelled as
|
|
2331
2502
|
* an application close code so foreign clients can reauth + reconnect. */
|
|
@@ -2448,6 +2619,9 @@ export declare const hasEnforcedGuard: (guards: DeclaredAccess | undefined) => b
|
|
|
2448
2619
|
* the RAW subject scopes — use `hasEffectiveScope` to include rbac roles. */
|
|
2449
2620
|
export declare const hasScope: (subject: Subject, scope: string) => boolean;
|
|
2450
2621
|
|
|
2622
|
+
/** Renew a fresh claim's lease while its handler runs; returns the stop. */
|
|
2623
|
+
export declare const holdIdempotentClaim: (store: IdempotencyStore, scope: string, key: string, inFlightLeaseMs?: number, now?: () => number) => (() => void);
|
|
2624
|
+
|
|
2451
2625
|
/**
|
|
2452
2626
|
* Short-circuit response shape. Returning a `HttpInterceptResponse`
|
|
2453
2627
|
* from the interceptor halts the pipeline — the framework sends the
|
|
@@ -2547,14 +2721,24 @@ export declare interface IdempotencyStore {
|
|
|
2547
2721
|
/** Current record for (scope, key), or null. Read-side (inspect/dashboard). */
|
|
2548
2722
|
readonly get: (scope: string, key: string) => Promise<IdempotencyRecord | null>;
|
|
2549
2723
|
/**
|
|
2550
|
-
* Atomically claim (scope, key) IF absent OR stale
|
|
2724
|
+
* Atomically claim (scope, key) IF absent OR stale — a COMPLETED record older
|
|
2725
|
+
* than `ttlMs` (the replay window), or an IN-FLIGHT one whose lease
|
|
2726
|
+
* (`inFlightLeaseMs`, renewed by the live handler) lapsed:
|
|
2551
2727
|
* write a fresh `in_flight` row and return `'claimed'`. Otherwise return the
|
|
2552
2728
|
* EXISTING (still-fresh) record. The atomicity here is the whole game — two
|
|
2553
2729
|
* concurrent same-key requests both hit this, exactly one gets `'claimed'`,
|
|
2554
2730
|
* the loser reads the winner's record. In SQL this is one
|
|
2555
2731
|
* `INSERT … ON CONFLICT DO UPDATE … WHERE existing.createdAt < now - ttl`.
|
|
2556
2732
|
*/
|
|
2557
|
-
readonly claim: (scope: string, key: string, now: number, ttlMs: number) => Promise<'claimed' | IdempotencyRecord>;
|
|
2733
|
+
readonly claim: (scope: string, key: string, now: number, ttlMs: number, inFlightLeaseMs: number) => Promise<'claimed' | IdempotencyRecord>;
|
|
2734
|
+
/**
|
|
2735
|
+
* Extend a RUNNING claim's lease: bump its timestamp while it is still
|
|
2736
|
+
* `in_flight` (a completed or released claim is left alone). The server calls
|
|
2737
|
+
* it while the handler runs; a process that dies stops calling it, and its
|
|
2738
|
+
* claim goes stale after `inFlightLeaseMs` instead of after the whole replay
|
|
2739
|
+
* window.
|
|
2740
|
+
*/
|
|
2741
|
+
readonly renew: (scope: string, key: string, now: number) => Promise<void>;
|
|
2558
2742
|
/** Flip the claim to `completed` and store the response. */
|
|
2559
2743
|
readonly complete: (scope: string, key: string, response: IdempotencyResponse, now: number) => Promise<void>;
|
|
2560
2744
|
/** Drop the claim (handler errored → a retry may re-process). */
|
|
@@ -2637,12 +2821,21 @@ export declare interface InsertTarget<Input = unknown, Row = unknown, Item = Rec
|
|
|
2637
2821
|
readonly shapeItem?: ((input: Input, optimisticId: string) => Item) | undefined;
|
|
2638
2822
|
}
|
|
2639
2823
|
|
|
2824
|
+
/** Is this failure a missing answer (retry it) rather than an answer (do not)? */
|
|
2825
|
+
export declare const isApiUnavailable: (error: unknown) => error is ApiUnavailable;
|
|
2826
|
+
|
|
2640
2827
|
/** Runtime narrowing for the identity variant. */
|
|
2641
2828
|
export declare const isAuthenticatedCheck: (g: AnyCheckSpec) => g is AuthenticatedCheckSpec;
|
|
2642
2829
|
|
|
2643
2830
|
/** Narrow a guard entry to the identity variant. */
|
|
2644
2831
|
export declare const isAuthenticatedGuard: <I>(g: AnyGuardSpec<I>) => g is AuthenticatedGuardSpec;
|
|
2645
2832
|
|
|
2833
|
+
/** Belongs in the app's own client group (`rpcGroup.generated.ts`). */
|
|
2834
|
+
export declare const isClientReachable: (descriptor: {
|
|
2835
|
+
readonly internal?: boolean | undefined;
|
|
2836
|
+
readonly service?: ServiceSpec | undefined;
|
|
2837
|
+
}) => boolean;
|
|
2838
|
+
|
|
2646
2839
|
export declare const isEventDescriptor: (value: unknown) => value is AnyEventDescriptor;
|
|
2647
2840
|
|
|
2648
2841
|
/** True when every row in the set carries an `id`. The dispatcher uses
|
|
@@ -2651,6 +2844,17 @@ export declare const isEventDescriptor: (value: unknown) => value is AnyEventDes
|
|
|
2651
2844
|
* diffed by id and falls back to shipping the full data. */
|
|
2652
2845
|
export declare const isIdKeyed: (rows: ReadonlyArray<Readonly<Record<string, unknown>>>) => rows is ReadonlyArray<PatchRow>;
|
|
2653
2846
|
|
|
2847
|
+
/**
|
|
2848
|
+
* A machine actor that works ACROSS tenants: the framework acting as itself
|
|
2849
|
+
* (`system`) or another app of the project calling in (`service`).
|
|
2850
|
+
*
|
|
2851
|
+
* This is a statement about DATA placement only — no row filter, no implicit
|
|
2852
|
+
* tenant, an explicit tenant for writes. It says nothing about authority: a
|
|
2853
|
+
* service holds no scopes, and every place that lets `system` bypass a check
|
|
2854
|
+
* keeps asking `isSystemSubject`.
|
|
2855
|
+
*/
|
|
2856
|
+
export declare const isMachineSubject: (subject: Subject) => boolean;
|
|
2857
|
+
|
|
2654
2858
|
/** Runtime narrowing for the declared-open variant. */
|
|
2655
2859
|
export declare const isOpenAccess: (g: AnyCheckSpec) => g is OpenAccessSpec;
|
|
2656
2860
|
|
|
@@ -2676,6 +2880,20 @@ export declare const isReactivityChannel: (value: unknown) => value is Reactivit
|
|
|
2676
2880
|
*/
|
|
2677
2881
|
export declare const isReactivityChannelKey: (key: string) => boolean;
|
|
2678
2882
|
|
|
2883
|
+
/** Runtime narrowing for the service-only variant. */
|
|
2884
|
+
export declare const isServiceAccess: (g: AnyCheckSpec) => g is ServiceAccessSpec;
|
|
2885
|
+
|
|
2886
|
+
/** Belongs in the group other apps call (`serviceGroup.generated.ts`). */
|
|
2887
|
+
export declare const isServiceReachable: (descriptor: {
|
|
2888
|
+
readonly internal?: boolean | undefined;
|
|
2889
|
+
readonly service?: ServiceSpec | undefined;
|
|
2890
|
+
}) => boolean;
|
|
2891
|
+
|
|
2892
|
+
/** Is this caller another app of the project, and which one? */
|
|
2893
|
+
export declare const isServiceSubject: (subject: Subject) => subject is Extract<Subject, {
|
|
2894
|
+
readonly type: "service";
|
|
2895
|
+
}>;
|
|
2896
|
+
|
|
2679
2897
|
export declare const isSystemSubject: (subject: Subject) => boolean;
|
|
2680
2898
|
|
|
2681
2899
|
export declare const isTenantSelectable: (subject: Subject) => subject is TenantSelectableSubject;
|
|
@@ -2807,6 +3025,9 @@ export declare interface MutationProcedureDescriptor<Name extends string, Input
|
|
|
2807
3025
|
* `openAccess: '<why>'`. Mutually exclusive with `guards`; together they are
|
|
2808
3026
|
* the only two shapes `security.defaultDeny` accepts. */
|
|
2809
3027
|
readonly openAccess: string | undefined;
|
|
3028
|
+
/** Only these apps of the project may call this procedure — see `service` on
|
|
3029
|
+
* the definer's options. Absent → the app's own clients call it. */
|
|
3030
|
+
readonly service: ServiceSpec | undefined;
|
|
2810
3031
|
/** Opt this mutation into a public REST endpoint (innovation/11). */
|
|
2811
3032
|
readonly publicApi: PublicApiSpec | undefined;
|
|
2812
3033
|
/** Opt this mutation into the auto-synthesized agent toolset (innovation/07). */
|
|
@@ -2862,7 +3083,7 @@ export declare interface NestedTargetFields<Input = unknown> {
|
|
|
2862
3083
|
/** Guard WHICH cached query entries this target patches: only entries whose
|
|
2863
3084
|
* CURRENT value satisfies the predicate. Pure + browser-safe. Prevents a
|
|
2864
3085
|
* patch from bleeding across sibling subscriptions that share a source table
|
|
2865
|
-
* (the guard
|
|
3086
|
+
* (the guard an app would otherwise hand-write as `roadmap.id === input.roadmapId`). Absent →
|
|
2866
3087
|
* every entry matching the target `table` is patched. */
|
|
2867
3088
|
readonly match?: ((value: unknown, input: Input) => boolean) | undefined;
|
|
2868
3089
|
}
|
|
@@ -2917,6 +3138,32 @@ declare const NoRowFound_base: Schema.TaggedErrorClass<NoRowFound, "NoRowFound",
|
|
|
2917
3138
|
found: typeof Schema.Number;
|
|
2918
3139
|
}>;
|
|
2919
3140
|
|
|
3141
|
+
/**
|
|
3142
|
+
* A resource guard's refusal when the resource it names does not exist — as
|
|
3143
|
+
* far as THIS caller may know.
|
|
3144
|
+
*
|
|
3145
|
+
* Only an app can say that. The guard never infers absence from an empty tuple
|
|
3146
|
+
* set or a `false` answer: "no relation" and "no row" look identical from the
|
|
3147
|
+
* outside, and telling them apart is an existence oracle. So this is raised
|
|
3148
|
+
* only when a tuple source or resolver answers `'missing'`
|
|
3149
|
+
* ({@link ResourceMissing}), and only for a signed-in caller — an anonymous one
|
|
3150
|
+
* gets the ordinary refusal whatever the source said.
|
|
3151
|
+
*
|
|
3152
|
+
* `resourceType` is the relationship guard's type, or `null` for a scope guard
|
|
3153
|
+
* with a `resource` extractor (which names no type). Merged into the wire union
|
|
3154
|
+
* of every procedure that declares a resource-bearing guard.
|
|
3155
|
+
*/
|
|
3156
|
+
export declare class NoSuchResource extends NoSuchResource_base {
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
declare const NoSuchResource_base: Schema.TaggedErrorClass<NoSuchResource, "NoSuchResource", {
|
|
3160
|
+
readonly _tag: Schema.tag<"NoSuchResource">;
|
|
3161
|
+
} & {
|
|
3162
|
+
resourceType: Schema.NullOr<typeof Schema.String>;
|
|
3163
|
+
resourceId: typeof Schema.String;
|
|
3164
|
+
message: typeof Schema.String;
|
|
3165
|
+
}>;
|
|
3166
|
+
|
|
2920
3167
|
/**
|
|
2921
3168
|
* What a plugin contributes to the OTel layer via `contributeObservability`.
|
|
2922
3169
|
* The OTel types are intentionally `unknown` so this browser-safe protocol
|
|
@@ -3001,6 +3248,38 @@ export declare const openAccessSpec: (reason: string) => OpenAccessSpec;
|
|
|
3001
3248
|
*/
|
|
3002
3249
|
export declare const orderByBearerPrefix: (strategies: ReadonlyArray<AuthStrategy>, headers: Readonly<Record<string, string | undefined>>) => ReadonlyArray<AuthStrategy>;
|
|
3003
3250
|
|
|
3251
|
+
export declare interface Pairing {
|
|
3252
|
+
/** The api's base url as the DEVICE reaches it — a LAN address, never `localhost`. */
|
|
3253
|
+
readonly api: string;
|
|
3254
|
+
/** The api process name (`main`), for the client's api binding. */
|
|
3255
|
+
readonly name: string;
|
|
3256
|
+
/** The dev inspect token, when the CLI knows it. */
|
|
3257
|
+
readonly token?: string;
|
|
3258
|
+
}
|
|
3259
|
+
|
|
3260
|
+
export declare const PAIRING_HOST = "pair";
|
|
3261
|
+
|
|
3262
|
+
export declare const PAIRING_SCHEME = "voltro-dev";
|
|
3263
|
+
|
|
3264
|
+
/** Where `applyPairing` keeps the record — the platform's plain storage. */
|
|
3265
|
+
export declare const PAIRING_STORAGE_KEY = "voltro:pairing";
|
|
3266
|
+
|
|
3267
|
+
/** The link text. Refuses a loopback api: a phone cannot reach the laptop's `localhost`. */
|
|
3268
|
+
export declare const pairingLink: (pairing: Pairing) => string;
|
|
3269
|
+
|
|
3270
|
+
/** A key/value store in either spelling: the platform's `StoreStorage`
|
|
3271
|
+
* (`getItem`/`setItem`, what `platform.storage('local')` returns) or a
|
|
3272
|
+
* `get`/`set` pair (a secure store, a test fake). */
|
|
3273
|
+
export declare type PairingStorage = {
|
|
3274
|
+
readonly get: (key: string) => Promise<string | null> | string | null;
|
|
3275
|
+
readonly set: (key: string, value: string) => Promise<void> | void;
|
|
3276
|
+
readonly remove?: (key: string) => Promise<void> | void;
|
|
3277
|
+
} | {
|
|
3278
|
+
readonly getItem: (key: string) => Promise<string | null> | string | null;
|
|
3279
|
+
readonly setItem: (key: string, value: string) => Promise<void> | void;
|
|
3280
|
+
readonly removeItem?: (key: string) => Promise<void> | void;
|
|
3281
|
+
};
|
|
3282
|
+
|
|
3004
3283
|
/** Split a route back into its three parts. */
|
|
3005
3284
|
export declare const parseEventRoute: (route: string) => {
|
|
3006
3285
|
readonly tenantId: string | null;
|
|
@@ -3008,6 +3287,11 @@ export declare const parseEventRoute: (route: string) => {
|
|
|
3008
3287
|
readonly key: string;
|
|
3009
3288
|
};
|
|
3010
3289
|
|
|
3290
|
+
/** The record from a link, or `null` for anything that is not a pairing link. */
|
|
3291
|
+
export declare const parsePairingLink: (url: string) => Pairing | null;
|
|
3292
|
+
|
|
3293
|
+
export declare const patchCellSchema: Schema.transform<typeof Schema.Unknown, typeof Schema.Unknown>;
|
|
3294
|
+
|
|
3011
3295
|
/** A single row in a subscription result. Must carry an `id`; everything
|
|
3012
3296
|
* else is opaque to the patch layer. */
|
|
3013
3297
|
export declare type PatchRow = Readonly<Record<string, unknown>> & {
|
|
@@ -3378,16 +3662,29 @@ export declare interface PluginDashboardMount {
|
|
|
3378
3662
|
export declare type PluginDeactivateHook = (ctx: PluginLifecycleContext) => Effect.Effect<void, unknown> | Promise<void> | void;
|
|
3379
3663
|
|
|
3380
3664
|
/**
|
|
3381
|
-
*
|
|
3382
|
-
*
|
|
3383
|
-
*
|
|
3384
|
-
*
|
|
3385
|
-
*
|
|
3386
|
-
*
|
|
3387
|
-
*
|
|
3388
|
-
* Structurally identical to `@voltro/env`'s `DeclaredEnvVar` (kept local here
|
|
3389
|
-
* to avoid a protocol → env package dependency).
|
|
3665
|
+
* One place a plugin sends data outside the installation — folded by
|
|
3666
|
+
* `voltro compliance generate` into `egress.json`, the machine-readable list an
|
|
3667
|
+
* operator reviews before opening a firewall, and answers an air-gap question
|
|
3668
|
+
* from. Declare what the plugin CAN reach with the options it was given: a
|
|
3669
|
+
* storage plugin on the database provider reaches nothing; on s3 it reaches
|
|
3670
|
+
* the bucket's endpoint.
|
|
3390
3671
|
*/
|
|
3672
|
+
export declare interface PluginEgressDeclaration {
|
|
3673
|
+
/**
|
|
3674
|
+
* Where: a host (`api.example.com`), a URL, or — when the address is data,
|
|
3675
|
+
* not configuration — what decides it, prefixed `runtime:`
|
|
3676
|
+
* (`runtime:webhook targets`).
|
|
3677
|
+
*/
|
|
3678
|
+
readonly destination: string;
|
|
3679
|
+
/** Why the data goes there, in one line. */
|
|
3680
|
+
readonly purpose: string;
|
|
3681
|
+
/** What leaves: `content` (what users write), `personal` (who someone is),
|
|
3682
|
+
* `files`, `metadata` (ids, names, timestamps), `telemetry`, `credentials`. */
|
|
3683
|
+
readonly data: ReadonlyArray<'content' | 'personal' | 'files' | 'metadata' | 'telemetry' | 'credentials'>;
|
|
3684
|
+
/** How an operator turns it off, and what the installation does then. */
|
|
3685
|
+
readonly disable: string;
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3391
3688
|
export declare interface PluginEnvVar {
|
|
3392
3689
|
/** The env var name, e.g. `DD_API_KEY`. */
|
|
3393
3690
|
readonly name: string;
|
|
@@ -3452,11 +3749,17 @@ export declare interface PluginErrorSchema {
|
|
|
3452
3749
|
|
|
3453
3750
|
/** A public raw-HTTP route a plugin serves on the framework listener. */
|
|
3454
3751
|
export declare interface PluginHttpRoute {
|
|
3455
|
-
/** HTTP method, or `'*'` for any (the handler decides).
|
|
3456
|
-
*
|
|
3457
|
-
*
|
|
3458
|
-
*
|
|
3752
|
+
/** HTTP method, or `'*'` for any (the handler decides). The server mounts the
|
|
3753
|
+
* path for exactly the methods its routes declare; `'*'` mounts it for every
|
|
3754
|
+
* method the router knows (34), so keep that for a route that really serves
|
|
3755
|
+
* them — see `answersOtherMethods` for one that only wants to refuse them. */
|
|
3459
3756
|
readonly method: '*' | 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
3757
|
+
/** `true`: the handler gates its own method, so a request with a method the
|
|
3758
|
+
* path does not declare is still handed to it — to answer with a precise
|
|
3759
|
+
* `405` and `Allow` instead of the router's `404`. The path is still mounted
|
|
3760
|
+
* only for `method`. A REST route sets it. Without it, a route that declares
|
|
3761
|
+
* one method never sees another. */
|
|
3762
|
+
readonly answersOtherMethods?: boolean | undefined;
|
|
3460
3763
|
/** Absolute path, e.g. `/_voltro/storage`. Matched byte for byte: the
|
|
3461
3764
|
* router folds case and a trailing slash to FIND the route, the dispatcher
|
|
3462
3765
|
* then asks whether the request's path is one the route declared — so
|
|
@@ -3947,6 +4250,14 @@ export declare type PluginMigrationSqlClient = SqlClient.SqlClient;
|
|
|
3947
4250
|
*/
|
|
3948
4251
|
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' | 'store:write' | 'migration:run' | 'store:changes:read' | `secrets:read:${string}` | `network:outbound:${string}` | `plugin:hook:${string}`;
|
|
3949
4252
|
|
|
4253
|
+
/** What a plugin collects and uses — folded by `voltro compliance generate`
|
|
4254
|
+
* into PrivacyInfo.xcprivacy and the Play Data-safety answers. A plugin that
|
|
4255
|
+
* moves data (routes, tables) and declares nothing is listed by name. */
|
|
4256
|
+
export declare interface PluginPrivacyDeclaration {
|
|
4257
|
+
readonly collects?: ReadonlyArray<PrivacyCollectedData>;
|
|
4258
|
+
readonly requiredReasonApis?: ReadonlyArray<PrivacyRequiredReasonApi>;
|
|
4259
|
+
}
|
|
4260
|
+
|
|
3950
4261
|
/**
|
|
3951
4262
|
* Per-call context handed to a plugin-contributed rpc route's
|
|
3952
4263
|
* executor. Mirror of the user-handler `AppContext` shape but typed
|
|
@@ -4221,9 +4532,10 @@ export declare interface PolicyGuardRequest {
|
|
|
4221
4532
|
* Answers "does `subject` have `action` on `<resourceType>:<resourceId>`".
|
|
4222
4533
|
* Registered once at boot via `setPolicyGuardResolver`. A failed Effect is
|
|
4223
4534
|
* treated as a DENIAL — a resolver wanting another posture catches its own
|
|
4224
|
-
* errors.
|
|
4535
|
+
* errors. Only `true` allows; `'missing'` refuses with {@link NoSuchResource}
|
|
4536
|
+
* for a signed-in caller.
|
|
4225
4537
|
*/
|
|
4226
|
-
export declare type PolicyGuardResolver = (req: PolicyGuardRequest) => Effect.Effect<
|
|
4538
|
+
export declare type PolicyGuardResolver = (req: PolicyGuardRequest) => Effect.Effect<ResourceVerdict, unknown>;
|
|
4227
4539
|
|
|
4228
4540
|
/**
|
|
4229
4541
|
* A relationship (ReBAC) guard — "may this subject perform ACTION on THIS row?"
|
|
@@ -4255,6 +4567,38 @@ export declare interface PolicyGuardSpec<Input = unknown> {
|
|
|
4255
4567
|
readonly resource: (input: Input) => string | undefined;
|
|
4256
4568
|
}
|
|
4257
4569
|
|
|
4570
|
+
/**
|
|
4571
|
+
* An environment variable a plugin reads. DECLARATION ONLY — metadata, not a
|
|
4572
|
+
* read path: the plugin still reads the value itself (typically
|
|
4573
|
+
* `options.X ?? process.env.X`). Declaring it makes the plugin's env needs
|
|
4574
|
+
* visible to the env manifest (`/_voltro/inspect/env`), the generated
|
|
4575
|
+
* `.env.example`, and the dashboard Env panel — so an operator can see, before
|
|
4576
|
+
* running, exactly what each plugin expects.
|
|
4577
|
+
*
|
|
4578
|
+
* Structurally identical to `@voltro/env`'s `DeclaredEnvVar` (kept local here
|
|
4579
|
+
* to avoid a protocol → env package dependency).
|
|
4580
|
+
*/
|
|
4581
|
+
/** One kind of data an app or plugin collects, in the vocabulary both stores
|
|
4582
|
+
* understand (`voltro compliance generate` maps it to Apple's and Google's). */
|
|
4583
|
+
export declare interface PrivacyCollectedData {
|
|
4584
|
+
readonly category: 'name' | 'email' | 'phone' | 'physical-address' | 'identifiers' | 'device-id' | 'payment-info' | 'purchase-history' | 'precise-location' | 'coarse-location' | 'photos-or-videos' | 'audio' | 'user-content' | 'browsing-history' | 'search-history' | 'product-interaction' | 'crash-data' | 'performance-data' | 'other-diagnostic-data' | 'other-data';
|
|
4585
|
+
/** Linked to the user's identity. */
|
|
4586
|
+
readonly linked: boolean;
|
|
4587
|
+
/** Used to track the user across apps or sites (advertising). */
|
|
4588
|
+
readonly tracking: boolean;
|
|
4589
|
+
readonly purposes: ReadonlyArray<'app-functionality' | 'analytics' | 'product-personalization' | 'developer-advertising' | 'third-party-advertising' | 'other'>;
|
|
4590
|
+
/** Play: shared with third parties. Default false. */
|
|
4591
|
+
readonly shared?: boolean;
|
|
4592
|
+
/** Play: the user can decline it. Default false. */
|
|
4593
|
+
readonly optional?: boolean;
|
|
4594
|
+
}
|
|
4595
|
+
|
|
4596
|
+
/** Apple's required-reason API use (`NSPrivacyAccessedAPICategory…` + reason codes). */
|
|
4597
|
+
export declare interface PrivacyRequiredReasonApi {
|
|
4598
|
+
readonly api: string;
|
|
4599
|
+
readonly reasons: ReadonlyArray<string>;
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4258
4602
|
export declare const PROBLEM_JSON = "application/problem+json; charset=utf-8";
|
|
4259
4603
|
|
|
4260
4604
|
/** RFC 9457 Problem Details for one failure: `type` from the tag, `title` from
|
|
@@ -4283,6 +4627,16 @@ export declare interface ProcedureLike {
|
|
|
4283
4627
|
|
|
4284
4628
|
export declare const procedureShapeDigest: (rpc: ProcedureLike) => string;
|
|
4285
4629
|
|
|
4630
|
+
/**
|
|
4631
|
+
* The error values a procedure's wire union can carry, as far as types can
|
|
4632
|
+
* tell: its own `error:`, the framework's unconditional members for its kind,
|
|
4633
|
+
* and every plugin-registered error.
|
|
4634
|
+
*/
|
|
4635
|
+
export declare type ProcedureWireError<D extends {
|
|
4636
|
+
readonly kind: WireProcedureKind;
|
|
4637
|
+
readonly error: Schema.Schema.All;
|
|
4638
|
+
}> = Schema.Schema.Type<D['error']> | FrameworkWireError<D['kind']> | RegisteredPluginError;
|
|
4639
|
+
|
|
4286
4640
|
export declare const PROTOCOL_VERSION: 1;
|
|
4287
4641
|
|
|
4288
4642
|
export declare type ProtocolVersion = typeof PROTOCOL_VERSION;
|
|
@@ -4425,6 +4779,13 @@ export declare interface PublicApiSpec {
|
|
|
4425
4779
|
* optional, the rest inherited. See `PublicApiProfileConfig`.
|
|
4426
4780
|
*/
|
|
4427
4781
|
readonly format?: PublicApiProfileConfig;
|
|
4782
|
+
/**
|
|
4783
|
+
* GET only: how long a CDN may keep a successful answer, and the tags it can
|
|
4784
|
+
* purge it by (`Cache-Tag`, `Surrogate-Key`). A request with a credential is
|
|
4785
|
+
* always answered `private` — see `RestCache`. `tags` receives the answer as
|
|
4786
|
+
* it goes on the wire.
|
|
4787
|
+
*/
|
|
4788
|
+
readonly cache?: RestCache;
|
|
4428
4789
|
}
|
|
4429
4790
|
|
|
4430
4791
|
/**
|
|
@@ -4512,6 +4873,9 @@ export declare interface QueryProcedureDescriptor<Name extends string, Input ext
|
|
|
4512
4873
|
* `openAccess: '<why>'`. Mutually exclusive with `guards`; together they are
|
|
4513
4874
|
* the only two shapes `security.defaultDeny` accepts. */
|
|
4514
4875
|
readonly openAccess: string | undefined;
|
|
4876
|
+
/** Only these apps of the project may call this procedure — see `service` on
|
|
4877
|
+
* the definer's options. Absent → the app's own clients call it. */
|
|
4878
|
+
readonly service: ServiceSpec | undefined;
|
|
4515
4879
|
/** Opt this query into a public REST endpoint (innovation/11). */
|
|
4516
4880
|
readonly publicApi: PublicApiSpec | undefined;
|
|
4517
4881
|
/** Opt this query into the auto-synthesized agent toolset (innovation/07). */
|
|
@@ -4584,7 +4948,7 @@ export declare const queryToRpc: <Name extends string, Input extends Schema.Sche
|
|
|
4584
4948
|
}>, Schema.Struct<{
|
|
4585
4949
|
op: Schema.Literal<["mergeCells"]>;
|
|
4586
4950
|
path: typeof Schema.String;
|
|
4587
|
-
value: Schema.Record$<typeof Schema.String, typeof Schema.Unknown
|
|
4951
|
+
value: Schema.Record$<typeof Schema.String, Schema.transform<typeof Schema.Unknown, typeof Schema.Unknown>>;
|
|
4588
4952
|
}>]>>;
|
|
4589
4953
|
order: Schema.Array$<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
|
|
4590
4954
|
}>;
|
|
@@ -4669,6 +5033,11 @@ export declare type ReactivitySource = TableName | ReactivityChannel;
|
|
|
4669
5033
|
*/
|
|
4670
5034
|
export declare type ReactivitySourceValue = string | ReactivityChannel;
|
|
4671
5035
|
|
|
5036
|
+
export declare const readPairing: (storage: PairingStorage) => Promise<Pairing | null>;
|
|
5037
|
+
|
|
5038
|
+
/** Every error a plugin registers, as one union (`never` before codegen). */
|
|
5039
|
+
export declare type RegisteredPluginError = VoltroPluginErrors[keyof VoltroPluginErrors];
|
|
5040
|
+
|
|
4672
5041
|
/**
|
|
4673
5042
|
* Declare, for this realm, what namespace each installed plugin actually
|
|
4674
5043
|
* answers to. Emitted into `rpcGroup.generated.ts` by the codegen — one call
|
|
@@ -4685,6 +5054,19 @@ export declare type ReactivitySourceValue = string | ReactivityChannel;
|
|
|
4685
5054
|
*/
|
|
4686
5055
|
export declare const registerPluginAliases: (aliases: Readonly<Record<string, string>>) => void;
|
|
4687
5056
|
|
|
5057
|
+
/**
|
|
5058
|
+
* The failure value as an `Error`, for a reporter that needs one — the value
|
|
5059
|
+
* itself when it already is one, else an `Error` named by its `_tag` (or
|
|
5060
|
+
* `NonErrorThrown`) with `errorMessage(value)` as its message and the value as
|
|
5061
|
+
* its `cause`.
|
|
5062
|
+
*
|
|
5063
|
+
* A loader that does not catch a refusal throws the declared error, which in a
|
|
5064
|
+
* web process is the plain object decoded from the wire. Handed to an error
|
|
5065
|
+
* reporter as it is, that becomes "Object captured as exception": no name to
|
|
5066
|
+
* group by, no stack, no message.
|
|
5067
|
+
*/
|
|
5068
|
+
export declare const reportableError: (err: unknown) => Error;
|
|
5069
|
+
|
|
4688
5070
|
/** Gate a handler on a scope; fails with a typed `ScopeError` if missing.
|
|
4689
5071
|
* Checks the EFFECTIVE set so role-derived scopes count. */
|
|
4690
5072
|
export declare const requireScope: (subject: Subject, scope: string) => Effect.Effect<void, ScopeError>;
|
|
@@ -4713,6 +5095,14 @@ export declare const resolveRestFormat: (config: PublicApiProfileConfig | undefi
|
|
|
4713
5095
|
*/
|
|
4714
5096
|
export declare const resolveWorkflowAccess: (name: string, options: WorkflowAccessOptions<never>) => WorkflowAccess;
|
|
4715
5097
|
|
|
5098
|
+
/**
|
|
5099
|
+
* The answer a tuple source or resolver gives when the resource a guard names
|
|
5100
|
+
* does not exist for this caller. Return it only when disclosing that is
|
|
5101
|
+
* acceptable — typically after a TENANT-SCOPED read, so a row in another tenant
|
|
5102
|
+
* reads as missing rather than as "exists, not yours".
|
|
5103
|
+
*/
|
|
5104
|
+
export declare type ResourceMissing = 'missing';
|
|
5105
|
+
|
|
4716
5106
|
/** The question the runtime asks a registered resource-scope resolver. */
|
|
4717
5107
|
export declare interface ResourceScopeRequest {
|
|
4718
5108
|
/** The authenticated caller. */
|
|
@@ -4729,11 +5119,53 @@ export declare interface ResourceScopeRequest {
|
|
|
4729
5119
|
* an Effect so it can read the app's role tables. It should NOT leak errors —
|
|
4730
5120
|
* `checkGuardsEffect` treats a failed resolver as a DENIAL (fail-closed), so a
|
|
4731
5121
|
* resolver that wants a different posture must catch its own errors.
|
|
5122
|
+
*
|
|
5123
|
+
* Only `true` allows. `'missing'` refuses with {@link NoSuchResource} (for a
|
|
5124
|
+
* signed-in caller); anything else refuses with `ScopeError`.
|
|
4732
5125
|
*/
|
|
4733
|
-
export declare type ResourceScopeResolver = (req: ResourceScopeRequest) => Effect.Effect<
|
|
5126
|
+
export declare type ResourceScopeResolver = (req: ResourceScopeRequest) => Effect.Effect<ResourceVerdict, unknown>;
|
|
5127
|
+
|
|
5128
|
+
/** A resource resolver's verdict: allowed, refused, or no such resource. */
|
|
5129
|
+
export declare type ResourceVerdict = boolean | ResourceMissing;
|
|
4734
5130
|
|
|
4735
5131
|
export declare const REST_PROFILE_NAMES: ReadonlyArray<PublicApiProfileName>;
|
|
4736
5132
|
|
|
5133
|
+
/** A BINARY streaming response (download/export). The serve layer pipes the
|
|
5134
|
+
* ReadableStream without buffering — a body larger than the heap is fine.
|
|
5135
|
+
* The LAZY thunk form defers opening the source until the response streams. */
|
|
5136
|
+
declare interface RestByteResponse {
|
|
5137
|
+
readonly __voltroRestBytes: true;
|
|
5138
|
+
readonly byteStream: {
|
|
5139
|
+
readonly stream: ReadableStream<Uint8Array> | (() => ReadableStream<Uint8Array>);
|
|
5140
|
+
readonly contentLength?: number;
|
|
5141
|
+
readonly contentDisposition?: string;
|
|
5142
|
+
};
|
|
5143
|
+
readonly contentType?: string;
|
|
5144
|
+
readonly status?: number;
|
|
5145
|
+
readonly headers?: Readonly<Record<string, string | ReadonlyArray<string>>>;
|
|
5146
|
+
}
|
|
5147
|
+
|
|
5148
|
+
/**
|
|
5149
|
+
* Caching for a GET route's successful (200) answers.
|
|
5150
|
+
*
|
|
5151
|
+
* An anonymous request's answer is `public` for `maxAge` seconds (`max-age`
|
|
5152
|
+
* and `s-maxage`), `stale-while-revalidate` when set, and carries `tags` as
|
|
5153
|
+
* `Cache-Tag` (comma-separated) and `Surrogate-Key` (space-separated) — the
|
|
5154
|
+
* headers CDNs purge by. A request that carries a credential (`Authorization`
|
|
5155
|
+
* or a cookie) gets `private, no-cache` and no tags, whatever is declared:
|
|
5156
|
+
* what a key or a session may see must never land in a shared cache. Every
|
|
5157
|
+
* such answer says `Vary: Authorization, Cookie`. Errors are not affected.
|
|
5158
|
+
*/
|
|
5159
|
+
declare interface RestCache {
|
|
5160
|
+
/** Seconds a cache may serve the answer without asking again. */
|
|
5161
|
+
readonly maxAge: number;
|
|
5162
|
+
/** Seconds after that a stale answer may still be served while the cache refetches. */
|
|
5163
|
+
readonly staleWhileRevalidate?: number;
|
|
5164
|
+
/** Purge tags from the answer as it goes on the wire, and the input.
|
|
5165
|
+
* A tag with whitespace or a comma is dropped (no header can carry it). */
|
|
5166
|
+
readonly tags?: (output: unknown, input: unknown) => ReadonlyArray<string>;
|
|
5167
|
+
}
|
|
5168
|
+
|
|
4737
5169
|
export declare type RestDates = 'iso' | 'epoch-ms';
|
|
4738
5170
|
|
|
4739
5171
|
export declare type RestEnvelope = 'none' | 'data' | 'jsonapi';
|
|
@@ -4823,6 +5255,11 @@ declare interface RestGuardRejection {
|
|
|
4823
5255
|
readonly message: string;
|
|
4824
5256
|
}
|
|
4825
5257
|
|
|
5258
|
+
/** What a REST handler may return: the decoded output, a `response(...)` with
|
|
5259
|
+
* its own status and headers, an `sse(...)` stream, or `bytes(...)` for a
|
|
5260
|
+
* non-JSON body (a file, an export, an XML document). */
|
|
5261
|
+
declare type RestHandlerResult<O> = O | RestResponse<O> | RestStreamResponse | RestByteResponse;
|
|
5262
|
+
|
|
4826
5263
|
declare type RestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
4827
5264
|
|
|
4828
5265
|
export declare type RestNaming = 'camelCase' | 'snake_case';
|
|
@@ -4886,7 +5323,7 @@ declare interface RestRouteDescriptor<I, O> {
|
|
|
4886
5323
|
/** Output schema. The handler returns the decoded `Type`; the desugar
|
|
4887
5324
|
* encodes it to JSON for the `200` response. */
|
|
4888
5325
|
readonly output: Schema.Schema<O, any, never>;
|
|
4889
|
-
readonly handler: (input: I, ctx: RestRouteContext) => Promise<
|
|
5326
|
+
readonly handler: (input: I, ctx: RestRouteContext) => Promise<RestHandlerResult<O>> | RestHandlerResult<O>;
|
|
4890
5327
|
readonly summary?: string;
|
|
4891
5328
|
readonly description?: string;
|
|
4892
5329
|
readonly example?: RestRouteExample;
|
|
@@ -4943,6 +5380,9 @@ declare interface RestRouteDescriptor<I, O> {
|
|
|
4943
5380
|
* of the JSON), so it is correct across content-encodings — the
|
|
4944
5381
|
* transport's compression varies the bytes, not the representation. */
|
|
4945
5382
|
readonly etag?: boolean;
|
|
5383
|
+
/** GET only: how long a shared cache (a CDN) may keep a successful answer,
|
|
5384
|
+
* and the tags it can be purged by. See {@link RestCache}. */
|
|
5385
|
+
readonly cache?: RestCache;
|
|
4946
5386
|
}
|
|
4947
5387
|
|
|
4948
5388
|
declare interface RestRouteExample {
|
|
@@ -4983,6 +5423,18 @@ declare interface RestRouteProjection {
|
|
|
4983
5423
|
readonly format: RestFormat;
|
|
4984
5424
|
}
|
|
4985
5425
|
|
|
5426
|
+
/**
|
|
5427
|
+
* What a REST handler returns to stream its response instead of resolving one
|
|
5428
|
+
* value: `sse((emit) => unsubscribe)`. The route's schema `output` is not used
|
|
5429
|
+
* for a stream (each frame is framed as it is produced), and everything the
|
|
5430
|
+
* desugar does BEFORE the handler — method gate, sunset, input decode, guards,
|
|
5431
|
+
* subject resolution — still applies.
|
|
5432
|
+
*/
|
|
5433
|
+
declare interface RestStreamResponse {
|
|
5434
|
+
readonly __voltroRestStream: true;
|
|
5435
|
+
readonly stream: PluginHttpRouteStream;
|
|
5436
|
+
}
|
|
5437
|
+
|
|
4986
5438
|
/**
|
|
4987
5439
|
* Rewrite a descriptor's schema into the shape the profile puts on the wire:
|
|
4988
5440
|
* `timestampMs` (`DateFromNumber`) becomes an RFC 3339 string under
|
|
@@ -5072,7 +5524,7 @@ export declare const rowPatchOpSchema: Schema.Union<[Schema.Struct<{
|
|
|
5072
5524
|
}>, Schema.Struct<{
|
|
5073
5525
|
op: Schema.Literal<["mergeCells"]>;
|
|
5074
5526
|
path: typeof Schema.String;
|
|
5075
|
-
value: Schema.Record$<typeof Schema.String, typeof Schema.Unknown
|
|
5527
|
+
value: Schema.Record$<typeof Schema.String, Schema.transform<typeof Schema.Unknown, typeof Schema.Unknown>>;
|
|
5076
5528
|
}>]>;
|
|
5077
5529
|
|
|
5078
5530
|
export declare const rowPatchSchema: Schema.Struct<{
|
|
@@ -5106,7 +5558,7 @@ export declare const rowPatchSchema: Schema.Struct<{
|
|
|
5106
5558
|
}>, Schema.Struct<{
|
|
5107
5559
|
op: Schema.Literal<["mergeCells"]>;
|
|
5108
5560
|
path: typeof Schema.String;
|
|
5109
|
-
value: Schema.Record$<typeof Schema.String, typeof Schema.Unknown
|
|
5561
|
+
value: Schema.Record$<typeof Schema.String, Schema.transform<typeof Schema.Unknown, typeof Schema.Unknown>>;
|
|
5110
5562
|
}>]>>;
|
|
5111
5563
|
order: Schema.Array$<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
|
|
5112
5564
|
}>;
|
|
@@ -5370,8 +5822,18 @@ export declare interface ServerErrorEvent {
|
|
|
5370
5822
|
readonly name?: string;
|
|
5371
5823
|
/** Distributed-trace id when one is in scope (workflows carry it). */
|
|
5372
5824
|
readonly traceId?: string;
|
|
5373
|
-
/** Extra context — op, runId, executionId, http status, etc.
|
|
5825
|
+
/** Extra context — op, runId, executionId, http status, etc. Identity only:
|
|
5826
|
+
* never the primitive's data. */
|
|
5374
5827
|
readonly fields?: Record<string, unknown>;
|
|
5828
|
+
/**
|
|
5829
|
+
* The error's CONTENT may carry data of a primitive declared encrypted
|
|
5830
|
+
* (`workflow({ encrypted: true })`): its message, its cause, a typed
|
|
5831
|
+
* failure's fields. A reporter that sends the event out of the process sends
|
|
5832
|
+
* {@link withheldServerError} instead — the class, the stack frames and the
|
|
5833
|
+
* identity fields, not the text. Encrypted at rest and then mailed to a
|
|
5834
|
+
* third party in plaintext would make the declaration decorative.
|
|
5835
|
+
*/
|
|
5836
|
+
readonly contentSensitive?: boolean;
|
|
5375
5837
|
}
|
|
5376
5838
|
|
|
5377
5839
|
declare type ServerErrorListener = (event: ServerErrorEvent) => void;
|
|
@@ -5405,6 +5867,132 @@ declare const ServerOnlyColumnWrite_base: Schema.TaggedErrorClass<ServerOnlyColu
|
|
|
5405
5867
|
columns: Schema.Array$<typeof Schema.String>;
|
|
5406
5868
|
}>;
|
|
5407
5869
|
|
|
5870
|
+
/** A service (app) name: what `serviceCallers`, `service.callers` and a service
|
|
5871
|
+
* credential all spell the same way. At most 56 characters: the caller writes
|
|
5872
|
+
* as `service:<name>`, which is an `actors.id` — an `id()` column, VARCHAR(64)
|
|
5873
|
+
* on three dialects — so a longer name would fail its first audited write. */
|
|
5874
|
+
export declare const SERVICE_NAME_PATTERN: RegExp;
|
|
5875
|
+
|
|
5876
|
+
/**
|
|
5877
|
+
* The runtime-erased form of a procedure's `service: { callers }` — "only these
|
|
5878
|
+
* apps of the project may call this, and nobody else".
|
|
5879
|
+
*
|
|
5880
|
+
* A guard entry for the reason `OpenAccessSpec` is one: every enforcement path
|
|
5881
|
+
* is handed the `guards` array and nothing else, so a decision that lived on a
|
|
5882
|
+
* separate descriptor field would be enforced by the paths somebody remembered
|
|
5883
|
+
* and skipped by the rest.
|
|
5884
|
+
*
|
|
5885
|
+
* It admits exactly a `service` subject whose name is listed. `admin:full` does
|
|
5886
|
+
* NOT bypass it: a service procedure is a machine contract between two apps,
|
|
5887
|
+
* and a browser session holding the admin scope is not one of the parties.
|
|
5888
|
+
*/
|
|
5889
|
+
export declare interface ServiceAccessSpec {
|
|
5890
|
+
/** The calling apps' names, as the callee declares them in `serviceCallers`.
|
|
5891
|
+
* Non-empty by construction — the definers refuse an empty list. */
|
|
5892
|
+
readonly service: ReadonlyArray<string>;
|
|
5893
|
+
}
|
|
5894
|
+
|
|
5895
|
+
/** Build the erased `service:` entry. The definers call this. */
|
|
5896
|
+
export declare const serviceAccessSpec: (callers: ReadonlyArray<string>) => ServiceAccessSpec;
|
|
5897
|
+
|
|
5898
|
+
/**
|
|
5899
|
+
* A procedure map (`ServiceProcedures`) turned into the nested object a caller
|
|
5900
|
+
* writes: `'deployments.activate'` becomes `.deployments.activate(...)`. A tag
|
|
5901
|
+
* that is both a procedure and a namespace prefix is both.
|
|
5902
|
+
*/
|
|
5903
|
+
export declare type ServiceApi<P> = 0 extends (1 & P) ? any : ServiceApiOf<P>;
|
|
5904
|
+
|
|
5905
|
+
declare type ServiceApiOf<P> = {
|
|
5906
|
+
readonly [H in ServiceTagHead<keyof P & string>]: (H extends keyof P ? ServiceCall<P[H]> : unknown) & ServiceApiOf<{
|
|
5907
|
+
[K in keyof P & string as K extends `${H}.${infer R}` ? R : never]: P[K];
|
|
5908
|
+
}>;
|
|
5909
|
+
};
|
|
5910
|
+
|
|
5911
|
+
/** One procedure as the caller sees it — callable, `.effect`, and `.subscribe` for a query. */
|
|
5912
|
+
export declare type ServiceCall<D> = D extends ServiceDescriptorShape ? ((input: ServiceDecoded<D['input']>, options?: ServiceCallOptions) => Promise<ServiceDecoded<D['output']>>) & {
|
|
5913
|
+
/** The same call as an Effect. Inside a workflow step its write key is
|
|
5914
|
+
* derived from the step, so a re-sent step replays instead of writing twice. */
|
|
5915
|
+
readonly effect: (input: ServiceDecoded<D['input']>, options?: ServiceCallOptions) => Effect.Effect<ServiceDecoded<D['output']>, unknown>;
|
|
5916
|
+
} & (D extends {
|
|
5917
|
+
readonly kind: 'query';
|
|
5918
|
+
} ? {
|
|
5919
|
+
/** Hold the live query open; `onValue` gets each materialized value. */
|
|
5920
|
+
readonly subscribe: (input: ServiceDecoded<D['input']>, handlers: ServiceSubscribeHandlers<ServiceDecoded<D['output']>>) => ServiceSubscription;
|
|
5921
|
+
} : unknown) : never;
|
|
5922
|
+
|
|
5923
|
+
/** The apps a guard array admits as service callers, or `undefined` when the
|
|
5924
|
+
* procedure is not a service procedure. */
|
|
5925
|
+
export declare const serviceCallersOf: (guards: ReadonlyArray<AnyCheckSpec> | undefined) => ReadonlyArray<string> | undefined;
|
|
5926
|
+
|
|
5927
|
+
export declare interface ServiceCallOptions {
|
|
5928
|
+
/** Deadline for this call. Default 10 seconds. */
|
|
5929
|
+
readonly timeoutMs?: number;
|
|
5930
|
+
/** Explicit idempotency key for a write. Overrides the ambient and the fresh one. */
|
|
5931
|
+
readonly idempotencyKey?: string;
|
|
5932
|
+
/** Interrupts the call when aborted. */
|
|
5933
|
+
readonly signal?: AbortSignal;
|
|
5934
|
+
}
|
|
5935
|
+
|
|
5936
|
+
/** The decoded (application-side) type of a schema slot. */
|
|
5937
|
+
export declare type ServiceDecoded<S> = S extends {
|
|
5938
|
+
readonly Type: infer T;
|
|
5939
|
+
} ? T : never;
|
|
5940
|
+
|
|
5941
|
+
/** What a service procedure's descriptor type carries that the facade reads. */
|
|
5942
|
+
export declare interface ServiceDescriptorShape {
|
|
5943
|
+
readonly kind: string;
|
|
5944
|
+
readonly input: unknown;
|
|
5945
|
+
readonly output: unknown;
|
|
5946
|
+
}
|
|
5947
|
+
|
|
5948
|
+
/**
|
|
5949
|
+
* A service procedure's declaration: which apps of the project may call it.
|
|
5950
|
+
*
|
|
5951
|
+
* service: { callers: ['worker'] }
|
|
5952
|
+
*
|
|
5953
|
+
* The names are the CALLING apps' names as this app lists them in
|
|
5954
|
+
* `serviceCallers` — the same name the caller's credential resolves to.
|
|
5955
|
+
*/
|
|
5956
|
+
export declare interface ServiceSpec {
|
|
5957
|
+
readonly callers: ReadonlyArray<string>;
|
|
5958
|
+
}
|
|
5959
|
+
|
|
5960
|
+
/**
|
|
5961
|
+
* The subject a verified service credential resolves to. Built by the service
|
|
5962
|
+
* strategy only — an app never constructs one, and nothing grants it scopes.
|
|
5963
|
+
*/
|
|
5964
|
+
export declare const serviceSubject: (service: string) => Extract<Subject, {
|
|
5965
|
+
readonly type: "service";
|
|
5966
|
+
}>;
|
|
5967
|
+
|
|
5968
|
+
export declare interface ServiceSubscribeHandlers<T> {
|
|
5969
|
+
/** Every materialized value of the live query, starting with the first snapshot. */
|
|
5970
|
+
readonly onValue: (value: T) => void;
|
|
5971
|
+
/** The subscription's own in-band error (e.g. an access refusal). */
|
|
5972
|
+
readonly onError?: (error: unknown) => void;
|
|
5973
|
+
}
|
|
5974
|
+
|
|
5975
|
+
export declare interface ServiceSubscription {
|
|
5976
|
+
readonly unsubscribe: () => void;
|
|
5977
|
+
}
|
|
5978
|
+
|
|
5979
|
+
/** The first segment of a dotted rpc tag. */
|
|
5980
|
+
export declare type ServiceTagHead<K extends string> = K extends `${infer H}.${string}` ? H : K;
|
|
5981
|
+
|
|
5982
|
+
/** The request header carrying a framework session value outside a cookie. */
|
|
5983
|
+
export declare const SESSION_HEADER_NAME: "x-voltro-session";
|
|
5984
|
+
|
|
5985
|
+
/**
|
|
5986
|
+
* The session value a request presents: the dedicated header when set,
|
|
5987
|
+
* otherwise the named cookie. Pure — no verification, no IO.
|
|
5988
|
+
*
|
|
5989
|
+
* The header wins when both are present. A client that sets the header did so
|
|
5990
|
+
* deliberately; a cookie is ambient and may belong to a different app on the
|
|
5991
|
+
* same host (the reason `sessionExpiryFromHeaders` tolerates one that does
|
|
5992
|
+
* not verify). Explicit beats ambient.
|
|
5993
|
+
*/
|
|
5994
|
+
export declare const sessionValueFromHeaders: (headers: Readonly<Record<string, string | undefined>>, cookieName: string, readCookie: (header: string | undefined, name: string) => string | undefined) => string | undefined;
|
|
5995
|
+
|
|
5408
5996
|
/**
|
|
5409
5997
|
* Publish the caller's fully-resolved scope set for this request (raw subject
|
|
5410
5998
|
* scopes ∪ role-derived scopes ∪ any extra grants). Called by the rbac
|
|
@@ -5442,6 +6030,12 @@ export declare const shapeDigest: (text: string) => string;
|
|
|
5442
6030
|
*/
|
|
5443
6031
|
export declare const sourceKeys: (source: ReactivitySourceValue | ReadonlyArray<ReactivitySourceValue> | undefined) => ReadonlyArray<string>;
|
|
5444
6032
|
|
|
6033
|
+
export declare const STORE_SCREENSHOT_PRESET_NAMES: [string, ...string[]];
|
|
6034
|
+
|
|
6035
|
+
export declare const STORE_SCREENSHOT_PRESETS: ReadonlyArray<StoreScreenshotPreset>;
|
|
6036
|
+
|
|
6037
|
+
export declare const STORE_SCREENSHOT_STORES: readonly ["app-store", "play", "mac-app-store", "microsoft-store"];
|
|
6038
|
+
|
|
5445
6039
|
/**
|
|
5446
6040
|
* Discriminated union of all framework-owned store errors. Use it on
|
|
5447
6041
|
* a mutation's `error:` schema when you want every kind surfaced
|
|
@@ -5495,6 +6089,33 @@ declare const StoreOperationFailed_base: Schema.TaggedErrorClass<StoreOperationF
|
|
|
5495
6089
|
cause: typeof Schema.String;
|
|
5496
6090
|
}>;
|
|
5497
6091
|
|
|
6092
|
+
/** The PNG size the store receives: viewport × scale factor. */
|
|
6093
|
+
export declare const storeScreenshotPixels: (preset: StoreScreenshotPreset) => {
|
|
6094
|
+
readonly width: number;
|
|
6095
|
+
readonly height: number;
|
|
6096
|
+
};
|
|
6097
|
+
|
|
6098
|
+
export declare interface StoreScreenshotPreset {
|
|
6099
|
+
readonly name: string;
|
|
6100
|
+
readonly label: string;
|
|
6101
|
+
readonly kind: 'phone' | 'tablet' | 'desktop';
|
|
6102
|
+
/** The CSS viewport the page is laid out in. */
|
|
6103
|
+
readonly viewport: {
|
|
6104
|
+
readonly width: number;
|
|
6105
|
+
readonly height: number;
|
|
6106
|
+
};
|
|
6107
|
+
readonly deviceScaleFactor: number;
|
|
6108
|
+
/** Which stores accept this size. */
|
|
6109
|
+
readonly stores: ReadonlyArray<StoreScreenshotStore>;
|
|
6110
|
+
}
|
|
6111
|
+
|
|
6112
|
+
export declare const storeScreenshotPreset: (name: string) => StoreScreenshotPreset | undefined;
|
|
6113
|
+
|
|
6114
|
+
/** The presets a store takes, in table order. */
|
|
6115
|
+
export declare const storeScreenshotPresetsFor: (store: StoreScreenshotStore) => ReadonlyArray<StoreScreenshotPreset>;
|
|
6116
|
+
|
|
6117
|
+
export declare type StoreScreenshotStore = (typeof STORE_SCREENSHOT_STORES)[number];
|
|
6118
|
+
|
|
5498
6119
|
export declare type StrategyResolution = {
|
|
5499
6120
|
readonly kind: 'matched';
|
|
5500
6121
|
readonly subject: Subject;
|
|
@@ -5617,6 +6238,14 @@ export declare const Subject: Schema.Union<[Schema.Struct<{
|
|
|
5617
6238
|
tenantId: typeof Schema.Null;
|
|
5618
6239
|
scopes: Schema.optional<Schema.Array$<typeof Schema.String>>;
|
|
5619
6240
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
6241
|
+
}>, Schema.Struct<{
|
|
6242
|
+
type: Schema.Literal<["service"]>;
|
|
6243
|
+
id: typeof Schema.String;
|
|
6244
|
+
/** The calling app's name, as the callee lists it in `serviceCallers`. */
|
|
6245
|
+
service: typeof Schema.String;
|
|
6246
|
+
tenantId: typeof Schema.Null;
|
|
6247
|
+
scopes: Schema.optional<Schema.Array$<typeof Schema.String>>;
|
|
6248
|
+
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
5620
6249
|
}>]>;
|
|
5621
6250
|
|
|
5622
6251
|
export declare type Subject = typeof Subject.Type;
|
|
@@ -5670,6 +6299,12 @@ export declare const SubjectIdentity: Schema.Union<[Schema.Struct<{
|
|
|
5670
6299
|
id: typeof Schema.String;
|
|
5671
6300
|
tenantId: typeof Schema.Null;
|
|
5672
6301
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
6302
|
+
}>, Schema.Struct<{
|
|
6303
|
+
type: Schema.Literal<["service"]>;
|
|
6304
|
+
id: typeof Schema.String;
|
|
6305
|
+
tenantId: typeof Schema.Null;
|
|
6306
|
+
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
6307
|
+
service: typeof Schema.String;
|
|
5673
6308
|
}>]>;
|
|
5674
6309
|
|
|
5675
6310
|
export declare type SubjectIdentity = typeof SubjectIdentity.Type;
|
|
@@ -5742,6 +6377,15 @@ declare const SubjectService_base: Context.TagClass<SubjectService, "@voltro/Sub
|
|
|
5742
6377
|
readonly metadata?: {
|
|
5743
6378
|
readonly [x: string]: unknown;
|
|
5744
6379
|
} | undefined;
|
|
6380
|
+
} | {
|
|
6381
|
+
readonly type: "service";
|
|
6382
|
+
readonly id: string;
|
|
6383
|
+
readonly tenantId: null;
|
|
6384
|
+
readonly scopes?: readonly string[] | undefined;
|
|
6385
|
+
readonly metadata?: {
|
|
6386
|
+
readonly [x: string]: unknown;
|
|
6387
|
+
} | undefined;
|
|
6388
|
+
readonly service: string;
|
|
5745
6389
|
}>;
|
|
5746
6390
|
|
|
5747
6391
|
/** Subscribe to server-primitive errors. Returns an unsubscribe fn. */
|
|
@@ -5805,7 +6449,7 @@ export declare const subscriptionEvent: <D extends Schema.Schema.Any>(data: D) =
|
|
|
5805
6449
|
}>, Schema.Struct<{
|
|
5806
6450
|
op: Schema.Literal<["mergeCells"]>;
|
|
5807
6451
|
path: typeof Schema.String;
|
|
5808
|
-
value: Schema.Record$<typeof Schema.String, typeof Schema.Unknown
|
|
6452
|
+
value: Schema.Record$<typeof Schema.String, Schema.transform<typeof Schema.Unknown, typeof Schema.Unknown>>;
|
|
5809
6453
|
}>]>>;
|
|
5810
6454
|
order: Schema.Array$<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
|
|
5811
6455
|
}>;
|
|
@@ -6108,7 +6752,7 @@ export declare const toRpc: <Name extends string, Input extends Schema.Schema.An
|
|
|
6108
6752
|
}>, Schema.Struct<{
|
|
6109
6753
|
op: Schema.Literal<["mergeCells"]>;
|
|
6110
6754
|
path: typeof Schema.String;
|
|
6111
|
-
value: Schema.Record$<typeof Schema.String, typeof Schema.Unknown
|
|
6755
|
+
value: Schema.Record$<typeof Schema.String, Schema.transform<typeof Schema.Unknown, typeof Schema.Unknown>>;
|
|
6112
6756
|
}>]>>;
|
|
6113
6757
|
order: Schema.Array$<Schema.Union<[typeof Schema.String, typeof Schema.Number]>>;
|
|
6114
6758
|
}>;
|
|
@@ -6419,6 +7063,10 @@ export declare interface VoltroPlugin {
|
|
|
6419
7063
|
* merge to the stricter `required` and the safer `secret`.
|
|
6420
7064
|
*/
|
|
6421
7065
|
readonly declaredEnv?: ReadonlyArray<PluginEnvVar>;
|
|
7066
|
+
/** What this plugin collects and uses — see `PluginPrivacyDeclaration`. */
|
|
7067
|
+
readonly privacy?: PluginPrivacyDeclaration;
|
|
7068
|
+
/** Where this plugin sends data outside the installation — see `PluginEgressDeclaration`. Omit when it sends nothing. */
|
|
7069
|
+
readonly egress?: ReadonlyArray<PluginEgressDeclaration>;
|
|
6422
7070
|
/**
|
|
6423
7071
|
* The authorization scopes this plugin DEFINES for the app — its scope
|
|
6424
7072
|
* vocabulary. Distinct from `permissions` above, which is what the plugin
|
|
@@ -6554,8 +7202,10 @@ export declare interface VoltroPlugin {
|
|
|
6554
7202
|
* that wants the enablers declares `(store, ctx)` and reads
|
|
6555
7203
|
* `ctx?.sql` / `ctx?.scheduleCoordinated(...)`; one that ignores `ctx`
|
|
6556
7204
|
* keeps working unchanged.
|
|
7205
|
+
* A returned Promise is awaited before the app begins serving requests.
|
|
7206
|
+
* Store-dependent initialization may run here when activation happened first.
|
|
6557
7207
|
*/
|
|
6558
|
-
readonly bindDataStore?: (store: DataStore, ctx?: PluginBindContext) => void
|
|
7208
|
+
readonly bindDataStore?: (store: DataStore, ctx?: PluginBindContext) => void | Promise<void>;
|
|
6559
7209
|
/**
|
|
6560
7210
|
* Capabilities this plugin offers to OTHER framework machinery, by name.
|
|
6561
7211
|
*
|
|
@@ -6666,6 +7316,29 @@ export declare interface VoltroPlugin {
|
|
|
6666
7316
|
* specific permission name in the error.
|
|
6667
7317
|
*/
|
|
6668
7318
|
readonly extendSchema?: PluginSchemaContribution;
|
|
7319
|
+
/**
|
|
7320
|
+
* A directory of APP-SHAPED primitives this plugin brings with it — the same
|
|
7321
|
+
* file conventions an app uses (`*.query.ts` + `.server.ts`, `*.mutation.ts`,
|
|
7322
|
+
* `*.workflow.tsx`, `*.cron.tsx`, `*.subscribe.ts`, `*.reaction.ts`,
|
|
7323
|
+
* `schema.ts` / `*.entity.ts`, …).
|
|
7324
|
+
*
|
|
7325
|
+
* sources: fileURLToPath(new URL('./app', import.meta.url))
|
|
7326
|
+
*
|
|
7327
|
+
* Every app that installs the plugin discovers those files exactly as it
|
|
7328
|
+
* discovers its own: the same codegen, browser-safety guard, access gate,
|
|
7329
|
+
* migrations and boot paths. That is what makes a reusable BUILDING BLOCK — a
|
|
7330
|
+
* ledger, an approval flow, an audit trail — shareable between apps of a
|
|
7331
|
+
* project without copying it.
|
|
7332
|
+
*
|
|
7333
|
+
* It shares CODE, never data: each installing app gets its own copy of the
|
|
7334
|
+
* block's tables, in its own database. Two apps that need each other's data
|
|
7335
|
+
* call each other (`apis:` + `service:` procedures).
|
|
7336
|
+
*
|
|
7337
|
+
* The block's procedures keep the names their descriptors declare; a name
|
|
7338
|
+
* that collides with the app's own is refused at codegen, as any collision is.
|
|
7339
|
+
* An absolute path to a directory; a missing one refuses the boot.
|
|
7340
|
+
*/
|
|
7341
|
+
readonly sources?: string;
|
|
6669
7342
|
/**
|
|
6670
7343
|
* Cross-cutting error schemas merged into every procedure's wire error
|
|
6671
7344
|
* union. Lets a plugin interceptor fail with a typed error (e.g.
|
|
@@ -6742,6 +7415,26 @@ export declare interface VoltroPlugin {
|
|
|
6742
7415
|
readonly onProcedureSurface?: (procedures: ReadonlyArray<ProcedureDescriptor>) => void;
|
|
6743
7416
|
}
|
|
6744
7417
|
|
|
7418
|
+
/**
|
|
7419
|
+
* The plugins' cross-cutting errors, at the TYPE level.
|
|
7420
|
+
*
|
|
7421
|
+
* A plugin's `errorSchemas` reach every procedure's wire union at boot — a
|
|
7422
|
+
* runtime fact the type system cannot see. The codegen closes that gap: it
|
|
7423
|
+
* augments this interface in `rpcGroup.generated.ts` with one entry per
|
|
7424
|
+
* registered schema, so `defineExecutor` accepts a failure a plugin registers
|
|
7425
|
+
* exactly where the server will deliver it typed. Empty until the first
|
|
7426
|
+
* codegen run, which makes an unregistered plugin error a compile error rather
|
|
7427
|
+
* than a silent `InternalError`.
|
|
7428
|
+
*
|
|
7429
|
+
* declare module '@voltro/protocol' {
|
|
7430
|
+
* interface VoltroPluginErrors {
|
|
7431
|
+
* readonly '@acme/errors#NotFoundError': NotFoundError
|
|
7432
|
+
* }
|
|
7433
|
+
* }
|
|
7434
|
+
*/
|
|
7435
|
+
export declare interface VoltroPluginErrors {
|
|
7436
|
+
}
|
|
7437
|
+
|
|
6745
7438
|
/**
|
|
6746
7439
|
* The table names THIS app declares — filled in by codegen, empty here.
|
|
6747
7440
|
*
|
|
@@ -6834,10 +7527,28 @@ export declare interface WebSocketGatewayRoute {
|
|
|
6834
7527
|
readonly onConnection: (connection: WebSocketGatewayConnection) => void | (() => void) | Promise<void | (() => void)>;
|
|
6835
7528
|
}
|
|
6836
7529
|
|
|
7530
|
+
/**
|
|
7531
|
+
* Who may call a procedure over the wire: the app's own clients, or only other
|
|
7532
|
+
* apps of the project.
|
|
7533
|
+
*
|
|
7534
|
+
* A `service:` procedure IS on the wire — the server routes it on the same
|
|
7535
|
+
* socket — but it belongs to a different client group. Codegen emits it into
|
|
7536
|
+
* `serviceGroup.generated.ts` (imported by server processes of other apps) and
|
|
7537
|
+
* never into `rpcGroup.generated.ts` (imported by browsers), so no browser
|
|
7538
|
+
* bundle names a machine contract. The server refuses every non-service caller
|
|
7539
|
+
* regardless; keeping it out of the browser group is what keeps it out of the
|
|
7540
|
+
* code people ship.
|
|
7541
|
+
*/
|
|
7542
|
+
export declare type WireAudience = 'client' | 'service';
|
|
7543
|
+
|
|
7544
|
+
export declare const wireAudienceOf: (descriptor: {
|
|
7545
|
+
readonly service?: ServiceSpec | undefined;
|
|
7546
|
+
}) => WireAudience;
|
|
7547
|
+
|
|
6837
7548
|
/**
|
|
6838
7549
|
* The error union a procedure ACTUALLY puts on the wire — `descriptor.error`
|
|
6839
7550
|
* plus everything the framework can produce for it before or around the
|
|
6840
|
-
* executor.
|
|
7551
|
+
* executor, plus the plugins' cross-cutting errors (`extraErrors`).
|
|
6841
7552
|
*
|
|
6842
7553
|
* ── Why this is exported rather than inlined in the lifters ────────────────
|
|
6843
7554
|
*
|
|
@@ -6867,13 +7578,34 @@ export declare interface WebSocketGatewayRoute {
|
|
|
6867
7578
|
* `ScopeError` themselves — is what made the two sets agree by hand.
|
|
6868
7579
|
*
|
|
6869
7580
|
* One function now, so they cannot disagree again.
|
|
7581
|
+
*
|
|
7582
|
+
* The plugins' errors are part of that answer for the same reason. A plugin's
|
|
7583
|
+
* `errorSchemas` entry is on every lifted union, and the judgement above was
|
|
7584
|
+
* handed the union WITHOUT them — so an interceptor's `RateLimited`, or an
|
|
7585
|
+
* app-wide error a local plugin registers, decoded typed on a query and was
|
|
7586
|
+
* collapsed to `InternalError` on every mutation and action, on both boot
|
|
7587
|
+
* paths. Pass the same `extraErrors` the lifter receives.
|
|
6870
7588
|
*/
|
|
6871
7589
|
export declare const wireErrorUnion: (descriptor: {
|
|
6872
7590
|
readonly error: Schema.Schema.All;
|
|
6873
7591
|
readonly guards?: DeclaredAccess | undefined;
|
|
6874
7592
|
readonly requiresApproval?: AnyApprovalPolicy | undefined;
|
|
6875
7593
|
readonly idempotencyScope?: MutationIdempotencyScope | undefined;
|
|
6876
|
-
}, kind: "query" | "mutation" | "action" | "stream") => Schema.Schema.All;
|
|
7594
|
+
}, kind: "query" | "mutation" | "action" | "stream", extraErrors?: ExtraErrors) => Schema.Schema.All;
|
|
7595
|
+
|
|
7596
|
+
/** A procedure kind that has a wire error union. */
|
|
7597
|
+
export declare type WireProcedureKind = keyof typeof FRAMEWORK_WIRE_ERRORS;
|
|
7598
|
+
|
|
7599
|
+
/**
|
|
7600
|
+
* The error of a {@link ServerErrorEvent} with its content withheld: same
|
|
7601
|
+
* `name` (the class, or a typed failure's tag), the original stack FRAMES —
|
|
7602
|
+
* code locations, which carry no data — and a message saying where the full
|
|
7603
|
+
* error can be read by someone allowed to. No `cause`, no own properties.
|
|
7604
|
+
*
|
|
7605
|
+
* The stack's first line repeats the message, so it is rebuilt from the frames
|
|
7606
|
+
* rather than copied.
|
|
7607
|
+
*/
|
|
7608
|
+
export declare const withheldServerError: (event: ServerErrorEvent) => Error;
|
|
6877
7609
|
|
|
6878
7610
|
/**
|
|
6879
7611
|
* Re-tag a procedure descriptor for the wire.
|
|
@@ -7367,6 +8099,147 @@ export declare const WorkflowQueuedControlTargetSchema: Schema.Struct<{
|
|
|
7367
8099
|
requestId: typeof Schema.NonEmptyString;
|
|
7368
8100
|
}>;
|
|
7369
8101
|
|
|
8102
|
+
export declare type WorkflowRestartCommand = typeof WorkflowRestartCommandSchema.Type;
|
|
8103
|
+
|
|
8104
|
+
export declare const WorkflowRestartCommandSchema: Schema.Struct<{
|
|
8105
|
+
selection: Schema.Union<[Schema.Struct<{
|
|
8106
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8107
|
+
}>, Schema.Struct<{
|
|
8108
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8109
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8110
|
+
}>]>;
|
|
8111
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8112
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8113
|
+
}>;
|
|
8114
|
+
|
|
8115
|
+
export declare type WorkflowRestartObservation = typeof WorkflowRestartObservationSchema.Type;
|
|
8116
|
+
|
|
8117
|
+
/** Pending is a durable reservation, not proof of reset or engine entry.
|
|
8118
|
+
* Entered confirms this command's generation; it does not claim run success. */
|
|
8119
|
+
export declare const WorkflowRestartObservationSchema: Schema.Union<[Schema.Struct<{
|
|
8120
|
+
kind: Schema.Literal<["not-found"]>;
|
|
8121
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8122
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8123
|
+
}>, Schema.Struct<{
|
|
8124
|
+
kind: Schema.Literal<["withdrawn"]>;
|
|
8125
|
+
workflowName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8126
|
+
withdrawnAt: Schema.filter<typeof Schema.Number>;
|
|
8127
|
+
selection: Schema.Union<[Schema.Struct<{
|
|
8128
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8129
|
+
}>, Schema.Struct<{
|
|
8130
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8131
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8132
|
+
}>]>;
|
|
8133
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8134
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8135
|
+
}>, Schema.Struct<{
|
|
8136
|
+
kind: Schema.Literal<["pending"]>;
|
|
8137
|
+
workflowName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8138
|
+
executionId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8139
|
+
originalGeneration: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8140
|
+
requestedAt: Schema.filter<typeof Schema.Number>;
|
|
8141
|
+
dispatchAttempts: Schema.refine<number, typeof Schema.NonNegative>;
|
|
8142
|
+
selection: Schema.Union<[Schema.Struct<{
|
|
8143
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8144
|
+
}>, Schema.Struct<{
|
|
8145
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8146
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8147
|
+
}>]>;
|
|
8148
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8149
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8150
|
+
}>, Schema.filter<Schema.Struct<{
|
|
8151
|
+
kind: Schema.Literal<["entered"]>;
|
|
8152
|
+
enteredGeneration: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8153
|
+
workflowName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8154
|
+
executionId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8155
|
+
originalGeneration: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8156
|
+
requestedAt: Schema.filter<typeof Schema.Number>;
|
|
8157
|
+
dispatchAttempts: Schema.refine<number, typeof Schema.NonNegative>;
|
|
8158
|
+
selection: Schema.Union<[Schema.Struct<{
|
|
8159
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8160
|
+
}>, Schema.Struct<{
|
|
8161
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8162
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8163
|
+
}>]>;
|
|
8164
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8165
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8166
|
+
}>>]>;
|
|
8167
|
+
|
|
8168
|
+
export declare type WorkflowRestartResult = typeof WorkflowRestartResultSchema.Type;
|
|
8169
|
+
|
|
8170
|
+
/** A refused reservation never reset the journal. Transport failures instead
|
|
8171
|
+
* require reading the original target; they are not proof of refusal. */
|
|
8172
|
+
export declare const WorkflowRestartResultSchema: Schema.Union<[Schema.Union<[Schema.Struct<{
|
|
8173
|
+
kind: Schema.Literal<["not-found"]>;
|
|
8174
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8175
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8176
|
+
}>, Schema.Struct<{
|
|
8177
|
+
kind: Schema.Literal<["withdrawn"]>;
|
|
8178
|
+
workflowName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8179
|
+
withdrawnAt: Schema.filter<typeof Schema.Number>;
|
|
8180
|
+
selection: Schema.Union<[Schema.Struct<{
|
|
8181
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8182
|
+
}>, Schema.Struct<{
|
|
8183
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8184
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8185
|
+
}>]>;
|
|
8186
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8187
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8188
|
+
}>, Schema.Struct<{
|
|
8189
|
+
kind: Schema.Literal<["pending"]>;
|
|
8190
|
+
workflowName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8191
|
+
executionId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8192
|
+
originalGeneration: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8193
|
+
requestedAt: Schema.filter<typeof Schema.Number>;
|
|
8194
|
+
dispatchAttempts: Schema.refine<number, typeof Schema.NonNegative>;
|
|
8195
|
+
selection: Schema.Union<[Schema.Struct<{
|
|
8196
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8197
|
+
}>, Schema.Struct<{
|
|
8198
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8199
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8200
|
+
}>]>;
|
|
8201
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8202
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8203
|
+
}>, Schema.filter<Schema.Struct<{
|
|
8204
|
+
kind: Schema.Literal<["entered"]>;
|
|
8205
|
+
enteredGeneration: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8206
|
+
workflowName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8207
|
+
executionId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8208
|
+
originalGeneration: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8209
|
+
requestedAt: Schema.filter<typeof Schema.Number>;
|
|
8210
|
+
dispatchAttempts: Schema.refine<number, typeof Schema.NonNegative>;
|
|
8211
|
+
selection: Schema.Union<[Schema.Struct<{
|
|
8212
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8213
|
+
}>, Schema.Struct<{
|
|
8214
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8215
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8216
|
+
}>]>;
|
|
8217
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8218
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8219
|
+
}>>]>, Schema.Struct<{
|
|
8220
|
+
kind: Schema.Literal<["not-reserved"]>;
|
|
8221
|
+
reason: Schema.Literal<["admission", "journal"]>;
|
|
8222
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8223
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8224
|
+
}>]>;
|
|
8225
|
+
|
|
8226
|
+
export declare type WorkflowRestartSelection = typeof WorkflowRestartSelectionSchema.Type;
|
|
8227
|
+
|
|
8228
|
+
export declare const WorkflowRestartSelectionSchema: Schema.Union<[Schema.Struct<{
|
|
8229
|
+
kind: Schema.Literal<["failed-steps"]>;
|
|
8230
|
+
}>, Schema.Struct<{
|
|
8231
|
+
kind: Schema.Literal<["from-step"]>;
|
|
8232
|
+
stepName: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8233
|
+
}>]>;
|
|
8234
|
+
|
|
8235
|
+
export declare type WorkflowRestartTarget = typeof WorkflowRestartTargetSchema.Type;
|
|
8236
|
+
|
|
8237
|
+
/** Persist before submitting; read this same target after an uncertain reply. */
|
|
8238
|
+
export declare const WorkflowRestartTargetSchema: Schema.Struct<{
|
|
8239
|
+
requestId: Schema.filter<Schema.filter<typeof Schema.NonEmptyString>>;
|
|
8240
|
+
runId: Schema.filter<typeof Schema.NonEmptyString>;
|
|
8241
|
+
}>;
|
|
8242
|
+
|
|
7370
8243
|
export declare const workflowResumeDescriptor: ActionProcedureDescriptor<"__voltro.workflow.resume", Schema.Struct<{
|
|
7371
8244
|
workflowName: typeof Schema.String;
|
|
7372
8245
|
executionId: typeof Schema.String;
|