@calimero-network/mero-js 22.2.0 → 22.4.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/README.md +5 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +295 -21
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +295 -21
- package/dist/index.mjs.map +4 -4
- package/dist/relay/index.d.ts +1 -1
- package/dist/relay/relay-client.d.ts +76 -0
- package/dist/relay/relay-client.js +77 -0
- package/dist/sealed/release.d.ts +16 -4
- package/dist/sealed/release.js +35 -5
- package/dist/warrant/creation-warrant.d.ts +145 -0
- package/dist/warrant/creation-warrant.js +189 -0
- package/dist/warrant/index.d.ts +2 -0
- package/dist/warrant/index.js +1 -0
- package/dist/warrant/warrant.d.ts +5 -0
- package/dist/warrant/warrant.js +5 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -79,6 +79,7 @@ __export(index_exports, {
|
|
|
79
79
|
createSignedReleaseVerifier: () => createSignedReleaseVerifier,
|
|
80
80
|
createTimeoutSignal: () => createTimeoutSignal,
|
|
81
81
|
createUniversalHttpClient: () => createUniversalHttpClient,
|
|
82
|
+
creationInitHash: () => creationInitHash,
|
|
82
83
|
deviceCertPayload: () => deviceCertPayload,
|
|
83
84
|
discoverLocalNodes: () => discoverLocalNodes,
|
|
84
85
|
encodeSignedInvitation: () => encodeSignedInvitation,
|
|
@@ -98,6 +99,7 @@ __export(index_exports, {
|
|
|
98
99
|
nodeEndpoint: () => nodeEndpoint,
|
|
99
100
|
nodeReleaseVersionFromImage: () => nodeReleaseVersionFromImage,
|
|
100
101
|
parseAuthCallback: () => parseAuthCallback,
|
|
102
|
+
parseCreationWarrant: () => parseCreationWarrant,
|
|
101
103
|
probeNodeHealth: () => probeNodeHealth,
|
|
102
104
|
redeemInvitation: () => redeemInvitation,
|
|
103
105
|
requestBodyHash: () => requestBodyHash,
|
|
@@ -105,6 +107,7 @@ __export(index_exports, {
|
|
|
105
107
|
shouldRetain: () => shouldRetain,
|
|
106
108
|
signAccountLink: () => signAccountLink,
|
|
107
109
|
signAccountLogin: () => signAccountLogin,
|
|
110
|
+
signCreationWarrant: () => signCreationWarrant,
|
|
108
111
|
signDeviceCert: () => signDeviceCert,
|
|
109
112
|
signLoginStatement: () => signLoginStatement,
|
|
110
113
|
signMemberJoinOp: () => signMemberJoinOp,
|
|
@@ -2306,11 +2309,11 @@ function u32le(value) {
|
|
|
2306
2309
|
function hex(bytes) {
|
|
2307
2310
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
2308
2311
|
}
|
|
2309
|
-
function fromHex(value,
|
|
2312
|
+
function fromHex(value, label2, expectedBytes) {
|
|
2310
2313
|
const clean = value.trim();
|
|
2311
2314
|
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length !== expectedBytes * 2) {
|
|
2312
2315
|
throw new Error(
|
|
2313
|
-
`${
|
|
2316
|
+
`${label2} must be ${expectedBytes * 2} hex characters, got ${clean.length}`
|
|
2314
2317
|
);
|
|
2315
2318
|
}
|
|
2316
2319
|
const bytes = new Uint8Array(expectedBytes);
|
|
@@ -2319,10 +2322,10 @@ function fromHex(value, label, expectedBytes) {
|
|
|
2319
2322
|
}
|
|
2320
2323
|
return bytes;
|
|
2321
2324
|
}
|
|
2322
|
-
function fromHexUnsized(value,
|
|
2325
|
+
function fromHexUnsized(value, label2) {
|
|
2323
2326
|
const clean = value.trim();
|
|
2324
2327
|
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
|
|
2325
|
-
throw new Error(`${
|
|
2328
|
+
throw new Error(`${label2} must be an even number of hex characters`);
|
|
2326
2329
|
}
|
|
2327
2330
|
const bytes = new Uint8Array(clean.length / 2);
|
|
2328
2331
|
for (let i = 0; i < bytes.length; i += 1) {
|
|
@@ -6636,14 +6639,172 @@ async function signWarrant(input) {
|
|
|
6636
6639
|
)
|
|
6637
6640
|
);
|
|
6638
6641
|
}
|
|
6639
|
-
function citedHeads(heads,
|
|
6642
|
+
function citedHeads(heads, label2) {
|
|
6640
6643
|
const list = heads ?? [];
|
|
6641
6644
|
if (list.length > MAX_CITED_HEADS) {
|
|
6642
6645
|
throw new Error(
|
|
6643
|
-
`${
|
|
6646
|
+
`${label2} cites ${list.length} heads, over the ${MAX_CITED_HEADS} a node accepts`
|
|
6644
6647
|
);
|
|
6645
6648
|
}
|
|
6646
|
-
return list.map((head, i) => fromHex(head, `${
|
|
6649
|
+
return list.map((head, i) => fromHex(head, `${label2}[${i}]`, 32));
|
|
6650
|
+
}
|
|
6651
|
+
|
|
6652
|
+
// src/warrant/creation-warrant.ts
|
|
6653
|
+
var SIGN_DOMAIN3 = new TextEncoder().encode("calimero.context-creation-warrant.v1");
|
|
6654
|
+
var INIT_DOMAIN = new TextEncoder().encode("calimero.context-creation.init.v1");
|
|
6655
|
+
var MAX_LABEL_BYTES = 256;
|
|
6656
|
+
async function creationInitHash(initArgs) {
|
|
6657
|
+
const bytes = new TextEncoder().encode(JSON.stringify(initArgs));
|
|
6658
|
+
return domainHash(INIT_DOMAIN, [bytes]);
|
|
6659
|
+
}
|
|
6660
|
+
async function creationWarrantPreimage(p) {
|
|
6661
|
+
return domainHash(SIGN_DOMAIN3, [
|
|
6662
|
+
p.group,
|
|
6663
|
+
p.seed,
|
|
6664
|
+
p.authorAccount,
|
|
6665
|
+
p.deviceKey,
|
|
6666
|
+
p.executor,
|
|
6667
|
+
p.applicationId,
|
|
6668
|
+
new Uint8Array([p.serviceName === null ? 0 : 1]),
|
|
6669
|
+
p.serviceName ?? new Uint8Array(0),
|
|
6670
|
+
new Uint8Array([p.name === null ? 0 : 1]),
|
|
6671
|
+
p.name ?? new Uint8Array(0),
|
|
6672
|
+
p.initHash,
|
|
6673
|
+
u64le(p.accountHeads.length),
|
|
6674
|
+
...p.accountHeads,
|
|
6675
|
+
u64le(p.governanceFloor.length),
|
|
6676
|
+
...p.governanceFloor,
|
|
6677
|
+
u64le(p.nonce),
|
|
6678
|
+
u64le(p.notAfter)
|
|
6679
|
+
]);
|
|
6680
|
+
}
|
|
6681
|
+
async function signCreationWarrant(input) {
|
|
6682
|
+
const group = fromHex(input.group, "group", 32);
|
|
6683
|
+
const seed = input.seed === void 0 ? crypto.getRandomValues(new Uint8Array(32)) : fromHex(input.seed, "seed", 32);
|
|
6684
|
+
const authorAccount = fromHex(input.authorAccount, "authorAccount", 32);
|
|
6685
|
+
const executor = fromHex(input.executor, "executor", 32);
|
|
6686
|
+
const applicationId = fromHex(input.applicationId, "applicationId", 32);
|
|
6687
|
+
const serviceName = label(input.serviceName, "serviceName");
|
|
6688
|
+
const name = label(input.name, "name");
|
|
6689
|
+
const accountHeads = citedHeads(input.accountHeads, "accountHeads");
|
|
6690
|
+
const governanceFloor = citedHeads(input.governanceFloor, "governanceFloor");
|
|
6691
|
+
const key = await importSigningKey(input.deviceSecret);
|
|
6692
|
+
const deviceKey = await derivePublicKey(input.deviceSecret);
|
|
6693
|
+
const initHash = await creationInitHash(input.initArgs);
|
|
6694
|
+
const preimage = await creationWarrantPreimage({
|
|
6695
|
+
group,
|
|
6696
|
+
seed,
|
|
6697
|
+
authorAccount,
|
|
6698
|
+
deviceKey,
|
|
6699
|
+
executor,
|
|
6700
|
+
applicationId,
|
|
6701
|
+
serviceName,
|
|
6702
|
+
name,
|
|
6703
|
+
initHash,
|
|
6704
|
+
accountHeads,
|
|
6705
|
+
governanceFloor,
|
|
6706
|
+
nonce: input.nonce,
|
|
6707
|
+
notAfter: input.notAfter
|
|
6708
|
+
});
|
|
6709
|
+
const signature = new Uint8Array(
|
|
6710
|
+
await crypto.subtle.sign({ name: "Ed25519" }, key, preimage)
|
|
6711
|
+
);
|
|
6712
|
+
const warrant = hex(
|
|
6713
|
+
concat(
|
|
6714
|
+
group,
|
|
6715
|
+
seed,
|
|
6716
|
+
authorAccount,
|
|
6717
|
+
deviceKey,
|
|
6718
|
+
executor,
|
|
6719
|
+
applicationId,
|
|
6720
|
+
borshOption(serviceName),
|
|
6721
|
+
borshOption(name),
|
|
6722
|
+
initHash,
|
|
6723
|
+
u32le(accountHeads.length),
|
|
6724
|
+
...accountHeads,
|
|
6725
|
+
u32le(governanceFloor.length),
|
|
6726
|
+
...governanceFloor,
|
|
6727
|
+
u64le(input.nonce),
|
|
6728
|
+
u64le(input.notAfter),
|
|
6729
|
+
signature
|
|
6730
|
+
)
|
|
6731
|
+
);
|
|
6732
|
+
return { warrant, seed: hex(seed) };
|
|
6733
|
+
}
|
|
6734
|
+
function parseCreationWarrant(warrant) {
|
|
6735
|
+
const clean = warrant.trim();
|
|
6736
|
+
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
|
|
6737
|
+
throw new Error("creation warrant must be an even number of hex characters");
|
|
6738
|
+
}
|
|
6739
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
6740
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
6741
|
+
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
6742
|
+
}
|
|
6743
|
+
const view = new DataView(bytes.buffer);
|
|
6744
|
+
let o = 0;
|
|
6745
|
+
const take = (n, what) => {
|
|
6746
|
+
if (o + n > bytes.length) {
|
|
6747
|
+
throw new Error(`creation warrant ends inside ${what} (${bytes.length} bytes)`);
|
|
6748
|
+
}
|
|
6749
|
+
const out = bytes.subarray(o, o + n);
|
|
6750
|
+
o += n;
|
|
6751
|
+
return out;
|
|
6752
|
+
};
|
|
6753
|
+
const u32 = (what) => view.getUint32(take(4, what).byteOffset, true);
|
|
6754
|
+
const u64 = (what) => view.getBigUint64(take(8, what).byteOffset, true);
|
|
6755
|
+
const option = (what) => {
|
|
6756
|
+
const tag = take(1, what)[0];
|
|
6757
|
+
if (tag === 0) return null;
|
|
6758
|
+
if (tag !== 1) throw new Error(`${what} has option tag ${tag}, expected 0 or 1`);
|
|
6759
|
+
const len = u32(what);
|
|
6760
|
+
if (len > MAX_LABEL_BYTES) {
|
|
6761
|
+
throw new Error(`${what} is ${len} bytes, over the ${MAX_LABEL_BYTES} a node accepts`);
|
|
6762
|
+
}
|
|
6763
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(take(len, what));
|
|
6764
|
+
};
|
|
6765
|
+
const heads = (what) => {
|
|
6766
|
+
const count = u32(what);
|
|
6767
|
+
if (count > 64) {
|
|
6768
|
+
throw new Error(`${what} cites ${count} heads, over the 64 a node accepts`);
|
|
6769
|
+
}
|
|
6770
|
+
return Array.from({ length: count }, () => hex(take(32, what)));
|
|
6771
|
+
};
|
|
6772
|
+
const fields = {
|
|
6773
|
+
group: hex(take(32, "group")),
|
|
6774
|
+
seed: hex(take(32, "seed")),
|
|
6775
|
+
authorAccount: hex(take(32, "authorAccount")),
|
|
6776
|
+
deviceKey: hex(take(32, "deviceKey")),
|
|
6777
|
+
executor: hex(take(32, "executor")),
|
|
6778
|
+
applicationId: hex(take(32, "applicationId")),
|
|
6779
|
+
serviceName: option("serviceName"),
|
|
6780
|
+
name: option("name"),
|
|
6781
|
+
initHash: hex(take(32, "initHash")),
|
|
6782
|
+
accountHeads: heads("accountHeads"),
|
|
6783
|
+
governanceFloor: heads("governanceFloor"),
|
|
6784
|
+
nonce: u64("nonce"),
|
|
6785
|
+
notAfter: u64("notAfter"),
|
|
6786
|
+
signature: hex(take(64, "signature"))
|
|
6787
|
+
};
|
|
6788
|
+
if (o !== bytes.length) {
|
|
6789
|
+
throw new Error(
|
|
6790
|
+
`creation warrant is ${bytes.length} bytes but its fields account for ${o}`
|
|
6791
|
+
);
|
|
6792
|
+
}
|
|
6793
|
+
return fields;
|
|
6794
|
+
}
|
|
6795
|
+
function label(value, what) {
|
|
6796
|
+
if (value === void 0) return null;
|
|
6797
|
+
const bytes = new TextEncoder().encode(value);
|
|
6798
|
+
if (bytes.length > MAX_LABEL_BYTES) {
|
|
6799
|
+
throw new Error(
|
|
6800
|
+
`${what} is ${bytes.length} UTF-8 bytes, over the ${MAX_LABEL_BYTES} a node accepts`
|
|
6801
|
+
);
|
|
6802
|
+
}
|
|
6803
|
+
return bytes;
|
|
6804
|
+
}
|
|
6805
|
+
function borshOption(bytes) {
|
|
6806
|
+
if (bytes === null) return new Uint8Array([0]);
|
|
6807
|
+
return concat(new Uint8Array([1]), u32le(bytes.length), bytes);
|
|
6647
6808
|
}
|
|
6648
6809
|
|
|
6649
6810
|
// src/relay/relay-client.ts
|
|
@@ -6706,6 +6867,94 @@ var RelayClient = class {
|
|
|
6706
6867
|
);
|
|
6707
6868
|
return { rootHash: body.data.rootHash, returns: body.data.returns ?? null };
|
|
6708
6869
|
}
|
|
6870
|
+
/**
|
|
6871
|
+
* Ask the relay what it can do about creating contexts in `groupId`.
|
|
6872
|
+
*
|
|
6873
|
+
* Pass `author` (an account, hex) to also learn whether that account may
|
|
6874
|
+
* create here — `authorMayCreate` is present only then.
|
|
6875
|
+
*/
|
|
6876
|
+
async describeCreation(groupId, opts = {}) {
|
|
6877
|
+
const query = opts.author ? `?author=${encodeURIComponent(opts.author)}` : "";
|
|
6878
|
+
const body = await this.json(
|
|
6879
|
+
"GET",
|
|
6880
|
+
`/admin-api/groups/${encodeURIComponent(groupId)}/context-intents${query}`
|
|
6881
|
+
);
|
|
6882
|
+
return body.data;
|
|
6883
|
+
}
|
|
6884
|
+
/**
|
|
6885
|
+
* Create a context in a group through the relay, as the author.
|
|
6886
|
+
*
|
|
6887
|
+
* Always asks {@link describeCreation} first — with the author, so both
|
|
6888
|
+
* standing checks happen before anything is signed. A relay without standing
|
|
6889
|
+
* in the group, or an author without `CAN_CREATE_CONTEXT`, is refused here as
|
|
6890
|
+
* an {@link IntentRefusedError} *before* a nonce is taken: the nonce source
|
|
6891
|
+
* is monotonic, and a warrant nobody will spend burns one for nothing.
|
|
6892
|
+
*
|
|
6893
|
+
* The creation warrant's nonce is spent in the new context's per-device
|
|
6894
|
+
* ledger — the same one later `execute` calls in that context draw from — so
|
|
6895
|
+
* it comes from the configured {@link NonceSource} like any other warrant.
|
|
6896
|
+
*
|
|
6897
|
+
* Sealing: nothing here is plaintext-specific. The request goes through the
|
|
6898
|
+
* injected `fetch`, so a `createAttestedSealedFetch` seals it exactly as it
|
|
6899
|
+
* seals `execute`. Whether the relay *accepts* it sealed is the node's call:
|
|
6900
|
+
* a proxy-auth relay only admits sealed requests for routes `merod` serves
|
|
6901
|
+
* without a credential, so `/admin-api/groups/:id/context-intents` must be on
|
|
6902
|
+
* that list on the core side or the request comes back
|
|
6903
|
+
* `403 sealed_route_unguarded`.
|
|
6904
|
+
*/
|
|
6905
|
+
async createContext(input) {
|
|
6906
|
+
const described = await this.describeCreation(input.groupId, {
|
|
6907
|
+
author: this.config.authorAccount
|
|
6908
|
+
});
|
|
6909
|
+
if (!described.canCreateOnBehalf) {
|
|
6910
|
+
throw new IntentRefusedError(
|
|
6911
|
+
`the relay (${described.executorAccount}) has no standing to act for members of group ${described.groupId}; an admin must admit it as a relay or grant it CAN_AUTHOR_ON_BEHALF (checked before signing \u2014 no nonce was spent)`,
|
|
6912
|
+
false,
|
|
6913
|
+
403
|
|
6914
|
+
);
|
|
6915
|
+
}
|
|
6916
|
+
if (described.authorMayCreate === false) {
|
|
6917
|
+
throw new IntentRefusedError(
|
|
6918
|
+
`the author (${this.config.authorAccount}) may not create contexts in group ${described.groupId}; it needs CAN_CREATE_CONTEXT or admin (checked before signing \u2014 no nonce was spent)`,
|
|
6919
|
+
false,
|
|
6920
|
+
403
|
|
6921
|
+
);
|
|
6922
|
+
}
|
|
6923
|
+
const configured = this.config.executorAccount;
|
|
6924
|
+
if (configured && configured.toLowerCase() !== described.executorAccount.toLowerCase()) {
|
|
6925
|
+
throw new Error(
|
|
6926
|
+
`configured executorAccount ${configured} is not the relay's account ${described.executorAccount}; a warrant naming it would be unspendable`
|
|
6927
|
+
);
|
|
6928
|
+
}
|
|
6929
|
+
const executor = described.executorAccount;
|
|
6930
|
+
this.executorAccount = executor;
|
|
6931
|
+
const initArgs = input.initArgs ?? {};
|
|
6932
|
+
const nonce2 = await this.config.nonces.next();
|
|
6933
|
+
const ttl = this.config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
6934
|
+
const { warrant } = await signCreationWarrant({
|
|
6935
|
+
group: input.groupId,
|
|
6936
|
+
seed: input.seed,
|
|
6937
|
+
authorAccount: this.config.authorAccount,
|
|
6938
|
+
executor,
|
|
6939
|
+
applicationId: input.applicationId,
|
|
6940
|
+
serviceName: input.serviceName,
|
|
6941
|
+
name: input.name,
|
|
6942
|
+
initArgs,
|
|
6943
|
+
nonce: nonce2,
|
|
6944
|
+
notAfter: BigInt(Math.floor(Date.now() / 1e3)) + BigInt(ttl),
|
|
6945
|
+
deviceSecret: this.config.deviceSecret
|
|
6946
|
+
});
|
|
6947
|
+
const body = await this.json(
|
|
6948
|
+
"POST",
|
|
6949
|
+
`/admin-api/groups/${encodeURIComponent(input.groupId)}/context-intents`,
|
|
6950
|
+
{ warrant, authorProof: this.config.authorProof, initArgs }
|
|
6951
|
+
);
|
|
6952
|
+
return {
|
|
6953
|
+
contextId: body.data.contextId,
|
|
6954
|
+
groupId: body.data.groupId,
|
|
6955
|
+
memberPublicKey: body.data.memberPublicKey
|
|
6956
|
+
};
|
|
6957
|
+
}
|
|
6709
6958
|
async json(method, path, body) {
|
|
6710
6959
|
const headers = { Accept: "application/json" };
|
|
6711
6960
|
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
@@ -7405,8 +7654,8 @@ var REGISTERS = ["mrtd", "rtmr0", "rtmr1", "rtmr2", "rtmr3"];
|
|
|
7405
7654
|
function createQuoteVerifier(options) {
|
|
7406
7655
|
const allowedMrtd = measurements(options.allowedMrtd ?? [], "allowedMrtd");
|
|
7407
7656
|
const allowedImages = (options.allowedMeasurements ?? []).map((image, index) => {
|
|
7408
|
-
const
|
|
7409
|
-
return REGISTERS.map((register) => measurements([image?.[register] ?? ""], `${
|
|
7657
|
+
const label2 = `allowedMeasurements[${index}]`;
|
|
7658
|
+
return REGISTERS.map((register) => measurements([image?.[register] ?? ""], `${label2}.${register}`)[0]).join();
|
|
7410
7659
|
});
|
|
7411
7660
|
const allowedRtmr = [
|
|
7412
7661
|
measurements(options.allowedRtmr0 ?? [], "allowedRtmr0"),
|
|
@@ -7475,11 +7724,11 @@ function createQuoteVerifier(options) {
|
|
|
7475
7724
|
};
|
|
7476
7725
|
return Object.assign(verifier, { includeCollateral: true });
|
|
7477
7726
|
}
|
|
7478
|
-
function measurements(values,
|
|
7727
|
+
function measurements(values, label2) {
|
|
7479
7728
|
return values.map((value) => {
|
|
7480
7729
|
const normalized = value.trim().toLowerCase();
|
|
7481
7730
|
if (!MEASUREMENT_HEX.test(normalized)) {
|
|
7482
|
-
throw new Error(`${
|
|
7731
|
+
throw new Error(`${label2} holds ${JSON.stringify(value)}, which is not a 48-byte hex measurement`);
|
|
7483
7732
|
}
|
|
7484
7733
|
return normalized;
|
|
7485
7734
|
});
|
|
@@ -7965,8 +8214,24 @@ function nodeReleaseVersionFromImage(osImage) {
|
|
|
7965
8214
|
return `${Number(match[1])}.${Number(match[2])}.${Number(match[3])}`;
|
|
7966
8215
|
}
|
|
7967
8216
|
async function fetchNodeReleaseVersion(baseUrl, options = {}) {
|
|
7968
|
-
const
|
|
7969
|
-
|
|
8217
|
+
const version = await readNodeReleaseVersion(baseUrl, options.fetch ?? fetch);
|
|
8218
|
+
if (version === void 0) {
|
|
8219
|
+
throw new Error(
|
|
8220
|
+
`${infoUrl(baseUrl)} was refused unsealed: the node requires sealing and is too old to name its release before a session exists. Name the release it runs yourself (createSignedReleaseSealedFetch's \`releaseVersion\`), or upgrade the node`
|
|
8221
|
+
);
|
|
8222
|
+
}
|
|
8223
|
+
return version;
|
|
8224
|
+
}
|
|
8225
|
+
function infoUrl(baseUrl) {
|
|
8226
|
+
return `${baseUrl.replace(/\/+$/, "")}/admin-api/tee/info`;
|
|
8227
|
+
}
|
|
8228
|
+
async function readNodeReleaseVersion(baseUrl, givenFetch) {
|
|
8229
|
+
const url = infoUrl(baseUrl);
|
|
8230
|
+
const response = await givenFetch(url, { headers: { accept: "application/json" } });
|
|
8231
|
+
if (response.status === 403) {
|
|
8232
|
+
const code = await response.json().then((body) => body?.error?.code).catch(() => void 0);
|
|
8233
|
+
if (code === "sealed_required") return void 0;
|
|
8234
|
+
}
|
|
7970
8235
|
if (!response.ok) throw new Error(`Fetching ${url} failed: HTTP ${response.status}`);
|
|
7971
8236
|
let osImage;
|
|
7972
8237
|
try {
|
|
@@ -8013,10 +8278,19 @@ function createSignedReleaseVerifier(options) {
|
|
|
8013
8278
|
return Object.assign(verifier, { includeCollateral: true });
|
|
8014
8279
|
}
|
|
8015
8280
|
function createSignedReleaseSealedFetch(options) {
|
|
8016
|
-
const {
|
|
8281
|
+
const {
|
|
8282
|
+
baseUrl,
|
|
8283
|
+
releaseSource,
|
|
8284
|
+
releaseVersion: fallbackVersion,
|
|
8285
|
+
applicationId,
|
|
8286
|
+
applicationHash,
|
|
8287
|
+
fetch: givenFetch,
|
|
8288
|
+
...verifierOptions
|
|
8289
|
+
} = options;
|
|
8290
|
+
if (fallbackVersion !== void 0) releaseVersion(fallbackVersion, "releaseVersion");
|
|
8017
8291
|
const baseFetch = givenFetch ?? ((input, init) => fetch(input, init));
|
|
8018
8292
|
const release = async () => {
|
|
8019
|
-
const version = await fetchNodeReleaseVersion(baseUrl, { fetch: baseFetch });
|
|
8293
|
+
const version = fallbackVersion === void 0 ? await fetchNodeReleaseVersion(baseUrl, { fetch: baseFetch }) : await readNodeReleaseVersion(baseUrl, baseFetch) ?? fallbackVersion;
|
|
8020
8294
|
return typeof releaseSource === "function" ? releaseSource({ baseUrl, version, fetch: baseFetch }) : fetchNodeRelease(cloudNodeReleaseUrl(releaseSource ?? DEFAULT_RELEASE_MIRROR, version), { fetch: baseFetch });
|
|
8021
8295
|
};
|
|
8022
8296
|
return createAttestedSealedFetch({
|
|
@@ -8076,18 +8350,18 @@ var ROOT_OP = {
|
|
|
8076
8350
|
NamespaceCreatedV2: 9,
|
|
8077
8351
|
MemberJoinedViaTeeAttestation: 10
|
|
8078
8352
|
};
|
|
8079
|
-
function bytes32(value,
|
|
8353
|
+
function bytes32(value, label2) {
|
|
8080
8354
|
if (value.length !== 32) {
|
|
8081
|
-
throw new Error(`${
|
|
8355
|
+
throw new Error(`${label2} must be 32 bytes, got ${value.length}`);
|
|
8082
8356
|
}
|
|
8083
8357
|
return new Uint8Array(value);
|
|
8084
8358
|
}
|
|
8085
|
-
function optionalBytes32(value,
|
|
8359
|
+
function optionalBytes32(value, label2) {
|
|
8086
8360
|
if (value === null || value === void 0) {
|
|
8087
8361
|
return new Uint8Array([0]);
|
|
8088
8362
|
}
|
|
8089
8363
|
if (value.length !== 32) {
|
|
8090
|
-
throw new Error(`${
|
|
8364
|
+
throw new Error(`${label2} must be 32 bytes, got ${value.length}`);
|
|
8091
8365
|
}
|
|
8092
8366
|
return concat(new Uint8Array([1]), new Uint8Array(value));
|
|
8093
8367
|
}
|
|
@@ -8169,7 +8443,7 @@ async function signMemberJoinOp(input) {
|
|
|
8169
8443
|
}
|
|
8170
8444
|
|
|
8171
8445
|
// src/login/login.ts
|
|
8172
|
-
var
|
|
8446
|
+
var SIGN_DOMAIN4 = new TextEncoder().encode("calimero.auth.login.v1");
|
|
8173
8447
|
var AUDIENCE_TAG = {
|
|
8174
8448
|
webOrigin: 0,
|
|
8175
8449
|
codeSigningId: 1,
|
|
@@ -8208,7 +8482,7 @@ async function signLoginStatement(input) {
|
|
|
8208
8482
|
const deviceKey = await derivePublicKey(input.deviceSecret);
|
|
8209
8483
|
const issuedAt = u64le(input.issuedAt);
|
|
8210
8484
|
const expiresAt = u64le(input.expiresAt);
|
|
8211
|
-
const preimage = await domainHash(
|
|
8485
|
+
const preimage = await domainHash(SIGN_DOMAIN4, [
|
|
8212
8486
|
node,
|
|
8213
8487
|
audienceSigningBytes(input.audience),
|
|
8214
8488
|
challenge,
|