@mdbase-dev/connect 0.1.0-beta.61 → 0.1.0-beta.62
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/dist/browser/integrity.json +1 -1
- package/dist/browser/mdbase-connect.min.js +2 -2
- package/dist/browser/mdbase-connect.min.js.sha384 +1 -1
- package/dist/connection-transport.js +5 -8
- package/dist/crypto.d.ts +1 -1
- package/dist/crypto.js +6 -1
- package/dist/fresh-encrypted-request.d.ts +1 -1
- package/dist/fresh-encrypted-request.js +2 -2
- package/dist/request-budget.d.ts +5 -0
- package/dist/request-budget.js +7 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
sha384-
|
|
1
|
+
sha384-bNuQ6oZAI3yOsHt34NNTiVWa2gbZsyM2B4Iy1Gy4WQdXBSxEtUIgtaPLepNJYZjW
|
|
@@ -7,7 +7,7 @@ import { PendingMutationStore } from "./pending-mutation-store.js";
|
|
|
7
7
|
import { directFallbackStatus, isMutation, localNetworkPermission, loopbackRequest, operationFingerprint, operationTransportError, sameAuthorization, throwIfCancelled, unknownMutationOutcome } from "./operation-helpers.js";
|
|
8
8
|
import { apiError, decodeJsonResponse, oauthErrorCode, parseStored, } from "./runtime-utils.js";
|
|
9
9
|
import { readStoredToken } from "./stored-token.js";
|
|
10
|
-
import { withCooperativeRequestBudget, withRequestBudget } from "./request-budget.js";
|
|
10
|
+
import { requestOptionsWithinBudget, withCooperativeRequestBudget, withRequestBudget } from "./request-budget.js";
|
|
11
11
|
import { sendAuthoritySyncRequest } from "./authority-sync-request.js";
|
|
12
12
|
import { freshEncryptedRequest } from "./fresh-encrypted-request.js";
|
|
13
13
|
import { isExplicitConnectorBusyResponse, retryExplicitConnectorBusy } from "./transient-retry.js";
|
|
@@ -127,10 +127,7 @@ export class ConnectionTransport {
|
|
|
127
127
|
return withCooperativeRequestBudget(options, this.timeouts.requestMs, (budget) => this.performOperationWithinBudget(pending.operation, pending.request?.input ?? {}, { ...options, signal: budget.signal }, pending));
|
|
128
128
|
}
|
|
129
129
|
async performOperation(operation, input, options = {}) {
|
|
130
|
-
return withCooperativeRequestBudget(options, this.timeouts.requestMs, (budget) => this.performOperationWithinBudget(operation, input,
|
|
131
|
-
...options,
|
|
132
|
-
signal: budget.signal
|
|
133
|
-
}));
|
|
130
|
+
return withCooperativeRequestBudget(options, this.timeouts.requestMs, (budget) => this.performOperationWithinBudget(operation, input, requestOptionsWithinBudget(options, budget)));
|
|
134
131
|
}
|
|
135
132
|
async performOperationWithinBudget(operation, input, options, storedPending, freshReadRetried = false, connectorBusyRetries = 0, knownRejectedMutationRetry = false) {
|
|
136
133
|
throwIfCancelled(options.signal);
|
|
@@ -383,7 +380,7 @@ export class ConnectionTransport {
|
|
|
383
380
|
encryptedRequest = pending.envelope;
|
|
384
381
|
}
|
|
385
382
|
else {
|
|
386
|
-
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input, requestId);
|
|
383
|
+
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input, requestId, options.deadlineUnixMs);
|
|
387
384
|
this.pendingMutationStore.store({
|
|
388
385
|
collectionId: token.collectionId,
|
|
389
386
|
...(token.grantId ? { grantId: token.grantId } : {}),
|
|
@@ -401,7 +398,7 @@ export class ConnectionTransport {
|
|
|
401
398
|
}
|
|
402
399
|
}
|
|
403
400
|
else {
|
|
404
|
-
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input);
|
|
401
|
+
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input, undefined, options.deadlineUnixMs);
|
|
405
402
|
}
|
|
406
403
|
}
|
|
407
404
|
catch (error) {
|
|
@@ -481,7 +478,7 @@ export class ConnectionTransport {
|
|
|
481
478
|
}
|
|
482
479
|
let response;
|
|
483
480
|
if (!pendingMutation) {
|
|
484
|
-
encryptedRequest = await freshEncryptedRequest(this.keyStore, relayToken, operation, input);
|
|
481
|
+
encryptedRequest = await freshEncryptedRequest(this.keyStore, relayToken, operation, input, options.deadlineUnixMs);
|
|
485
482
|
requestId = encryptedRequest.request_id;
|
|
486
483
|
}
|
|
487
484
|
try {
|
package/dist/crypto.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export interface AuthorityProofInput {
|
|
|
46
46
|
/** Sign one remote-authority or token-refresh request with the approved grant key. */
|
|
47
47
|
export declare function signAuthorityRequest(store: GrantKeyStore, handle: string, expectedPublicKey: string, input: AuthorityProofInput): Promise<Record<string, string>>;
|
|
48
48
|
export declare function authorityProofMessage(input: Required<Pick<AuthorityProofInput, "method" | "target" | "credential" | "timestamp" | "nonce">> & Pick<AuthorityProofInput, "body">): Promise<string>;
|
|
49
|
-
export declare function encryptRelayRequest(store: GrantKeyStore, handle: string, binding: RelayBinding, operation: EncryptedRelayOperation, input: unknown, requestId?: string): Promise<EncryptedRelayOperationRequest>;
|
|
49
|
+
export declare function encryptRelayRequest(store: GrantKeyStore, handle: string, binding: RelayBinding, operation: EncryptedRelayOperation, input: unknown, requestId?: string, deadlineUnixMs?: number): Promise<EncryptedRelayOperationRequest>;
|
|
50
50
|
export declare function decryptRelayResponse<Result>(store: GrantKeyStore, handle: string, binding: RelayBinding, request: EncryptedRelayOperationRequest, response: EncryptedRelayOperationResponse): Promise<{
|
|
51
51
|
ok: true;
|
|
52
52
|
result: Result;
|
package/dist/crypto.js
CHANGED
|
@@ -157,8 +157,12 @@ export async function authorityProofMessage(input) {
|
|
|
157
157
|
input.nonce
|
|
158
158
|
].join("\n");
|
|
159
159
|
}
|
|
160
|
-
export async function encryptRelayRequest(store, handle, binding, operation, input, requestId = crypto.randomUUID()) {
|
|
160
|
+
export async function encryptRelayRequest(store, handle, binding, operation, input, requestId = crypto.randomUUID(), deadlineUnixMs) {
|
|
161
161
|
validateGrantEncryption(binding.encryption);
|
|
162
|
+
if (deadlineUnixMs !== undefined
|
|
163
|
+
&& (!Number.isSafeInteger(deadlineUnixMs) || deadlineUnixMs <= 0)) {
|
|
164
|
+
throw new RelayCryptoError("invalid_deadline", "The operation deadline is invalid.");
|
|
165
|
+
}
|
|
162
166
|
const record = await requireAgreementKey(store, handle, binding.encryption.application_agreement_public_key);
|
|
163
167
|
const counter = await store.nextCounter(handle);
|
|
164
168
|
const metadata = {
|
|
@@ -179,6 +183,7 @@ export async function encryptRelayRequest(store, handle, binding, operation, inp
|
|
|
179
183
|
return {
|
|
180
184
|
type: "encrypted_operation_request",
|
|
181
185
|
...envelopeMetadata(metadata),
|
|
186
|
+
...(deadlineUnixMs === undefined ? {} : { deadline_unix_ms: deadlineUnixMs }),
|
|
182
187
|
ciphertext: bytesToBase64Url(new Uint8Array(ciphertext))
|
|
183
188
|
};
|
|
184
189
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CollectionOperation, EncryptedRelayOperationRequest } from "@mdbase-dev/connect-protocol";
|
|
2
2
|
import { type GrantKeyStore } from "./crypto.js";
|
|
3
3
|
import type { StoredToken } from "./internal-types.js";
|
|
4
|
-
export declare function freshEncryptedRequest(keyStore: GrantKeyStore, token: StoredToken, operation: CollectionOperation, input: unknown): Promise<EncryptedRelayOperationRequest>;
|
|
4
|
+
export declare function freshEncryptedRequest(keyStore: GrantKeyStore, token: StoredToken, operation: CollectionOperation, input: unknown, deadlineUnixMs?: number): Promise<EncryptedRelayOperationRequest>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { encryptRelayRequest, RelayCryptoError } from "./crypto.js";
|
|
2
2
|
import { connectError, serverConnectError } from "./errors.js";
|
|
3
|
-
export async function freshEncryptedRequest(keyStore, token, operation, input) {
|
|
3
|
+
export async function freshEncryptedRequest(keyStore, token, operation, input, deadlineUnixMs) {
|
|
4
4
|
if (!token.encryption || !token.grantId || !token.keyHandle) {
|
|
5
5
|
throw connectError("authorization_binding_incompatible", "The refreshed authorization no longer supports encrypted connector operations.", {
|
|
6
6
|
details: {
|
|
@@ -17,7 +17,7 @@ export async function freshEncryptedRequest(keyStore, token, operation, input) {
|
|
|
17
17
|
grantId: token.grantId,
|
|
18
18
|
applicationId: token.clientId,
|
|
19
19
|
encryption: token.encryption
|
|
20
|
-
}, operation, input);
|
|
20
|
+
}, operation, input, undefined, deadlineUnixMs);
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
23
23
|
if (error instanceof RelayCryptoError) {
|
package/dist/request-budget.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ export interface RequestBudget {
|
|
|
19
19
|
remainingMs(): number | null;
|
|
20
20
|
dispose(): void;
|
|
21
21
|
}
|
|
22
|
+
export type OperationRequestOptions = ConnectRequestOptions & {
|
|
23
|
+
/** Absolute budget shared with the connector; never supplied directly by callers. */
|
|
24
|
+
deadlineUnixMs?: number;
|
|
25
|
+
};
|
|
26
|
+
export declare function requestOptionsWithinBudget(options: ConnectRequestOptions, budget: RequestBudget): OperationRequestOptions;
|
|
22
27
|
export declare function createRequestBudget(options?: ConnectRequestOptions, defaultTimeoutMs?: number | null, now?: () => number): RequestBudget;
|
|
23
28
|
export declare function withRequestBudget<Result>(options: ConnectRequestOptions | undefined, defaultTimeoutMs: number | null, operation: (budget: RequestBudget) => Promise<Result>): Promise<Result>;
|
|
24
29
|
/**
|
package/dist/request-budget.js
CHANGED
|
@@ -13,6 +13,13 @@ export function resolveConnectTimeouts(timeouts = {}) {
|
|
|
13
13
|
syncMs: configuredTimeout(timeouts.syncMs, DEFAULT_SYNC_TIMEOUT_MS, "syncMs")
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
+
export function requestOptionsWithinBudget(options, budget) {
|
|
17
|
+
return {
|
|
18
|
+
...options,
|
|
19
|
+
signal: budget.signal,
|
|
20
|
+
...(budget.deadline === null ? {} : { deadlineUnixMs: budget.deadline })
|
|
21
|
+
};
|
|
22
|
+
}
|
|
16
23
|
export function createRequestBudget(options = {}, defaultTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS, now = Date.now) {
|
|
17
24
|
const configured = options.timeoutMs === undefined ? defaultTimeoutMs : options.timeoutMs;
|
|
18
25
|
const timeoutMs = configured === null ? null : validTimeout(configured);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mdbase-dev/connect",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.62",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@mdbase-dev/connect-protocol": "0.1.0-beta.
|
|
36
|
+
"@mdbase-dev/connect-protocol": "0.1.0-beta.62"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"esbuild": "^0.28.1",
|