@fabricorg/experience-gateway 2.1.6 → 2.1.8
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 +34 -0
- package/dist/index.cjs +316 -308
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +141 -142
- package/dist/index.d.ts +141 -142
- package/dist/index.js +309 -279
- package/dist/index.js.map +1 -1
- package/package.json +12 -11
package/dist/index.d.ts
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { ExperienceIntentRequest, ExperienceReadRequest } from
|
|
5
|
-
import { ExperienceScope, ExperienceServerRuntime } from
|
|
6
|
-
|
|
7
|
-
interface TrustedExperienceRequestContext {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { GovernedActionHost, SubmitActionInput, SubmitActionResult } from "@fabricorg/platform-host";
|
|
2
|
+
import { ActorClaims, IdentityPort } from "@fabricorg/ports";
|
|
3
|
+
import { ProjectionHost } from "@fabricorg/projection-host";
|
|
4
|
+
import { ExperienceIntentRequest, ExperienceReadRequest } from "@fabricorg/experience-runtime";
|
|
5
|
+
import { ExperienceScope, ExperienceServerRuntime } from "@fabricorg/experience-runtime/server";
|
|
6
|
+
//#region index.d.ts
|
|
7
|
+
export interface TrustedExperienceRequestContext {
|
|
8
|
+
/** Presented only to IdentityPort and never persisted or forwarded. */
|
|
9
|
+
credential: string;
|
|
10
|
+
tenantId: string;
|
|
11
|
+
spaceId: string;
|
|
12
12
|
}
|
|
13
|
-
interface ExperienceGateway {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
13
|
+
export interface ExperienceGateway {
|
|
14
|
+
invoke(input: {
|
|
15
|
+
context: TrustedExperienceRequestContext;
|
|
16
|
+
request: ExperienceIntentRequest;
|
|
17
|
+
executionReason?: "initial" | "offline_replay";
|
|
18
|
+
/**
|
|
19
|
+
* When the operator acted, for a replay. Required whenever
|
|
20
|
+
* `executionReason` is `offline_replay`: reading it through an untyped
|
|
21
|
+
* cast made omitting it the easy mistake, and omitting it silently
|
|
22
|
+
* stamped receipt time into durable capture evidence.
|
|
23
|
+
*/
|
|
24
|
+
capturedAt?: string;
|
|
25
|
+
}): Promise<SubmitActionResult>;
|
|
26
|
+
read(input: {
|
|
27
|
+
context: TrustedExperienceRequestContext;
|
|
28
|
+
request: ExperienceReadRequest;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
data: unknown;
|
|
31
|
+
evidence: {
|
|
32
|
+
releaseDigest: string;
|
|
33
|
+
assemblyDigest: string;
|
|
34
|
+
eventCursor: string | null;
|
|
35
|
+
source: "cache" | "replay";
|
|
36
|
+
};
|
|
37
|
+
}>;
|
|
38
38
|
}
|
|
39
|
-
interface ExperienceAdmissionInput {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
export interface ExperienceAdmissionInput {
|
|
40
|
+
kind: "invoke" | "read";
|
|
41
|
+
scope: ExperienceScope;
|
|
42
|
+
claims: ActorClaims;
|
|
43
|
+
planId: string;
|
|
44
|
+
fragmentId: string;
|
|
45
|
+
/** The event or binding name the client named; the capability it resolves to is not yet known. */
|
|
46
|
+
name: string;
|
|
47
47
|
}
|
|
48
|
-
type ExperienceAdmissionDecision = {
|
|
49
|
-
|
|
48
|
+
export type ExperienceAdmissionDecision = {
|
|
49
|
+
allowed: true;
|
|
50
50
|
} | {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
allowed: false;
|
|
52
|
+
reason: string;
|
|
53
|
+
retryAfterMs?: number;
|
|
54
54
|
};
|
|
55
55
|
/** A request the edge would not admit. `retryable` is true when a later attempt may be admitted. */
|
|
56
|
-
declare class ExperienceAdmissionError extends Error {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
export declare class ExperienceAdmissionError extends Error {
|
|
57
|
+
readonly reason: string;
|
|
58
|
+
readonly retryAfterMs?: number | undefined;
|
|
59
|
+
readonly code: "EXPERIENCE_ADMISSION_REFUSED";
|
|
60
|
+
constructor(reason: string, retryAfterMs?: number | undefined);
|
|
61
|
+
get retryable(): boolean;
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* A reference admission policy: a token bucket per key, refilled over time.
|
|
@@ -66,101 +66,100 @@ declare class ExperienceAdmissionError extends Error {
|
|
|
66
66
|
* Enough to throttle a tenant or an actor at the edge; a deployment with a
|
|
67
67
|
* shared limiter puts it behind the same option. Keys default to the tenant.
|
|
68
68
|
*/
|
|
69
|
-
declare function createTokenBucketAdmission(options: {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
export declare function createTokenBucketAdmission(options: {
|
|
70
|
+
capacity: number;
|
|
71
|
+
refillPerSecond: number;
|
|
72
|
+
key?(input: ExperienceAdmissionInput): string;
|
|
73
|
+
now?(): number;
|
|
74
74
|
}): (input: ExperienceAdmissionInput) => ExperienceAdmissionDecision;
|
|
75
|
-
interface ExperienceGatewayConformanceSubject {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
75
|
+
export interface ExperienceGatewayConformanceSubject {
|
|
76
|
+
gateway: ExperienceGateway;
|
|
77
|
+
validIntent: Parameters<ExperienceGateway["invoke"]>[0];
|
|
78
|
+
deniedIntent: Parameters<ExperienceGateway["invoke"]>[0];
|
|
79
|
+
validRead: Parameters<ExperienceGateway["read"]>[0];
|
|
80
|
+
/**
|
|
81
|
+
* What the governed hosts actually saw.
|
|
82
|
+
*
|
|
83
|
+
* A returned invocation id proves only that a string was produced. The
|
|
84
|
+
* point of a gateway is that mutations reach `PlatformHost.submitAction` and
|
|
85
|
+
* reads reach `ProjectionHost.project`; a replacement that fabricates an id
|
|
86
|
+
* and queries the database directly satisfies every observable contract
|
|
87
|
+
* except this one, so the subject has to report the calls.
|
|
88
|
+
*/
|
|
89
|
+
observed: {
|
|
90
|
+
submitActionCount(): number;
|
|
91
|
+
projectionCount(): number;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* An intent the deployment's admission policy refuses. Optional so an
|
|
95
|
+
* existing subject still compiles; without it the admission check reports
|
|
96
|
+
* `skipped` and says what was not proven, since a deployment that cannot
|
|
97
|
+
* show one refusal has not configured admission.
|
|
98
|
+
*/
|
|
99
|
+
throttledIntent?: Parameters<ExperienceGateway["invoke"]>[0];
|
|
100
100
|
}
|
|
101
|
-
interface ExperienceGatewayCheck {
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
export interface ExperienceGatewayCheck {
|
|
102
|
+
id: "fabric.experience.gateway-host-routing.v1" | "fabric.experience.gateway-scope-denial.v1" | "fabric.experience.gateway-projection-routing.v1" | "fabric.experience.gateway-admission-refusal.v1";
|
|
103
|
+
run(subject: ExperienceGatewayConformanceSubject): Promise<string[]>;
|
|
104
104
|
}
|
|
105
|
-
declare function experienceGatewayChecks(): readonly ExperienceGatewayCheck[];
|
|
106
|
-
declare function runExperienceGatewayChecks(subject: ExperienceGatewayConformanceSubject, checks?: readonly ExperienceGatewayCheck[]): Promise<{
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
export declare function experienceGatewayChecks(): readonly ExperienceGatewayCheck[];
|
|
106
|
+
export declare function runExperienceGatewayChecks(subject: ExperienceGatewayConformanceSubject, checks?: readonly ExperienceGatewayCheck[]): Promise<{
|
|
107
|
+
passed: boolean;
|
|
108
|
+
checks: Array<{
|
|
109
|
+
id: ExperienceGatewayCheck["id"];
|
|
110
|
+
status: "passed" | "failed" | "skipped";
|
|
111
|
+
evidence: string[];
|
|
112
|
+
error?: string;
|
|
113
|
+
}>;
|
|
114
114
|
}>;
|
|
115
|
-
interface InitiatingReleaseEvidence {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
export interface InitiatingReleaseEvidence {
|
|
116
|
+
bind(input: SubmitActionInput, releaseDigest: string): void;
|
|
117
|
+
resolve(input: SubmitActionInput): string | undefined;
|
|
118
|
+
release(input: SubmitActionInput): void;
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
121
|
* Creates an instance-scoped, non-serializable evidence seam. The Host's
|
|
122
122
|
* `composition.resolveInitiatingReleaseDigest` reads this WeakMap using the
|
|
123
123
|
* exact submission object. A browser field cannot populate or forge it.
|
|
124
124
|
*/
|
|
125
|
-
declare function createInitiatingReleaseEvidence(): InitiatingReleaseEvidence;
|
|
126
|
-
declare function createExperienceGateway(options: {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
125
|
+
export declare function createInitiatingReleaseEvidence(): InitiatingReleaseEvidence;
|
|
126
|
+
export declare function createExperienceGateway(options: {
|
|
127
|
+
identity: IdentityPort;
|
|
128
|
+
runtime: ExperienceServerRuntime;
|
|
129
|
+
host: Pick<GovernedActionHost, "submitAction">;
|
|
130
|
+
projectionHost: Pick<ProjectionHost, "project">;
|
|
131
|
+
evidence: InitiatingReleaseEvidence;
|
|
132
|
+
assemblyDigest: string;
|
|
133
|
+
actionVersion(actionId: `${string}.${string}`): number | undefined;
|
|
134
|
+
nextCorrelationId(): string;
|
|
135
|
+
/**
|
|
136
|
+
* How old an offline capture may be and still replay.
|
|
137
|
+
*
|
|
138
|
+
* Required to accept replay at all. The Host's own staleness check is
|
|
139
|
+
* conditional on the capture-authority adapter supplying an `expiresAt`, and
|
|
140
|
+
* is skipped entirely for actions governed at capture time, so without this
|
|
141
|
+
* a client-reported instant has no lower bound.
|
|
142
|
+
*/
|
|
143
|
+
maxOfflineReplayAgeMs?: number;
|
|
144
|
+
/**
|
|
145
|
+
* Admission control at the edge, decided after the credential is verified
|
|
146
|
+
* and before anything governed is touched. Per-tenant request budgets,
|
|
147
|
+
* render-cost quotas, and abuse throttles live here, as a seam the
|
|
148
|
+
* deployment fills; the gateway itself imposes no policy. A refusal
|
|
149
|
+
* surfaces as `ExperienceAdmissionError`, carrying `retryAfterMs` when the
|
|
150
|
+
* caller should come back rather than give up.
|
|
151
|
+
*/
|
|
152
|
+
admission?(input: ExperienceAdmissionInput): Promise<ExperienceAdmissionDecision> | ExperienceAdmissionDecision;
|
|
153
|
+
captureAuthority?(input: {
|
|
154
|
+
actionId: `${string}.${string}`;
|
|
155
|
+
scope: ExperienceScope;
|
|
156
|
+
parameters: Record<string, unknown>;
|
|
157
|
+
parameterDigest: string;
|
|
158
|
+
capturedAt: string;
|
|
159
|
+
}): Promise<{
|
|
160
|
+
id: string;
|
|
161
|
+
expiresAt?: string;
|
|
162
|
+
}>;
|
|
163
|
+
now?: () => Date;
|
|
164
164
|
}): ExperienceGateway;
|
|
165
|
-
|
|
166
|
-
export { type ExperienceAdmissionDecision, ExperienceAdmissionError, type ExperienceAdmissionInput, type ExperienceGateway, type ExperienceGatewayCheck, type ExperienceGatewayConformanceSubject, type InitiatingReleaseEvidence, type TrustedExperienceRequestContext, createExperienceGateway, createInitiatingReleaseEvidence, createTokenBucketAdmission, experienceGatewayChecks, runExperienceGatewayChecks };
|
|
165
|
+
//#endregion
|