@oaath/server 0.1.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.
@@ -0,0 +1,71 @@
1
+ import { b as relayFailure, m as timestamp } from "./records-Bgr-9PUh.js";
2
+ //#region src/clock.ts
3
+ /**
4
+ * Injected clock. Expiry is never read from `Date.now()` directly, so tests and
5
+ * deployments own time.
6
+ *
7
+ * @author taek <leekt216@gmail.com>
8
+ */
9
+ function relayNow(clock) {
10
+ let value;
11
+ try {
12
+ value = clock.now();
13
+ } catch {
14
+ return relayFailure("relay_internal", "injected clock failed");
15
+ }
16
+ return timestamp(value, "clock time", "relay_internal");
17
+ }
18
+ //#endregion
19
+ //#region src/authorization/challenge.ts
20
+ /**
21
+ * PKCE S256 challenge verification and the relay's random/digest primitives.
22
+ *
23
+ * Only WebCrypto and base64url are used, so this file stays platform-neutral.
24
+ * The verifier is never stored: the store holds the S256 challenge, and consume
25
+ * recomputes it.
26
+ *
27
+ * @author taek <leekt216@gmail.com>
28
+ */
29
+ /** RFC 7636 code verifier: 43-128 unreserved characters. */
30
+ const CODE_VERIFIER = /^[A-Za-z0-9._~-]{43,128}$/u;
31
+ const IDENTIFIER_BYTES = 32;
32
+ function base64Url(bytes) {
33
+ let binary = "";
34
+ for (const byte of bytes) binary += String.fromCharCode(byte);
35
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
36
+ }
37
+ /** 256 bits of CSPRNG output, base64url encoded. */
38
+ function randomIdentifier() {
39
+ return base64Url(crypto.getRandomValues(new Uint8Array(IDENTIFIER_BYTES)));
40
+ }
41
+ async function sha256Base64Url(value) {
42
+ let digest;
43
+ try {
44
+ digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
45
+ } catch {
46
+ return relayFailure("relay_internal", "WebCrypto SHA-256 is unavailable");
47
+ }
48
+ return base64Url(new Uint8Array(digest));
49
+ }
50
+ function timingSafeEqualText(left, right) {
51
+ if (left.length !== right.length) return false;
52
+ let difference = 0;
53
+ for (let index = 0; index < left.length; index += 1) difference |= left.charCodeAt(index) ^ right.charCodeAt(index);
54
+ return difference === 0;
55
+ }
56
+ /**
57
+ * True only when `codeVerifier` is a well-formed RFC 7636 verifier whose S256
58
+ * digest equals the stored challenge. Any malformed input is a mismatch.
59
+ */
60
+ async function verifyPkceS256(codeVerifier, storedCodeChallenge) {
61
+ if (!CODE_VERIFIER.test(codeVerifier)) return false;
62
+ return timingSafeEqualText(await sha256Base64Url(codeVerifier), storedCodeChallenge);
63
+ }
64
+ /** True when the value can be a stored S256 challenge (43 base64url characters). */
65
+ function isCodeChallengeS256(value) {
66
+ return /^[A-Za-z0-9_-]{43}$/u.test(value);
67
+ }
68
+ //#endregion
69
+ export { relayNow as a, verifyPkceS256 as i, randomIdentifier as n, sha256Base64Url as r, isCodeChallengeS256 as t };
70
+
71
+ //# sourceMappingURL=challenge-AGTmUfj2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"challenge-AGTmUfj2.js","names":[],"sources":["../src/clock.ts","../src/authorization/challenge.ts"],"sourcesContent":["/**\n * Injected clock. Expiry is never read from `Date.now()` directly, so tests and\n * deployments own time.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { relayFailure } from \"./relay/errors.js\";\nimport { timestamp } from \"./store/records.js\";\n\nexport interface RelayClock {\n /** Milliseconds since the Unix epoch as a non-negative safe integer. */\n now(): number;\n}\n\nexport function relayNow(clock: RelayClock): number {\n let value: unknown;\n try {\n value = clock.now();\n } catch {\n return relayFailure(\"relay_internal\", \"injected clock failed\");\n }\n return timestamp(value, \"clock time\", \"relay_internal\");\n}\n","/**\n * PKCE S256 challenge verification and the relay's random/digest primitives.\n *\n * Only WebCrypto and base64url are used, so this file stays platform-neutral.\n * The verifier is never stored: the store holds the S256 challenge, and consume\n * recomputes it.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { relayFailure } from \"../relay/errors.js\";\n\n/** RFC 7636 code verifier: 43-128 unreserved characters. */\nconst CODE_VERIFIER = /^[A-Za-z0-9._~-]{43,128}$/u;\n\nconst IDENTIFIER_BYTES = 32;\n\nfunction base64Url(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\n\n/** 256 bits of CSPRNG output, base64url encoded. */\nexport function randomIdentifier(): string {\n return base64Url(crypto.getRandomValues(new Uint8Array(IDENTIFIER_BYTES)));\n}\n\nexport async function sha256Base64Url(value: string): Promise<string> {\n let digest: ArrayBuffer;\n try {\n digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(value));\n } catch {\n return relayFailure(\"relay_internal\", \"WebCrypto SHA-256 is unavailable\");\n }\n return base64Url(new Uint8Array(digest));\n}\n\nfunction timingSafeEqualText(left: string, right: string): boolean {\n // Both operands are base64url digests, so length is not itself a secret.\n if (left.length !== right.length) return false;\n let difference = 0;\n for (let index = 0; index < left.length; index += 1) {\n difference |= left.charCodeAt(index) ^ right.charCodeAt(index);\n }\n return difference === 0;\n}\n\n/**\n * True only when `codeVerifier` is a well-formed RFC 7636 verifier whose S256\n * digest equals the stored challenge. Any malformed input is a mismatch.\n */\nexport async function verifyPkceS256(\n codeVerifier: string,\n storedCodeChallenge: string,\n): Promise<boolean> {\n if (!CODE_VERIFIER.test(codeVerifier)) return false;\n return timingSafeEqualText(await sha256Base64Url(codeVerifier), storedCodeChallenge);\n}\n\n/** True when the value can be a stored S256 challenge (43 base64url characters). */\nexport function isCodeChallengeS256(value: string): boolean {\n return /^[A-Za-z0-9_-]{43}$/u.test(value);\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,SAAS,OAA2B;CAClD,IAAI;CACJ,IAAI;EACF,QAAQ,MAAM,IAAI;CACpB,QAAQ;EACN,OAAO,aAAa,kBAAkB,uBAAuB;CAC/D;CACA,OAAO,UAAU,OAAO,cAAc,gBAAgB;AACxD;;;;;;;;;;;;;ACVA,MAAM,gBAAgB;AAEtB,MAAM,mBAAmB;AAEzB,SAAS,UAAU,OAA2B;CAC5C,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,OAAO,UAAU,OAAO,aAAa,IAAI;CAC5D,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,CAAC,WAAW,KAAK,EAAE;AAClF;;AAGA,SAAgB,mBAA2B;CACzC,OAAO,UAAU,OAAO,gBAAgB,IAAI,WAAW,gBAAgB,CAAC,CAAC;AAC3E;AAEA,eAAsB,gBAAgB,OAAgC;CACpE,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,CAAC;CAChF,QAAQ;EACN,OAAO,aAAa,kBAAkB,kCAAkC;CAC1E;CACA,OAAO,UAAU,IAAI,WAAW,MAAM,CAAC;AACzC;AAEA,SAAS,oBAAoB,MAAc,OAAwB;CAEjE,IAAI,KAAK,WAAW,MAAM,QAAQ,OAAO;CACzC,IAAI,aAAa;CACjB,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAChD,cAAc,KAAK,WAAW,KAAK,IAAI,MAAM,WAAW,KAAK;CAE/D,OAAO,eAAe;AACxB;;;;;AAMA,eAAsB,eACpB,cACA,qBACkB;CAClB,IAAI,CAAC,cAAc,KAAK,YAAY,GAAG,OAAO;CAC9C,OAAO,oBAAoB,MAAM,gBAAgB,YAAY,GAAG,mBAAmB;AACrF;;AAGA,SAAgB,oBAAoB,OAAwB;CAC1D,OAAO,uBAAuB,KAAK,KAAK;AAC1C"}
@@ -0,0 +1,53 @@
1
+ import { i as RelayClock, n as RelayCaller } from "./authentication-HUYWk5Y2.js";
2
+ import { t as RelayStore } from "./interface-WwvwWs8e.js";
3
+ //#region src/security/kms.d.ts
4
+ /**
5
+ * Deployment-owned encryption port.
6
+ *
7
+ * The relay stores only the opaque reference this port returns. It never sees a
8
+ * key, and plaintext never reaches the store.
9
+ *
10
+ * @author taek <leekt216@gmail.com>
11
+ */
12
+ interface RelayKms {
13
+ /** Resolves to an opaque bounded string reference for the ciphertext. */
14
+ encrypt(plaintext: string): Promise<unknown>;
15
+ /** Resolves to the plaintext for a reference this port previously returned. */
16
+ decrypt(ciphertextRef: string): Promise<unknown>;
17
+ }
18
+ //#endregion
19
+ //#region src/authorization/decision.d.ts
20
+ type AuthorizationDecisionCommand =
21
+ /** The owner approves and hands over the artifact the client will claim once. */
22
+ Readonly<{
23
+ outcome: "approved";
24
+ artifact: string;
25
+ }> | Readonly<{
26
+ outcome: "rejected";
27
+ }>;
28
+ interface SubmitAuthorizationDecisionInput {
29
+ readonly store: RelayStore;
30
+ readonly clock: RelayClock;
31
+ readonly kms: RelayKms;
32
+ /** Authenticated `owner` caller; only the bound subject may decide. */
33
+ readonly caller: RelayCaller;
34
+ readonly requestId: string;
35
+ readonly command: AuthorizationDecisionCommand;
36
+ readonly codeTtlMs: number;
37
+ }
38
+ type SubmittedAuthorizationDecision = Readonly<{
39
+ outcome: "approved";
40
+ decidedAt: number;
41
+ /** Released exactly once, here. Only its SHA-256 is stored. */
42
+ code: string;
43
+ artifactId: string;
44
+ redirectUri: string;
45
+ codeExpiresAt: number;
46
+ }> | Readonly<{
47
+ outcome: "rejected";
48
+ decidedAt: number;
49
+ }>;
50
+ declare function submitAuthorizationDecision(input: SubmitAuthorizationDecisionInput): Promise<SubmittedAuthorizationDecision>;
51
+ //#endregion
52
+ export { RelayKms as a, submitAuthorizationDecision as i, SubmitAuthorizationDecisionInput as n, SubmittedAuthorizationDecision as r, AuthorizationDecisionCommand as t };
53
+ //# sourceMappingURL=decision-dEe9n108.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-dEe9n108.d.ts","names":[],"sources":["../src/security/kms.ts","../src/authorization/decision.ts"],"mappings":";;;;;;;;;;;UASiB;;EAEf,QAAQ,oBAAoB;;EAE5B,QAAQ,wBAAwB;;;;KCoCtB;;AAEV;EAAW;EAAqB;KAAsB;EAAW;;UAElD;WACN,OAAO;WACP,OAAO;WACP,KAAK;;WAEL,QAAQ;WACR;WACA,SAAS;WACT;;KAGC,iCACR;EACE;EACA;;EAEA;EACA;EACA;EACA;KAEF;EAAW;EAAqB;;iBAEd,4BACpB,OAAO,mCACN,QAAQ"}
@@ -0,0 +1,335 @@
1
+ import { i as RelayClock, n as RelayCaller, r as RelayCallerRole, t as RelayAuthentication } from "./authentication-HUYWk5Y2.js";
2
+ import { a as AuthorizationDecisionRecord, c as OAATH_AUTHORIZATION_CODE_RECORD_VERSION, d as OAATH_ENCRYPTED_ARTIFACT_RECORD_VERSION, i as AuthorizationDecisionOutcome, l as OAATH_AUTHORIZATION_DECISION_RECORD_VERSION, n as RelayTransaction, o as AuthorizationRequestRecord, r as AuthorizationCodeRecord, s as EncryptedArtifactRecord, t as RelayStore, u as OAATH_AUTHORIZATION_REQUEST_RECORD_VERSION } from "./interface-WwvwWs8e.js";
3
+ import { a as RelayKms, i as submitAuthorizationDecision, n as SubmitAuthorizationDecisionInput, r as SubmittedAuthorizationDecision, t as AuthorizationDecisionCommand } from "./decision-dEe9n108.js";
4
+ //#region src/relay/errors.d.ts
5
+ /**
6
+ * Closed relay failure codes and their stable HTTP projection.
7
+ *
8
+ * Machine decisions and wire responses use these codes only. `Error.message`
9
+ * exists for local diagnostics and never reaches a response body.
10
+ *
11
+ * @author taek <leekt216@gmail.com>
12
+ */
13
+ type RelayErrorCode =
14
+ /** Wire input is missing, malformed, oversized, or contains unknown fields. */
15
+ "relay_request_invalid" |
16
+ /** The deployment authentication port did not authenticate the caller. */
17
+ "relay_unauthenticated" |
18
+ /** Authenticated caller may not act in the required role. */
19
+ "relay_forbidden" |
20
+ /** Route, or a record the caller is entitled to see, does not exist. */
21
+ "relay_not_found" |
22
+ /** Route exists with a different method. */
23
+ "relay_method_not_allowed" |
24
+ /** The authorization request or code is past its injected-clock expiry. */
25
+ "relay_expired" |
26
+ /** The authorization request already reached a terminal decision. */
27
+ "relay_already_decided" |
28
+ /** The one-time authorization code was already consumed. */
29
+ "relay_code_already_consumed" |
30
+ /** The one-time encrypted artifact was already claimed. */
31
+ "relay_artifact_already_claimed" |
32
+ /**
33
+ * Authorization code redemption failed. One code for every reason it can
34
+ * fail — unknown code, another client's code, wrong redirect URI, wrong PKCE
35
+ * verifier — so the endpoint never confirms that a guessed code was correct.
36
+ * A code that existed is burned.
37
+ */
38
+ "relay_code_invalid" |
39
+ /** The optional deployment limiter rejected the call. */
40
+ "relay_rate_limited" |
41
+ /** A durable record could not be read as the current schema version. */
42
+ "relay_record_unreadable" |
43
+ /** The KMS port was unavailable or returned an unusable result. */
44
+ "relay_kms_unavailable" |
45
+ /** The store failed before any state change could have been committed. */
46
+ "relay_store_unavailable" |
47
+ /**
48
+ * The store could not prove whether a transition committed. The caller must
49
+ * treat the transition as neither applied nor retryable: an ambiguous commit
50
+ * never authorizes resubmission.
51
+ */
52
+ "relay_state_ambiguous" |
53
+ /**
54
+ * EXPERIMENTAL PREVIEW (`@oaath/server/apns`): the constructed APNs payload
55
+ * exceeded Apple's 4096-byte limit, so nothing was sent.
56
+ */
57
+ "relay_apns_payload_too_large" |
58
+ /**
59
+ * EXPERIMENTAL PREVIEW (`@oaath/server/apns`): the injected Apple credential
60
+ * capability is not a usable P-256 signing key, key id, team id, or topic.
61
+ */
62
+ "relay_apns_credentials_invalid" |
63
+ /** A deployment-injected chain execution port failed or answered unusably. */
64
+ "relay_chain_unavailable" |
65
+ /** The Grant's capability is durably invalidated; nothing more executes here. */
66
+ "relay_capability_invalidated" |
67
+ /** An invariant the relay owns was violated. */
68
+ "relay_internal";
69
+ /**
70
+ * Status projection. `relay_state_ambiguous` is deliberately 500 and not 503,
71
+ * because 503 invites the retry that an ambiguous commit forbids.
72
+ */
73
+ declare const RELAY_ERROR_STATUS: Readonly<Record<RelayErrorCode, number>>;
74
+ declare class OaathRelayError extends Error {
75
+ readonly code: RelayErrorCode;
76
+ constructor(code: RelayErrorCode, message: string);
77
+ }
78
+ //#endregion
79
+ //#region src/artifact/claim.d.ts
80
+ interface ClaimEncryptedArtifactInput {
81
+ readonly store: RelayStore;
82
+ readonly clock: RelayClock;
83
+ readonly kms: RelayKms;
84
+ /** Authenticated `client` caller; only the bound client may claim. */
85
+ readonly caller: RelayCaller;
86
+ /** Released only by a successful code consume. */
87
+ readonly artifactId: string;
88
+ }
89
+ interface ClaimedEncryptedArtifact {
90
+ readonly requestId: string;
91
+ readonly artifact: string;
92
+ }
93
+ declare function claimEncryptedArtifact(input: ClaimEncryptedArtifactInput): Promise<ClaimedEncryptedArtifact>;
94
+ //#endregion
95
+ //#region src/artifact/encrypt.d.ts
96
+ /**
97
+ * Encrypts an approval artifact and returns the opaque reference to store.
98
+ * A port that echoes plaintext is rejected: the store must never hold it.
99
+ */
100
+ declare function sealArtifact(kms: RelayKms, plaintext: string): Promise<string>;
101
+ /** Opens a reference this KMS previously sealed. Called only after the claim commits. */
102
+ declare function openArtifact(kms: RelayKms, ciphertextRef: string): Promise<string>;
103
+ //#endregion
104
+ //#region src/authorization/challenge.d.ts
105
+ /**
106
+ * True only when `codeVerifier` is a well-formed RFC 7636 verifier whose S256
107
+ * digest equals the stored challenge. Any malformed input is a mismatch.
108
+ */
109
+ declare function verifyPkceS256(codeVerifier: string, storedCodeChallenge: string): Promise<boolean>;
110
+ /** True when the value can be a stored S256 challenge (43 base64url characters). */
111
+ declare function isCodeChallengeS256(value: string): boolean;
112
+ //#endregion
113
+ //#region src/authorization/code.d.ts
114
+ interface ConsumeAuthorizationCodeInput {
115
+ readonly store: RelayStore;
116
+ readonly clock: RelayClock;
117
+ /** Authenticated `client` caller; only the bound client may consume. */
118
+ readonly caller: RelayCaller;
119
+ readonly code: string;
120
+ readonly codeVerifier: string;
121
+ readonly redirectUri: string;
122
+ }
123
+ interface ConsumedAuthorizationCode {
124
+ readonly requestId: string;
125
+ /** One-time claim handle for the encrypted artifact. */
126
+ readonly artifactId: string;
127
+ }
128
+ declare function consumeAuthorizationCode(input: ConsumeAuthorizationCodeInput): Promise<ConsumedAuthorizationCode>;
129
+ //#endregion
130
+ //#region src/authorization/request.d.ts
131
+ interface CreateAuthorizationRequestInput {
132
+ readonly store: RelayStore;
133
+ readonly clock: RelayClock;
134
+ /** Authenticated `client` caller; it owns `clientId` and `subject`. */
135
+ readonly caller: RelayCaller;
136
+ readonly redirectUri: string;
137
+ readonly codeChallenge: string;
138
+ readonly requestedScope: string;
139
+ readonly requestTtlMs: number;
140
+ }
141
+ interface CreatedAuthorizationRequest {
142
+ readonly requestId: string;
143
+ readonly expiresAt: number;
144
+ }
145
+ interface AuthorizationState {
146
+ readonly requestId: string;
147
+ readonly clientId: string;
148
+ readonly redirectUri: string;
149
+ readonly requestedScope: string;
150
+ readonly expiresAt: number;
151
+ readonly expired: boolean;
152
+ readonly decision: Readonly<{
153
+ outcome: AuthorizationDecisionOutcome;
154
+ decidedAt: number;
155
+ }> | null;
156
+ }
157
+ declare function createAuthorizationRequest(input: CreateAuthorizationRequestInput): Promise<CreatedAuthorizationRequest>;
158
+ interface FetchAuthorizationRequestInput {
159
+ readonly store: RelayStore;
160
+ readonly clock: RelayClock;
161
+ /** Authenticated `owner` caller; only the bound subject may read the request. */
162
+ readonly caller: RelayCaller;
163
+ readonly requestId: string;
164
+ }
165
+ /** Read for the approving owner. */
166
+ declare function fetchAuthorizationRequest(input: FetchAuthorizationRequestInput): Promise<AuthorizationState>;
167
+ //#endregion
168
+ //#region src/authorization/resume.d.ts
169
+ interface ResumeAuthorizationInput {
170
+ readonly store: RelayStore;
171
+ readonly clock: RelayClock;
172
+ /** Freshly authenticated `client` caller; only the bound client may resume. */
173
+ readonly caller: RelayCaller;
174
+ readonly requestId: string;
175
+ }
176
+ declare function resumeAuthorization(input: ResumeAuthorizationInput): Promise<AuthorizationState>;
177
+ //#endregion
178
+ //#region src/security/rate-limit.d.ts
179
+ /**
180
+ * Optional deployment-owned limiter port.
181
+ *
182
+ * There is no default limiter: an unset port means no limiting, and the relay
183
+ * never invents a policy the deployment did not choose. A limiter that fails is
184
+ * treated as `limited`, because an unreadable limiter is not permission.
185
+ *
186
+ * @author taek <leekt216@gmail.com>
187
+ */
188
+ interface RelayRateLimitInput {
189
+ /** Stable route name, never a credential-bearing URL. */
190
+ readonly route: string;
191
+ readonly clientId: string | null;
192
+ }
193
+ interface RelayRateLimiter {
194
+ /** Resolves to `"allowed"` or `"limited"`. Anything else is `limited`. */
195
+ check(input: RelayRateLimitInput): Promise<unknown>;
196
+ }
197
+ //#endregion
198
+ //#region src/session-signer/kms-provider.d.ts
199
+ interface SessionSignerIdentity {
200
+ readonly clientId: string;
201
+ readonly subject: string;
202
+ readonly deviceId: string;
203
+ }
204
+ interface SessionSignerSignRequest extends SessionSignerIdentity {
205
+ /** The exact 32-byte hash to sign; never a message to interpret. */
206
+ readonly hash: `0x${string}`;
207
+ }
208
+ interface RelaySessionSignerProvider {
209
+ /**
210
+ * The operator credential for one authenticated identity, creating the key
211
+ * on first use. Idempotent: the same identity always answers the same
212
+ * credential.
213
+ */
214
+ readonly credential: (request: Readonly<SessionSignerIdentity>) => Promise<unknown>;
215
+ /** One ECDSA signature over one exact hash, under that identity's key. */
216
+ readonly sign: (request: Readonly<SessionSignerSignRequest>) => Promise<unknown>;
217
+ }
218
+ declare function createKmsSessionSignerProvider(input: {
219
+ readonly kms: RelayKms;
220
+ }): RelaySessionSignerProvider;
221
+ //#endregion
222
+ //#region src/relay/handler.d.ts
223
+ /**
224
+ * One deployment-injected chain execution surface the relay serves to clients.
225
+ * Each port takes exactly one captured request value and answers with the
226
+ * evidence it owns; the relay never interprets the payload beyond exact wire
227
+ * hygiene, so port meaning stays with its SDK owner.
228
+ */
229
+ interface RelayChainPort {
230
+ readonly chainId: number;
231
+ readonly reads: (request: unknown) => Promise<unknown>;
232
+ readonly observation: (request: unknown) => Promise<unknown>;
233
+ readonly bundler: (request: unknown) => Promise<unknown>;
234
+ readonly quote: (request: unknown) => Promise<unknown>;
235
+ /** Opens, sends, and settles one submission in one call; never retried here. */
236
+ readonly submission: (request: unknown) => Promise<unknown>;
237
+ /** Finalized per-grant usage evidence, or null when this chain serves none. */
238
+ readonly usage: ((request: unknown) => Promise<unknown>) | null;
239
+ readonly feePayer: Readonly<{
240
+ address: `0x${string}`;
241
+ balance: string;
242
+ }> | null;
243
+ /** Authenticated commitment to one exact ERC-7902 static paymaster, or null. */
244
+ readonly staticPaymasterConfigurationHash: `0x${string}` | null;
245
+ }
246
+ /** The identity facts `GET /bootstrap` serves; chains derive from `chains`. */
247
+ interface RelayBootstrapConfiguration {
248
+ readonly application: unknown;
249
+ readonly userHandle: string;
250
+ readonly account: unknown;
251
+ readonly ownerValidator: `0x${string}` | null;
252
+ }
253
+ /**
254
+ * Remote session-key custody, declared once for the deployment: the mode and
255
+ * provider identity are served through the bootstrap document, and the same
256
+ * provider answers the `/session-signers` routes. For `oaath_hosted` the
257
+ * provider is typically `createKmsSessionSignerProvider`; for
258
+ * `application_backend` it is the deployment's own authenticated port to the
259
+ * integrating application's signer — never a client-supplied endpoint.
260
+ */
261
+ interface RelaySessionSignerConfiguration {
262
+ readonly mode: "application_backend" | "oaath_hosted";
263
+ readonly providerId: string;
264
+ readonly provider: Readonly<RelaySessionSignerProvider>;
265
+ }
266
+ /** Authenticated identity and one opaque ERC-7677 params tuple. */
267
+ interface RelayPaymasterServiceRequest {
268
+ readonly caller: Readonly<{
269
+ clientId: string;
270
+ subject: string;
271
+ }>;
272
+ readonly params: unknown;
273
+ readonly signal: AbortSignal;
274
+ }
275
+ /**
276
+ * One deployment-owned paymaster provider. The relay exposes only these two
277
+ * closed ERC-7677 operations and invokes the selected method once.
278
+ */
279
+ interface RelayPaymasterServiceProvider {
280
+ readonly getPaymasterStubData: (request: Readonly<RelayPaymasterServiceRequest>) => Promise<unknown>;
281
+ readonly getPaymasterData: (request: Readonly<RelayPaymasterServiceRequest>) => Promise<unknown>;
282
+ }
283
+ interface RelayPaymasterServiceConfiguration {
284
+ readonly chainId: number;
285
+ readonly providerId: string;
286
+ /** Hard response deadline; the provider also receives its abort signal. */
287
+ readonly requestTimeoutMs: number;
288
+ readonly provider: Readonly<RelayPaymasterServiceProvider>;
289
+ }
290
+ interface RelayHandlerOptions {
291
+ readonly store: RelayStore;
292
+ readonly authentication: RelayAuthentication;
293
+ readonly kms: RelayKms;
294
+ readonly clock: RelayClock;
295
+ /** Optional. There is no default limiter. */
296
+ readonly rateLimit?: RelayRateLimiter;
297
+ readonly requestTtlMs?: number;
298
+ readonly codeTtlMs?: number;
299
+ readonly maxBodyBytes?: number;
300
+ /** Optional URL-only bootstrap surface; requires `chains` as well. */
301
+ readonly bootstrap?: Readonly<RelayBootstrapConfiguration>;
302
+ /** Optional chain execution relays; required when `bootstrap` is served. */
303
+ readonly chains?: readonly Readonly<RelayChainPort>[];
304
+ /** Optional remote session-key custody; requires `bootstrap` as well. */
305
+ readonly sessionSigner?: Readonly<RelaySessionSignerConfiguration>;
306
+ /**
307
+ * Optional deployment-owned paymaster services, at most one per chain.
308
+ * Configuration requires both bootstrap and a deployment rate limiter.
309
+ */
310
+ readonly paymasterServices?: readonly Readonly<RelayPaymasterServiceConfiguration>[];
311
+ }
312
+ type RelayHandler = (request: Request) => Promise<Response>;
313
+ declare function createRelayHandler(options: RelayHandlerOptions): RelayHandler;
314
+ //#endregion
315
+ //#region src/security/redact.d.ts
316
+ /**
317
+ * Bounded credential and URL redaction for diagnostics only.
318
+ *
319
+ * Nothing here shapes a response or a machine decision. Its only job is to make
320
+ * an adopter's log line safe and finite: no authorization code, verifier, token,
321
+ * artifact, ciphertext, credential-bearing URL, or unbounded provider blob.
322
+ *
323
+ * @author taek <leekt216@gmail.com>
324
+ */
325
+ declare const REDACTED = "[redacted]";
326
+ /** Keeps scheme, host, and path. Drops userinfo, query, and fragment. */
327
+ declare function redactUrl(value: unknown): string;
328
+ /** Returns a bounded, credential-free projection safe to hand to a logger. */
329
+ declare function redactForLog(value: unknown): unknown;
330
+ //#endregion
331
+ //#region src/store/memory.d.ts
332
+ declare function createMemoryRelayStore(): RelayStore;
333
+ //#endregion
334
+ export { type AuthorizationCodeRecord, type AuthorizationDecisionCommand, type AuthorizationDecisionOutcome, type AuthorizationDecisionRecord, type AuthorizationRequestRecord, type AuthorizationState, type ClaimEncryptedArtifactInput, type ClaimedEncryptedArtifact, type ConsumeAuthorizationCodeInput, type ConsumedAuthorizationCode, type CreateAuthorizationRequestInput, type CreatedAuthorizationRequest, type EncryptedArtifactRecord, type FetchAuthorizationRequestInput, OAATH_AUTHORIZATION_CODE_RECORD_VERSION, OAATH_AUTHORIZATION_DECISION_RECORD_VERSION, OAATH_AUTHORIZATION_REQUEST_RECORD_VERSION, OAATH_ENCRYPTED_ARTIFACT_RECORD_VERSION, OaathRelayError, REDACTED, RELAY_ERROR_STATUS, type RelayAuthentication, type RelayCaller, type RelayCallerRole, type RelayClock, type RelayErrorCode, type RelayHandler, type RelayHandlerOptions, type RelayKms, type RelayPaymasterServiceConfiguration, type RelayPaymasterServiceProvider, type RelayPaymasterServiceRequest, type RelayRateLimitInput, type RelayRateLimiter, type RelaySessionSignerConfiguration, type RelaySessionSignerProvider, type RelayStore, type RelayTransaction, type ResumeAuthorizationInput, type SessionSignerIdentity, type SessionSignerSignRequest, type SubmitAuthorizationDecisionInput, type SubmittedAuthorizationDecision, claimEncryptedArtifact, consumeAuthorizationCode, createAuthorizationRequest, createKmsSessionSignerProvider, createMemoryRelayStore, createRelayHandler, fetchAuthorizationRequest, isCodeChallengeS256, openArtifact, redactForLog, redactUrl, resumeAuthorization, sealArtifact, submitAuthorizationDecision, verifyPkceS256 };
335
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/relay/errors.ts","../src/artifact/claim.ts","../src/artifact/encrypt.ts","../src/authorization/challenge.ts","../src/authorization/code.ts","../src/authorization/request.ts","../src/authorization/resume.ts","../src/security/rate-limit.ts","../src/session-signer/kms-provider.ts","../src/relay/handler.ts","../src/security/redact.ts","../src/store/memory.ts"],"mappings":";;;;;;;;;;;;KASY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6DC,oBAAoB,SAAS,OAAO;cAyBpC,wBAAwB;WAC1B,MAAM;EAEf,YAAY,MAAM,gBAAgB;;;;UC1EnB;WACN,OAAO;WACP,OAAO;WACP,KAAK;;WAEL,QAAQ;;WAER;;UAGM;WACN;WACA;;iBAGW,uBACpB,OAAO,8BACN,QAAQ;;;;;;;iBCzBW,aAAa,KAAK,UAAU,oBAAoB;;iBAoBhD,aAAa,KAAK,UAAU,wBAAwB;;;;;;;iBCgBpD,eACpB,sBACA,8BACC;;iBAMa,oBAAoB;;;UChCnB;WACN,OAAO;WACP,OAAO;;WAEP,QAAQ;WACR;WACA;WACA;;UAGM;WACN;;WAEA;;iBAOW,yBACpB,OAAO,gCACN,QAAQ;;;UC9BM;WACN,OAAO;WACP,OAAO;;WAEP,QAAQ;WACR;WACA;WACA;WACA;;UAGM;WACN;WACA;;UAGM;WACN;WACA;WACA;WACA;WACA;WACA;WACA,UAAU;IACjB,SAAS;IACT;;;iBAIkB,2BACpB,OAAO,kCACN,QAAQ;UA8DM;WACN,OAAO;WACP,OAAO;;WAEP,QAAQ;WACR;;;iBAIK,0BACd,OAAO,iCACN,QAAQ;;;UC7GM;WACN,OAAO;WACP,OAAO;;WAEP,QAAQ;WACR;;iBAGK,oBAAoB,OAAO,2BAA2B,QAAQ;;;;;;;;;;;;UCZ7D;;WAEN;WACA;;UAGM;;EAEf,MAAM,OAAO,sBAAsB;;;;UCWpB;WACN;WACA;WACA;;UAGM,iCAAiC;;WAEvC;;UAGM;;;;;;WAMN,aAAa,SAAS,SAAS,2BAA2B;;WAE1D,OAAO,SAAS,SAAS,8BAA8B;;iBAkBlD,+BAA+B;WACpC,KAAK;IACZ;;;;;;;;;UC6Ba;WACN;WACA,QAAQ,qBAAqB;WAC7B,cAAc,qBAAqB;WACnC,UAAU,qBAAqB;WAC/B,QAAQ,qBAAqB;;WAE7B,aAAa,qBAAqB;;WAElC,SAAS,qBAAqB;WAC9B,UAAU;IAAW;IAAwB;;;WAE7C;;;UAIM;WACN;WACA;WACA;WACA;;;;;;;;;;UAWM;WACN;WACA;WACA,UAAU,SAAS;;;UAIb;WACN,QAAQ;IAAW;IAAkB;;WACrC;WACA,QAAQ;;;;;;UAOF;WACN,uBACP,SAAS,SAAS,kCACf;WACI,mBAAmB,SAAS,SAAS,kCAAkC;;UAGjE;WACN;WACA;;WAEA;WACA,UAAU,SAAS;;UAGb;WACN,OAAO;WACP,gBAAgB;WAChB,KAAK;WACL,OAAO;;WAEP,YAAY;WACZ;WACA;WACA;;WAEA,YAAY,SAAS;;WAErB,kBAAkB,SAAS;;WAE3B,gBAAgB,SAAS;;;;;WAKzB,6BAA6B,SAAS;;KAGrC,gBAAgB,SAAS,YAAY,QAAQ;iBAoazC,mBAAmB,SAAS,sBAAsB;;;;;;;;;;;;cCnlBrD;;iBAiDG,UAAU;;iBA+DV,aAAa;;;iBCnDb,0BAA0B"}