@calimero-network/mero-js 24.6.0 → 24.7.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/dist/account/create-context.js +17 -6
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.js +1 -1
- package/dist/account/session.d.ts +23 -1
- package/dist/account/session.js +96 -12
- package/dist/admin-api/admin-types.d.ts +2 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +3 -3
- package/dist/index.cjs +73 -12
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +73 -12
- package/dist/index.mjs.map +3 -3
- package/dist/transport/mero-client.d.ts +9 -0
- package/dist/transport/mero-client.js +13 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export { signerFromSecret, signerFromCryptoKey } from "./signer/index.js";
|
|
|
28
28
|
export type { Signer } from "./signer/index.js";
|
|
29
29
|
export { generateAccountRoot, accountRootFromPhrase, accountRootFromSecret, createAccountRootSigner, accountRootSignerFromPhrase, signAccountLink, signAccountLogin, resolveRoot, resolveRootPair, } from "./account/index.js";
|
|
30
30
|
export type { AccountRoot, RecoverableAccountRoot, AccountRootSigner, NewAccountRootSigner, AccountLinkInput, AccountLoginInput, RootSource, ResolvedRoot, } from "./account/index.js";
|
|
31
|
-
export { readDelegatedSession, saveDelegatedSession, clearDelegatedSession, readDelegatedCredential, saveDelegatedCredential, clearDelegatedCredential, persistedNonces, markContextNonceSpent, pinRelayNodeKey, readPinnedRelayNodeKey, attemptRelayNodeKey, resolveRelayNodeKey, learnRelayNodeKey, RELAY_NODE_KEY_RETRY_MS, forgetMethodKinds, buildDelegatedClient, readRelayMap, rememberRelay, relayForContext, carryExecutorAccount, knownRelays, listDelegatedContexts, listDelegatedNamespaces, resolveRelayFromInvitation, normaliseAccount, joinWithNode, bootstrapFromInvitation, joinAsAccount, createDelegatedContext, createDelegatedPrivateContext, foundDelegatedNamespace, delegatedGovernance, latestPublishedVersion, HA_ACCOUNT_NOT_LINKED_MESSAGE, HA_REFUSAL_MESSAGES, governGroup, governRoot, namespaceOfGroup, rememberGroupNamespace, applicationIdForBundle, fetchRegistryBundles, resolveApplicationIdFromRegistry, selectLatestBundle, createAccountAdmin, InvitationNotClaimableError, NoRelayError, NotForAccountError, createNodeAdmin, } from "./account/index.js";
|
|
31
|
+
export { readDelegatedSession, saveDelegatedSession, clearDelegatedSession, readDelegatedCredential, saveDelegatedCredential, clearDelegatedCredential, persistedNonces, markContextNonceSpent, pinRelayNodeKey, readPinnedRelayNodeKey, attemptRelayNodeKey, resolveRelayNodeKey, learnRelayNodeKey, RELAY_NODE_KEY_RETRY_MS, forgetMethodKinds, forgetRelaySealing, relayTransportFetch, buildDelegatedClient, readRelayMap, rememberRelay, relayForContext, carryExecutorAccount, knownRelays, listDelegatedContexts, listDelegatedNamespaces, resolveRelayFromInvitation, normaliseAccount, joinWithNode, bootstrapFromInvitation, joinAsAccount, createDelegatedContext, createDelegatedPrivateContext, foundDelegatedNamespace, delegatedGovernance, latestPublishedVersion, HA_ACCOUNT_NOT_LINKED_MESSAGE, HA_REFUSAL_MESSAGES, governGroup, governRoot, namespaceOfGroup, rememberGroupNamespace, applicationIdForBundle, fetchRegistryBundles, resolveApplicationIdFromRegistry, selectLatestBundle, createAccountAdmin, InvitationNotClaimableError, NoRelayError, NotForAccountError, createNodeAdmin, } from "./account/index.js";
|
|
32
32
|
export type { DelegatedCredential, DelegatedAccountSession, RelayMap, RelayNodeKeyAttempt, RelayResolutionStep, RelayResolutionFailure, ResolvedInvitationRelay, ResolveRelayResult, ResolveRelayFromInvitationInput, JoinWithNodeInput, JoinWithNodeResult, JoinWithNodeSuccess, JoinWithNodeFailure, JoinWithNodeStep, BootstrapStep, BootstrapResult, BootstrapSuccess, BootstrapFailure, BootstrapFromInvitationInput, CreateDelegatedContextRequest, FoundedDelegatedNamespace, RegistryBundle, ResolvedApplication, AccountAdminDeps, NodeAdminDeps, } from "./account/index.js";
|
|
33
33
|
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, accountForRootPublicKey, parseDeviceCredential, verifyDeviceCredential, } from "./device-cert/index.js";
|
|
34
34
|
export type { DeviceCertInput, DeviceCredential } from "./device-cert/index.js";
|
package/dist/index.js
CHANGED
|
@@ -52,7 +52,7 @@ resolveRoot, resolveRootPair, } from "./account/index.js";
|
|
|
52
52
|
// Framework-free; mero-react re-exports every one of these under the same name
|
|
53
53
|
// (its `DelegatedSession` is `DelegatedAccountSession` here: the login module
|
|
54
54
|
// already owns the bare name for the session `login()` mints).
|
|
55
|
-
export { readDelegatedSession, saveDelegatedSession, clearDelegatedSession, readDelegatedCredential, saveDelegatedCredential, clearDelegatedCredential, persistedNonces, markContextNonceSpent, pinRelayNodeKey, readPinnedRelayNodeKey, attemptRelayNodeKey, resolveRelayNodeKey, learnRelayNodeKey, RELAY_NODE_KEY_RETRY_MS, forgetMethodKinds, buildDelegatedClient, readRelayMap, rememberRelay, relayForContext, carryExecutorAccount, knownRelays, listDelegatedContexts, listDelegatedNamespaces, resolveRelayFromInvitation, normaliseAccount, joinWithNode, bootstrapFromInvitation, joinAsAccount, createDelegatedContext, createDelegatedPrivateContext, foundDelegatedNamespace, delegatedGovernance, latestPublishedVersion, HA_ACCOUNT_NOT_LINKED_MESSAGE, HA_REFUSAL_MESSAGES, governGroup, governRoot, namespaceOfGroup, rememberGroupNamespace, applicationIdForBundle, fetchRegistryBundles, resolveApplicationIdFromRegistry, selectLatestBundle, createAccountAdmin, InvitationNotClaimableError, NoRelayError, NotForAccountError, createNodeAdmin, } from "./account/index.js";
|
|
55
|
+
export { readDelegatedSession, saveDelegatedSession, clearDelegatedSession, readDelegatedCredential, saveDelegatedCredential, clearDelegatedCredential, persistedNonces, markContextNonceSpent, pinRelayNodeKey, readPinnedRelayNodeKey, attemptRelayNodeKey, resolveRelayNodeKey, learnRelayNodeKey, RELAY_NODE_KEY_RETRY_MS, forgetMethodKinds, forgetRelaySealing, relayTransportFetch, buildDelegatedClient, readRelayMap, rememberRelay, relayForContext, carryExecutorAccount, knownRelays, listDelegatedContexts, listDelegatedNamespaces, resolveRelayFromInvitation, normaliseAccount, joinWithNode, bootstrapFromInvitation, joinAsAccount, createDelegatedContext, createDelegatedPrivateContext, foundDelegatedNamespace, delegatedGovernance, latestPublishedVersion, HA_ACCOUNT_NOT_LINKED_MESSAGE, HA_REFUSAL_MESSAGES, governGroup, governRoot, namespaceOfGroup, rememberGroupNamespace, applicationIdForBundle, fetchRegistryBundles, resolveApplicationIdFromRegistry, selectLatestBundle, createAccountAdmin, InvitationNotClaimableError, NoRelayError, NotForAccountError, createNodeAdmin, } from "./account/index.js";
|
|
56
56
|
export { signDeviceCert, mintDeviceId, deviceCertPayload, accountForRoot, accountForRootPublicKey, parseDeviceCredential, verifyDeviceCredential, } from "./device-cert/index.js";
|
|
57
57
|
// A device's scope — signed by the root beside its certificate, and what a relay
|
|
58
58
|
// needs with it to bind the device of an account that has no node.
|
package/dist/index.mjs
CHANGED
|
@@ -8836,7 +8836,7 @@ function missingNodeKey(surface) {
|
|
|
8836
8836
|
`this relay-transport client cannot open ${surface}: it was given no relay node key. A relay is an ordinary node and does serve /sse and /ws \u2014 but the login statement must be signed against the node's device signing key, learned out of band (never read from the node, and never derived from its peerId). Pass it as \`observe: { nodeKey }\`. For a cloud-hosted relay the cloud does not publish it yet \u2014 see mdma #312.`
|
|
8837
8837
|
);
|
|
8838
8838
|
}
|
|
8839
|
-
function buildObserver(relay, observe) {
|
|
8839
|
+
function buildObserver(relay, observe, fetchImpl) {
|
|
8840
8840
|
const nodeKey = observe?.nodeKey;
|
|
8841
8841
|
if (!nodeKey) return null;
|
|
8842
8842
|
return new RelayObserver({
|
|
@@ -8847,7 +8847,7 @@ function buildObserver(relay, observe) {
|
|
|
8847
8847
|
signer: observe?.signer ? async () => observe.signer : () => relay.authorSigner(),
|
|
8848
8848
|
clientName: observe?.clientName,
|
|
8849
8849
|
ttlSeconds: observe?.ttlSeconds,
|
|
8850
|
-
fetch: observe?.fetch,
|
|
8850
|
+
fetch: observe?.fetch ?? fetchImpl,
|
|
8851
8851
|
timeoutMs: observe?.timeoutMs
|
|
8852
8852
|
});
|
|
8853
8853
|
}
|
|
@@ -8868,12 +8868,16 @@ var MeroClient = class {
|
|
|
8868
8868
|
this.proofAuthorizer = null;
|
|
8869
8869
|
this.relayUrl = null;
|
|
8870
8870
|
this.proofEvents = null;
|
|
8871
|
+
/** The relay transport's `fetch`, if one was given. */
|
|
8872
|
+
this.relayFetch = void 0;
|
|
8871
8873
|
this.relayPresence = null;
|
|
8872
8874
|
if (config.transport === "relay") {
|
|
8873
8875
|
this.transport = "relay";
|
|
8874
8876
|
this.nodeClient = null;
|
|
8875
|
-
const
|
|
8876
|
-
this.
|
|
8877
|
+
const fetchImpl = config.fetch;
|
|
8878
|
+
this.relayFetch = fetchImpl;
|
|
8879
|
+
const relay = config.relay instanceof RelayClient ? config.relay : new RelayClient({ ...config.relay, fetch: config.relay.fetch ?? fetchImpl });
|
|
8880
|
+
this.relayObserver = buildObserver(relay, config.observe, fetchImpl);
|
|
8877
8881
|
this.rpcTransport = new RelayTransport(relay, this.relayObserver);
|
|
8878
8882
|
this.relayUrl = relay.relayUrl;
|
|
8879
8883
|
if (config.proof) {
|
|
@@ -8883,13 +8887,14 @@ var MeroClient = class {
|
|
|
8883
8887
|
const token = config.session;
|
|
8884
8888
|
this.relayAdmin = createAdminApiClient({
|
|
8885
8889
|
baseUrl: relay.relayUrl,
|
|
8886
|
-
getAuthToken: typeof token === "string" ? async () => token : token
|
|
8890
|
+
getAuthToken: typeof token === "string" ? async () => token : token,
|
|
8891
|
+
fetch: fetchImpl
|
|
8887
8892
|
});
|
|
8888
8893
|
} else if (this.proofAuthorizer) {
|
|
8889
8894
|
const authorizeRequest = this.proofAuthorizer;
|
|
8890
8895
|
this.relayAdmin = createAdminApiClientFromHttpClient(
|
|
8891
8896
|
createHttpClient({
|
|
8892
|
-
fetch: (url, init) => globalThis.fetch(url, init),
|
|
8897
|
+
fetch: (url, init) => fetchImpl ? fetchImpl(url, init) : globalThis.fetch(url, init),
|
|
8893
8898
|
baseUrl: relay.relayUrl,
|
|
8894
8899
|
authorizeRequest
|
|
8895
8900
|
}),
|
|
@@ -9003,7 +9008,8 @@ var MeroClient = class {
|
|
|
9003
9008
|
if (this.proofAuthorizer && this.relayUrl) {
|
|
9004
9009
|
this.proofEvents ?? (this.proofEvents = new SseClient({
|
|
9005
9010
|
baseUrl: this.relayUrl,
|
|
9006
|
-
authorize: this.proofAuthorizer
|
|
9011
|
+
authorize: this.proofAuthorizer,
|
|
9012
|
+
fetch: this.relayFetch
|
|
9007
9013
|
}));
|
|
9008
9014
|
return this.proofEvents;
|
|
9009
9015
|
}
|
|
@@ -9253,8 +9259,8 @@ function relayQuoteVerifier(relayUrl, fetchRelay) {
|
|
|
9253
9259
|
};
|
|
9254
9260
|
return Object.assign(verify, { includeCollateral: true });
|
|
9255
9261
|
}
|
|
9256
|
-
async function attemptRelayNodeKey(relayUrl) {
|
|
9257
|
-
const pinned = readPinnedRelayNodeKey(relayUrl);
|
|
9262
|
+
async function attemptRelayNodeKey(relayUrl, options = {}) {
|
|
9263
|
+
const pinned = options.fresh ? null : readPinnedRelayNodeKey(relayUrl);
|
|
9258
9264
|
if (pinned) return { kind: "learned", nodeKey: pinned };
|
|
9259
9265
|
const marked = { failure: null };
|
|
9260
9266
|
const fetchRelay = relayFetch(marked);
|
|
@@ -9318,6 +9324,54 @@ function jwtExpiryMs2(token) {
|
|
|
9318
9324
|
return null;
|
|
9319
9325
|
}
|
|
9320
9326
|
}
|
|
9327
|
+
var sealedFetches = /* @__PURE__ */ new Map();
|
|
9328
|
+
function forgetRelaySealing() {
|
|
9329
|
+
sealedFetches.clear();
|
|
9330
|
+
}
|
|
9331
|
+
async function isUnguardedRefusal(response) {
|
|
9332
|
+
if (response.status !== 403) return false;
|
|
9333
|
+
try {
|
|
9334
|
+
const body = await response.clone().json();
|
|
9335
|
+
return body.error?.code === "sealed_route_unguarded";
|
|
9336
|
+
} catch {
|
|
9337
|
+
return false;
|
|
9338
|
+
}
|
|
9339
|
+
}
|
|
9340
|
+
function needsSession(request) {
|
|
9341
|
+
return request.headers.has("authorization") || new URL(request.url).pathname.startsWith("/auth/");
|
|
9342
|
+
}
|
|
9343
|
+
function sealedRelayFetch(relayUrl) {
|
|
9344
|
+
const plain = (input, init) => globalThis.fetch(input, init);
|
|
9345
|
+
const sealed = createAttestedSealedFetch({
|
|
9346
|
+
baseUrl: relayUrl,
|
|
9347
|
+
verify: relayQuoteVerifier(relayUrl, plain),
|
|
9348
|
+
fetch: plain
|
|
9349
|
+
});
|
|
9350
|
+
let unguarded = false;
|
|
9351
|
+
return async (input, init) => {
|
|
9352
|
+
const request = new Request(input, init);
|
|
9353
|
+
if (unguarded && needsSession(request)) return plain(request);
|
|
9354
|
+
const response = await sealed(request.clone());
|
|
9355
|
+
if (!await isUnguardedRefusal(response)) return response;
|
|
9356
|
+
if (!unguarded) {
|
|
9357
|
+
unguarded = true;
|
|
9358
|
+
console.warn(
|
|
9359
|
+
`[mero-js] ${relayOrigin(relayUrl)} cannot guard logged-in calls sealed (no forward_auth); they go over its TLS until it does`
|
|
9360
|
+
);
|
|
9361
|
+
}
|
|
9362
|
+
return plain(request);
|
|
9363
|
+
};
|
|
9364
|
+
}
|
|
9365
|
+
function relayTransportFetch(relayUrl) {
|
|
9366
|
+
if (isLoopback(relayUrl)) return void 0;
|
|
9367
|
+
const origin2 = relayOrigin(relayUrl);
|
|
9368
|
+
let found = sealedFetches.get(origin2);
|
|
9369
|
+
if (!found) {
|
|
9370
|
+
found = sealedRelayFetch(relayUrl);
|
|
9371
|
+
sealedFetches.set(origin2, found);
|
|
9372
|
+
}
|
|
9373
|
+
return found;
|
|
9374
|
+
}
|
|
9321
9375
|
function relaySession(s, nodeKey) {
|
|
9322
9376
|
let token = null;
|
|
9323
9377
|
let inflight = null;
|
|
@@ -9327,6 +9381,8 @@ function relaySession(s, nodeKey) {
|
|
|
9327
9381
|
if (!inflight) {
|
|
9328
9382
|
inflight = login({
|
|
9329
9383
|
nodeUrl: s.relayUrl,
|
|
9384
|
+
// Sealed: the token is the session, and the TLS ends outside the TD.
|
|
9385
|
+
fetch: relayTransportFetch(s.relayUrl),
|
|
9330
9386
|
node: nodeKey,
|
|
9331
9387
|
deviceSecret: s.deviceSecret,
|
|
9332
9388
|
accountProof: s.credential,
|
|
@@ -9422,6 +9478,9 @@ function buildDelegatedClient(s, _contextId) {
|
|
|
9422
9478
|
const nodeKey = readPinnedRelayNodeKey(s.relayUrl);
|
|
9423
9479
|
const client2 = createMeroClient({
|
|
9424
9480
|
transport: "relay",
|
|
9481
|
+
// Every request sealed to the relay's attested TD: intents, admin reads,
|
|
9482
|
+
// queries, the login and events (see `relayTransportFetch`).
|
|
9483
|
+
fetch: relayTransportFetch(s.relayUrl),
|
|
9425
9484
|
relay: {
|
|
9426
9485
|
relayUrl: s.relayUrl,
|
|
9427
9486
|
authorAccount: s.account,
|
|
@@ -10511,7 +10570,7 @@ function client(s, relayUrl, nonces, fetch2) {
|
|
|
10511
10570
|
authorProof: s.credential,
|
|
10512
10571
|
deviceSecret: s.deviceSecret,
|
|
10513
10572
|
nonces,
|
|
10514
|
-
fetch: fetch2
|
|
10573
|
+
fetch: fetch2 ?? relayTransportFetch(relayUrl)
|
|
10515
10574
|
});
|
|
10516
10575
|
}
|
|
10517
10576
|
async function createDelegatedContext(s, req, deps = {}) {
|
|
@@ -10598,10 +10657,10 @@ async function foundingExecutor(s, relay, fetch2) {
|
|
|
10598
10657
|
return { executorAccount: described.executorAccount, executorKey };
|
|
10599
10658
|
}
|
|
10600
10659
|
async function attestedNodeKey(relay) {
|
|
10601
|
-
const key = await attemptRelayNodeKey(relay);
|
|
10660
|
+
const key = await attemptRelayNodeKey(relay, { fresh: true });
|
|
10602
10661
|
if (key.kind === "learned") return key.nodeKey;
|
|
10603
10662
|
throw new Error(
|
|
10604
|
-
key.kind === "unavailable" ? "the relay's signing key could not be learned: its attestation did not answer, try again" : "the relay's attestation was refused, so founding through it is not possible
|
|
10663
|
+
key.kind === "unavailable" ? "the relay's signing key could not be learned: its attestation did not answer, try again" : "the relay's attestation was refused, so founding through it is not possible: it is not a signed locked-read-only release"
|
|
10605
10664
|
);
|
|
10606
10665
|
}
|
|
10607
10666
|
var HA_ACCOUNT_NOT_LINKED_MESSAGE = "link this account to your cloud user in the wallet so invitees can find this namespace";
|
|
@@ -12721,6 +12780,7 @@ export {
|
|
|
12721
12780
|
fetchNodeReleaseVersion,
|
|
12722
12781
|
fetchRegistryBundles,
|
|
12723
12782
|
forgetMethodKinds,
|
|
12783
|
+
forgetRelaySealing,
|
|
12724
12784
|
foundDelegatedNamespace,
|
|
12725
12785
|
foundedNamespaceId,
|
|
12726
12786
|
generateAccountRoot,
|
|
@@ -12781,6 +12841,7 @@ export {
|
|
|
12781
12841
|
readRelayMap,
|
|
12782
12842
|
redeemInvitation,
|
|
12783
12843
|
relayForContext,
|
|
12844
|
+
relayTransportFetch,
|
|
12784
12845
|
rememberGroupNamespace,
|
|
12785
12846
|
rememberRelay,
|
|
12786
12847
|
reportDataOf,
|