@tinycloud/sdk-core 3.2.1 → 3.2.3-beta.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/{credential-admission-CJ1ZPqcx.d.ts → credential-admission-7I_ymo-C.d.ts} +2 -1
- package/dist/{credential-admission-1EOQgdzY.d.cts → credential-admission-Cg1M9uyV.d.cts} +2 -1
- package/dist/delegations/index.cjs.map +1 -1
- 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 +29 -3
- package/dist/index.d.ts +29 -3
- 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/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1059,12 +1059,12 @@ var Decoder = class {
|
|
|
1059
1059
|
this.prefixCodePoint = prefixCodePoint;
|
|
1060
1060
|
this.baseDecode = baseDecode;
|
|
1061
1061
|
}
|
|
1062
|
-
decode(
|
|
1063
|
-
if (typeof
|
|
1064
|
-
if (
|
|
1065
|
-
throw Error(`Unable to decode multibase string ${JSON.stringify(
|
|
1062
|
+
decode(text3) {
|
|
1063
|
+
if (typeof text3 === "string") {
|
|
1064
|
+
if (text3.codePointAt(0) !== this.prefixCodePoint) {
|
|
1065
|
+
throw Error(`Unable to decode multibase string ${JSON.stringify(text3)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`);
|
|
1066
1066
|
}
|
|
1067
|
-
return this.baseDecode(
|
|
1067
|
+
return this.baseDecode(text3.slice(this.prefix.length));
|
|
1068
1068
|
} else {
|
|
1069
1069
|
throw Error("Can only multibase decode strings");
|
|
1070
1070
|
}
|
|
@@ -1128,7 +1128,7 @@ function baseX({ name: name2, prefix, alphabet: alphabet2 }) {
|
|
|
1128
1128
|
prefix,
|
|
1129
1129
|
name: name2,
|
|
1130
1130
|
encode: encode5,
|
|
1131
|
-
decode: (
|
|
1131
|
+
decode: (text3) => coerce(decode7(text3))
|
|
1132
1132
|
});
|
|
1133
1133
|
}
|
|
1134
1134
|
function decode(string2, alphabetIdx, bitsPerChar, name2) {
|
|
@@ -4233,7 +4233,7 @@ function parseSignedCompactUcanAttenuation(input, expectedCid) {
|
|
|
4233
4233
|
throw new Error("compact UCAN signed audience is missing");
|
|
4234
4234
|
const cid2 = CID.createV1(85, create(30, blake3(new TextEncoder().encode(input)))).toString();
|
|
4235
4235
|
if (expectedCid !== void 0 && cid2 !== expectedCid) throw new Error("compact UCAN CID does not match exact Authorization bytes");
|
|
4236
|
-
return { cid: cid2, payload: { att, aud: payloadValue.aud } };
|
|
4236
|
+
return { cid: cid2, payload: { att, aud: payloadValue.aud, iss: payloadValue.iss } };
|
|
4237
4237
|
}
|
|
4238
4238
|
function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
4239
4239
|
const parsed = parseCompactUcanAuthorization(authorization);
|
|
@@ -4402,9 +4402,9 @@ function policyV2DigestHex(input) {
|
|
|
4402
4402
|
);
|
|
4403
4403
|
}
|
|
4404
4404
|
function date(value, label) {
|
|
4405
|
-
const
|
|
4406
|
-
if (!Number.isFinite(Date.parse(
|
|
4407
|
-
return
|
|
4405
|
+
const text3 = nonEmpty(value, label);
|
|
4406
|
+
if (!Number.isFinite(Date.parse(text3))) throw new Error(`${label} is invalid`);
|
|
4407
|
+
return text3;
|
|
4408
4408
|
}
|
|
4409
4409
|
function rfc3339Seconds2(value) {
|
|
4410
4410
|
return new Date(Math.floor(value.getTime() / 1e3) * 1e3).toISOString().replace(/\.000Z$/, "Z");
|
|
@@ -8361,64 +8361,64 @@ function canonicalJson(value) {
|
|
|
8361
8361
|
}
|
|
8362
8362
|
throw new ShareEnvelopeError("invalid-envelope", "unsupported JSON value");
|
|
8363
8363
|
}
|
|
8364
|
-
function skipWhitespace(
|
|
8364
|
+
function skipWhitespace(text3, start) {
|
|
8365
8365
|
let index = start;
|
|
8366
|
-
while (/\s/.test(
|
|
8366
|
+
while (/\s/.test(text3[index] ?? "")) index += 1;
|
|
8367
8367
|
return index;
|
|
8368
8368
|
}
|
|
8369
|
-
function scanJsonValue(
|
|
8370
|
-
let index = skipWhitespace(
|
|
8371
|
-
const first =
|
|
8369
|
+
function scanJsonValue(text3, start) {
|
|
8370
|
+
let index = skipWhitespace(text3, start);
|
|
8371
|
+
const first = text3[index];
|
|
8372
8372
|
if (first === '"') {
|
|
8373
8373
|
index += 1;
|
|
8374
|
-
while (index <
|
|
8375
|
-
if (
|
|
8376
|
-
else if (
|
|
8374
|
+
while (index < text3.length) {
|
|
8375
|
+
if (text3[index] === "\\") index += 2;
|
|
8376
|
+
else if (text3[index++] === '"') return index;
|
|
8377
8377
|
}
|
|
8378
8378
|
throw new ShareEnvelopeError("invalid-envelope", "unterminated JSON string");
|
|
8379
8379
|
}
|
|
8380
8380
|
if (first === "{") {
|
|
8381
8381
|
const keys = /* @__PURE__ */ new Set();
|
|
8382
|
-
index = skipWhitespace(
|
|
8383
|
-
if (
|
|
8384
|
-
while (index <
|
|
8385
|
-
index = skipWhitespace(
|
|
8386
|
-
if (
|
|
8382
|
+
index = skipWhitespace(text3, index + 1);
|
|
8383
|
+
if (text3[index] === "}") return index + 1;
|
|
8384
|
+
while (index < text3.length) {
|
|
8385
|
+
index = skipWhitespace(text3, index);
|
|
8386
|
+
if (text3[index] !== '"') throw new ShareEnvelopeError("invalid-envelope", "object key must be a string");
|
|
8387
8387
|
const keyStart = index;
|
|
8388
|
-
index = scanJsonValue(
|
|
8389
|
-
const key = JSON.parse(
|
|
8388
|
+
index = scanJsonValue(text3, index);
|
|
8389
|
+
const key = JSON.parse(text3.slice(keyStart, index));
|
|
8390
8390
|
if (keys.has(key)) throw new ShareEnvelopeError("invalid-envelope", `duplicate JSON key ${key}`);
|
|
8391
8391
|
keys.add(key);
|
|
8392
|
-
index = skipWhitespace(
|
|
8393
|
-
if (
|
|
8394
|
-
index = scanJsonValue(
|
|
8395
|
-
index = skipWhitespace(
|
|
8396
|
-
if (
|
|
8397
|
-
if (
|
|
8392
|
+
index = skipWhitespace(text3, index);
|
|
8393
|
+
if (text3[index++] !== ":") throw new ShareEnvelopeError("invalid-envelope", "missing object colon");
|
|
8394
|
+
index = scanJsonValue(text3, index);
|
|
8395
|
+
index = skipWhitespace(text3, index);
|
|
8396
|
+
if (text3[index] === "}") return index + 1;
|
|
8397
|
+
if (text3[index++] !== ",") throw new ShareEnvelopeError("invalid-envelope", "invalid object separator");
|
|
8398
8398
|
}
|
|
8399
8399
|
throw new ShareEnvelopeError("invalid-envelope", "unterminated JSON object");
|
|
8400
8400
|
}
|
|
8401
8401
|
if (first === "[") {
|
|
8402
|
-
index = skipWhitespace(
|
|
8403
|
-
if (
|
|
8404
|
-
while (index <
|
|
8405
|
-
index = scanJsonValue(
|
|
8406
|
-
index = skipWhitespace(
|
|
8407
|
-
if (
|
|
8408
|
-
if (
|
|
8402
|
+
index = skipWhitespace(text3, index + 1);
|
|
8403
|
+
if (text3[index] === "]") return index + 1;
|
|
8404
|
+
while (index < text3.length) {
|
|
8405
|
+
index = scanJsonValue(text3, index);
|
|
8406
|
+
index = skipWhitespace(text3, index);
|
|
8407
|
+
if (text3[index] === "]") return index + 1;
|
|
8408
|
+
if (text3[index++] !== ",") throw new ShareEnvelopeError("invalid-envelope", "invalid array separator");
|
|
8409
8409
|
}
|
|
8410
8410
|
throw new ShareEnvelopeError("invalid-envelope", "unterminated JSON array");
|
|
8411
8411
|
}
|
|
8412
|
-
const match =
|
|
8412
|
+
const match = text3.slice(index).match(/^(?:true|false|null|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)/);
|
|
8413
8413
|
if (!match) throw new ShareEnvelopeError("invalid-envelope", "invalid JSON value");
|
|
8414
8414
|
return index + match[0].length;
|
|
8415
8415
|
}
|
|
8416
|
-
function parseCanonicalJson(
|
|
8416
|
+
function parseCanonicalJson(text3) {
|
|
8417
8417
|
try {
|
|
8418
|
-
const end = scanJsonValue(
|
|
8419
|
-
if (skipWhitespace(
|
|
8420
|
-
const parsed = JSON.parse(
|
|
8421
|
-
if (canonicalJson(parsed) !==
|
|
8418
|
+
const end = scanJsonValue(text3, 0);
|
|
8419
|
+
if (skipWhitespace(text3, end) !== text3.length) throw new Error("trailing JSON");
|
|
8420
|
+
const parsed = JSON.parse(text3);
|
|
8421
|
+
if (canonicalJson(parsed) !== text3) throw new Error("non-canonical JSON");
|
|
8422
8422
|
return parsed;
|
|
8423
8423
|
} catch (error) {
|
|
8424
8424
|
if (error instanceof ShareEnvelopeError) throw error;
|
|
@@ -11847,8 +11847,8 @@ async function createPolicyEnforcementDelegation(input) {
|
|
|
11847
11847
|
return { cid: cid(dagCborBytes), dagCbor: b64(dagCborBytes), issuerDid: input.shareKey.did, audienceDid: input.enforcerDid, facts, signature };
|
|
11848
11848
|
}
|
|
11849
11849
|
async function canonicalOwnerSharePolicy(policy) {
|
|
11850
|
-
const
|
|
11851
|
-
const policyBytes = new TextEncoder().encode(
|
|
11850
|
+
const text3 = canonicalizeSignedObjectUnsigned({ domain: POLICY_DOMAIN, policy });
|
|
11851
|
+
const policyBytes = new TextEncoder().encode(text3);
|
|
11852
11852
|
return { bytes: policyBytes, cid: cid(policyBytes), digest: digest3(policyBytes) };
|
|
11853
11853
|
}
|
|
11854
11854
|
function computeOwnerShareRegistrationCid(registration) {
|
|
@@ -12098,6 +12098,222 @@ import {
|
|
|
12098
12098
|
toShareErrorInfo
|
|
12099
12099
|
} from "@tinycloud/share-sdk";
|
|
12100
12100
|
|
|
12101
|
+
// src/delegations/cacao.ts
|
|
12102
|
+
import { blake3 as blake34 } from "@noble/hashes/blake3";
|
|
12103
|
+
import { SiweMessage as SiweMessage2 } from "siwe";
|
|
12104
|
+
import { bytesToHex as bytesToHex4 } from "viem";
|
|
12105
|
+
var MAX_CACAO_BYTES = 64 * 1024;
|
|
12106
|
+
var MAX_CBOR_DEPTH = 64;
|
|
12107
|
+
var RECAP_PREFIX = "urn:recap:";
|
|
12108
|
+
var RECAP_STATEMENT = "I further authorize the stated URI to perform the following actions on my behalf:";
|
|
12109
|
+
function compareKeys(left, right) {
|
|
12110
|
+
if (left.length !== right.length) return left.length - right.length;
|
|
12111
|
+
for (let index = 0; index < left.length; index++) {
|
|
12112
|
+
if (left[index] !== right[index]) return left[index] - right[index];
|
|
12113
|
+
}
|
|
12114
|
+
return 0;
|
|
12115
|
+
}
|
|
12116
|
+
function decodeDagCbor(bytes2) {
|
|
12117
|
+
let offset = 0;
|
|
12118
|
+
const view = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength);
|
|
12119
|
+
const take = (length2) => {
|
|
12120
|
+
if (length2 > bytes2.length - offset) throw new Error("CBOR input ended early");
|
|
12121
|
+
return bytes2.subarray(offset, offset += length2);
|
|
12122
|
+
};
|
|
12123
|
+
const read2 = (depth) => {
|
|
12124
|
+
if (depth > MAX_CBOR_DEPTH) throw new Error(`CBOR nesting exceeds ${MAX_CBOR_DEPTH} levels`);
|
|
12125
|
+
const [initial] = take(1);
|
|
12126
|
+
const major = initial >> 5;
|
|
12127
|
+
const info = initial & 31;
|
|
12128
|
+
if (major === 7) {
|
|
12129
|
+
if (info === 20) return false;
|
|
12130
|
+
if (info === 21) return true;
|
|
12131
|
+
if (info === 22) return null;
|
|
12132
|
+
throw new Error("CBOR floats and other simple values are not part of a CACAO");
|
|
12133
|
+
}
|
|
12134
|
+
if (major === 6) throw new Error("CBOR tags are not part of a CACAO");
|
|
12135
|
+
let argument;
|
|
12136
|
+
if (info < 24) argument = info;
|
|
12137
|
+
else if (info === 24) argument = take(1)[0];
|
|
12138
|
+
else if (info === 25) argument = view.getUint16(take(2).byteOffset - bytes2.byteOffset);
|
|
12139
|
+
else if (info === 26) argument = view.getUint32(take(4).byteOffset - bytes2.byteOffset);
|
|
12140
|
+
else if (info === 27) {
|
|
12141
|
+
const value2 = view.getBigUint64(take(8).byteOffset - bytes2.byteOffset);
|
|
12142
|
+
if (value2 > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error("CBOR integer is too large");
|
|
12143
|
+
argument = Number(value2);
|
|
12144
|
+
} else throw new Error("CBOR indefinite lengths are not DAG-CBOR");
|
|
12145
|
+
switch (major) {
|
|
12146
|
+
case 0:
|
|
12147
|
+
return argument;
|
|
12148
|
+
case 1:
|
|
12149
|
+
return -1 - argument;
|
|
12150
|
+
case 2:
|
|
12151
|
+
return take(argument).slice();
|
|
12152
|
+
case 3:
|
|
12153
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(take(argument));
|
|
12154
|
+
case 4: {
|
|
12155
|
+
if (argument > bytes2.length - offset) throw new Error("CBOR input ended early");
|
|
12156
|
+
const items = [];
|
|
12157
|
+
for (let index = 0; index < argument; index++) items.push(read2(depth + 1));
|
|
12158
|
+
return items;
|
|
12159
|
+
}
|
|
12160
|
+
default: {
|
|
12161
|
+
if (argument > bytes2.length - offset) throw new Error("CBOR input ended early");
|
|
12162
|
+
const map2 = /* @__PURE__ */ Object.create(null);
|
|
12163
|
+
for (let index = 0; index < argument; index++) {
|
|
12164
|
+
const key = read2(depth + 1);
|
|
12165
|
+
if (typeof key !== "string") throw new Error("CBOR map keys must be strings");
|
|
12166
|
+
if (key === "__proto__") throw new Error("CBOR map key __proto__ is not allowed");
|
|
12167
|
+
if (Object.prototype.hasOwnProperty.call(map2, key)) throw new Error(`CBOR map has a duplicate key ${JSON.stringify(key)}`);
|
|
12168
|
+
map2[key] = read2(depth + 1);
|
|
12169
|
+
}
|
|
12170
|
+
return map2;
|
|
12171
|
+
}
|
|
12172
|
+
}
|
|
12173
|
+
};
|
|
12174
|
+
const value = read2(0);
|
|
12175
|
+
if (offset !== bytes2.length) throw new Error("CBOR input has trailing bytes");
|
|
12176
|
+
return value;
|
|
12177
|
+
}
|
|
12178
|
+
function encodeDagCbor(value) {
|
|
12179
|
+
const output = [];
|
|
12180
|
+
const head = (major, argument) => {
|
|
12181
|
+
if (argument < 24) output.push(major << 5 | argument);
|
|
12182
|
+
else if (argument < 256) output.push(major << 5 | 24, argument);
|
|
12183
|
+
else if (argument < 65536) output.push(major << 5 | 25, argument >> 8, argument & 255);
|
|
12184
|
+
else if (argument < 4294967296) output.push(major << 5 | 26, ...[24, 16, 8, 0].map((shift) => argument >>> shift & 255));
|
|
12185
|
+
else output.push(major << 5 | 27, ...[56n, 48n, 40n, 32n, 24n, 16n, 8n, 0n].map((shift) => Number(BigInt(argument) >> shift & 0xffn)));
|
|
12186
|
+
};
|
|
12187
|
+
const write = (item) => {
|
|
12188
|
+
if (item === null) output.push(246);
|
|
12189
|
+
else if (item === false) output.push(244);
|
|
12190
|
+
else if (item === true) output.push(245);
|
|
12191
|
+
else if (typeof item === "number" && Number.isSafeInteger(item)) {
|
|
12192
|
+
if (item >= 0) head(0, item);
|
|
12193
|
+
else head(1, -1 - item);
|
|
12194
|
+
} else if (typeof item === "string") {
|
|
12195
|
+
const encoded = new TextEncoder().encode(item);
|
|
12196
|
+
head(3, encoded.length);
|
|
12197
|
+
output.push(...encoded);
|
|
12198
|
+
} else if (item instanceof Uint8Array) {
|
|
12199
|
+
head(2, item.length);
|
|
12200
|
+
output.push(...item);
|
|
12201
|
+
} else if (Array.isArray(item)) {
|
|
12202
|
+
head(4, item.length);
|
|
12203
|
+
item.forEach(write);
|
|
12204
|
+
} else if (typeof item === "object") {
|
|
12205
|
+
const entries = Object.keys(item).map((key) => [new TextEncoder().encode(key), item[key]]);
|
|
12206
|
+
entries.sort(([left], [right]) => compareKeys(left, right));
|
|
12207
|
+
head(5, entries.length);
|
|
12208
|
+
for (const [key, entry] of entries) {
|
|
12209
|
+
head(3, key.length);
|
|
12210
|
+
output.push(...key);
|
|
12211
|
+
write(entry);
|
|
12212
|
+
}
|
|
12213
|
+
} else throw new Error("value is not DAG-CBOR encodable");
|
|
12214
|
+
};
|
|
12215
|
+
write(value);
|
|
12216
|
+
return Uint8Array.from(output);
|
|
12217
|
+
}
|
|
12218
|
+
function map(value, label, keys, optional = []) {
|
|
12219
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || value instanceof Uint8Array) throw new Error(`CACAO ${label} must be a map`);
|
|
12220
|
+
const entries = value;
|
|
12221
|
+
for (const key of Object.keys(entries)) {
|
|
12222
|
+
if (!keys.includes(key) && !optional.includes(key)) throw new Error(`CACAO ${label} has unknown field ${JSON.stringify(key)}`);
|
|
12223
|
+
}
|
|
12224
|
+
for (const key of keys) if (!(key in entries)) throw new Error(`CACAO ${label} is missing ${key}`);
|
|
12225
|
+
return entries;
|
|
12226
|
+
}
|
|
12227
|
+
function text2(value, label) {
|
|
12228
|
+
if (typeof value !== "string" || value.length === 0) throw new Error(`CACAO ${label} must be a non-empty string`);
|
|
12229
|
+
return value;
|
|
12230
|
+
}
|
|
12231
|
+
function reCapStatement(attenuation) {
|
|
12232
|
+
var _a3;
|
|
12233
|
+
let index = 0;
|
|
12234
|
+
let lines = "";
|
|
12235
|
+
for (const resource of Object.keys(attenuation).sort()) {
|
|
12236
|
+
const namespaces = /* @__PURE__ */ Object.create(null);
|
|
12237
|
+
for (const ability of Object.keys(attenuation[resource]).sort()) {
|
|
12238
|
+
const slash = ability.indexOf("/");
|
|
12239
|
+
if (slash <= 0) throw new Error("ReCap ability must be namespace/name");
|
|
12240
|
+
(namespaces[_a3 = ability.slice(0, slash)] ?? (namespaces[_a3] = [])).push(ability.slice(slash + 1));
|
|
12241
|
+
}
|
|
12242
|
+
for (const namespace of Object.keys(namespaces).sort()) {
|
|
12243
|
+
lines += ` (${++index}) '${namespace}': ${namespaces[namespace].map((name2) => `'${name2}'`).join(", ")} for '${resource}'.`;
|
|
12244
|
+
}
|
|
12245
|
+
}
|
|
12246
|
+
return `${RECAP_STATEMENT}${lines}`;
|
|
12247
|
+
}
|
|
12248
|
+
function reCapAttenuation(resource) {
|
|
12249
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12250
|
+
const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(decodeBase64Url(resource.slice(RECAP_PREFIX.length))));
|
|
12251
|
+
if (!isObject(parsed) || !("att" in parsed) || !isObject(parsed.att)) throw new Error("ReCap attenuation must be an object");
|
|
12252
|
+
const attenuation = /* @__PURE__ */ Object.create(null);
|
|
12253
|
+
for (const [target, abilities] of Object.entries(parsed.att)) {
|
|
12254
|
+
if (target === "__proto__" || !isObject(abilities) || Object.keys(abilities).length === 0) throw new Error("ReCap resource must map to abilities");
|
|
12255
|
+
const copy = /* @__PURE__ */ Object.create(null);
|
|
12256
|
+
for (const [ability, caveats] of Object.entries(abilities)) {
|
|
12257
|
+
if (ability === "__proto__" || !/^[^/]+\/[^/]/.test(ability)) throw new Error("ReCap ability must be namespace/name");
|
|
12258
|
+
if (!Array.isArray(caveats) || caveats.length === 0 || !caveats.every(isObject)) throw new Error("ReCap caveats must be a non-empty array of objects");
|
|
12259
|
+
copy[ability] = caveats;
|
|
12260
|
+
}
|
|
12261
|
+
attenuation[target] = copy;
|
|
12262
|
+
}
|
|
12263
|
+
return attenuation;
|
|
12264
|
+
}
|
|
12265
|
+
async function parseSignedSiweCacao(authorization, expectedCid) {
|
|
12266
|
+
if (authorization.length > Math.ceil(MAX_CACAO_BYTES / 3) * 4 + 2) throw new Error(`CACAO exceeds ${MAX_CACAO_BYTES} bytes`);
|
|
12267
|
+
if (!/^[A-Za-z0-9_-]+={0,2}$/.test(authorization)) throw new Error("CACAO must be base64url DAG-CBOR");
|
|
12268
|
+
const bytes2 = decodeBase64Url(authorization.replace(/=+$/, ""));
|
|
12269
|
+
if (bytes2.length > MAX_CACAO_BYTES) throw new Error(`CACAO exceeds ${MAX_CACAO_BYTES} bytes`);
|
|
12270
|
+
const cid2 = CID.createV1(85, create(30, blake34(bytes2))).toString();
|
|
12271
|
+
if (expectedCid !== void 0 && cid2 !== expectedCid) throw new Error("CACAO CID does not match exact Authorization bytes");
|
|
12272
|
+
const decoded = decodeDagCbor(bytes2);
|
|
12273
|
+
const canonical = encodeDagCbor(decoded);
|
|
12274
|
+
if (canonical.length !== bytes2.length || canonical.some((byte, index) => byte !== bytes2[index])) throw new Error("CACAO is not canonical DAG-CBOR");
|
|
12275
|
+
const cacao = map(decoded, "envelope", ["h", "p", "s"]);
|
|
12276
|
+
if (map(cacao.h, "header", ["t"]).t !== "eip4361") throw new Error("CACAO header must be eip4361");
|
|
12277
|
+
const signature = map(cacao.s, "signature", ["t", "s"]);
|
|
12278
|
+
if (signature.t !== "eip191" || !(signature.s instanceof Uint8Array) || signature.s.length !== 65) throw new Error("CACAO signature must be a 65-byte eip191 signature");
|
|
12279
|
+
const payload = map(cacao.p, "payload", ["domain", "iss", "aud", "version", "nonce", "iat"], ["exp", "nbf", "statement", "requestId", "resources"]);
|
|
12280
|
+
if (payload.version !== 1) throw new Error("CACAO SIWE version must be the integer 1");
|
|
12281
|
+
const issuer = text2(payload.iss, "iss");
|
|
12282
|
+
const pkh = /^did:pkh:eip155:([1-9]\d*):(0x[0-9a-fA-F]{40})$/.exec(issuer);
|
|
12283
|
+
const chainId = Number(pkh?.[1]);
|
|
12284
|
+
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");
|
|
12285
|
+
const audience = text2(payload.aud, "aud");
|
|
12286
|
+
const optional = (key) => payload[key] === void 0 ? void 0 : text2(payload[key], key);
|
|
12287
|
+
const statement = optional("statement");
|
|
12288
|
+
const expiresAt = optional("exp");
|
|
12289
|
+
const notBefore = optional("nbf");
|
|
12290
|
+
const requestId = optional("requestId");
|
|
12291
|
+
let resources = [];
|
|
12292
|
+
if ("resources" in payload) {
|
|
12293
|
+
if (!Array.isArray(payload.resources) || payload.resources.length === 0) throw new Error("CACAO resources must be a non-empty array when present");
|
|
12294
|
+
resources = payload.resources.map((resource, index) => text2(resource, `resources[${index}]`));
|
|
12295
|
+
}
|
|
12296
|
+
const last = resources.at(-1);
|
|
12297
|
+
const attenuation = last?.startsWith(RECAP_PREFIX) ? reCapAttenuation(last) : /* @__PURE__ */ Object.create(null);
|
|
12298
|
+
if (last?.startsWith(RECAP_PREFIX) && !statement?.endsWith(reCapStatement(attenuation))) throw new Error("CACAO statement does not match its ReCap");
|
|
12299
|
+
const message = new SiweMessage2({
|
|
12300
|
+
domain: text2(payload.domain, "domain"),
|
|
12301
|
+
address: pkh[2],
|
|
12302
|
+
uri: audience,
|
|
12303
|
+
version: "1",
|
|
12304
|
+
chainId,
|
|
12305
|
+
nonce: text2(payload.nonce, "nonce"),
|
|
12306
|
+
issuedAt: text2(payload.iat, "iat"),
|
|
12307
|
+
...statement === void 0 ? {} : { statement },
|
|
12308
|
+
...expiresAt === void 0 ? {} : { expirationTime: expiresAt },
|
|
12309
|
+
...notBefore === void 0 ? {} : { notBefore },
|
|
12310
|
+
...requestId === void 0 ? {} : { requestId },
|
|
12311
|
+
...resources.length === 0 ? {} : { resources }
|
|
12312
|
+
}).prepareMessage();
|
|
12313
|
+
if (!await verifyEip191MessageSignature(message, bytesToHex4(signature.s), pkh[2])) throw new Error("CACAO signature is invalid");
|
|
12314
|
+
return { cid: cid2, issuer, audience, attenuation, ...expiresAt === void 0 ? {} : { expiresAt } };
|
|
12315
|
+
}
|
|
12316
|
+
|
|
12101
12317
|
// src/networkId.ts
|
|
12102
12318
|
import {
|
|
12103
12319
|
buildNetworkId,
|
|
@@ -13770,11 +13986,11 @@ var TinyCloud = class _TinyCloud {
|
|
|
13770
13986
|
if (contentType?.includes("application/json")) {
|
|
13771
13987
|
data = await response.json();
|
|
13772
13988
|
} else {
|
|
13773
|
-
const
|
|
13989
|
+
const text3 = await response.text();
|
|
13774
13990
|
try {
|
|
13775
|
-
data = JSON.parse(
|
|
13991
|
+
data = JSON.parse(text3);
|
|
13776
13992
|
} catch {
|
|
13777
|
-
data =
|
|
13993
|
+
data = text3;
|
|
13778
13994
|
}
|
|
13779
13995
|
}
|
|
13780
13996
|
return ok2(data);
|
|
@@ -17990,10 +18206,10 @@ async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fe
|
|
|
17990
18206
|
if (!response.ok) {
|
|
17991
18207
|
throw new LocationRegistryHttpError(`location registry returned HTTP ${response.status}`, response.status);
|
|
17992
18208
|
}
|
|
17993
|
-
const
|
|
18209
|
+
const text3 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
17994
18210
|
let body;
|
|
17995
18211
|
try {
|
|
17996
|
-
body = JSON.parse(
|
|
18212
|
+
body = JSON.parse(text3);
|
|
17997
18213
|
} catch {
|
|
17998
18214
|
throw new LocationRecordValidationError("registry response is not JSON");
|
|
17999
18215
|
}
|
|
@@ -18035,10 +18251,10 @@ async function publishLocationRecord(options2) {
|
|
|
18035
18251
|
if (!response.ok) {
|
|
18036
18252
|
throw new LocationRegistryHttpError(`location registry publish returned HTTP ${response.status}`, response.status);
|
|
18037
18253
|
}
|
|
18038
|
-
const
|
|
18254
|
+
const text3 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
18039
18255
|
let body;
|
|
18040
18256
|
try {
|
|
18041
|
-
body = JSON.parse(
|
|
18257
|
+
body = JSON.parse(text3);
|
|
18042
18258
|
} catch {
|
|
18043
18259
|
throw new LocationRecordValidationError("registry publish response is not JSON");
|
|
18044
18260
|
}
|
|
@@ -18405,10 +18621,10 @@ async function verifyOwnerNodeBinding(options2) {
|
|
|
18405
18621
|
Object.assign(failure, { status: response.status });
|
|
18406
18622
|
throw failure;
|
|
18407
18623
|
}
|
|
18408
|
-
const
|
|
18624
|
+
const text3 = await boundedResponseText(response, "target node /info", 16 * 1024);
|
|
18409
18625
|
let body;
|
|
18410
18626
|
try {
|
|
18411
|
-
body = JSON.parse(
|
|
18627
|
+
body = JSON.parse(text3);
|
|
18412
18628
|
} catch {
|
|
18413
18629
|
throw new LocationRecordValidationError("target node /info response is not JSON");
|
|
18414
18630
|
}
|
|
@@ -19025,6 +19241,7 @@ export {
|
|
|
19025
19241
|
parseShareArtifact,
|
|
19026
19242
|
parseShareUrl,
|
|
19027
19243
|
parseSignedCompactUcanAttenuation,
|
|
19244
|
+
parseSignedSiweCacao,
|
|
19028
19245
|
parseSpaceUri,
|
|
19029
19246
|
parseStorageRejection,
|
|
19030
19247
|
parseStorageStatus,
|