@tinycloud/sdk-core 3.2.2 → 3.2.3
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/{credential-admission-1EOQgdzY.d.cts → credential-admission-CaWVn8yO.d.cts} +6 -5
- package/dist/{credential-admission-CJ1ZPqcx.d.ts → credential-admission-CqXwBvDS.d.ts} +6 -5
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +29 -29
- package/dist/delegations/index.d.ts +29 -29
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +274 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -15
- package/dist/index.d.ts +41 -15
- package/dist/index.js +272 -55
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +1 -1
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.d.cts +2 -2
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +1 -1
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-D-IMys0b.d.cts → recipient-types.schema-D7YiY246.d.cts} +177 -177
- package/dist/{recipient-types.schema-D-IMys0b.d.ts → recipient-types.schema-D7YiY246.d.ts} +177 -177
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -408,6 +408,7 @@ __export(index_exports, {
|
|
|
408
408
|
parseShareArtifact: () => parseShareArtifact,
|
|
409
409
|
parseShareUrl: () => parseShareUrl,
|
|
410
410
|
parseSignedCompactUcanAttenuation: () => parseSignedCompactUcanAttenuation,
|
|
411
|
+
parseSignedSiweCacao: () => parseSignedSiweCacao,
|
|
411
412
|
parseSpaceUri: () => parseSpaceUri,
|
|
412
413
|
parseStorageRejection: () => import_sdk_services9.parseStorageRejection,
|
|
413
414
|
parseStorageStatus: () => import_sdk_services9.parseStorageStatus,
|
|
@@ -1545,12 +1546,12 @@ var Decoder = class {
|
|
|
1545
1546
|
this.prefixCodePoint = prefixCodePoint;
|
|
1546
1547
|
this.baseDecode = baseDecode;
|
|
1547
1548
|
}
|
|
1548
|
-
decode(
|
|
1549
|
-
if (typeof
|
|
1550
|
-
if (
|
|
1551
|
-
throw Error(`Unable to decode multibase string ${JSON.stringify(
|
|
1549
|
+
decode(text3) {
|
|
1550
|
+
if (typeof text3 === "string") {
|
|
1551
|
+
if (text3.codePointAt(0) !== this.prefixCodePoint) {
|
|
1552
|
+
throw Error(`Unable to decode multibase string ${JSON.stringify(text3)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`);
|
|
1552
1553
|
}
|
|
1553
|
-
return this.baseDecode(
|
|
1554
|
+
return this.baseDecode(text3.slice(this.prefix.length));
|
|
1554
1555
|
} else {
|
|
1555
1556
|
throw Error("Can only multibase decode strings");
|
|
1556
1557
|
}
|
|
@@ -1614,7 +1615,7 @@ function baseX({ name: name2, prefix, alphabet: alphabet2 }) {
|
|
|
1614
1615
|
prefix,
|
|
1615
1616
|
name: name2,
|
|
1616
1617
|
encode: encode5,
|
|
1617
|
-
decode: (
|
|
1618
|
+
decode: (text3) => coerce(decode7(text3))
|
|
1618
1619
|
});
|
|
1619
1620
|
}
|
|
1620
1621
|
function decode(string2, alphabetIdx, bitsPerChar, name2) {
|
|
@@ -4719,7 +4720,7 @@ function parseSignedCompactUcanAttenuation(input, expectedCid) {
|
|
|
4719
4720
|
throw new Error("compact UCAN signed audience is missing");
|
|
4720
4721
|
const cid2 = CID.createV1(85, create(30, (0, import_blake3.blake3)(new TextEncoder().encode(input)))).toString();
|
|
4721
4722
|
if (expectedCid !== void 0 && cid2 !== expectedCid) throw new Error("compact UCAN CID does not match exact Authorization bytes");
|
|
4722
|
-
return { cid: cid2, payload: { att, aud: payloadValue.aud } };
|
|
4723
|
+
return { cid: cid2, payload: { att, aud: payloadValue.aud, iss: payloadValue.iss } };
|
|
4723
4724
|
}
|
|
4724
4725
|
function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
4725
4726
|
const parsed = parseCompactUcanAuthorization(authorization);
|
|
@@ -4888,9 +4889,9 @@ function policyV2DigestHex(input) {
|
|
|
4888
4889
|
);
|
|
4889
4890
|
}
|
|
4890
4891
|
function date(value, label) {
|
|
4891
|
-
const
|
|
4892
|
-
if (!Number.isFinite(Date.parse(
|
|
4893
|
-
return
|
|
4892
|
+
const text3 = nonEmpty(value, label);
|
|
4893
|
+
if (!Number.isFinite(Date.parse(text3))) throw new Error(`${label} is invalid`);
|
|
4894
|
+
return text3;
|
|
4894
4895
|
}
|
|
4895
4896
|
function rfc3339Seconds2(value) {
|
|
4896
4897
|
return new Date(Math.floor(value.getTime() / 1e3) * 1e3).toISOString().replace(/\.000Z$/, "Z");
|
|
@@ -8843,64 +8844,64 @@ function canonicalJson(value) {
|
|
|
8843
8844
|
}
|
|
8844
8845
|
throw new ShareEnvelopeError("invalid-envelope", "unsupported JSON value");
|
|
8845
8846
|
}
|
|
8846
|
-
function skipWhitespace(
|
|
8847
|
+
function skipWhitespace(text3, start) {
|
|
8847
8848
|
let index = start;
|
|
8848
|
-
while (/\s/.test(
|
|
8849
|
+
while (/\s/.test(text3[index] ?? "")) index += 1;
|
|
8849
8850
|
return index;
|
|
8850
8851
|
}
|
|
8851
|
-
function scanJsonValue(
|
|
8852
|
-
let index = skipWhitespace(
|
|
8853
|
-
const first =
|
|
8852
|
+
function scanJsonValue(text3, start) {
|
|
8853
|
+
let index = skipWhitespace(text3, start);
|
|
8854
|
+
const first = text3[index];
|
|
8854
8855
|
if (first === '"') {
|
|
8855
8856
|
index += 1;
|
|
8856
|
-
while (index <
|
|
8857
|
-
if (
|
|
8858
|
-
else if (
|
|
8857
|
+
while (index < text3.length) {
|
|
8858
|
+
if (text3[index] === "\\") index += 2;
|
|
8859
|
+
else if (text3[index++] === '"') return index;
|
|
8859
8860
|
}
|
|
8860
8861
|
throw new ShareEnvelopeError("invalid-envelope", "unterminated JSON string");
|
|
8861
8862
|
}
|
|
8862
8863
|
if (first === "{") {
|
|
8863
8864
|
const keys = /* @__PURE__ */ new Set();
|
|
8864
|
-
index = skipWhitespace(
|
|
8865
|
-
if (
|
|
8866
|
-
while (index <
|
|
8867
|
-
index = skipWhitespace(
|
|
8868
|
-
if (
|
|
8865
|
+
index = skipWhitespace(text3, index + 1);
|
|
8866
|
+
if (text3[index] === "}") return index + 1;
|
|
8867
|
+
while (index < text3.length) {
|
|
8868
|
+
index = skipWhitespace(text3, index);
|
|
8869
|
+
if (text3[index] !== '"') throw new ShareEnvelopeError("invalid-envelope", "object key must be a string");
|
|
8869
8870
|
const keyStart = index;
|
|
8870
|
-
index = scanJsonValue(
|
|
8871
|
-
const key = JSON.parse(
|
|
8871
|
+
index = scanJsonValue(text3, index);
|
|
8872
|
+
const key = JSON.parse(text3.slice(keyStart, index));
|
|
8872
8873
|
if (keys.has(key)) throw new ShareEnvelopeError("invalid-envelope", `duplicate JSON key ${key}`);
|
|
8873
8874
|
keys.add(key);
|
|
8874
|
-
index = skipWhitespace(
|
|
8875
|
-
if (
|
|
8876
|
-
index = scanJsonValue(
|
|
8877
|
-
index = skipWhitespace(
|
|
8878
|
-
if (
|
|
8879
|
-
if (
|
|
8875
|
+
index = skipWhitespace(text3, index);
|
|
8876
|
+
if (text3[index++] !== ":") throw new ShareEnvelopeError("invalid-envelope", "missing object colon");
|
|
8877
|
+
index = scanJsonValue(text3, index);
|
|
8878
|
+
index = skipWhitespace(text3, index);
|
|
8879
|
+
if (text3[index] === "}") return index + 1;
|
|
8880
|
+
if (text3[index++] !== ",") throw new ShareEnvelopeError("invalid-envelope", "invalid object separator");
|
|
8880
8881
|
}
|
|
8881
8882
|
throw new ShareEnvelopeError("invalid-envelope", "unterminated JSON object");
|
|
8882
8883
|
}
|
|
8883
8884
|
if (first === "[") {
|
|
8884
|
-
index = skipWhitespace(
|
|
8885
|
-
if (
|
|
8886
|
-
while (index <
|
|
8887
|
-
index = scanJsonValue(
|
|
8888
|
-
index = skipWhitespace(
|
|
8889
|
-
if (
|
|
8890
|
-
if (
|
|
8885
|
+
index = skipWhitespace(text3, index + 1);
|
|
8886
|
+
if (text3[index] === "]") return index + 1;
|
|
8887
|
+
while (index < text3.length) {
|
|
8888
|
+
index = scanJsonValue(text3, index);
|
|
8889
|
+
index = skipWhitespace(text3, index);
|
|
8890
|
+
if (text3[index] === "]") return index + 1;
|
|
8891
|
+
if (text3[index++] !== ",") throw new ShareEnvelopeError("invalid-envelope", "invalid array separator");
|
|
8891
8892
|
}
|
|
8892
8893
|
throw new ShareEnvelopeError("invalid-envelope", "unterminated JSON array");
|
|
8893
8894
|
}
|
|
8894
|
-
const match =
|
|
8895
|
+
const match = text3.slice(index).match(/^(?:true|false|null|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)/);
|
|
8895
8896
|
if (!match) throw new ShareEnvelopeError("invalid-envelope", "invalid JSON value");
|
|
8896
8897
|
return index + match[0].length;
|
|
8897
8898
|
}
|
|
8898
|
-
function parseCanonicalJson(
|
|
8899
|
+
function parseCanonicalJson(text3) {
|
|
8899
8900
|
try {
|
|
8900
|
-
const end = scanJsonValue(
|
|
8901
|
-
if (skipWhitespace(
|
|
8902
|
-
const parsed = JSON.parse(
|
|
8903
|
-
if (canonicalJson(parsed) !==
|
|
8901
|
+
const end = scanJsonValue(text3, 0);
|
|
8902
|
+
if (skipWhitespace(text3, end) !== text3.length) throw new Error("trailing JSON");
|
|
8903
|
+
const parsed = JSON.parse(text3);
|
|
8904
|
+
if (canonicalJson(parsed) !== text3) throw new Error("non-canonical JSON");
|
|
8904
8905
|
return parsed;
|
|
8905
8906
|
} catch (error) {
|
|
8906
8907
|
if (error instanceof ShareEnvelopeError) throw error;
|
|
@@ -12329,8 +12330,8 @@ async function createPolicyEnforcementDelegation(input) {
|
|
|
12329
12330
|
return { cid: cid(dagCborBytes), dagCbor: b64(dagCborBytes), issuerDid: input.shareKey.did, audienceDid: input.enforcerDid, facts, signature };
|
|
12330
12331
|
}
|
|
12331
12332
|
async function canonicalOwnerSharePolicy(policy) {
|
|
12332
|
-
const
|
|
12333
|
-
const policyBytes = new TextEncoder().encode(
|
|
12333
|
+
const text3 = canonicalizeSignedObjectUnsigned({ domain: POLICY_DOMAIN, policy });
|
|
12334
|
+
const policyBytes = new TextEncoder().encode(text3);
|
|
12334
12335
|
return { bytes: policyBytes, cid: cid(policyBytes), digest: digest3(policyBytes) };
|
|
12335
12336
|
}
|
|
12336
12337
|
function computeOwnerShareRegistrationCid(registration) {
|
|
@@ -12562,6 +12563,222 @@ var SenderShareStore = class {
|
|
|
12562
12563
|
var import_share_sdk = require("@tinycloud/share-sdk");
|
|
12563
12564
|
var import_share_sdk2 = require("@tinycloud/share-sdk");
|
|
12564
12565
|
|
|
12566
|
+
// src/delegations/cacao.ts
|
|
12567
|
+
var import_blake34 = require("@noble/hashes/blake3");
|
|
12568
|
+
var import_siwe2 = require("siwe");
|
|
12569
|
+
var import_viem5 = require("viem");
|
|
12570
|
+
var MAX_CACAO_BYTES = 64 * 1024;
|
|
12571
|
+
var MAX_CBOR_DEPTH = 64;
|
|
12572
|
+
var RECAP_PREFIX = "urn:recap:";
|
|
12573
|
+
var RECAP_STATEMENT = "I further authorize the stated URI to perform the following actions on my behalf:";
|
|
12574
|
+
function compareKeys(left, right) {
|
|
12575
|
+
if (left.length !== right.length) return left.length - right.length;
|
|
12576
|
+
for (let index = 0; index < left.length; index++) {
|
|
12577
|
+
if (left[index] !== right[index]) return left[index] - right[index];
|
|
12578
|
+
}
|
|
12579
|
+
return 0;
|
|
12580
|
+
}
|
|
12581
|
+
function decodeDagCbor(bytes2) {
|
|
12582
|
+
let offset = 0;
|
|
12583
|
+
const view = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
12584
|
+
const take = (length2) => {
|
|
12585
|
+
if (length2 > bytes2.length - offset) throw new Error("CBOR input ended early");
|
|
12586
|
+
return bytes2.subarray(offset, offset += length2);
|
|
12587
|
+
};
|
|
12588
|
+
const read2 = (depth) => {
|
|
12589
|
+
if (depth > MAX_CBOR_DEPTH) throw new Error(`CBOR nesting exceeds ${MAX_CBOR_DEPTH} levels`);
|
|
12590
|
+
const [initial] = take(1);
|
|
12591
|
+
const major = initial >> 5;
|
|
12592
|
+
const info = initial & 31;
|
|
12593
|
+
if (major === 7) {
|
|
12594
|
+
if (info === 20) return false;
|
|
12595
|
+
if (info === 21) return true;
|
|
12596
|
+
if (info === 22) return null;
|
|
12597
|
+
throw new Error("CBOR floats and other simple values are not part of a CACAO");
|
|
12598
|
+
}
|
|
12599
|
+
if (major === 6) throw new Error("CBOR tags are not part of a CACAO");
|
|
12600
|
+
let argument;
|
|
12601
|
+
if (info < 24) argument = info;
|
|
12602
|
+
else if (info === 24) argument = take(1)[0];
|
|
12603
|
+
else if (info === 25) argument = view.getUint16(take(2).byteOffset - bytes2.byteOffset);
|
|
12604
|
+
else if (info === 26) argument = view.getUint32(take(4).byteOffset - bytes2.byteOffset);
|
|
12605
|
+
else if (info === 27) {
|
|
12606
|
+
const value2 = view.getBigUint64(take(8).byteOffset - bytes2.byteOffset);
|
|
12607
|
+
if (value2 > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error("CBOR integer is too large");
|
|
12608
|
+
argument = Number(value2);
|
|
12609
|
+
} else throw new Error("CBOR indefinite lengths are not DAG-CBOR");
|
|
12610
|
+
switch (major) {
|
|
12611
|
+
case 0:
|
|
12612
|
+
return argument;
|
|
12613
|
+
case 1:
|
|
12614
|
+
return -1 - argument;
|
|
12615
|
+
case 2:
|
|
12616
|
+
return take(argument).slice();
|
|
12617
|
+
case 3:
|
|
12618
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(take(argument));
|
|
12619
|
+
case 4: {
|
|
12620
|
+
if (argument > bytes2.length - offset) throw new Error("CBOR input ended early");
|
|
12621
|
+
const items = [];
|
|
12622
|
+
for (let index = 0; index < argument; index++) items.push(read2(depth + 1));
|
|
12623
|
+
return items;
|
|
12624
|
+
}
|
|
12625
|
+
default: {
|
|
12626
|
+
if (argument > bytes2.length - offset) throw new Error("CBOR input ended early");
|
|
12627
|
+
const map2 = /* @__PURE__ */ Object.create(null);
|
|
12628
|
+
for (let index = 0; index < argument; index++) {
|
|
12629
|
+
const key = read2(depth + 1);
|
|
12630
|
+
if (typeof key !== "string") throw new Error("CBOR map keys must be strings");
|
|
12631
|
+
if (key === "__proto__") throw new Error("CBOR map key __proto__ is not allowed");
|
|
12632
|
+
if (Object.prototype.hasOwnProperty.call(map2, key)) throw new Error(`CBOR map has a duplicate key ${JSON.stringify(key)}`);
|
|
12633
|
+
map2[key] = read2(depth + 1);
|
|
12634
|
+
}
|
|
12635
|
+
return map2;
|
|
12636
|
+
}
|
|
12637
|
+
}
|
|
12638
|
+
};
|
|
12639
|
+
const value = read2(0);
|
|
12640
|
+
if (offset !== bytes2.length) throw new Error("CBOR input has trailing bytes");
|
|
12641
|
+
return value;
|
|
12642
|
+
}
|
|
12643
|
+
function encodeDagCbor(value) {
|
|
12644
|
+
const output = [];
|
|
12645
|
+
const head = (major, argument) => {
|
|
12646
|
+
if (argument < 24) output.push(major << 5 | argument);
|
|
12647
|
+
else if (argument < 256) output.push(major << 5 | 24, argument);
|
|
12648
|
+
else if (argument < 65536) output.push(major << 5 | 25, argument >> 8, argument & 255);
|
|
12649
|
+
else if (argument < 4294967296) output.push(major << 5 | 26, ...[24, 16, 8, 0].map((shift) => argument >>> shift & 255));
|
|
12650
|
+
else output.push(major << 5 | 27, ...[56n, 48n, 40n, 32n, 24n, 16n, 8n, 0n].map((shift) => Number(BigInt(argument) >> shift & 0xffn)));
|
|
12651
|
+
};
|
|
12652
|
+
const write = (item) => {
|
|
12653
|
+
if (item === null) output.push(246);
|
|
12654
|
+
else if (item === false) output.push(244);
|
|
12655
|
+
else if (item === true) output.push(245);
|
|
12656
|
+
else if (typeof item === "number" && Number.isSafeInteger(item)) {
|
|
12657
|
+
if (item >= 0) head(0, item);
|
|
12658
|
+
else head(1, -1 - item);
|
|
12659
|
+
} else if (typeof item === "string") {
|
|
12660
|
+
const encoded = new TextEncoder().encode(item);
|
|
12661
|
+
head(3, encoded.length);
|
|
12662
|
+
output.push(...encoded);
|
|
12663
|
+
} else if (item instanceof Uint8Array) {
|
|
12664
|
+
head(2, item.length);
|
|
12665
|
+
output.push(...item);
|
|
12666
|
+
} else if (Array.isArray(item)) {
|
|
12667
|
+
head(4, item.length);
|
|
12668
|
+
item.forEach(write);
|
|
12669
|
+
} else if (typeof item === "object") {
|
|
12670
|
+
const entries = Object.keys(item).map((key) => [new TextEncoder().encode(key), item[key]]);
|
|
12671
|
+
entries.sort(([left], [right]) => compareKeys(left, right));
|
|
12672
|
+
head(5, entries.length);
|
|
12673
|
+
for (const [key, entry] of entries) {
|
|
12674
|
+
head(3, key.length);
|
|
12675
|
+
output.push(...key);
|
|
12676
|
+
write(entry);
|
|
12677
|
+
}
|
|
12678
|
+
} else throw new Error("value is not DAG-CBOR encodable");
|
|
12679
|
+
};
|
|
12680
|
+
write(value);
|
|
12681
|
+
return Uint8Array.from(output);
|
|
12682
|
+
}
|
|
12683
|
+
function map(value, label, keys, optional = []) {
|
|
12684
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || value instanceof Uint8Array) throw new Error(`CACAO ${label} must be a map`);
|
|
12685
|
+
const entries = value;
|
|
12686
|
+
for (const key of Object.keys(entries)) {
|
|
12687
|
+
if (!keys.includes(key) && !optional.includes(key)) throw new Error(`CACAO ${label} has unknown field ${JSON.stringify(key)}`);
|
|
12688
|
+
}
|
|
12689
|
+
for (const key of keys) if (!(key in entries)) throw new Error(`CACAO ${label} is missing ${key}`);
|
|
12690
|
+
return entries;
|
|
12691
|
+
}
|
|
12692
|
+
function text2(value, label) {
|
|
12693
|
+
if (typeof value !== "string" || value.length === 0) throw new Error(`CACAO ${label} must be a non-empty string`);
|
|
12694
|
+
return value;
|
|
12695
|
+
}
|
|
12696
|
+
function reCapStatement(attenuation) {
|
|
12697
|
+
var _a3;
|
|
12698
|
+
let index = 0;
|
|
12699
|
+
let lines = "";
|
|
12700
|
+
for (const resource of Object.keys(attenuation).sort()) {
|
|
12701
|
+
const namespaces = /* @__PURE__ */ Object.create(null);
|
|
12702
|
+
for (const ability of Object.keys(attenuation[resource]).sort()) {
|
|
12703
|
+
const slash = ability.indexOf("/");
|
|
12704
|
+
if (slash <= 0) throw new Error("ReCap ability must be namespace/name");
|
|
12705
|
+
(namespaces[_a3 = ability.slice(0, slash)] ?? (namespaces[_a3] = [])).push(ability.slice(slash + 1));
|
|
12706
|
+
}
|
|
12707
|
+
for (const namespace of Object.keys(namespaces).sort()) {
|
|
12708
|
+
lines += ` (${++index}) '${namespace}': ${namespaces[namespace].map((name2) => `'${name2}'`).join(", ")} for '${resource}'.`;
|
|
12709
|
+
}
|
|
12710
|
+
}
|
|
12711
|
+
return `${RECAP_STATEMENT}${lines}`;
|
|
12712
|
+
}
|
|
12713
|
+
function reCapAttenuation(resource) {
|
|
12714
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12715
|
+
const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(decodeBase64Url(resource.slice(RECAP_PREFIX.length))));
|
|
12716
|
+
if (!isObject(parsed) || !("att" in parsed) || !isObject(parsed.att)) throw new Error("ReCap attenuation must be an object");
|
|
12717
|
+
const attenuation = /* @__PURE__ */ Object.create(null);
|
|
12718
|
+
for (const [target, abilities] of Object.entries(parsed.att)) {
|
|
12719
|
+
if (target === "__proto__" || !isObject(abilities) || Object.keys(abilities).length === 0) throw new Error("ReCap resource must map to abilities");
|
|
12720
|
+
const copy = /* @__PURE__ */ Object.create(null);
|
|
12721
|
+
for (const [ability, caveats] of Object.entries(abilities)) {
|
|
12722
|
+
if (ability === "__proto__" || !/^[^/]+\/[^/]/.test(ability)) throw new Error("ReCap ability must be namespace/name");
|
|
12723
|
+
if (!Array.isArray(caveats) || caveats.length === 0 || !caveats.every(isObject)) throw new Error("ReCap caveats must be a non-empty array of objects");
|
|
12724
|
+
copy[ability] = caveats;
|
|
12725
|
+
}
|
|
12726
|
+
attenuation[target] = copy;
|
|
12727
|
+
}
|
|
12728
|
+
return attenuation;
|
|
12729
|
+
}
|
|
12730
|
+
async function parseSignedSiweCacao(authorization, expectedCid) {
|
|
12731
|
+
if (authorization.length > Math.ceil(MAX_CACAO_BYTES / 3) * 4 + 2) throw new Error(`CACAO exceeds ${MAX_CACAO_BYTES} bytes`);
|
|
12732
|
+
if (!/^[A-Za-z0-9_-]+={0,2}$/.test(authorization)) throw new Error("CACAO must be base64url DAG-CBOR");
|
|
12733
|
+
const bytes2 = decodeBase64Url(authorization.replace(/=+$/, ""));
|
|
12734
|
+
if (bytes2.length > MAX_CACAO_BYTES) throw new Error(`CACAO exceeds ${MAX_CACAO_BYTES} bytes`);
|
|
12735
|
+
const cid2 = CID.createV1(85, create(30, (0, import_blake34.blake3)(bytes2))).toString();
|
|
12736
|
+
if (expectedCid !== void 0 && cid2 !== expectedCid) throw new Error("CACAO CID does not match exact Authorization bytes");
|
|
12737
|
+
const decoded = decodeDagCbor(bytes2);
|
|
12738
|
+
const canonical = encodeDagCbor(decoded);
|
|
12739
|
+
if (canonical.length !== bytes2.length || canonical.some((byte, index) => byte !== bytes2[index])) throw new Error("CACAO is not canonical DAG-CBOR");
|
|
12740
|
+
const cacao = map(decoded, "envelope", ["h", "p", "s"]);
|
|
12741
|
+
if (map(cacao.h, "header", ["t"]).t !== "eip4361") throw new Error("CACAO header must be eip4361");
|
|
12742
|
+
const signature = map(cacao.s, "signature", ["t", "s"]);
|
|
12743
|
+
if (signature.t !== "eip191" || !(signature.s instanceof Uint8Array) || signature.s.length !== 65) throw new Error("CACAO signature must be a 65-byte eip191 signature");
|
|
12744
|
+
const payload = map(cacao.p, "payload", ["domain", "iss", "aud", "version", "nonce", "iat"], ["exp", "nbf", "statement", "requestId", "resources"]);
|
|
12745
|
+
if (payload.version !== 1) throw new Error("CACAO SIWE version must be the integer 1");
|
|
12746
|
+
const issuer = text2(payload.iss, "iss");
|
|
12747
|
+
const pkh = /^did:pkh:eip155:([1-9]\d*):(0x[0-9a-fA-F]{40})$/.exec(issuer);
|
|
12748
|
+
const chainId = Number(pkh?.[1]);
|
|
12749
|
+
if (pkh === null || !Number.isSafeInteger(chainId) || String(chainId) !== pkh[1]) throw new Error("CACAO issuer must be did:pkh:eip155 with a safe-integer chain ID");
|
|
12750
|
+
const audience = text2(payload.aud, "aud");
|
|
12751
|
+
const optional = (key) => payload[key] === void 0 ? void 0 : text2(payload[key], key);
|
|
12752
|
+
const statement = optional("statement");
|
|
12753
|
+
const expiresAt = optional("exp");
|
|
12754
|
+
const notBefore = optional("nbf");
|
|
12755
|
+
const requestId = optional("requestId");
|
|
12756
|
+
let resources = [];
|
|
12757
|
+
if ("resources" in payload) {
|
|
12758
|
+
if (!Array.isArray(payload.resources) || payload.resources.length === 0) throw new Error("CACAO resources must be a non-empty array when present");
|
|
12759
|
+
resources = payload.resources.map((resource, index) => text2(resource, `resources[${index}]`));
|
|
12760
|
+
}
|
|
12761
|
+
const last = resources.at(-1);
|
|
12762
|
+
const attenuation = last?.startsWith(RECAP_PREFIX) ? reCapAttenuation(last) : /* @__PURE__ */ Object.create(null);
|
|
12763
|
+
if (last?.startsWith(RECAP_PREFIX) && !statement?.endsWith(reCapStatement(attenuation))) throw new Error("CACAO statement does not match its ReCap");
|
|
12764
|
+
const message = new import_siwe2.SiweMessage({
|
|
12765
|
+
domain: text2(payload.domain, "domain"),
|
|
12766
|
+
address: pkh[2],
|
|
12767
|
+
uri: audience,
|
|
12768
|
+
version: "1",
|
|
12769
|
+
chainId,
|
|
12770
|
+
nonce: text2(payload.nonce, "nonce"),
|
|
12771
|
+
issuedAt: text2(payload.iat, "iat"),
|
|
12772
|
+
...statement === void 0 ? {} : { statement },
|
|
12773
|
+
...expiresAt === void 0 ? {} : { expirationTime: expiresAt },
|
|
12774
|
+
...notBefore === void 0 ? {} : { notBefore },
|
|
12775
|
+
...requestId === void 0 ? {} : { requestId },
|
|
12776
|
+
...resources.length === 0 ? {} : { resources }
|
|
12777
|
+
}).prepareMessage();
|
|
12778
|
+
if (!await verifyEip191MessageSignature(message, (0, import_viem5.bytesToHex)(signature.s), pkh[2])) throw new Error("CACAO signature is invalid");
|
|
12779
|
+
return { cid: cid2, issuer, audience, attenuation, ...expiresAt === void 0 ? {} : { expiresAt } };
|
|
12780
|
+
}
|
|
12781
|
+
|
|
12565
12782
|
// src/networkId.ts
|
|
12566
12783
|
var import_sdk_services4 = require("@tinycloud/sdk-services");
|
|
12567
12784
|
function canonicalizeNetworkId(networkId) {
|
|
@@ -14221,11 +14438,11 @@ var TinyCloud = class _TinyCloud {
|
|
|
14221
14438
|
if (contentType?.includes("application/json")) {
|
|
14222
14439
|
data = await response.json();
|
|
14223
14440
|
} else {
|
|
14224
|
-
const
|
|
14441
|
+
const text3 = await response.text();
|
|
14225
14442
|
try {
|
|
14226
|
-
data = JSON.parse(
|
|
14443
|
+
data = JSON.parse(text3);
|
|
14227
14444
|
} catch {
|
|
14228
|
-
data =
|
|
14445
|
+
data = text3;
|
|
14229
14446
|
}
|
|
14230
14447
|
}
|
|
14231
14448
|
return (0, import_sdk_services6.ok)(data);
|
|
@@ -18141,7 +18358,7 @@ function portForProtocol(protocol) {
|
|
|
18141
18358
|
|
|
18142
18359
|
// src/location.ts
|
|
18143
18360
|
var import_ed2551910 = require("@noble/curves/ed25519");
|
|
18144
|
-
var
|
|
18361
|
+
var import_viem6 = require("viem");
|
|
18145
18362
|
var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
18146
18363
|
var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
18147
18364
|
var DEFAULT_LOCAL_NODE_URL = "http://127.0.0.1:8000";
|
|
@@ -18311,10 +18528,10 @@ async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fe
|
|
|
18311
18528
|
if (!response.ok) {
|
|
18312
18529
|
throw new LocationRegistryHttpError(`location registry returned HTTP ${response.status}`, response.status);
|
|
18313
18530
|
}
|
|
18314
|
-
const
|
|
18531
|
+
const text3 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
18315
18532
|
let body;
|
|
18316
18533
|
try {
|
|
18317
|
-
body = JSON.parse(
|
|
18534
|
+
body = JSON.parse(text3);
|
|
18318
18535
|
} catch {
|
|
18319
18536
|
throw new LocationRecordValidationError("registry response is not JSON");
|
|
18320
18537
|
}
|
|
@@ -18356,10 +18573,10 @@ async function publishLocationRecord(options2) {
|
|
|
18356
18573
|
if (!response.ok) {
|
|
18357
18574
|
throw new LocationRegistryHttpError(`location registry publish returned HTTP ${response.status}`, response.status);
|
|
18358
18575
|
}
|
|
18359
|
-
const
|
|
18576
|
+
const text3 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
18360
18577
|
let body;
|
|
18361
18578
|
try {
|
|
18362
|
-
body = JSON.parse(
|
|
18579
|
+
body = JSON.parse(text3);
|
|
18363
18580
|
} catch {
|
|
18364
18581
|
throw new LocationRecordValidationError("registry publish response is not JSON");
|
|
18365
18582
|
}
|
|
@@ -18726,10 +18943,10 @@ async function verifyOwnerNodeBinding(options2) {
|
|
|
18726
18943
|
Object.assign(failure, { status: response.status });
|
|
18727
18944
|
throw failure;
|
|
18728
18945
|
}
|
|
18729
|
-
const
|
|
18946
|
+
const text3 = await boundedResponseText(response, "target node /info", 16 * 1024);
|
|
18730
18947
|
let body;
|
|
18731
18948
|
try {
|
|
18732
|
-
body = JSON.parse(
|
|
18949
|
+
body = JSON.parse(text3);
|
|
18733
18950
|
} catch {
|
|
18734
18951
|
throw new LocationRecordValidationError("target node /info response is not JSON");
|
|
18735
18952
|
}
|
|
@@ -18894,7 +19111,7 @@ async function verifyPkhSignature(did, payload, signature) {
|
|
|
18894
19111
|
if (!/^0x[0-9a-fA-F]+$/.test(signature)) {
|
|
18895
19112
|
throw new LocationRecordValidationError("did:pkh signature must be hex");
|
|
18896
19113
|
}
|
|
18897
|
-
return (0,
|
|
19114
|
+
return (0, import_viem6.verifyMessage)({
|
|
18898
19115
|
address,
|
|
18899
19116
|
message: payload,
|
|
18900
19117
|
signature
|