@tinycloud/sdk-core 2.11.0-beta.1 → 2.11.0-beta.11
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/bootstrap/index.cjs +0 -4
- package/dist/delegations/index.cjs +702 -330
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +9 -8
- package/dist/delegations/index.d.ts +9 -8
- package/dist/delegations/index.js +722 -263
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +2338 -1156
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +350 -24
- package/dist/index.d.ts +350 -24
- package/dist/index.js +2333 -810
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +878 -250
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.d.cts +3 -2
- package/dist/policy/index.d.ts +3 -2
- package/dist/policy/index.js +877 -183
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-CWIt63Qp.d.cts → recipient-types.schema-CuDpskPd.d.cts} +236 -98
- package/dist/{recipient-types.schema-CWIt63Qp.d.ts → recipient-types.schema-CuDpskPd.d.ts} +236 -98
- package/dist/requester/index.cjs +10 -38
- package/dist/requester/index.cjs.map +1 -1
- package/dist/requester/index.js +10 -8
- package/dist/requester/index.js.map +1 -1
- package/dist/unified-BYPfXp5S.d.ts +429 -0
- package/dist/unified-BdfNHNrx.d.cts +429 -0
- package/package.json +6 -3
- package/dist/signed-object-C6mWbTbB.d.ts +0 -149
- package/dist/signed-object-IMAm5a32.d.cts +0 -149
package/dist/index.js
CHANGED
|
@@ -147,8 +147,8 @@ function makePkhSpaceId(address, chainId, name2) {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
// src/requester/index.ts
|
|
150
|
-
import { bytesToHex as bytesToHex3, sha256 as
|
|
151
|
-
import { blake3 } from "@noble/hashes/blake3";
|
|
150
|
+
import { bytesToHex as bytesToHex3, sha256 as sha2565 } from "viem";
|
|
151
|
+
import { blake3 as blake32 } from "@noble/hashes/blake3";
|
|
152
152
|
|
|
153
153
|
// ../../node_modules/multiformats/dist/src/bases/base32.js
|
|
154
154
|
var base32_exports = {};
|
|
@@ -1056,7 +1056,7 @@ function encodeCID(version, code3, multihash) {
|
|
|
1056
1056
|
var cidSymbol = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
|
|
1057
1057
|
|
|
1058
1058
|
// src/requester/index.ts
|
|
1059
|
-
import { z as
|
|
1059
|
+
import { z as z3 } from "zod";
|
|
1060
1060
|
|
|
1061
1061
|
// src/policy/errors.ts
|
|
1062
1062
|
var SignedObjectProfileError = class extends Error {
|
|
@@ -1365,16 +1365,16 @@ function policyCapabilityContains(authority, request) {
|
|
|
1365
1365
|
return caveatsContain(auth.caveats, req.caveats);
|
|
1366
1366
|
}
|
|
1367
1367
|
function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
1368
|
-
const
|
|
1369
|
-
assertExactKeys(
|
|
1370
|
-
const service = requiredString(
|
|
1368
|
+
const object2 = expectObject(input, "$");
|
|
1369
|
+
assertExactKeys(object2, ["service", "space", "path", "actions", "caveats"], "$");
|
|
1370
|
+
const service = requiredString(object2, "service", "$", "policy-capability-malformed-service");
|
|
1371
1371
|
if (!CEILING_SERVICES.has(service)) {
|
|
1372
1372
|
throw new PolicyCapabilityError(
|
|
1373
1373
|
"policy-capability-malformed-service",
|
|
1374
1374
|
"$.service is outside the frozen permissionsCeiling vocabulary"
|
|
1375
1375
|
);
|
|
1376
1376
|
}
|
|
1377
|
-
const space = requiredString(
|
|
1377
|
+
const space = requiredString(object2, "space", "$", "policy-capability-malformed-space");
|
|
1378
1378
|
validateConcreteSpace(space);
|
|
1379
1379
|
const canonicalSpace = space.normalize("NFC");
|
|
1380
1380
|
if (options2.requireCanonical && canonicalSpace !== space) {
|
|
@@ -1383,7 +1383,7 @@ function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
|
1383
1383
|
"$.space must already be canonical NFC"
|
|
1384
1384
|
);
|
|
1385
1385
|
}
|
|
1386
|
-
const rawPath = requiredString(
|
|
1386
|
+
const rawPath = requiredString(object2, "path", "$", "policy-capability-malformed-path");
|
|
1387
1387
|
validateRawPath(rawPath, options2);
|
|
1388
1388
|
const path = normalizePath(rawPath);
|
|
1389
1389
|
if (options2.requireCanonical && path !== rawPath) {
|
|
@@ -1394,7 +1394,7 @@ function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
|
1394
1394
|
}
|
|
1395
1395
|
validateRawPath(path, options2);
|
|
1396
1396
|
const actions = normalizeActions(
|
|
1397
|
-
requiredArray(
|
|
1397
|
+
requiredArray(object2, "actions", "$", "policy-capability-malformed-action"),
|
|
1398
1398
|
service,
|
|
1399
1399
|
options2
|
|
1400
1400
|
);
|
|
@@ -1403,9 +1403,9 @@ function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
|
1403
1403
|
output.space = canonicalSpace;
|
|
1404
1404
|
output.path = path;
|
|
1405
1405
|
output.actions = actions;
|
|
1406
|
-
if (hasOwn(
|
|
1406
|
+
if (hasOwn(object2, "caveats")) {
|
|
1407
1407
|
output.caveats = validateCaveats(
|
|
1408
|
-
requiredValue(
|
|
1408
|
+
requiredValue(object2, "caveats", "$", "policy-capability-malformed-caveats"),
|
|
1409
1409
|
output.service
|
|
1410
1410
|
);
|
|
1411
1411
|
}
|
|
@@ -1428,9 +1428,9 @@ function expectObject(input, path) {
|
|
|
1428
1428
|
);
|
|
1429
1429
|
}
|
|
1430
1430
|
}
|
|
1431
|
-
function assertExactKeys(
|
|
1431
|
+
function assertExactKeys(object2, allowed, path) {
|
|
1432
1432
|
const allowedSet = new Set(allowed);
|
|
1433
|
-
for (const key of Object.keys(
|
|
1433
|
+
for (const key of Object.keys(object2)) {
|
|
1434
1434
|
if (!allowedSet.has(key)) {
|
|
1435
1435
|
throw new PolicyCapabilityError(
|
|
1436
1436
|
key === "id" || key === "scope" ? "policy-capability-malformed" : "policy-capability-unknown-key",
|
|
@@ -1439,21 +1439,21 @@ function assertExactKeys(object, allowed, path) {
|
|
|
1439
1439
|
}
|
|
1440
1440
|
}
|
|
1441
1441
|
}
|
|
1442
|
-
function requiredValue(
|
|
1443
|
-
if (!hasOwn(
|
|
1442
|
+
function requiredValue(object2, key, path, code3) {
|
|
1443
|
+
if (!hasOwn(object2, key)) {
|
|
1444
1444
|
throw new PolicyCapabilityError(code3, `${path}.${key} is required`);
|
|
1445
1445
|
}
|
|
1446
|
-
return
|
|
1446
|
+
return object2[key];
|
|
1447
1447
|
}
|
|
1448
|
-
function requiredString(
|
|
1449
|
-
const value = requiredValue(
|
|
1448
|
+
function requiredString(object2, key, path, code3) {
|
|
1449
|
+
const value = requiredValue(object2, key, path, code3);
|
|
1450
1450
|
if (typeof value !== "string" || value.length === 0) {
|
|
1451
1451
|
throw new PolicyCapabilityError(code3, `${path}.${key} must be a non-empty string`);
|
|
1452
1452
|
}
|
|
1453
1453
|
return value;
|
|
1454
1454
|
}
|
|
1455
|
-
function requiredArray(
|
|
1456
|
-
const value = requiredValue(
|
|
1455
|
+
function requiredArray(object2, key, path, code3) {
|
|
1456
|
+
const value = requiredValue(object2, key, path, code3);
|
|
1457
1457
|
if (!Array.isArray(value)) {
|
|
1458
1458
|
throw new PolicyCapabilityError(code3, `${path}.${key} must be an array`);
|
|
1459
1459
|
}
|
|
@@ -1598,11 +1598,11 @@ function validateSqlStatement(input, path) {
|
|
|
1598
1598
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
1599
1599
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
1600
1600
|
}
|
|
1601
|
-
const
|
|
1602
|
-
assertCaveatKeys(
|
|
1603
|
-
caveatString(
|
|
1604
|
-
caveatString(
|
|
1605
|
-
const fixedParams = requiredCaveat(
|
|
1601
|
+
const object2 = input;
|
|
1602
|
+
assertCaveatKeys(object2, ["name", "sql", "fixedParams"], path);
|
|
1603
|
+
caveatString(object2, "name", path);
|
|
1604
|
+
caveatString(object2, "sql", path);
|
|
1605
|
+
const fixedParams = requiredCaveat(object2, "fixedParams", path);
|
|
1606
1606
|
if (!Array.isArray(fixedParams)) {
|
|
1607
1607
|
throw new PolicyCapabilityError(
|
|
1608
1608
|
"policy-capability-malformed-caveats",
|
|
@@ -1617,20 +1617,20 @@ function validateFixedParam(input, path) {
|
|
|
1617
1617
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
1618
1618
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
1619
1619
|
}
|
|
1620
|
-
const
|
|
1621
|
-
assertCaveatKeys(
|
|
1622
|
-
const index = requiredCaveat(
|
|
1620
|
+
const object2 = input;
|
|
1621
|
+
assertCaveatKeys(object2, ["index", "value"], path);
|
|
1622
|
+
const index = requiredCaveat(object2, "index", path);
|
|
1623
1623
|
if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0) {
|
|
1624
1624
|
throw new PolicyCapabilityError(
|
|
1625
1625
|
"policy-capability-malformed-caveats",
|
|
1626
1626
|
`${path}.index must be a non-negative integer`
|
|
1627
1627
|
);
|
|
1628
1628
|
}
|
|
1629
|
-
requiredCaveat(
|
|
1629
|
+
requiredCaveat(object2, "value", path);
|
|
1630
1630
|
}
|
|
1631
|
-
function assertCaveatKeys(
|
|
1631
|
+
function assertCaveatKeys(object2, allowed, path) {
|
|
1632
1632
|
const allowedSet = new Set(allowed);
|
|
1633
|
-
for (const key of Object.keys(
|
|
1633
|
+
for (const key of Object.keys(object2)) {
|
|
1634
1634
|
if (!allowedSet.has(key)) {
|
|
1635
1635
|
throw new PolicyCapabilityError(
|
|
1636
1636
|
"policy-capability-malformed-caveats",
|
|
@@ -1639,17 +1639,17 @@ function assertCaveatKeys(object, allowed, path) {
|
|
|
1639
1639
|
}
|
|
1640
1640
|
}
|
|
1641
1641
|
}
|
|
1642
|
-
function requiredCaveat(
|
|
1643
|
-
if (!hasOwn(
|
|
1642
|
+
function requiredCaveat(object2, key, path) {
|
|
1643
|
+
if (!hasOwn(object2, key)) {
|
|
1644
1644
|
throw new PolicyCapabilityError(
|
|
1645
1645
|
"policy-capability-malformed-caveats",
|
|
1646
1646
|
`${path}.${key} is required`
|
|
1647
1647
|
);
|
|
1648
1648
|
}
|
|
1649
|
-
return
|
|
1649
|
+
return object2[key];
|
|
1650
1650
|
}
|
|
1651
|
-
function caveatString(
|
|
1652
|
-
const value = requiredCaveat(
|
|
1651
|
+
function caveatString(object2, key, path) {
|
|
1652
|
+
const value = requiredCaveat(object2, key, path);
|
|
1653
1653
|
if (typeof value !== "string" || value.length === 0) {
|
|
1654
1654
|
throw new PolicyCapabilityError(
|
|
1655
1655
|
"policy-capability-malformed-caveats",
|
|
@@ -1680,8 +1680,8 @@ function caveatsContain(authority, request) {
|
|
|
1680
1680
|
(statement) => authorityStatements.some((candidate) => jcsCanonicalize(candidate) === jcsCanonicalize(statement))
|
|
1681
1681
|
);
|
|
1682
1682
|
}
|
|
1683
|
-
function hasOwn(
|
|
1684
|
-
return objectHasOwn2(
|
|
1683
|
+
function hasOwn(object2, key) {
|
|
1684
|
+
return objectHasOwn2(object2, key);
|
|
1685
1685
|
}
|
|
1686
1686
|
|
|
1687
1687
|
// src/policy/signed-object.ts
|
|
@@ -1858,13 +1858,12 @@ function digest(input, options2) {
|
|
|
1858
1858
|
}
|
|
1859
1859
|
var identity2 = { code: code2, name, encode: encode4, digest };
|
|
1860
1860
|
|
|
1861
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
1862
|
-
var
|
|
1863
|
-
__export(
|
|
1861
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
1862
|
+
var sha2_browser_exports = {};
|
|
1863
|
+
__export(sha2_browser_exports, {
|
|
1864
1864
|
sha256: () => sha2562,
|
|
1865
1865
|
sha512: () => sha512
|
|
1866
1866
|
});
|
|
1867
|
-
import crypto2 from "crypto";
|
|
1868
1867
|
|
|
1869
1868
|
// ../../node_modules/multiformats/dist/src/hashes/hasher.js
|
|
1870
1869
|
var DEFAULT_MIN_DIGEST_LENGTH = 20;
|
|
@@ -1914,21 +1913,24 @@ function createDigest(digest4, code3, truncate) {
|
|
|
1914
1913
|
return create(code3, digest4);
|
|
1915
1914
|
}
|
|
1916
1915
|
|
|
1917
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
1916
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
1917
|
+
function sha(name2) {
|
|
1918
|
+
return async (data) => new Uint8Array(await crypto.subtle.digest(name2, data));
|
|
1919
|
+
}
|
|
1918
1920
|
var sha2562 = from2({
|
|
1919
1921
|
name: "sha2-256",
|
|
1920
1922
|
code: 18,
|
|
1921
|
-
encode: (
|
|
1923
|
+
encode: sha("SHA-256")
|
|
1922
1924
|
});
|
|
1923
1925
|
var sha512 = from2({
|
|
1924
1926
|
name: "sha2-512",
|
|
1925
1927
|
code: 19,
|
|
1926
|
-
encode: (
|
|
1928
|
+
encode: sha("SHA-512")
|
|
1927
1929
|
});
|
|
1928
1930
|
|
|
1929
1931
|
// ../../node_modules/multiformats/dist/src/basics.js
|
|
1930
1932
|
var bases = { ...identity_exports, ...base2_exports, ...base8_exports, ...base10_exports, ...base16_exports, ...base32_exports, ...base36_exports, ...base58_exports, ...base64_exports, ...base256emoji_exports };
|
|
1931
|
-
var hashes = { ...
|
|
1933
|
+
var hashes = { ...sha2_browser_exports, ...identity_exports2 };
|
|
1932
1934
|
|
|
1933
1935
|
// src/policy/signed-object.ts
|
|
1934
1936
|
import { bytesToHex as bytesToHex2, sha256 as sha2563, verifyMessage } from "viem";
|
|
@@ -2007,17 +2009,17 @@ async function createAndSignSignedObject(input, signer) {
|
|
|
2007
2009
|
}
|
|
2008
2010
|
function createAndSignPolicy(input, signer) {
|
|
2009
2011
|
return createAndSignSignedObject(input, signer).then(
|
|
2010
|
-
(
|
|
2012
|
+
(object2) => validatePolicySignedShape(object2)
|
|
2011
2013
|
);
|
|
2012
2014
|
}
|
|
2013
2015
|
function createAndSignPolicyStatus(input, signer) {
|
|
2014
2016
|
return createAndSignSignedObject(input, signer).then(
|
|
2015
|
-
(
|
|
2017
|
+
(object2) => validatePolicyStatusSignedShape(object2)
|
|
2016
2018
|
);
|
|
2017
2019
|
}
|
|
2018
2020
|
function createAndSignPolicyEngineRecord(input, signer) {
|
|
2019
2021
|
return createAndSignSignedObject(input, signer).then(
|
|
2020
|
-
(
|
|
2022
|
+
(object2) => validatePolicyEngineRecordSignedShape(object2)
|
|
2021
2023
|
);
|
|
2022
2024
|
}
|
|
2023
2025
|
async function verifySignedObject(input) {
|
|
@@ -2121,9 +2123,9 @@ function validateUnsignedForDescriptor(input, descriptor) {
|
|
|
2121
2123
|
}
|
|
2122
2124
|
}
|
|
2123
2125
|
function validatePolicyShape(input, signed) {
|
|
2124
|
-
const
|
|
2126
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2125
2127
|
assertExactKeys2(
|
|
2126
|
-
|
|
2128
|
+
object2,
|
|
2127
2129
|
signed ? [
|
|
2128
2130
|
"schema",
|
|
2129
2131
|
"policyId",
|
|
@@ -2151,30 +2153,30 @@ function validatePolicyShape(input, signed) {
|
|
|
2151
2153
|
],
|
|
2152
2154
|
"$"
|
|
2153
2155
|
);
|
|
2154
|
-
expectConst(requiredString2(
|
|
2156
|
+
expectConst(requiredString2(object2, "schema", "$"), POLICY_SCHEMA, "$.schema");
|
|
2155
2157
|
if (signed) {
|
|
2156
|
-
requiredString2(
|
|
2157
|
-
validateSignature(requiredValue2(
|
|
2158
|
+
requiredString2(object2, "policyId", "$");
|
|
2159
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2158
2160
|
}
|
|
2159
|
-
requiredString2(
|
|
2160
|
-
requiredString2(
|
|
2161
|
-
requiredDateString(
|
|
2162
|
-
optionalDateString(
|
|
2163
|
-
validatePolicyResource(requiredValue2(
|
|
2164
|
-
validateExpression(requiredValue2(
|
|
2165
|
-
validateGrant(requiredValue2(
|
|
2166
|
-
if (hasOwn2(
|
|
2167
|
-
validateDisclosure(requiredValue2(
|
|
2161
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2162
|
+
requiredString2(object2, "signingKeyDid", "$");
|
|
2163
|
+
requiredDateString(object2, "createdAt", "$");
|
|
2164
|
+
optionalDateString(object2, "expiresAt", "$");
|
|
2165
|
+
validatePolicyResource(requiredValue2(object2, "resource", "$"), "$.resource");
|
|
2166
|
+
validateExpression(requiredValue2(object2, "when", "$"), "$.when");
|
|
2167
|
+
validateGrant(requiredValue2(object2, "grant", "$"), "$.grant");
|
|
2168
|
+
if (hasOwn2(object2, "disclosure")) {
|
|
2169
|
+
validateDisclosure(requiredValue2(object2, "disclosure", "$"), "$.disclosure");
|
|
2168
2170
|
}
|
|
2169
|
-
if (hasOwn2(
|
|
2170
|
-
validateAudit(requiredValue2(
|
|
2171
|
+
if (hasOwn2(object2, "audit")) {
|
|
2172
|
+
validateAudit(requiredValue2(object2, "audit", "$"), "$.audit");
|
|
2171
2173
|
}
|
|
2172
|
-
return
|
|
2174
|
+
return object2;
|
|
2173
2175
|
}
|
|
2174
2176
|
function validatePolicyStatusShape(input, signed) {
|
|
2175
|
-
const
|
|
2177
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2176
2178
|
assertExactKeys2(
|
|
2177
|
-
|
|
2179
|
+
object2,
|
|
2178
2180
|
signed ? [
|
|
2179
2181
|
"schema",
|
|
2180
2182
|
"statusId",
|
|
@@ -2198,28 +2200,28 @@ function validatePolicyStatusShape(input, signed) {
|
|
|
2198
2200
|
],
|
|
2199
2201
|
"$"
|
|
2200
2202
|
);
|
|
2201
|
-
expectConst(requiredString2(
|
|
2203
|
+
expectConst(requiredString2(object2, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
|
|
2202
2204
|
if (signed) {
|
|
2203
|
-
requiredString2(
|
|
2204
|
-
validateSignature(requiredValue2(
|
|
2205
|
+
requiredString2(object2, "statusId", "$");
|
|
2206
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2205
2207
|
}
|
|
2206
|
-
requiredString2(
|
|
2207
|
-
requiredString2(
|
|
2208
|
-
requiredInteger(
|
|
2209
|
-
expectOneOf(requiredString2(
|
|
2208
|
+
requiredString2(object2, "policyId", "$");
|
|
2209
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2210
|
+
requiredInteger(object2, "sequence", "$", 0);
|
|
2211
|
+
expectOneOf(requiredString2(object2, "disposition", "$"), [
|
|
2210
2212
|
"active",
|
|
2211
2213
|
"suspended",
|
|
2212
2214
|
"revoked"
|
|
2213
2215
|
], "$.disposition");
|
|
2214
|
-
requiredDateString(
|
|
2215
|
-
optionalString(
|
|
2216
|
-
requiredString2(
|
|
2217
|
-
return
|
|
2216
|
+
requiredDateString(object2, "effectiveAt", "$");
|
|
2217
|
+
optionalString(object2, "reasonCode", "$");
|
|
2218
|
+
requiredString2(object2, "signingKeyDid", "$");
|
|
2219
|
+
return object2;
|
|
2218
2220
|
}
|
|
2219
2221
|
function validatePolicyEngineRecordShape(input, signed) {
|
|
2220
|
-
const
|
|
2222
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2221
2223
|
assertExactKeys2(
|
|
2222
|
-
|
|
2224
|
+
object2,
|
|
2223
2225
|
signed ? [
|
|
2224
2226
|
"schema",
|
|
2225
2227
|
"engineRecordId",
|
|
@@ -2244,44 +2246,44 @@ function validatePolicyEngineRecordShape(input, signed) {
|
|
|
2244
2246
|
"$"
|
|
2245
2247
|
);
|
|
2246
2248
|
expectConst(
|
|
2247
|
-
requiredString2(
|
|
2249
|
+
requiredString2(object2, "schema", "$"),
|
|
2248
2250
|
POLICY_ENGINE_RECORD_SCHEMA,
|
|
2249
2251
|
"$.schema"
|
|
2250
2252
|
);
|
|
2251
2253
|
if (signed) {
|
|
2252
|
-
requiredString2(
|
|
2253
|
-
validateSignature(requiredValue2(
|
|
2254
|
+
requiredString2(object2, "engineRecordId", "$");
|
|
2255
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2254
2256
|
}
|
|
2255
|
-
requiredString2(
|
|
2256
|
-
requiredString2(
|
|
2257
|
-
requiredString2(
|
|
2257
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2258
|
+
requiredString2(object2, "endpoint", "$");
|
|
2259
|
+
requiredString2(object2, "audience", "$");
|
|
2258
2260
|
requiredStringArray(
|
|
2259
|
-
|
|
2261
|
+
object2,
|
|
2260
2262
|
"supportedPolicyVersions",
|
|
2261
2263
|
"$",
|
|
2262
2264
|
(value, path) => expectConst(value, "v0", path)
|
|
2263
2265
|
);
|
|
2264
|
-
requiredStringArray(
|
|
2265
|
-
requiredString2(
|
|
2266
|
-
requiredDateString(
|
|
2267
|
-
return
|
|
2266
|
+
requiredStringArray(object2, "supportedEvidenceVerifiers", "$");
|
|
2267
|
+
requiredString2(object2, "grantIssuerDid", "$");
|
|
2268
|
+
requiredDateString(object2, "expiresAt", "$");
|
|
2269
|
+
return object2;
|
|
2268
2270
|
}
|
|
2269
2271
|
function validateSignature(input) {
|
|
2270
|
-
const
|
|
2271
|
-
assertExactKeys2(
|
|
2272
|
-
const suite = requiredString2(
|
|
2272
|
+
const object2 = expectJsonObject(input, "$.signature");
|
|
2273
|
+
assertExactKeys2(object2, ["suite", "signerDid", "value"], "$.signature");
|
|
2274
|
+
const suite = requiredString2(object2, "suite", "$.signature");
|
|
2273
2275
|
assertSupportedSignatureSuite(suite);
|
|
2274
|
-
const signerDid = requiredString2(
|
|
2275
|
-
const value = requiredString2(
|
|
2276
|
+
const signerDid = requiredString2(object2, "signerDid", "$.signature");
|
|
2277
|
+
const value = requiredString2(object2, "value", "$.signature");
|
|
2276
2278
|
decodeSignatureValue(value, suite);
|
|
2277
2279
|
return { suite, signerDid, value };
|
|
2278
2280
|
}
|
|
2279
2281
|
function validatePolicyResource(input, path) {
|
|
2280
|
-
const
|
|
2281
|
-
assertExactKeys2(
|
|
2282
|
-
requiredString2(
|
|
2283
|
-
requiredString2(
|
|
2284
|
-
const ceiling = requiredArray2(
|
|
2282
|
+
const object2 = expectJsonObject(input, path);
|
|
2283
|
+
assertExactKeys2(object2, ["resourceType", "resourceId", "permissionsCeiling"], path);
|
|
2284
|
+
requiredString2(object2, "resourceType", path);
|
|
2285
|
+
requiredString2(object2, "resourceId", path);
|
|
2286
|
+
const ceiling = requiredArray2(object2, "permissionsCeiling", path, 1);
|
|
2285
2287
|
for (let index = 0; index < ceiling.length; index++) {
|
|
2286
2288
|
validatePolicyCapability(ceiling[index], `${path}.permissionsCeiling[${index}]`);
|
|
2287
2289
|
}
|
|
@@ -2297,10 +2299,10 @@ function validatePolicyPermissionsCeilingForSigning(input) {
|
|
|
2297
2299
|
}
|
|
2298
2300
|
}
|
|
2299
2301
|
function validatePolicyCapability(input, path) {
|
|
2300
|
-
const
|
|
2302
|
+
const object2 = expectJsonObject(input, path);
|
|
2301
2303
|
try {
|
|
2302
|
-
const canonical = canonicalizePolicyCapability(
|
|
2303
|
-
if (jcsCanonicalize(
|
|
2304
|
+
const canonical = canonicalizePolicyCapability(object2);
|
|
2305
|
+
if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
|
|
2304
2306
|
throw new SignedObjectSchemaError(`${path} must be canonical PolicyCapability JSON`);
|
|
2305
2307
|
}
|
|
2306
2308
|
} catch (error) {
|
|
@@ -2313,10 +2315,10 @@ function validatePolicyCapability(input, path) {
|
|
|
2313
2315
|
}
|
|
2314
2316
|
}
|
|
2315
2317
|
function validatePolicyCapabilityForSigning(input, path) {
|
|
2316
|
-
const
|
|
2318
|
+
const object2 = expectJsonObject(input, path);
|
|
2317
2319
|
try {
|
|
2318
|
-
const canonical = normalizePolicyCapability(
|
|
2319
|
-
if (jcsCanonicalize(
|
|
2320
|
+
const canonical = normalizePolicyCapability(object2);
|
|
2321
|
+
if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
|
|
2320
2322
|
throw new SignedObjectSchemaError(`${path} must be strict canonical PolicyCapability JSON`);
|
|
2321
2323
|
}
|
|
2322
2324
|
} catch (error) {
|
|
@@ -2329,43 +2331,43 @@ function validatePolicyCapabilityForSigning(input, path) {
|
|
|
2329
2331
|
}
|
|
2330
2332
|
}
|
|
2331
2333
|
function validateExpression(input, path) {
|
|
2332
|
-
const
|
|
2333
|
-
const keys = Object.keys(
|
|
2334
|
+
const object2 = expectJsonObject(input, path);
|
|
2335
|
+
const keys = Object.keys(object2);
|
|
2334
2336
|
if (keys.length !== 1) {
|
|
2335
2337
|
throw new SignedObjectSchemaError(`${path} must have exactly one expression key`);
|
|
2336
2338
|
}
|
|
2337
2339
|
const key = keys[0];
|
|
2338
2340
|
if (key === "allOf" || key === "anyOf") {
|
|
2339
|
-
const values = requiredArray2(
|
|
2341
|
+
const values = requiredArray2(object2, key, path, 1);
|
|
2340
2342
|
for (let index = 0; index < values.length; index++) {
|
|
2341
2343
|
validateExpression(values[index], `${path}.${key}[${index}]`);
|
|
2342
2344
|
}
|
|
2343
2345
|
return;
|
|
2344
2346
|
}
|
|
2345
2347
|
if (key === "subject") {
|
|
2346
|
-
const subject = expectJsonObject(requiredValue2(
|
|
2348
|
+
const subject = expectJsonObject(requiredValue2(object2, "subject", path), `${path}.subject`);
|
|
2347
2349
|
assertExactKeys2(subject, ["did"], `${path}.subject`);
|
|
2348
2350
|
requiredString2(subject, "did", `${path}.subject`);
|
|
2349
2351
|
return;
|
|
2350
2352
|
}
|
|
2351
2353
|
if (key === "evidence") {
|
|
2352
|
-
validateEvidenceRequirement(requiredValue2(
|
|
2354
|
+
validateEvidenceRequirement(requiredValue2(object2, "evidence", path), `${path}.evidence`);
|
|
2353
2355
|
return;
|
|
2354
2356
|
}
|
|
2355
2357
|
throw new SignedObjectSchemaError(`${path} has unknown expression key ${key}`);
|
|
2356
2358
|
}
|
|
2357
2359
|
function validateEvidenceRequirement(input, path) {
|
|
2358
|
-
const
|
|
2360
|
+
const object2 = expectJsonObject(input, path);
|
|
2359
2361
|
assertExactKeys2(
|
|
2360
|
-
|
|
2362
|
+
object2,
|
|
2361
2363
|
["requirementId", "verifier", "requirements", "authority", "freshness"],
|
|
2362
2364
|
path
|
|
2363
2365
|
);
|
|
2364
|
-
requiredString2(
|
|
2365
|
-
requiredString2(
|
|
2366
|
-
requiredValue2(
|
|
2367
|
-
if (hasOwn2(
|
|
2368
|
-
const authority = expectJsonObject(requiredValue2(
|
|
2366
|
+
requiredString2(object2, "requirementId", path);
|
|
2367
|
+
requiredString2(object2, "verifier", path);
|
|
2368
|
+
requiredValue2(object2, "requirements", path);
|
|
2369
|
+
if (hasOwn2(object2, "authority")) {
|
|
2370
|
+
const authority = expectJsonObject(requiredValue2(object2, "authority", path), `${path}.authority`);
|
|
2369
2371
|
assertExactKeys2(
|
|
2370
2372
|
authority,
|
|
2371
2373
|
["profile", "acceptedIssuers", "allowOwnerAuthorizedIssuer"],
|
|
@@ -2377,35 +2379,35 @@ function validateEvidenceRequirement(input, path) {
|
|
|
2377
2379
|
}
|
|
2378
2380
|
optionalBoolean(authority, "allowOwnerAuthorizedIssuer", `${path}.authority`);
|
|
2379
2381
|
}
|
|
2380
|
-
if (hasOwn2(
|
|
2381
|
-
const freshness = expectJsonObject(requiredValue2(
|
|
2382
|
+
if (hasOwn2(object2, "freshness")) {
|
|
2383
|
+
const freshness = expectJsonObject(requiredValue2(object2, "freshness", path), `${path}.freshness`);
|
|
2382
2384
|
assertExactKeys2(freshness, ["maxStatusAgeSeconds"], `${path}.freshness`);
|
|
2383
2385
|
requiredInteger(freshness, "maxStatusAgeSeconds", `${path}.freshness`, 0);
|
|
2384
2386
|
}
|
|
2385
2387
|
}
|
|
2386
2388
|
function validateGrant(input, path) {
|
|
2387
|
-
const
|
|
2388
|
-
assertExactKeys2(
|
|
2389
|
-
expectConst(requiredString2(
|
|
2390
|
-
requiredInteger(
|
|
2391
|
-
expectOneOf(requiredString2(
|
|
2389
|
+
const object2 = expectJsonObject(input, path);
|
|
2390
|
+
assertExactKeys2(object2, ["output", "maxTtlSeconds", "delegationMode", "revocation"], path);
|
|
2391
|
+
expectConst(requiredString2(object2, "output", path), "portable-delegation", `${path}.output`);
|
|
2392
|
+
requiredInteger(object2, "maxTtlSeconds", path, 1);
|
|
2393
|
+
expectOneOf(requiredString2(object2, "delegationMode", path), [
|
|
2392
2394
|
"terminal",
|
|
2393
2395
|
"attenuable"
|
|
2394
2396
|
], `${path}.delegationMode`);
|
|
2395
|
-
expectOneOf(requiredString2(
|
|
2397
|
+
expectOneOf(requiredString2(object2, "revocation", path), [
|
|
2396
2398
|
"refresh_only",
|
|
2397
2399
|
"active_cutoff"
|
|
2398
2400
|
], `${path}.revocation`);
|
|
2399
2401
|
}
|
|
2400
2402
|
function validateDisclosure(input, path) {
|
|
2401
|
-
const
|
|
2402
|
-
assertExactKeys2(
|
|
2403
|
-
expectOneOf(requiredString2(
|
|
2403
|
+
const object2 = expectJsonObject(input, path);
|
|
2404
|
+
assertExactKeys2(object2, ["denial"], path);
|
|
2405
|
+
expectOneOf(requiredString2(object2, "denial", path), ["none", "code", "debug"], `${path}.denial`);
|
|
2404
2406
|
}
|
|
2405
2407
|
function validateAudit(input, path) {
|
|
2406
|
-
const
|
|
2407
|
-
assertExactKeys2(
|
|
2408
|
-
expectOneOf(requiredString2(
|
|
2408
|
+
const object2 = expectJsonObject(input, path);
|
|
2409
|
+
assertExactKeys2(object2, ["issuance"], path);
|
|
2410
|
+
expectOneOf(requiredString2(object2, "issuance", path), ["off", "security", "full"], `${path}.issuance`);
|
|
2409
2411
|
}
|
|
2410
2412
|
function materialForUnsigned(unsigned, descriptor) {
|
|
2411
2413
|
const jcs = jcsCanonicalize(unsigned);
|
|
@@ -2554,9 +2556,9 @@ function encodeSignatureValue(value, suite) {
|
|
|
2554
2556
|
decodeSignatureValue(encoded, suite);
|
|
2555
2557
|
return encoded;
|
|
2556
2558
|
}
|
|
2557
|
-
function stripOwnIdAndSignature(
|
|
2559
|
+
function stripOwnIdAndSignature(object2, descriptor) {
|
|
2558
2560
|
const output = /* @__PURE__ */ Object.create(null);
|
|
2559
|
-
for (const [key, value] of Object.entries(
|
|
2561
|
+
for (const [key, value] of Object.entries(object2)) {
|
|
2560
2562
|
if (key === descriptor.idField || key === "signature") {
|
|
2561
2563
|
continue;
|
|
2562
2564
|
}
|
|
@@ -2565,8 +2567,8 @@ function stripOwnIdAndSignature(object, descriptor) {
|
|
|
2565
2567
|
return output;
|
|
2566
2568
|
}
|
|
2567
2569
|
function descriptorForUnsigned(input) {
|
|
2568
|
-
const
|
|
2569
|
-
return descriptorForSchema(requiredString2(
|
|
2570
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2571
|
+
return descriptorForSchema(requiredString2(object2, "schema", "$"));
|
|
2570
2572
|
}
|
|
2571
2573
|
function descriptorForSchema(schema) {
|
|
2572
2574
|
if (schema === POLICY_SCHEMA) return DESCRIPTORS.Policy;
|
|
@@ -2580,28 +2582,28 @@ function expectJsonObject(input, path) {
|
|
|
2580
2582
|
}
|
|
2581
2583
|
return input;
|
|
2582
2584
|
}
|
|
2583
|
-
function assertExactKeys2(
|
|
2585
|
+
function assertExactKeys2(object2, allowed, path) {
|
|
2584
2586
|
const allowedSet = new Set(allowed);
|
|
2585
|
-
for (const key of Object.keys(
|
|
2587
|
+
for (const key of Object.keys(object2)) {
|
|
2586
2588
|
if (!allowedSet.has(key)) {
|
|
2587
2589
|
throw new SignedObjectSchemaError(`${path} has unknown field ${key}`);
|
|
2588
2590
|
}
|
|
2589
2591
|
}
|
|
2590
2592
|
}
|
|
2591
|
-
function requiredValue2(
|
|
2592
|
-
if (!hasOwn2(
|
|
2593
|
+
function requiredValue2(object2, key, path) {
|
|
2594
|
+
if (!hasOwn2(object2, key)) {
|
|
2593
2595
|
throw new SignedObjectSchemaError(`${path}.${key} is required`);
|
|
2594
2596
|
}
|
|
2595
|
-
return
|
|
2597
|
+
return object2[key];
|
|
2596
2598
|
}
|
|
2597
|
-
function requiredString2(
|
|
2598
|
-
return requireStringType(requiredValue2(
|
|
2599
|
+
function requiredString2(object2, key, path) {
|
|
2600
|
+
return requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
|
|
2599
2601
|
}
|
|
2600
|
-
function optionalString(
|
|
2601
|
-
if (!hasOwn2(
|
|
2602
|
+
function optionalString(object2, key, path) {
|
|
2603
|
+
if (!hasOwn2(object2, key)) {
|
|
2602
2604
|
return;
|
|
2603
2605
|
}
|
|
2604
|
-
requireStringType(requiredValue2(
|
|
2606
|
+
requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
|
|
2605
2607
|
}
|
|
2606
2608
|
function requireStringType(value, path) {
|
|
2607
2609
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -2609,16 +2611,16 @@ function requireStringType(value, path) {
|
|
|
2609
2611
|
}
|
|
2610
2612
|
return value;
|
|
2611
2613
|
}
|
|
2612
|
-
function optionalBoolean(
|
|
2613
|
-
if (!hasOwn2(
|
|
2614
|
+
function optionalBoolean(object2, key, path) {
|
|
2615
|
+
if (!hasOwn2(object2, key)) {
|
|
2614
2616
|
return;
|
|
2615
2617
|
}
|
|
2616
|
-
if (typeof requiredValue2(
|
|
2618
|
+
if (typeof requiredValue2(object2, key, path) !== "boolean") {
|
|
2617
2619
|
throw new SignedObjectSchemaError(`${path}.${key} must be a boolean`);
|
|
2618
2620
|
}
|
|
2619
2621
|
}
|
|
2620
|
-
function requiredInteger(
|
|
2621
|
-
const value = requiredValue2(
|
|
2622
|
+
function requiredInteger(object2, key, path, minimum) {
|
|
2623
|
+
const value = requiredValue2(object2, key, path);
|
|
2622
2624
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum) {
|
|
2623
2625
|
throw new SignedObjectSchemaError(
|
|
2624
2626
|
`${path}.${key} must be an integer >= ${minimum}`
|
|
@@ -2626,8 +2628,8 @@ function requiredInteger(object, key, path, minimum) {
|
|
|
2626
2628
|
}
|
|
2627
2629
|
return value;
|
|
2628
2630
|
}
|
|
2629
|
-
function requiredArray2(
|
|
2630
|
-
const value = requiredValue2(
|
|
2631
|
+
function requiredArray2(object2, key, path, minimum) {
|
|
2632
|
+
const value = requiredValue2(object2, key, path);
|
|
2631
2633
|
if (!Array.isArray(value) || value.length < minimum) {
|
|
2632
2634
|
throw new SignedObjectSchemaError(
|
|
2633
2635
|
`${path}.${key} must be an array with at least ${minimum} item(s)`
|
|
@@ -2635,22 +2637,22 @@ function requiredArray2(object, key, path, minimum) {
|
|
|
2635
2637
|
}
|
|
2636
2638
|
return value;
|
|
2637
2639
|
}
|
|
2638
|
-
function requiredStringArray(
|
|
2639
|
-
const values = requiredArray2(
|
|
2640
|
+
function requiredStringArray(object2, key, path, check) {
|
|
2641
|
+
const values = requiredArray2(object2, key, path, 0);
|
|
2640
2642
|
for (let index = 0; index < values.length; index++) {
|
|
2641
2643
|
const itemPath = `${path}.${key}[${index}]`;
|
|
2642
2644
|
const value = requireStringType(values[index], itemPath);
|
|
2643
2645
|
check?.(value, itemPath);
|
|
2644
2646
|
}
|
|
2645
2647
|
}
|
|
2646
|
-
function requiredDateString(
|
|
2647
|
-
assertRfc3339(requiredString2(
|
|
2648
|
+
function requiredDateString(object2, key, path) {
|
|
2649
|
+
assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
|
|
2648
2650
|
}
|
|
2649
|
-
function optionalDateString(
|
|
2650
|
-
if (!hasOwn2(
|
|
2651
|
+
function optionalDateString(object2, key, path) {
|
|
2652
|
+
if (!hasOwn2(object2, key)) {
|
|
2651
2653
|
return;
|
|
2652
2654
|
}
|
|
2653
|
-
assertRfc3339(requiredString2(
|
|
2655
|
+
assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
|
|
2654
2656
|
}
|
|
2655
2657
|
function assertRfc3339(value, path) {
|
|
2656
2658
|
const match = value.match(
|
|
@@ -2682,8 +2684,8 @@ function expectOneOf(actual, allowed, path) {
|
|
|
2682
2684
|
}
|
|
2683
2685
|
throw new SignedObjectSchemaError(`${path} has unsupported value ${actual}`);
|
|
2684
2686
|
}
|
|
2685
|
-
function hasOwn2(
|
|
2686
|
-
return objectHasOwn3(
|
|
2687
|
+
function hasOwn2(object2, key) {
|
|
2688
|
+
return objectHasOwn3(object2, key);
|
|
2687
2689
|
}
|
|
2688
2690
|
function assertSupportedSignatureSuite(suite) {
|
|
2689
2691
|
if (suite !== ED25519_JCS_SIGNATURE_SUITE && suite !== EIP191_JCS_SIGNATURE_SUITE) {
|
|
@@ -2762,13 +2764,13 @@ function base64UrlDecode(value) {
|
|
|
2762
2764
|
return decoded;
|
|
2763
2765
|
}
|
|
2764
2766
|
function hexToBytes(value) {
|
|
2765
|
-
const
|
|
2766
|
-
if (
|
|
2767
|
+
const hex2 = value.slice(2);
|
|
2768
|
+
if (hex2.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex2)) {
|
|
2767
2769
|
throw new SignatureMaterialError("hex signature must have even length");
|
|
2768
2770
|
}
|
|
2769
|
-
const output = new Uint8Array(
|
|
2771
|
+
const output = new Uint8Array(hex2.length / 2);
|
|
2770
2772
|
for (let index = 0; index < output.length; index++) {
|
|
2771
|
-
output[index] = Number.parseInt(
|
|
2773
|
+
output[index] = Number.parseInt(hex2.slice(index * 2, index * 2 + 2), 16);
|
|
2772
2774
|
}
|
|
2773
2775
|
return output;
|
|
2774
2776
|
}
|
|
@@ -2910,9 +2912,9 @@ function expectObject2(input, path, code3) {
|
|
|
2910
2912
|
);
|
|
2911
2913
|
}
|
|
2912
2914
|
}
|
|
2913
|
-
function assertExactKeys3(
|
|
2915
|
+
function assertExactKeys3(object2, allowed, path) {
|
|
2914
2916
|
const allowedSet = new Set(allowed);
|
|
2915
|
-
for (const key of Object.keys(
|
|
2917
|
+
for (const key of Object.keys(object2)) {
|
|
2916
2918
|
if (!allowedSet.has(key)) {
|
|
2917
2919
|
throw new PolicyAuthoringError(
|
|
2918
2920
|
"policy-authoring-unknown-key",
|
|
@@ -2921,17 +2923,17 @@ function assertExactKeys3(object, allowed, path) {
|
|
|
2921
2923
|
}
|
|
2922
2924
|
}
|
|
2923
2925
|
}
|
|
2924
|
-
function requiredValue3(
|
|
2925
|
-
if (!hasOwn3(
|
|
2926
|
+
function requiredValue3(object2, key, path) {
|
|
2927
|
+
if (!hasOwn3(object2, key)) {
|
|
2926
2928
|
throw new PolicyAuthoringError(
|
|
2927
2929
|
"policy-authoring-malformed",
|
|
2928
2930
|
`${path}.${key} is required`
|
|
2929
2931
|
);
|
|
2930
2932
|
}
|
|
2931
|
-
return
|
|
2933
|
+
return object2[key];
|
|
2932
2934
|
}
|
|
2933
|
-
function requiredString3(
|
|
2934
|
-
const value = requiredValue3(
|
|
2935
|
+
function requiredString3(object2, key, path) {
|
|
2936
|
+
const value = requiredValue3(object2, key, path);
|
|
2935
2937
|
if (typeof value !== "string" || value.length === 0) {
|
|
2936
2938
|
throw new PolicyAuthoringError(
|
|
2937
2939
|
"policy-authoring-malformed",
|
|
@@ -2940,11 +2942,11 @@ function requiredString3(object, key, path) {
|
|
|
2940
2942
|
}
|
|
2941
2943
|
return value;
|
|
2942
2944
|
}
|
|
2943
|
-
function fieldString(
|
|
2944
|
-
if (!hasOwn3(
|
|
2945
|
+
function fieldString(object2, key, path, code3) {
|
|
2946
|
+
if (!hasOwn3(object2, key)) {
|
|
2945
2947
|
throw new PolicyAuthoringError(code3, `${path}.${key} is required`);
|
|
2946
2948
|
}
|
|
2947
|
-
const value =
|
|
2949
|
+
const value = object2[key];
|
|
2948
2950
|
if (typeof value !== "string" || value.length === 0) {
|
|
2949
2951
|
throw new PolicyAuthoringError(
|
|
2950
2952
|
code3,
|
|
@@ -2982,8 +2984,609 @@ function parseStrictRfc3339(value, path) {
|
|
|
2982
2984
|
var objectHasOwn4 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
2983
2985
|
Object.prototype.hasOwnProperty
|
|
2984
2986
|
);
|
|
2985
|
-
function hasOwn3(
|
|
2986
|
-
return objectHasOwn4(
|
|
2987
|
+
function hasOwn3(object2, key) {
|
|
2988
|
+
return objectHasOwn4(object2, key);
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
// src/policy/unified.ts
|
|
2992
|
+
import { sha256 as sha2564 } from "@noble/hashes/sha256";
|
|
2993
|
+
import { blake3 } from "@noble/hashes/blake3";
|
|
2994
|
+
import { ed25519 as ed255192 } from "@noble/curves/ed25519";
|
|
2995
|
+
import { z as z2 } from "zod";
|
|
2996
|
+
var POLICY_V1_SCHEMA = "xyz.tinycloud.policy/policy/v1";
|
|
2997
|
+
var POLICY_CAPABILITY_V1_SCHEMA = "xyz.tinycloud.policy/capability/v1";
|
|
2998
|
+
var POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA = "xyz.tinycloud.policy/enforcement-delegation/v2";
|
|
2999
|
+
var ATTESTED_ENFORCER_BINDING_V2_SCHEMA = "xyz.tinycloud.policy/attested-enforcer/v2";
|
|
3000
|
+
var ROOT_STATUS_CHECKPOINT_V1_SCHEMA = "xyz.tinycloud.policy/root-status/v1";
|
|
3001
|
+
var ROOT_REVOCATION_V1_SCHEMA = "xyz.tinycloud.policy/root-revocation/v1";
|
|
3002
|
+
var POLICY_SESSION_UCAN_V1_PROFILE = "policy-session-ucan/v1";
|
|
3003
|
+
var POLICY_V1_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
|
|
3004
|
+
var POLICY_CAPABILITY_V1_DOMAIN = "xyz.tinycloud.policy/PolicyCapability/v1\0";
|
|
3005
|
+
var CONTENT_SOURCE_V1_DOMAIN = "xyz.tinycloud.policy/ContentSource/v1\0";
|
|
3006
|
+
var NATIVE_PROJECTION_V1_DOMAIN = "xyz.tinycloud.policy/NativeProjection/v1\0";
|
|
3007
|
+
var ROOT_STATUS_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusCheckpoint/v1\0";
|
|
3008
|
+
var ROOT_STATUS_RENEWAL_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusRenewal/v1\0";
|
|
3009
|
+
var ROOT_REVOCATION_V1_DOMAIN = "xyz.tinycloud.policy/RootRevocation/v1\0";
|
|
3010
|
+
var LAST_V2_CREATE_AT = "2026-09-30T00:00:00Z";
|
|
3011
|
+
var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
|
|
3012
|
+
var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
|
|
3013
|
+
function verifyPolicyRootStatusCheckpointV3(input) {
|
|
3014
|
+
const checkpoint = input.checkpoint;
|
|
3015
|
+
const allowed = /* @__PURE__ */ new Set(["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "state", "sequence", "checkedAt", "freshUntil", "revokedAt", "revocationCid", "previousCheckpointDigestHex", "issuerDid", "signature"]);
|
|
3016
|
+
if (Object.keys(checkpoint).some((key) => !allowed.has(key)) || checkpoint.schema !== ROOT_STATUS_CHECKPOINT_V1_SCHEMA || checkpoint.targetCid !== input.rootCid || checkpoint.targetRole !== "policy-authority" && checkpoint.targetRole !== "policy-enforcement" || checkpoint.state !== "active" && checkpoint.state !== "revoked" || typeof checkpoint.ownerDid !== "string" || typeof checkpoint.nodeAudience !== "string" || checkpoint.issuerDid !== checkpoint.nodeAudience || input.expectedNodeAudience !== void 0 && checkpoint.nodeAudience !== input.expectedNodeAudience || !Number.isInteger(checkpoint.sequence) || checkpoint.sequence < 1 || typeof checkpoint.checkedAt !== "string" || typeof checkpoint.freshUntil !== "string") return false;
|
|
3017
|
+
const checkedAt = Date.parse(checkpoint.checkedAt);
|
|
3018
|
+
const freshUntil = Date.parse(checkpoint.freshUntil);
|
|
3019
|
+
const now = (input.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
3020
|
+
if (!Number.isFinite(checkedAt) || !Number.isFinite(freshUntil) || freshUntil < now || freshUntil <= checkedAt || freshUntil - checkedAt > 3e5) return false;
|
|
3021
|
+
if (checkpoint.sequence === 1 !== (checkpoint.previousCheckpointDigestHex === void 0)) return false;
|
|
3022
|
+
if (checkpoint.sequence !== 1 && (typeof checkpoint.previousCheckpointDigestHex !== "string" || !/^[0-9a-f]{64}$/.test(checkpoint.previousCheckpointDigestHex))) return false;
|
|
3023
|
+
if (checkpoint.state === "active" && (checkpoint.revokedAt !== void 0 || checkpoint.revocationCid !== void 0)) return false;
|
|
3024
|
+
if (checkpoint.state === "revoked" && (typeof checkpoint.revokedAt !== "string" || typeof checkpoint.revocationCid !== "string")) return false;
|
|
3025
|
+
const signature = checkpoint.signature;
|
|
3026
|
+
if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== checkpoint.issuerDid || typeof signature.value !== "string") return false;
|
|
3027
|
+
try {
|
|
3028
|
+
const principal = checkpoint.issuerDid.split("#", 1)[0];
|
|
3029
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3030
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
|
|
3031
|
+
const unsigned = { ...checkpoint };
|
|
3032
|
+
delete unsigned.signature;
|
|
3033
|
+
return ed255192.verify(
|
|
3034
|
+
decodeBase64Url(signature.value),
|
|
3035
|
+
sha2564(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(unsigned))),
|
|
3036
|
+
didMaterial.slice(2)
|
|
3037
|
+
);
|
|
3038
|
+
} catch {
|
|
3039
|
+
return false;
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
async function getPolicyRootStatusV3(input) {
|
|
3043
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3044
|
+
const response = await fetchFn(new URL(`/share/v3/policy/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
|
|
3045
|
+
method: "GET",
|
|
3046
|
+
redirect: "error",
|
|
3047
|
+
headers: { accept: "application/json" }
|
|
3048
|
+
});
|
|
3049
|
+
if (!response.ok) throw new Error(`policy root status rejected (${response.status})`);
|
|
3050
|
+
const value = object(await response.json(), "policy root status");
|
|
3051
|
+
const checkpoint = object(value.checkpoint, "policy root checkpoint");
|
|
3052
|
+
if (value.rootCid !== input.rootCid || value.state !== "active" && value.state !== "revoked" || value.state !== checkpoint.state || !verifyPolicyRootStatusCheckpointV3({ rootCid: input.rootCid, checkpoint, expectedNodeAudience: input.expectedNodeAudience, now: input.now }))
|
|
3053
|
+
throw new Error("policy root status binding is invalid");
|
|
3054
|
+
const revocation = value.revocation === void 0 ? void 0 : object(value.revocation, "policy root revocation");
|
|
3055
|
+
if (value.state === "revoked" !== (revocation !== void 0) || revocation !== void 0 && !verifyPolicyRootRevocationV3({
|
|
3056
|
+
rootCid: input.rootCid,
|
|
3057
|
+
checkpoint,
|
|
3058
|
+
revocation,
|
|
3059
|
+
expectedEnforcerDid: input.expectedEnforcerDid
|
|
3060
|
+
})) throw new Error("policy root status revocation evidence is invalid");
|
|
3061
|
+
return { rootCid: input.rootCid, state: value.state, checkpoint, ...revocation === void 0 ? {} : { revocation } };
|
|
3062
|
+
}
|
|
3063
|
+
function verifyPolicyRootRevocationV3(input) {
|
|
3064
|
+
const value = input.revocation;
|
|
3065
|
+
const allowed = ["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "revokedAt", "reason", "issuerDid", "signature"];
|
|
3066
|
+
if (Object.keys(value).length !== allowed.length || Object.keys(value).some((key) => !allowed.includes(key)) || value.schema !== ROOT_REVOCATION_V1_SCHEMA || value.targetCid !== input.rootCid || value.targetRole !== input.checkpoint.targetRole || value.ownerDid !== input.checkpoint.ownerDid || value.nodeAudience !== input.checkpoint.nodeAudience || value.revokedAt !== input.checkpoint.revokedAt || typeof value.reason !== "string" || value.reason.length === 0 || typeof value.issuerDid !== "string") return false;
|
|
3067
|
+
const authorized = value.issuerDid === value.ownerDid || value.targetRole === "policy-enforcement" && value.issuerDid === input.expectedEnforcerDid;
|
|
3068
|
+
if (!authorized) return false;
|
|
3069
|
+
const signature = value.signature;
|
|
3070
|
+
if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== value.issuerDid || typeof signature.value !== "string") return false;
|
|
3071
|
+
try {
|
|
3072
|
+
const principal = value.issuerDid.split("#", 1)[0];
|
|
3073
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3074
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
|
|
3075
|
+
const unsigned = { ...value };
|
|
3076
|
+
delete unsigned.signature;
|
|
3077
|
+
const digest4 = sha2564(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned)));
|
|
3078
|
+
return input.checkpoint.revocationCid === hex(digest4) && ed255192.verify(decodeBase64Url(signature.value), digest4, didMaterial.slice(2));
|
|
3079
|
+
} catch {
|
|
3080
|
+
return false;
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
async function renewPolicyRootStatusV3(input) {
|
|
3084
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3085
|
+
const current = await getPolicyRootStatusV3({ nodeOrigin: input.nodeOrigin, rootCid: input.rootCid, expectedNodeAudience: input.nodeAudience, now: input.now, fetch: fetchFn });
|
|
3086
|
+
if (current.state !== "active" || current.checkpoint.ownerDid !== input.ownerDid || current.checkpoint.nodeAudience !== input.nodeAudience || current.checkpoint.state !== "active" || !Number.isInteger(current.checkpoint.sequence))
|
|
3087
|
+
throw new Error("policy root status cannot be renewed");
|
|
3088
|
+
const currentUnsigned = { ...current.checkpoint };
|
|
3089
|
+
delete currentUnsigned.signature;
|
|
3090
|
+
const previousCheckpointDigestHex = hex(sha2564(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(currentUnsigned))));
|
|
3091
|
+
const unsigned = {
|
|
3092
|
+
schema: "xyz.tinycloud.policy/root-status-renewal/v1",
|
|
3093
|
+
targetCid: input.rootCid,
|
|
3094
|
+
ownerDid: input.ownerDid,
|
|
3095
|
+
nodeAudience: input.nodeAudience,
|
|
3096
|
+
issuedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
3097
|
+
nonce: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3098
|
+
sequence: current.checkpoint.sequence + 1,
|
|
3099
|
+
previousCheckpointDigestHex
|
|
3100
|
+
};
|
|
3101
|
+
const signature = await input.sign(sha2564(new TextEncoder().encode(ROOT_STATUS_RENEWAL_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3102
|
+
if (signature.length !== 64) throw new Error("policy root renewal signature must be Ed25519");
|
|
3103
|
+
const response = await fetchFn(new URL("/share/v3/policy/status", input.nodeOrigin), {
|
|
3104
|
+
method: "POST",
|
|
3105
|
+
redirect: "error",
|
|
3106
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3107
|
+
body: JSON.stringify({ rootCid: input.rootCid, renewal: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.ownerDid, value: encodeBase64Url(signature) } } })
|
|
3108
|
+
});
|
|
3109
|
+
if (!response.ok) throw new Error(`policy root renewal rejected (${response.status})`);
|
|
3110
|
+
return object(await response.json(), "policy root renewal");
|
|
3111
|
+
}
|
|
3112
|
+
async function revokePolicyRootV3(input) {
|
|
3113
|
+
if (input.reason.length === 0) throw new Error("policy root revocation reason is required");
|
|
3114
|
+
const unsigned = {
|
|
3115
|
+
schema: ROOT_REVOCATION_V1_SCHEMA,
|
|
3116
|
+
targetCid: input.rootCid,
|
|
3117
|
+
targetRole: input.targetRole,
|
|
3118
|
+
ownerDid: input.ownerDid,
|
|
3119
|
+
nodeAudience: input.nodeAudience,
|
|
3120
|
+
revokedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
3121
|
+
reason: input.reason,
|
|
3122
|
+
issuerDid: input.issuerDid
|
|
3123
|
+
};
|
|
3124
|
+
const signature = await input.sign(sha2564(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3125
|
+
if (signature.length !== 64) throw new Error("policy root revocation signature must be Ed25519");
|
|
3126
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3127
|
+
const response = await fetchFn(new URL("/revoke", input.nodeOrigin), {
|
|
3128
|
+
method: "POST",
|
|
3129
|
+
redirect: "error",
|
|
3130
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3131
|
+
body: JSON.stringify({ revocation: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.issuerDid, value: encodeBase64Url(signature) } } })
|
|
3132
|
+
});
|
|
3133
|
+
if (!response.ok) throw new Error(`policy root revocation rejected (${response.status})`);
|
|
3134
|
+
return object(await response.json(), "policy root revocation");
|
|
3135
|
+
}
|
|
3136
|
+
var POLICY_SESSION_FACT_KEYS = [
|
|
3137
|
+
"profile",
|
|
3138
|
+
"ownerDid",
|
|
3139
|
+
"policyId",
|
|
3140
|
+
"policyDigestHex",
|
|
3141
|
+
"policyCid",
|
|
3142
|
+
"policyDelegationCid",
|
|
3143
|
+
"enforcementDelegationCid",
|
|
3144
|
+
"contentSourceDigestHex",
|
|
3145
|
+
"capabilityCeilingHashHex",
|
|
3146
|
+
"nativeProjectionHashHex",
|
|
3147
|
+
"enforcerDid",
|
|
3148
|
+
"nodeAudience",
|
|
3149
|
+
"recipientDid",
|
|
3150
|
+
"challengeId",
|
|
3151
|
+
"claimDigestHex",
|
|
3152
|
+
"claimJti",
|
|
3153
|
+
"vpDigestHex",
|
|
3154
|
+
"credentialEvidenceDigestHex",
|
|
3155
|
+
"decisionContextDigestHex",
|
|
3156
|
+
"issuanceAuditDigestHex",
|
|
3157
|
+
"remainingRedelegationDepth"
|
|
3158
|
+
];
|
|
3159
|
+
var KV_ACTIONS = /* @__PURE__ */ new Set([
|
|
3160
|
+
"tinycloud.kv/get",
|
|
3161
|
+
"tinycloud.kv/list",
|
|
3162
|
+
"tinycloud.kv/metadata",
|
|
3163
|
+
"tinycloud.kv/put"
|
|
3164
|
+
]);
|
|
3165
|
+
function object(value, label) {
|
|
3166
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3167
|
+
throw new Error(`${label} must be an object`);
|
|
3168
|
+
}
|
|
3169
|
+
return value;
|
|
3170
|
+
}
|
|
3171
|
+
function exactKeys(value, allowed, label) {
|
|
3172
|
+
const keys = new Set(allowed);
|
|
3173
|
+
if (Object.keys(value).some((key) => !keys.has(key)))
|
|
3174
|
+
throw new Error(`${label} contains an unknown field`);
|
|
3175
|
+
}
|
|
3176
|
+
function nonEmptyString(value, label) {
|
|
3177
|
+
if (typeof value !== "string" || value.length === 0)
|
|
3178
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
3179
|
+
return value;
|
|
3180
|
+
}
|
|
3181
|
+
function parseKvResource(resource) {
|
|
3182
|
+
const match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
|
|
3183
|
+
if (!match || match[1].includes(":") || match[1].includes("?") || match[1].includes("#") || match[1].includes("%") || match[2].startsWith("/") || match[2].endsWith("/") || match[2].includes("//") || match[2].split("/").some((part) => part === "." || part === ".." || part.length === 0)) {
|
|
3184
|
+
throw new Error("KV resource is not canonical");
|
|
3185
|
+
}
|
|
3186
|
+
return { space: match[1], path: match[2] };
|
|
3187
|
+
}
|
|
3188
|
+
function parseEncryptionResource(resource) {
|
|
3189
|
+
if (!resource.startsWith("urn:tinycloud:encryption:")) throw new Error("encryption capability is invalid");
|
|
3190
|
+
const rest = resource.slice("urn:tinycloud:encryption:".length);
|
|
3191
|
+
const separator = rest.lastIndexOf(":");
|
|
3192
|
+
const ownerDid = separator < 0 ? "" : rest.slice(0, separator);
|
|
3193
|
+
const network = separator < 0 ? "" : rest.slice(separator + 1);
|
|
3194
|
+
if (!ownerDid.startsWith("did:") || network.length === 0 || network.includes(":") || network.includes("/") || network.includes("%") || network.includes("?") || network.includes("#")) {
|
|
3195
|
+
throw new Error("encryption capability is invalid");
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
function normalizeUnifiedPolicyCapability(input) {
|
|
3199
|
+
const value = object(input, "capability");
|
|
3200
|
+
const kind = nonEmptyString(value.kind, "capability.kind");
|
|
3201
|
+
if (kind === "kv") {
|
|
3202
|
+
exactKeys(
|
|
3203
|
+
value,
|
|
3204
|
+
["kind", "resource", "selector", "actions"],
|
|
3205
|
+
"KV capability"
|
|
3206
|
+
);
|
|
3207
|
+
const resource = nonEmptyString(value.resource, "capability.resource");
|
|
3208
|
+
parseKvResource(resource);
|
|
3209
|
+
if (value.selector !== "exact" && value.selector !== "prefix")
|
|
3210
|
+
throw new Error("capability.selector is invalid");
|
|
3211
|
+
if (!Array.isArray(value.actions) || value.actions.length === 0)
|
|
3212
|
+
throw new Error("capability.actions is invalid");
|
|
3213
|
+
const actions = value.actions.map(
|
|
3214
|
+
(action) => nonEmptyString(action, "capability.actions[]")
|
|
3215
|
+
);
|
|
3216
|
+
if (new Set(actions).size !== actions.length || actions.some((action) => !KV_ACTIONS.has(action)))
|
|
3217
|
+
throw new Error("capability.actions is invalid");
|
|
3218
|
+
return {
|
|
3219
|
+
kind: "kv",
|
|
3220
|
+
resource,
|
|
3221
|
+
selector: value.selector,
|
|
3222
|
+
actions: [...actions].sort()
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
if (kind === "encryption") {
|
|
3226
|
+
exactKeys(value, ["kind", "resource", "action"], "encryption capability");
|
|
3227
|
+
const resource = nonEmptyString(value.resource, "capability.resource");
|
|
3228
|
+
if (value.action !== "tinycloud.encryption/decrypt")
|
|
3229
|
+
throw new Error("encryption capability is invalid");
|
|
3230
|
+
parseEncryptionResource(resource);
|
|
3231
|
+
return {
|
|
3232
|
+
kind: "encryption",
|
|
3233
|
+
resource,
|
|
3234
|
+
action: "tinycloud.encryption/decrypt"
|
|
3235
|
+
};
|
|
3236
|
+
}
|
|
3237
|
+
throw new Error("capability.kind is invalid");
|
|
3238
|
+
}
|
|
3239
|
+
function canonicalizeUnifiedPolicyCapability(input) {
|
|
3240
|
+
return normalizeUnifiedPolicyCapability(input);
|
|
3241
|
+
}
|
|
3242
|
+
function unifiedPolicyCapabilityDigestHex(input) {
|
|
3243
|
+
return hex(
|
|
3244
|
+
sha2564(
|
|
3245
|
+
new TextEncoder().encode(
|
|
3246
|
+
POLICY_CAPABILITY_V1_DOMAIN + jcsCanonicalize(normalizeUnifiedPolicyCapability(input))
|
|
3247
|
+
)
|
|
3248
|
+
)
|
|
3249
|
+
);
|
|
3250
|
+
}
|
|
3251
|
+
function unifiedPolicyCapabilityContains(authorityInput, requestedInput) {
|
|
3252
|
+
try {
|
|
3253
|
+
const authority = normalizeUnifiedPolicyCapability(authorityInput);
|
|
3254
|
+
const requested = normalizeUnifiedPolicyCapability(requestedInput);
|
|
3255
|
+
if (authority.kind !== requested.kind) return false;
|
|
3256
|
+
if (authority.kind === "encryption" && requested.kind === "encryption")
|
|
3257
|
+
return authority.resource === requested.resource && authority.action === requested.action;
|
|
3258
|
+
if (authority.kind !== "kv" || requested.kind !== "kv") return false;
|
|
3259
|
+
const { resource: authorized } = authority;
|
|
3260
|
+
const { resource: requestedResource } = requested;
|
|
3261
|
+
const pathContained = authority.selector === "exact" ? authorized === requestedResource : authorized === requestedResource || requestedResource.startsWith(`${authorized}/`);
|
|
3262
|
+
if (!pathContained || authority.selector === "exact" && requested.selector === "prefix")
|
|
3263
|
+
return false;
|
|
3264
|
+
return requested.actions.every(
|
|
3265
|
+
(action) => authority.actions.includes(action)
|
|
3266
|
+
);
|
|
3267
|
+
} catch {
|
|
3268
|
+
return false;
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
function projectUnifiedPolicyCapability(input) {
|
|
3272
|
+
const capability = normalizeUnifiedPolicyCapability(input);
|
|
3273
|
+
if (capability.kind === "encryption") {
|
|
3274
|
+
return {
|
|
3275
|
+
service: "tinycloud.encryption",
|
|
3276
|
+
space: capability.resource,
|
|
3277
|
+
path: capability.resource,
|
|
3278
|
+
actions: [capability.action]
|
|
3279
|
+
};
|
|
3280
|
+
}
|
|
3281
|
+
const { space, path } = parseKvResource(capability.resource);
|
|
3282
|
+
return {
|
|
3283
|
+
service: "tinycloud.kv",
|
|
3284
|
+
space,
|
|
3285
|
+
path,
|
|
3286
|
+
actions: [...capability.actions],
|
|
3287
|
+
caveat: {
|
|
3288
|
+
type: "xyz.tinycloud.resource/selector",
|
|
3289
|
+
kind: capability.selector,
|
|
3290
|
+
value: capability.resource
|
|
3291
|
+
}
|
|
3292
|
+
};
|
|
3293
|
+
}
|
|
3294
|
+
function projectUnifiedPolicyCapabilities(input) {
|
|
3295
|
+
return input.map(projectUnifiedPolicyCapability).sort((left, right) => {
|
|
3296
|
+
const a = jcsCanonicalize(left);
|
|
3297
|
+
const b = jcsCanonicalize(right);
|
|
3298
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
3299
|
+
});
|
|
3300
|
+
}
|
|
3301
|
+
function unifiedNativeProjectionHashHex(input) {
|
|
3302
|
+
return hex(
|
|
3303
|
+
sha2564(
|
|
3304
|
+
new TextEncoder().encode(
|
|
3305
|
+
NATIVE_PROJECTION_V1_DOMAIN + jcsCanonicalize(projectUnifiedPolicyCapabilities(input))
|
|
3306
|
+
)
|
|
3307
|
+
)
|
|
3308
|
+
);
|
|
3309
|
+
}
|
|
3310
|
+
function unifiedPolicyCapabilityFromNative(input) {
|
|
3311
|
+
const value = object(input, "native capability");
|
|
3312
|
+
exactKeys(
|
|
3313
|
+
value,
|
|
3314
|
+
["service", "space", "path", "actions", "caveat"],
|
|
3315
|
+
"native capability"
|
|
3316
|
+
);
|
|
3317
|
+
const service = nonEmptyString(value.service, "native.service");
|
|
3318
|
+
const actions = value.actions;
|
|
3319
|
+
if (!Array.isArray(actions)) throw new Error("native.actions is invalid");
|
|
3320
|
+
if (service === "tinycloud.encryption" && value.caveat === void 0 && value.space === value.path && actions.length === 1 && actions[0] === "tinycloud.encryption/decrypt") {
|
|
3321
|
+
return normalizeUnifiedPolicyCapability({
|
|
3322
|
+
kind: "encryption",
|
|
3323
|
+
resource: value.space,
|
|
3324
|
+
action: actions[0]
|
|
3325
|
+
});
|
|
3326
|
+
}
|
|
3327
|
+
if (service !== "tinycloud.kv" || typeof value.space !== "string" || typeof value.path !== "string")
|
|
3328
|
+
throw new Error("native capability is not supported");
|
|
3329
|
+
const caveat = object(value.caveat, "native.caveat");
|
|
3330
|
+
exactKeys(caveat, ["type", "kind", "value"], "native selector caveat");
|
|
3331
|
+
if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `tinycloud://${value.space}/kv/${value.path}`)
|
|
3332
|
+
throw new Error("native selector caveat does not match capability");
|
|
3333
|
+
return normalizeUnifiedPolicyCapability({
|
|
3334
|
+
kind: "kv",
|
|
3335
|
+
resource: caveat.value,
|
|
3336
|
+
selector: caveat.kind,
|
|
3337
|
+
actions
|
|
3338
|
+
});
|
|
3339
|
+
}
|
|
3340
|
+
function contentSourceDigestHex(input) {
|
|
3341
|
+
return hex(
|
|
3342
|
+
sha2564(
|
|
3343
|
+
new TextEncoder().encode(
|
|
3344
|
+
CONTENT_SOURCE_V1_DOMAIN + jcsCanonicalize(input)
|
|
3345
|
+
)
|
|
3346
|
+
)
|
|
3347
|
+
);
|
|
3348
|
+
}
|
|
3349
|
+
function policyDigestHex(policy) {
|
|
3350
|
+
const canonicalPolicy = {
|
|
3351
|
+
...policy,
|
|
3352
|
+
capabilityCeiling: policy.capabilityCeiling.map(
|
|
3353
|
+
normalizeUnifiedPolicyCapability
|
|
3354
|
+
)
|
|
3355
|
+
};
|
|
3356
|
+
return hex(
|
|
3357
|
+
sha2564(
|
|
3358
|
+
new TextEncoder().encode(
|
|
3359
|
+
POLICY_V1_DOMAIN + jcsCanonicalize(canonicalPolicy)
|
|
3360
|
+
)
|
|
3361
|
+
)
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3364
|
+
function policyIdForDigestHex(digestHex) {
|
|
3365
|
+
const digest4 = Uint8Array.from(
|
|
3366
|
+
(digestHex.match(/.{2}/g) ?? []).map((byte) => Number.parseInt(byte, 16))
|
|
3367
|
+
);
|
|
3368
|
+
if (digest4.length !== 32) throw new Error("policy digest must be 32 bytes");
|
|
3369
|
+
return `pol_${base32Lower(digest4)}`;
|
|
3370
|
+
}
|
|
3371
|
+
function policyCidFromCanonicalBytes(bytes2) {
|
|
3372
|
+
return CID.createV1(85, create(18, sha2564(bytes2))).toString();
|
|
3373
|
+
}
|
|
3374
|
+
var CompactHeaderSchema = z2.object({
|
|
3375
|
+
alg: z2.literal("EdDSA"),
|
|
3376
|
+
jwk: z2.object({ alg: z2.literal("EdDSA"), crv: z2.literal("Ed25519"), kty: z2.literal("OKP"), x: z2.string().min(1) }).strict(),
|
|
3377
|
+
typ: z2.literal("JWT"),
|
|
3378
|
+
ucv: z2.literal("0.10.0")
|
|
3379
|
+
}).strict();
|
|
3380
|
+
var CompactPayloadSchema = z2.object({
|
|
3381
|
+
att: z2.record(z2.record(z2.array(z2.unknown()).min(1))),
|
|
3382
|
+
aud: z2.string().min(1),
|
|
3383
|
+
exp: z2.number().int(),
|
|
3384
|
+
fct: z2.array(z2.record(z2.unknown())).length(1),
|
|
3385
|
+
iss: z2.string().min(1),
|
|
3386
|
+
nbf: z2.number().int(),
|
|
3387
|
+
nnc: z2.string().min(1),
|
|
3388
|
+
prf: z2.array(z2.string().min(1))
|
|
3389
|
+
}).strict();
|
|
3390
|
+
async function signCompactUcanAuthorization(input) {
|
|
3391
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
|
|
3392
|
+
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
3393
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
3394
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3395
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3396
|
+
throw new Error("compact UCAN signer must be did:key Ed25519");
|
|
3397
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(didMaterial.slice(2)) }, typ: "JWT", ucv: "0.10.0" };
|
|
3398
|
+
const payload = {
|
|
3399
|
+
att: input.attenuation,
|
|
3400
|
+
aud: input.audienceDid,
|
|
3401
|
+
exp: input.expiresAt,
|
|
3402
|
+
fct: input.facts,
|
|
3403
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3404
|
+
nbf: input.notBefore,
|
|
3405
|
+
nnc: input.nonce,
|
|
3406
|
+
prf: input.proofs
|
|
3407
|
+
};
|
|
3408
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3409
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3410
|
+
const signature = await input.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`));
|
|
3411
|
+
if (signature.length !== 64) throw new Error("compact Authorization signature must be Ed25519");
|
|
3412
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3413
|
+
}
|
|
3414
|
+
function createCompactPolicyInvocation(input) {
|
|
3415
|
+
const session = parsePolicySessionUcan(input.sessionAuthorization);
|
|
3416
|
+
if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
|
|
3417
|
+
throw new Error("policy session does not bind the recipient signer");
|
|
3418
|
+
const principal = input.recipientDid.split("#", 1)[0];
|
|
3419
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3420
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3421
|
+
throw new Error("policy invocation signer must be did:key Ed25519");
|
|
3422
|
+
const publicKey = ed255192.getPublicKey(input.privateKey);
|
|
3423
|
+
if (!equalBytes(publicKey, didMaterial.slice(2)))
|
|
3424
|
+
throw new Error("policy invocation private key does not bind recipient DID");
|
|
3425
|
+
const now = input.now ?? Math.floor(Date.now() / 1e3);
|
|
3426
|
+
const exp = Math.min(now + 60, session.exp);
|
|
3427
|
+
if (exp <= now) throw new Error("policy session has expired");
|
|
3428
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3429
|
+
const payload = {
|
|
3430
|
+
att: { [input.resource]: { [input.action]: [input.caveat ?? {}] } },
|
|
3431
|
+
aud: input.audienceDid,
|
|
3432
|
+
exp,
|
|
3433
|
+
fct: [input.facts ?? { type: "tinycloud.policy.invocation/v1", policyCid: session.fact.policyCid, sessionCid: session.cid }],
|
|
3434
|
+
iss: input.recipientDid.includes("#") ? input.recipientDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3435
|
+
nbf: now,
|
|
3436
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3437
|
+
prf: [session.cid]
|
|
3438
|
+
};
|
|
3439
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3440
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3441
|
+
const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
|
|
3442
|
+
const signature = ed255192.sign(signingInput, input.privateKey);
|
|
3443
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3444
|
+
}
|
|
3445
|
+
function createCompactPolicyDescendant(input) {
|
|
3446
|
+
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
3447
|
+
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
3448
|
+
const parentFact = parent.payload.fct[0];
|
|
3449
|
+
const depth = parentFact.remainingRedelegationDepth;
|
|
3450
|
+
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
3451
|
+
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
3452
|
+
throw new Error("policy descendant exceeds the parent attenuation");
|
|
3453
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
3454
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3455
|
+
const publicKey = ed255192.getPublicKey(input.privateKey);
|
|
3456
|
+
if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
3457
|
+
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
3458
|
+
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
3459
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
3460
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3461
|
+
const payload = {
|
|
3462
|
+
att: input.attenuation,
|
|
3463
|
+
aud: input.audienceDid,
|
|
3464
|
+
exp,
|
|
3465
|
+
fct: [{ ...parentFact, remainingRedelegationDepth: depth - 1 }],
|
|
3466
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3467
|
+
nbf: now,
|
|
3468
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3469
|
+
prf: [parent.cid]
|
|
3470
|
+
};
|
|
3471
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3472
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3473
|
+
const signature = ed255192.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
3474
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3475
|
+
}
|
|
3476
|
+
function compactAttenuationContains(parent, child) {
|
|
3477
|
+
const selector = (value) => {
|
|
3478
|
+
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
3479
|
+
const caveat = value[0];
|
|
3480
|
+
if (Object.keys(caveat).length !== 3 || caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || typeof caveat.value !== "string") return void 0;
|
|
3481
|
+
return { kind: caveat.kind, value: caveat.value };
|
|
3482
|
+
};
|
|
3483
|
+
const equal = (left, right) => jcsCanonicalize(left) === jcsCanonicalize(right);
|
|
3484
|
+
return Object.entries(child).every(
|
|
3485
|
+
([childResource, childActions]) => Object.entries(childActions).every(
|
|
3486
|
+
([action, childCaveats]) => Object.entries(parent).some(([parentResource, parentActions]) => {
|
|
3487
|
+
const parentCaveats = parentActions[action];
|
|
3488
|
+
if (parentCaveats === void 0) return false;
|
|
3489
|
+
if (parentResource === childResource && equal(parentCaveats, childCaveats)) return true;
|
|
3490
|
+
const parentSelector = selector(parentCaveats);
|
|
3491
|
+
const childSelector = selector(childCaveats);
|
|
3492
|
+
return parentSelector?.kind === "prefix" && childSelector !== void 0 && parentSelector.value === parentResource && childSelector.value === childResource && (childResource === parentResource || childResource.startsWith(`${parentResource}/`));
|
|
3493
|
+
})
|
|
3494
|
+
)
|
|
3495
|
+
);
|
|
3496
|
+
}
|
|
3497
|
+
function isRecordValue(value) {
|
|
3498
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3499
|
+
}
|
|
3500
|
+
function parseCompactUcanAuthorization(input, expectedCid) {
|
|
3501
|
+
if (typeof input !== "string" || /\s/.test(input))
|
|
3502
|
+
throw new Error("Authorization must be compact UCAN bytes");
|
|
3503
|
+
const segments = input.split(".");
|
|
3504
|
+
if (segments.length !== 3 || segments.some((segment) => segment.length === 0))
|
|
3505
|
+
throw new Error("Authorization must have three compact segments");
|
|
3506
|
+
const [headerSegment, payloadSegment, signatureSegment] = segments;
|
|
3507
|
+
const headerBytes = decodeBase64Url(headerSegment);
|
|
3508
|
+
const payloadBytes = decodeBase64Url(payloadSegment);
|
|
3509
|
+
const signature = decodeBase64Url(signatureSegment);
|
|
3510
|
+
const headerValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(headerBytes));
|
|
3511
|
+
const payloadValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes));
|
|
3512
|
+
if (jcsCanonicalize(headerValue) !== new TextDecoder().decode(headerBytes) || jcsCanonicalize(payloadValue) !== new TextDecoder().decode(payloadBytes))
|
|
3513
|
+
throw new Error("compact UCAN segments are not canonical JCS");
|
|
3514
|
+
const header = CompactHeaderSchema.parse(headerValue);
|
|
3515
|
+
const payload = CompactPayloadSchema.parse(payloadValue);
|
|
3516
|
+
if (payload.nbf >= payload.exp) throw new Error("compact UCAN validity is empty");
|
|
3517
|
+
const principal = payload.iss.split("#", 1)[0];
|
|
3518
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3519
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3520
|
+
throw new Error("compact UCAN issuer must be did:key Ed25519");
|
|
3521
|
+
const publicKey = didMaterial.slice(2);
|
|
3522
|
+
if (!equalBytes(publicKey, decodeBase64Url(header.jwk.x)))
|
|
3523
|
+
throw new Error("compact UCAN JWK does not bind issuer");
|
|
3524
|
+
if (!ed255192.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey))
|
|
3525
|
+
throw new Error("compact UCAN signature is invalid");
|
|
3526
|
+
const cid2 = CID.createV1(85, create(30, blake3(new TextEncoder().encode(input)))).toString();
|
|
3527
|
+
if (expectedCid !== void 0 && cid2 !== expectedCid)
|
|
3528
|
+
throw new Error("compact UCAN CID does not match exact Authorization bytes");
|
|
3529
|
+
return { authorization: input, cid: cid2, header, payload };
|
|
3530
|
+
}
|
|
3531
|
+
function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
3532
|
+
const parsed = parseCompactUcanAuthorization(authorization);
|
|
3533
|
+
const fact = parsed.payload.fct[0];
|
|
3534
|
+
if (parsed.payload.prf.length !== 2 || parsed.payload.prf[0] === parsed.payload.prf[1])
|
|
3535
|
+
throw new Error("policy session UCAN requires two distinct ordered proofs");
|
|
3536
|
+
if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
|
|
3537
|
+
throw new Error("policy session UCAN ordered proofs do not match");
|
|
3538
|
+
const factKeys = Object.keys(fact);
|
|
3539
|
+
if (factKeys.length !== POLICY_SESSION_FACT_KEYS.length || factKeys.some((key) => !POLICY_SESSION_FACT_KEYS.includes(key)) || POLICY_SESSION_FACT_KEYS.some((key) => !(key in fact)))
|
|
3540
|
+
throw new Error("policy session UCAN fact is incomplete");
|
|
3541
|
+
if (fact.profile !== POLICY_SESSION_UCAN_V1_PROFILE || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || parsed.payload.exp - parsed.payload.nbf > 60 || parsed.payload.iss.split("#", 1)[0] !== fact.enforcerDid || parsed.payload.aud !== fact.recipientDid)
|
|
3542
|
+
throw new Error("policy session UCAN fact is invalid");
|
|
3543
|
+
return {
|
|
3544
|
+
authorization,
|
|
3545
|
+
cid: parsed.cid,
|
|
3546
|
+
iss: parsed.payload.iss,
|
|
3547
|
+
aud: parsed.payload.aud,
|
|
3548
|
+
prf: parsed.payload.prf,
|
|
3549
|
+
att: parsed.payload.att,
|
|
3550
|
+
nbf: parsed.payload.nbf,
|
|
3551
|
+
exp: parsed.payload.exp,
|
|
3552
|
+
nnc: parsed.payload.nnc,
|
|
3553
|
+
fact
|
|
3554
|
+
};
|
|
3555
|
+
}
|
|
3556
|
+
function decodeBase64Url(value) {
|
|
3557
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
|
|
3558
|
+
throw new Error("value is not canonical base64url");
|
|
3559
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
3560
|
+
const binary = typeof Buffer !== "undefined" ? Buffer.from(normalized, "base64").toString("binary") : atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="));
|
|
3561
|
+
const bytes2 = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
3562
|
+
const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes2).toString("base64url") : btoa(String.fromCharCode(...bytes2)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
3563
|
+
if (encoded !== value) throw new Error("value is not canonical base64url");
|
|
3564
|
+
return bytes2;
|
|
3565
|
+
}
|
|
3566
|
+
function encodeBase64Url(value) {
|
|
3567
|
+
return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
3568
|
+
}
|
|
3569
|
+
function equalBytes(left, right) {
|
|
3570
|
+
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
3571
|
+
}
|
|
3572
|
+
function hex(bytes2) {
|
|
3573
|
+
return [...bytes2].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3574
|
+
}
|
|
3575
|
+
function base32Lower(bytes2) {
|
|
3576
|
+
const alphabet2 = "abcdefghijklmnopqrstuvwxyz234567";
|
|
3577
|
+
let output = "";
|
|
3578
|
+
let buffer = 0;
|
|
3579
|
+
let bits = 0;
|
|
3580
|
+
for (const byte of bytes2) {
|
|
3581
|
+
buffer = buffer << 8 | byte;
|
|
3582
|
+
bits += 8;
|
|
3583
|
+
while (bits >= 5) {
|
|
3584
|
+
output += alphabet2[buffer >>> bits - 5 & 31];
|
|
3585
|
+
bits -= 5;
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
if (bits > 0) output += alphabet2[buffer << 5 - bits & 31];
|
|
3589
|
+
return output;
|
|
2987
3590
|
}
|
|
2988
3591
|
|
|
2989
3592
|
// src/requester/index.ts
|
|
@@ -3062,109 +3665,109 @@ var TranscriptRequesterError = class extends Error {
|
|
|
3062
3665
|
this.status = status;
|
|
3063
3666
|
}
|
|
3064
3667
|
};
|
|
3065
|
-
var JsonValueSchema =
|
|
3066
|
-
() =>
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3668
|
+
var JsonValueSchema = z3.lazy(
|
|
3669
|
+
() => z3.union([
|
|
3670
|
+
z3.string(),
|
|
3671
|
+
z3.number().finite(),
|
|
3672
|
+
z3.boolean(),
|
|
3673
|
+
z3.null(),
|
|
3674
|
+
z3.array(JsonValueSchema),
|
|
3675
|
+
z3.record(JsonValueSchema)
|
|
3073
3676
|
])
|
|
3074
3677
|
);
|
|
3075
|
-
var Rfc3339Schema =
|
|
3678
|
+
var Rfc3339Schema = z3.string().refine((value) => parseStrictRfc33392(value) !== void 0, {
|
|
3076
3679
|
message: "must be strict RFC 3339 date-time with timezone"
|
|
3077
3680
|
});
|
|
3078
|
-
var SignedRecordSchema =
|
|
3079
|
-
schema:
|
|
3080
|
-
engineRecordId:
|
|
3081
|
-
ownerDid:
|
|
3082
|
-
endpoint:
|
|
3083
|
-
audience:
|
|
3084
|
-
supportedPolicyVersions:
|
|
3085
|
-
supportedEvidenceVerifiers:
|
|
3086
|
-
grantIssuerDid:
|
|
3681
|
+
var SignedRecordSchema = z3.object({
|
|
3682
|
+
schema: z3.string(),
|
|
3683
|
+
engineRecordId: z3.string(),
|
|
3684
|
+
ownerDid: z3.string(),
|
|
3685
|
+
endpoint: z3.string(),
|
|
3686
|
+
audience: z3.string(),
|
|
3687
|
+
supportedPolicyVersions: z3.array(z3.string()),
|
|
3688
|
+
supportedEvidenceVerifiers: z3.array(z3.string()),
|
|
3689
|
+
grantIssuerDid: z3.string(),
|
|
3087
3690
|
expiresAt: Rfc3339Schema,
|
|
3088
|
-
signature:
|
|
3089
|
-
suite:
|
|
3090
|
-
signerDid:
|
|
3091
|
-
value:
|
|
3691
|
+
signature: z3.object({
|
|
3692
|
+
suite: z3.string(),
|
|
3693
|
+
signerDid: z3.string(),
|
|
3694
|
+
value: z3.string()
|
|
3092
3695
|
}).strict()
|
|
3093
3696
|
}).strict();
|
|
3094
|
-
var PolicyEngineSchema =
|
|
3095
|
-
endpoint:
|
|
3096
|
-
audience:
|
|
3097
|
-
supportedEvidenceVerifiers:
|
|
3098
|
-
|
|
3697
|
+
var PolicyEngineSchema = z3.object({
|
|
3698
|
+
endpoint: z3.string().url(),
|
|
3699
|
+
audience: z3.string(),
|
|
3700
|
+
supportedEvidenceVerifiers: z3.tuple([
|
|
3701
|
+
z3.literal(W3C_VC_CREDENTIAL_VERIFIER)
|
|
3099
3702
|
]),
|
|
3100
3703
|
signedRecord: SignedRecordSchema
|
|
3101
3704
|
}).strict();
|
|
3102
|
-
var OwnerNodeSchema =
|
|
3103
|
-
schema:
|
|
3104
|
-
endpoint:
|
|
3105
|
-
spaceId:
|
|
3705
|
+
var OwnerNodeSchema = z3.object({
|
|
3706
|
+
schema: z3.literal(OWNER_NODE_ENDPOINT_SCHEMA),
|
|
3707
|
+
endpoint: z3.string().url(),
|
|
3708
|
+
spaceId: z3.string().min(1)
|
|
3106
3709
|
}).strict();
|
|
3107
|
-
var ResourceHintSchema =
|
|
3108
|
-
resourceType:
|
|
3109
|
-
resourceId:
|
|
3110
|
-
requestedCapabilities:
|
|
3710
|
+
var ResourceHintSchema = z3.object({
|
|
3711
|
+
resourceType: z3.string(),
|
|
3712
|
+
resourceId: z3.string(),
|
|
3713
|
+
requestedCapabilities: z3.array(JsonValueSchema).min(1)
|
|
3111
3714
|
}).strict();
|
|
3112
|
-
var BootstrapSchema =
|
|
3113
|
-
schema:
|
|
3114
|
-
policyId:
|
|
3715
|
+
var BootstrapSchema = z3.object({
|
|
3716
|
+
schema: z3.literal(TRANSCRIPT_SHARE_BOOTSTRAP_SCHEMA),
|
|
3717
|
+
policyId: z3.string(),
|
|
3115
3718
|
policyEngine: PolicyEngineSchema,
|
|
3116
3719
|
ownerNode: OwnerNodeSchema,
|
|
3117
3720
|
resourceHint: ResourceHintSchema
|
|
3118
3721
|
}).strict();
|
|
3119
|
-
var SignatureSchema =
|
|
3120
|
-
suite:
|
|
3121
|
-
signerDid:
|
|
3122
|
-
value:
|
|
3722
|
+
var SignatureSchema = z3.object({
|
|
3723
|
+
suite: z3.string(),
|
|
3724
|
+
signerDid: z3.string(),
|
|
3725
|
+
value: z3.string()
|
|
3123
3726
|
}).strict();
|
|
3124
|
-
var ChallengeSchema =
|
|
3125
|
-
schema:
|
|
3126
|
-
challengeId:
|
|
3127
|
-
policyId:
|
|
3128
|
-
audience:
|
|
3129
|
-
nonce:
|
|
3727
|
+
var ChallengeSchema = z3.object({
|
|
3728
|
+
schema: z3.literal(POLICY_ENGINE_CHALLENGE_RESPONSE_SCHEMA),
|
|
3729
|
+
challengeId: z3.string(),
|
|
3730
|
+
policyId: z3.string(),
|
|
3731
|
+
audience: z3.string(),
|
|
3732
|
+
nonce: z3.string().min(16),
|
|
3130
3733
|
challengeExpiresAt: Rfc3339Schema,
|
|
3131
|
-
acceptedSuites:
|
|
3132
|
-
requestedCapabilitiesTemplate:
|
|
3734
|
+
acceptedSuites: z3.array(z3.string()).min(1),
|
|
3735
|
+
requestedCapabilitiesTemplate: z3.array(JsonValueSchema).optional(),
|
|
3133
3736
|
signature: SignatureSchema
|
|
3134
3737
|
}).strict();
|
|
3135
|
-
var ChallengeResponseSchema =
|
|
3136
|
-
var DenialSchema =
|
|
3137
|
-
schema:
|
|
3138
|
-
code:
|
|
3139
|
-
message:
|
|
3738
|
+
var ChallengeResponseSchema = z3.object({ challenge: ChallengeSchema }).strict();
|
|
3739
|
+
var DenialSchema = z3.object({
|
|
3740
|
+
schema: z3.literal(POLICY_ENGINE_DENIAL_SCHEMA),
|
|
3741
|
+
code: z3.enum(POLICY_ENGINE_GRANT_PRESENTATION_DENIAL_CODES),
|
|
3742
|
+
message: z3.string().optional()
|
|
3140
3743
|
}).strict();
|
|
3141
|
-
var ErrorEnvelopeDenialSchema =
|
|
3142
|
-
error:
|
|
3143
|
-
code:
|
|
3144
|
-
message:
|
|
3744
|
+
var ErrorEnvelopeDenialSchema = z3.object({
|
|
3745
|
+
error: z3.object({
|
|
3746
|
+
code: z3.enum(POLICY_ENGINE_GRANT_PRESENTATION_DENIAL_CODES),
|
|
3747
|
+
message: z3.string().optional()
|
|
3145
3748
|
}).strict()
|
|
3146
3749
|
}).strict();
|
|
3147
|
-
var WireDelegationSchema =
|
|
3148
|
-
delegationId:
|
|
3149
|
-
issuanceId:
|
|
3150
|
-
issuerDid:
|
|
3151
|
-
holderDid:
|
|
3152
|
-
policyId:
|
|
3153
|
-
capabilityHashHex:
|
|
3154
|
-
revocationMode:
|
|
3750
|
+
var WireDelegationSchema = z3.object({
|
|
3751
|
+
delegationId: z3.string(),
|
|
3752
|
+
issuanceId: z3.string().min(1),
|
|
3753
|
+
issuerDid: z3.string(),
|
|
3754
|
+
holderDid: z3.string(),
|
|
3755
|
+
policyId: z3.string(),
|
|
3756
|
+
capabilityHashHex: z3.string().regex(/^[0-9a-f]{64}$/),
|
|
3757
|
+
revocationMode: z3.literal("refresh_only"),
|
|
3155
3758
|
issuedAt: Rfc3339Schema,
|
|
3156
3759
|
expiresAt: Rfc3339Schema,
|
|
3157
|
-
terminal:
|
|
3158
|
-
encoded:
|
|
3760
|
+
terminal: z3.boolean(),
|
|
3761
|
+
encoded: z3.string()
|
|
3159
3762
|
}).strict();
|
|
3160
|
-
var ResolveResponseSchema =
|
|
3161
|
-
var DelegateReceiptSchema =
|
|
3162
|
-
cid:
|
|
3163
|
-
activated:
|
|
3164
|
-
skipped:
|
|
3763
|
+
var ResolveResponseSchema = z3.object({ delegation: WireDelegationSchema }).strict();
|
|
3764
|
+
var DelegateReceiptSchema = z3.object({
|
|
3765
|
+
cid: z3.string().min(1),
|
|
3766
|
+
activated: z3.array(z3.string()),
|
|
3767
|
+
skipped: z3.array(z3.string())
|
|
3165
3768
|
}).strict();
|
|
3166
|
-
var SqlReadResponseSchema =
|
|
3167
|
-
var KvReadResponseSchema =
|
|
3769
|
+
var SqlReadResponseSchema = z3.object({ rows: z3.array(JsonValueSchema) }).strict();
|
|
3770
|
+
var KvReadResponseSchema = z3.object({ value: JsonValueSchema }).strict();
|
|
3168
3771
|
var LISTEN_SQL_STATEMENT_CATALOG = [
|
|
3169
3772
|
{
|
|
3170
3773
|
name: "listen.getConversation",
|
|
@@ -3899,7 +4502,7 @@ function requestedCapabilitiesHash(capabilities) {
|
|
|
3899
4502
|
const bytes2 = new Uint8Array(domain.length + body.length);
|
|
3900
4503
|
bytes2.set(domain, 0);
|
|
3901
4504
|
bytes2.set(body, domain.length);
|
|
3902
|
-
return bytesToHex3(
|
|
4505
|
+
return bytesToHex3(sha2565(bytes2, "bytes")).slice(2);
|
|
3903
4506
|
}
|
|
3904
4507
|
function normalizeWireDelegation(delegation) {
|
|
3905
4508
|
const signed = delegationAuthorityFromCompactJws(delegation.encoded);
|
|
@@ -4154,7 +4757,7 @@ function nodeErrorMessage(body) {
|
|
|
4154
4757
|
return "native node refusal";
|
|
4155
4758
|
}
|
|
4156
4759
|
function deriveDelegationCid(encoded) {
|
|
4157
|
-
const digest4 = create(30,
|
|
4760
|
+
const digest4 = create(30, blake32(new TextEncoder().encode(encoded)));
|
|
4158
4761
|
return CID.createV1(85, digest4).toString();
|
|
4159
4762
|
}
|
|
4160
4763
|
function headersRecord(headers) {
|
|
@@ -4301,55 +4904,55 @@ function parseStrictRfc33392(value) {
|
|
|
4301
4904
|
}
|
|
4302
4905
|
|
|
4303
4906
|
// src/delegations/types.schema.ts
|
|
4304
|
-
import { z as
|
|
4305
|
-
var JWKSchema =
|
|
4907
|
+
import { z as z4 } from "zod";
|
|
4908
|
+
var JWKSchema = z4.object({
|
|
4306
4909
|
/** Key type (e.g., "EC", "RSA", "OKP") */
|
|
4307
|
-
kty:
|
|
4910
|
+
kty: z4.string(),
|
|
4308
4911
|
/** Curve for EC/OKP keys (e.g., "P-256", "Ed25519") */
|
|
4309
|
-
crv:
|
|
4912
|
+
crv: z4.string().optional(),
|
|
4310
4913
|
/** X coordinate for EC keys, public key for OKP */
|
|
4311
|
-
x:
|
|
4914
|
+
x: z4.string().optional(),
|
|
4312
4915
|
/** Y coordinate for EC keys */
|
|
4313
|
-
y:
|
|
4916
|
+
y: z4.string().optional(),
|
|
4314
4917
|
/** Private key value (d parameter) */
|
|
4315
|
-
d:
|
|
4918
|
+
d: z4.string().optional(),
|
|
4316
4919
|
/** Public exponent for RSA keys */
|
|
4317
|
-
e:
|
|
4920
|
+
e: z4.string().optional(),
|
|
4318
4921
|
/** Modulus for RSA keys */
|
|
4319
|
-
n:
|
|
4922
|
+
n: z4.string().optional(),
|
|
4320
4923
|
/** Key ID */
|
|
4321
|
-
kid:
|
|
4924
|
+
kid: z4.string().optional(),
|
|
4322
4925
|
/** Algorithm */
|
|
4323
|
-
alg:
|
|
4926
|
+
alg: z4.string().optional(),
|
|
4324
4927
|
/** Key use (e.g., "sig", "enc") */
|
|
4325
|
-
use:
|
|
4928
|
+
use: z4.string().optional(),
|
|
4326
4929
|
/** Key operations (e.g., ["sign", "verify"]) */
|
|
4327
|
-
key_ops:
|
|
4930
|
+
key_ops: z4.array(z4.string()).optional()
|
|
4328
4931
|
});
|
|
4329
|
-
var KeyTypeSchema =
|
|
4330
|
-
var KeyInfoSchema =
|
|
4932
|
+
var KeyTypeSchema = z4.enum(["main", "session", "ingested"]);
|
|
4933
|
+
var KeyInfoSchema = z4.object({
|
|
4331
4934
|
/** Unique identifier for this key */
|
|
4332
|
-
id:
|
|
4935
|
+
id: z4.string(),
|
|
4333
4936
|
/** DID associated with this key */
|
|
4334
|
-
did:
|
|
4937
|
+
did: z4.string(),
|
|
4335
4938
|
/** Type of key determining its authority level */
|
|
4336
4939
|
type: KeyTypeSchema,
|
|
4337
4940
|
/** Private key in JWK format */
|
|
4338
4941
|
jwk: JWKSchema.optional(),
|
|
4339
4942
|
/** Priority for key selection (lower = higher priority) */
|
|
4340
|
-
priority:
|
|
4943
|
+
priority: z4.number()
|
|
4341
4944
|
});
|
|
4342
|
-
var DelegationErrorSchema =
|
|
4945
|
+
var DelegationErrorSchema = z4.object({
|
|
4343
4946
|
/** Error code for programmatic handling */
|
|
4344
|
-
code:
|
|
4947
|
+
code: z4.string(),
|
|
4345
4948
|
/** Human-readable error message */
|
|
4346
|
-
message:
|
|
4949
|
+
message: z4.string(),
|
|
4347
4950
|
/** The service that produced the error */
|
|
4348
|
-
service:
|
|
4951
|
+
service: z4.literal("delegation"),
|
|
4349
4952
|
/** Original error if wrapping another error */
|
|
4350
|
-
cause:
|
|
4953
|
+
cause: z4.instanceof(Error).optional(),
|
|
4351
4954
|
/** Additional metadata about the error */
|
|
4352
|
-
meta:
|
|
4955
|
+
meta: z4.record(z4.string(), z4.unknown()).optional()
|
|
4353
4956
|
});
|
|
4354
4957
|
var DelegationErrorCodes = {
|
|
4355
4958
|
AUTH_REQUIRED: "AUTH_REQUIRED",
|
|
@@ -4369,313 +4972,313 @@ var DelegationErrorCodes = {
|
|
|
4369
4972
|
DATA_FETCH_FAILED: "DATA_FETCH_FAILED",
|
|
4370
4973
|
VALIDATION_ERROR: "VALIDATION_ERROR"
|
|
4371
4974
|
};
|
|
4372
|
-
var DelegationSchema =
|
|
4975
|
+
var DelegationSchema = z4.object({
|
|
4373
4976
|
/** Content identifier (CID) of the delegation */
|
|
4374
|
-
cid:
|
|
4977
|
+
cid: z4.string(),
|
|
4375
4978
|
/** DID of the delegate (the party receiving the delegation) */
|
|
4376
|
-
delegateDID:
|
|
4979
|
+
delegateDID: z4.string(),
|
|
4377
4980
|
/** Space ID this delegation applies to */
|
|
4378
|
-
spaceId:
|
|
4981
|
+
spaceId: z4.string(),
|
|
4379
4982
|
/** Resource path this delegation grants access to */
|
|
4380
|
-
path:
|
|
4983
|
+
path: z4.string(),
|
|
4381
4984
|
/** Actions this delegation authorizes */
|
|
4382
|
-
actions:
|
|
4985
|
+
actions: z4.array(z4.string()),
|
|
4383
4986
|
/** Exact ReCap caveats that constrain every action in this scope. */
|
|
4384
|
-
caveats:
|
|
4987
|
+
caveats: z4.array(z4.record(z4.string(), z4.unknown())).optional(),
|
|
4385
4988
|
/** When this delegation expires (accepts Date or ISO string from JSON) */
|
|
4386
|
-
expiry:
|
|
4989
|
+
expiry: z4.coerce.date(),
|
|
4387
4990
|
/** Whether this delegation has been revoked */
|
|
4388
|
-
isRevoked:
|
|
4991
|
+
isRevoked: z4.boolean(),
|
|
4389
4992
|
/** DID of the delegator (the party granting the delegation) */
|
|
4390
|
-
delegatorDID:
|
|
4993
|
+
delegatorDID: z4.string().optional(),
|
|
4391
4994
|
/** When this delegation was created (accepts Date or ISO string from JSON) */
|
|
4392
|
-
createdAt:
|
|
4995
|
+
createdAt: z4.coerce.date().optional(),
|
|
4393
4996
|
/** Parent delegation CID if this is a sub-delegation */
|
|
4394
|
-
parentCid:
|
|
4997
|
+
parentCid: z4.string().optional(),
|
|
4395
4998
|
/** Whether sub-delegation is allowed */
|
|
4396
|
-
allowSubDelegation:
|
|
4999
|
+
allowSubDelegation: z4.boolean().optional(),
|
|
4397
5000
|
/** Authorization header (UCAN bearer token) */
|
|
4398
|
-
authHeader:
|
|
5001
|
+
authHeader: z4.string().optional()
|
|
4399
5002
|
});
|
|
4400
|
-
var DelegationStatusSchema =
|
|
4401
|
-
cid:
|
|
4402
|
-
status:
|
|
4403
|
-
exists:
|
|
4404
|
-
active:
|
|
4405
|
-
revoked:
|
|
4406
|
-
expired:
|
|
5003
|
+
var DelegationStatusSchema = z4.object({
|
|
5004
|
+
cid: z4.string().min(1),
|
|
5005
|
+
status: z4.enum(["active", "revoked", "expired", "unavailable", "not_found"]),
|
|
5006
|
+
exists: z4.boolean(),
|
|
5007
|
+
active: z4.boolean(),
|
|
5008
|
+
revoked: z4.boolean(),
|
|
5009
|
+
expired: z4.boolean()
|
|
4407
5010
|
}).strict().superRefine((value, context) => {
|
|
4408
5011
|
const valid = value.status === "active" ? value.exists && value.active && !value.revoked && !value.expired : value.status === "revoked" ? value.exists && !value.active && value.revoked && !value.expired : value.status === "expired" ? value.exists && !value.active && !value.revoked && value.expired : value.status === "unavailable" ? value.exists && !value.active && !value.revoked && !value.expired : !value.exists && !value.active && !value.revoked && !value.expired;
|
|
4409
5012
|
if (!valid) {
|
|
4410
5013
|
context.addIssue({
|
|
4411
|
-
code:
|
|
5014
|
+
code: z4.ZodIssueCode.custom,
|
|
4412
5015
|
message: "delegation status flags do not match status"
|
|
4413
5016
|
});
|
|
4414
5017
|
}
|
|
4415
5018
|
});
|
|
4416
|
-
var DelegationRevocationReceiptSchema =
|
|
4417
|
-
revoked:
|
|
4418
|
-
cid:
|
|
5019
|
+
var DelegationRevocationReceiptSchema = z4.object({
|
|
5020
|
+
revoked: z4.literal(true),
|
|
5021
|
+
cid: z4.string().min(1)
|
|
4419
5022
|
}).strict();
|
|
4420
|
-
var AccountDelegationResourceSchema =
|
|
4421
|
-
resource:
|
|
4422
|
-
actions:
|
|
4423
|
-
caveats:
|
|
5023
|
+
var AccountDelegationResourceSchema = z4.object({
|
|
5024
|
+
resource: z4.string().min(1),
|
|
5025
|
+
actions: z4.array(z4.string()),
|
|
5026
|
+
caveats: z4.array(z4.record(z4.string(), z4.unknown()))
|
|
4424
5027
|
}).strict();
|
|
4425
|
-
var AccountDelegationDateSchema =
|
|
4426
|
-
var AccountDelegationRecordSchema =
|
|
4427
|
-
cid:
|
|
4428
|
-
direction:
|
|
4429
|
-
delegatorDid:
|
|
4430
|
-
delegateDid:
|
|
4431
|
-
resources:
|
|
4432
|
-
parents:
|
|
5028
|
+
var AccountDelegationDateSchema = z4.string().datetime({ offset: true }).transform((value) => new Date(value));
|
|
5029
|
+
var AccountDelegationRecordSchema = z4.object({
|
|
5030
|
+
cid: z4.string().min(1),
|
|
5031
|
+
direction: z4.enum(["granted", "received"]),
|
|
5032
|
+
delegatorDid: z4.string().min(1),
|
|
5033
|
+
delegateDid: z4.string().min(1),
|
|
5034
|
+
resources: z4.array(AccountDelegationResourceSchema),
|
|
5035
|
+
parents: z4.array(z4.string()),
|
|
4433
5036
|
issuedAt: AccountDelegationDateSchema.nullable(),
|
|
4434
5037
|
notBefore: AccountDelegationDateSchema.nullable(),
|
|
4435
5038
|
expiresAt: AccountDelegationDateSchema.nullable(),
|
|
4436
|
-
status:
|
|
5039
|
+
status: z4.enum(["active", "pending", "expired", "revoked", "ancestor_revoked"]),
|
|
4437
5040
|
revokedAt: AccountDelegationDateSchema.nullable().optional(),
|
|
4438
|
-
revokedBy:
|
|
4439
|
-
revokedAncestorCid:
|
|
5041
|
+
revokedBy: z4.string().optional(),
|
|
5042
|
+
revokedAncestorCid: z4.string().optional()
|
|
4440
5043
|
}).strict();
|
|
4441
|
-
var AccountDelegationPageSchema =
|
|
4442
|
-
schemaVersion:
|
|
4443
|
-
items:
|
|
4444
|
-
nextCursor:
|
|
5044
|
+
var AccountDelegationPageSchema = z4.object({
|
|
5045
|
+
schemaVersion: z4.literal(2),
|
|
5046
|
+
items: z4.array(AccountDelegationRecordSchema),
|
|
5047
|
+
nextCursor: z4.string().optional()
|
|
4445
5048
|
}).strict();
|
|
4446
|
-
var AccountDelegationQueryOptionsSchema =
|
|
4447
|
-
direction:
|
|
4448
|
-
status:
|
|
4449
|
-
space:
|
|
4450
|
-
limit:
|
|
4451
|
-
cursor:
|
|
5049
|
+
var AccountDelegationQueryOptionsSchema = z4.object({
|
|
5050
|
+
direction: z4.enum(["granted", "received", "all"]).optional(),
|
|
5051
|
+
status: z4.enum(["active", "pending", "expired", "revoked", "ancestor_revoked"]).optional(),
|
|
5052
|
+
space: z4.string().trim().min(1).optional(),
|
|
5053
|
+
limit: z4.number().int().min(1).max(100).optional(),
|
|
5054
|
+
cursor: z4.string().min(1).optional()
|
|
4452
5055
|
}).strict();
|
|
4453
|
-
var CapabilityEntrySchema =
|
|
5056
|
+
var CapabilityEntrySchema = z4.object({
|
|
4454
5057
|
/** Resource URI this capability applies to */
|
|
4455
|
-
resource:
|
|
5058
|
+
resource: z4.string(),
|
|
4456
5059
|
/** Action this capability authorizes */
|
|
4457
|
-
action:
|
|
5060
|
+
action: z4.string(),
|
|
4458
5061
|
/** Keys that can exercise this capability, ordered by priority */
|
|
4459
|
-
keys:
|
|
5062
|
+
keys: z4.array(KeyInfoSchema),
|
|
4460
5063
|
/** The delegation that grants this capability */
|
|
4461
5064
|
delegation: DelegationSchema,
|
|
4462
5065
|
/** When this capability expires (accepts Date or ISO string from JSON) */
|
|
4463
|
-
expiresAt:
|
|
5066
|
+
expiresAt: z4.coerce.date().optional()
|
|
4464
5067
|
});
|
|
4465
|
-
var DelegationRecordSchema =
|
|
5068
|
+
var DelegationRecordSchema = z4.object({
|
|
4466
5069
|
/** Content identifier (CID) of the delegation */
|
|
4467
|
-
cid:
|
|
5070
|
+
cid: z4.string(),
|
|
4468
5071
|
/** Space ID this delegation applies to */
|
|
4469
|
-
spaceId:
|
|
5072
|
+
spaceId: z4.string(),
|
|
4470
5073
|
/** DID of the delegator (grantor) */
|
|
4471
|
-
delegator:
|
|
5074
|
+
delegator: z4.string(),
|
|
4472
5075
|
/** DID of the delegatee (recipient) */
|
|
4473
|
-
delegatee:
|
|
5076
|
+
delegatee: z4.string(),
|
|
4474
5077
|
/** Key ID used to sign/exercise this delegation */
|
|
4475
|
-
keyId:
|
|
5078
|
+
keyId: z4.string().optional(),
|
|
4476
5079
|
/** Resource path pattern this delegation grants access to */
|
|
4477
|
-
path:
|
|
5080
|
+
path: z4.string(),
|
|
4478
5081
|
/** Actions this delegation authorizes */
|
|
4479
|
-
actions:
|
|
5082
|
+
actions: z4.array(z4.string()),
|
|
4480
5083
|
/** When this delegation expires (accepts Date or ISO string from JSON) */
|
|
4481
|
-
expiry:
|
|
5084
|
+
expiry: z4.coerce.date().optional(),
|
|
4482
5085
|
/** When this delegation becomes valid (not before) (accepts Date or ISO string) */
|
|
4483
|
-
notBefore:
|
|
5086
|
+
notBefore: z4.coerce.date().optional(),
|
|
4484
5087
|
/** Whether this delegation has been revoked */
|
|
4485
|
-
isRevoked:
|
|
5088
|
+
isRevoked: z4.boolean(),
|
|
4486
5089
|
/** When this delegation was created (accepts Date or ISO string from JSON) */
|
|
4487
|
-
createdAt:
|
|
5090
|
+
createdAt: z4.coerce.date(),
|
|
4488
5091
|
/** Parent delegation CID if this is a sub-delegation */
|
|
4489
|
-
parentCid:
|
|
5092
|
+
parentCid: z4.string().optional()
|
|
4490
5093
|
});
|
|
4491
|
-
var CreateDelegationParamsSchema =
|
|
5094
|
+
var CreateDelegationParamsSchema = z4.object({
|
|
4492
5095
|
/** DID of the delegate (the party receiving the delegation) */
|
|
4493
|
-
delegateDID:
|
|
5096
|
+
delegateDID: z4.string(),
|
|
4494
5097
|
/** Resource path this delegation grants access to */
|
|
4495
|
-
path:
|
|
5098
|
+
path: z4.string(),
|
|
4496
5099
|
/** Actions to authorize */
|
|
4497
|
-
actions:
|
|
5100
|
+
actions: z4.array(z4.string()),
|
|
4498
5101
|
/** When this delegation expires (accepts Date or ISO string) */
|
|
4499
|
-
expiry:
|
|
5102
|
+
expiry: z4.coerce.date().optional(),
|
|
4500
5103
|
/** Whether to disable sub-delegation */
|
|
4501
|
-
disableSubDelegation:
|
|
5104
|
+
disableSubDelegation: z4.boolean().optional(),
|
|
4502
5105
|
/** Optional statement for the SIWE message */
|
|
4503
|
-
statement:
|
|
5106
|
+
statement: z4.string().optional()
|
|
4504
5107
|
});
|
|
4505
|
-
var DelegationChainSchema =
|
|
4506
|
-
var DelegationChainV2Schema =
|
|
5108
|
+
var DelegationChainSchema = z4.array(DelegationSchema);
|
|
5109
|
+
var DelegationChainV2Schema = z4.object({
|
|
4507
5110
|
/** The root delegation from the original authority */
|
|
4508
5111
|
root: DelegationSchema,
|
|
4509
5112
|
/** Intermediate delegations in the chain (may be empty) */
|
|
4510
|
-
chain:
|
|
5113
|
+
chain: z4.array(DelegationSchema),
|
|
4511
5114
|
/** The final delegation to the current user */
|
|
4512
5115
|
leaf: DelegationSchema
|
|
4513
5116
|
});
|
|
4514
|
-
var DelegationDirectionSchema =
|
|
4515
|
-
var DelegationFiltersSchema =
|
|
5117
|
+
var DelegationDirectionSchema = z4.enum(["granted", "received", "all"]);
|
|
5118
|
+
var DelegationFiltersSchema = z4.object({
|
|
4516
5119
|
/** Filter by delegation direction */
|
|
4517
5120
|
direction: DelegationDirectionSchema.optional(),
|
|
4518
5121
|
/** Filter by resource path pattern */
|
|
4519
|
-
path:
|
|
5122
|
+
path: z4.string().optional(),
|
|
4520
5123
|
/** Filter by required actions */
|
|
4521
|
-
actions:
|
|
5124
|
+
actions: z4.array(z4.string()).optional(),
|
|
4522
5125
|
/** Include revoked delegations */
|
|
4523
|
-
includeRevoked:
|
|
5126
|
+
includeRevoked: z4.boolean().optional(),
|
|
4524
5127
|
/** Filter by delegator DID */
|
|
4525
|
-
delegator:
|
|
5128
|
+
delegator: z4.string().optional(),
|
|
4526
5129
|
/** Filter by delegatee DID */
|
|
4527
|
-
delegatee:
|
|
5130
|
+
delegatee: z4.string().optional(),
|
|
4528
5131
|
/** Only include delegations valid at this time */
|
|
4529
|
-
validAt:
|
|
5132
|
+
validAt: z4.coerce.date().optional(),
|
|
4530
5133
|
/** Maximum number of results to return */
|
|
4531
|
-
limit:
|
|
5134
|
+
limit: z4.number().optional(),
|
|
4532
5135
|
/** Cursor for pagination */
|
|
4533
|
-
cursor:
|
|
5136
|
+
cursor: z4.string().optional()
|
|
4534
5137
|
});
|
|
4535
|
-
var SpaceOwnershipSchema =
|
|
4536
|
-
var SpaceInfoSchema =
|
|
5138
|
+
var SpaceOwnershipSchema = z4.enum(["owned", "delegated"]);
|
|
5139
|
+
var SpaceInfoSchema = z4.object({
|
|
4537
5140
|
/** Space identifier */
|
|
4538
|
-
id:
|
|
5141
|
+
id: z4.string(),
|
|
4539
5142
|
/** Human-readable name for the space */
|
|
4540
|
-
name:
|
|
5143
|
+
name: z4.string().optional(),
|
|
4541
5144
|
/** DID of the space owner */
|
|
4542
|
-
owner:
|
|
5145
|
+
owner: z4.string(),
|
|
4543
5146
|
/** Whether user owns or has delegated access */
|
|
4544
5147
|
type: SpaceOwnershipSchema,
|
|
4545
5148
|
/** Permissions the user has in this space */
|
|
4546
|
-
permissions:
|
|
5149
|
+
permissions: z4.array(z4.string()).optional(),
|
|
4547
5150
|
/** When the access expires (for delegated spaces) */
|
|
4548
|
-
expiresAt:
|
|
5151
|
+
expiresAt: z4.coerce.date().optional()
|
|
4549
5152
|
});
|
|
4550
|
-
var ShareSchemaSchema =
|
|
4551
|
-
var ShareLinkSchema =
|
|
5153
|
+
var ShareSchemaSchema = z4.enum(["base64", "compact", "ipfs"]);
|
|
5154
|
+
var ShareLinkSchema = z4.object({
|
|
4552
5155
|
/** Unique token identifying this share link */
|
|
4553
|
-
token:
|
|
5156
|
+
token: z4.string(),
|
|
4554
5157
|
/** Full URL for sharing */
|
|
4555
|
-
url:
|
|
5158
|
+
url: z4.string(),
|
|
4556
5159
|
/** The delegation this link grants access to */
|
|
4557
5160
|
delegation: DelegationSchema,
|
|
4558
5161
|
/** Encoding schema used for the link */
|
|
4559
5162
|
schema: ShareSchemaSchema,
|
|
4560
5163
|
/** When this share link expires */
|
|
4561
|
-
expiresAt:
|
|
5164
|
+
expiresAt: z4.coerce.date().optional(),
|
|
4562
5165
|
/** Human-readable description of what is being shared */
|
|
4563
|
-
description:
|
|
5166
|
+
description: z4.string().optional()
|
|
4564
5167
|
});
|
|
4565
5168
|
function createShareLinkDataSchema(dataSchema) {
|
|
4566
|
-
return
|
|
5169
|
+
return z4.object({
|
|
4567
5170
|
/** The retrieved data */
|
|
4568
5171
|
data: dataSchema,
|
|
4569
5172
|
/** The delegation that authorized this access */
|
|
4570
5173
|
delegation: DelegationSchema,
|
|
4571
5174
|
/** The space the data belongs to */
|
|
4572
|
-
spaceId:
|
|
5175
|
+
spaceId: z4.string(),
|
|
4573
5176
|
/** The resource path that was accessed */
|
|
4574
|
-
path:
|
|
5177
|
+
path: z4.string()
|
|
4575
5178
|
});
|
|
4576
5179
|
}
|
|
4577
|
-
var ShareLinkDataSchema = createShareLinkDataSchema(
|
|
4578
|
-
var IngestOptionsSchema =
|
|
5180
|
+
var ShareLinkDataSchema = createShareLinkDataSchema(z4.unknown());
|
|
5181
|
+
var IngestOptionsSchema = z4.object({
|
|
4579
5182
|
/** Whether to persist the delegation to storage */
|
|
4580
|
-
persist:
|
|
5183
|
+
persist: z4.boolean().optional(),
|
|
4581
5184
|
/** Whether to validate the full delegation chain */
|
|
4582
|
-
validateChain:
|
|
5185
|
+
validateChain: z4.boolean().optional(),
|
|
4583
5186
|
/** Name for the ingested key */
|
|
4584
|
-
keyName:
|
|
5187
|
+
keyName: z4.string().optional(),
|
|
4585
5188
|
/** Whether to create a session key for this delegation */
|
|
4586
|
-
createSessionKey:
|
|
5189
|
+
createSessionKey: z4.boolean().optional(),
|
|
4587
5190
|
/** Override the priority for the ingested key */
|
|
4588
|
-
priority:
|
|
5191
|
+
priority: z4.number().optional()
|
|
4589
5192
|
});
|
|
4590
|
-
var GenerateShareParamsSchema =
|
|
5193
|
+
var GenerateShareParamsSchema = z4.object({
|
|
4591
5194
|
/** Resource path to share */
|
|
4592
|
-
path:
|
|
5195
|
+
path: z4.string(),
|
|
4593
5196
|
/** Actions to authorize */
|
|
4594
|
-
actions:
|
|
5197
|
+
actions: z4.array(z4.string()).optional(),
|
|
4595
5198
|
/** When the share link expires */
|
|
4596
|
-
expiry:
|
|
5199
|
+
expiry: z4.coerce.date().optional(),
|
|
4597
5200
|
/** Encoding schema for the link */
|
|
4598
5201
|
schema: ShareSchemaSchema.optional(),
|
|
4599
5202
|
/** Human-readable description */
|
|
4600
|
-
description:
|
|
5203
|
+
description: z4.string().optional(),
|
|
4601
5204
|
/** Base URL for the share link */
|
|
4602
|
-
baseUrl:
|
|
5205
|
+
baseUrl: z4.string().optional()
|
|
4603
5206
|
});
|
|
4604
|
-
var DelegationManagerConfigSchema =
|
|
5207
|
+
var DelegationManagerConfigSchema = z4.object({
|
|
4605
5208
|
/** TinyCloud host URLs */
|
|
4606
|
-
hosts:
|
|
5209
|
+
hosts: z4.array(z4.string()),
|
|
4607
5210
|
/** Account space used by account-wide delegation history queries */
|
|
4608
|
-
accountSpaceId:
|
|
5211
|
+
accountSpaceId: z4.string().min(1).optional(),
|
|
4609
5212
|
/** Active session for authentication */
|
|
4610
|
-
session:
|
|
5213
|
+
session: z4.unknown().refine(
|
|
4611
5214
|
(val) => val !== null && typeof val === "object",
|
|
4612
5215
|
{ message: "Expected a ServiceSession object" }
|
|
4613
5216
|
),
|
|
4614
5217
|
/** Platform-specific invoke function */
|
|
4615
|
-
invoke:
|
|
5218
|
+
invoke: z4.unknown().refine(
|
|
4616
5219
|
(val) => typeof val === "function",
|
|
4617
5220
|
{ message: "Expected an invoke function" }
|
|
4618
5221
|
),
|
|
4619
5222
|
/** Platform-specific invoke function for raw resource URIs */
|
|
4620
|
-
invokeAny:
|
|
5223
|
+
invokeAny: z4.unknown().refine(
|
|
4621
5224
|
(val) => val === void 0 || typeof val === "function",
|
|
4622
5225
|
{ message: "Expected an invokeAny function or undefined" }
|
|
4623
5226
|
).optional(),
|
|
4624
5227
|
/** Optional custom fetch implementation */
|
|
4625
|
-
fetch:
|
|
5228
|
+
fetch: z4.unknown().refine(
|
|
4626
5229
|
(val) => val === void 0 || typeof val === "function",
|
|
4627
5230
|
{ message: "Expected a fetch function or undefined" }
|
|
4628
5231
|
).optional()
|
|
4629
5232
|
});
|
|
4630
|
-
var KeyProviderSchema =
|
|
5233
|
+
var KeyProviderSchema = z4.object({
|
|
4631
5234
|
/** Generate a new session key, returns key ID */
|
|
4632
|
-
createSessionKey:
|
|
5235
|
+
createSessionKey: z4.unknown().refine(
|
|
4633
5236
|
(val) => typeof val === "function",
|
|
4634
5237
|
{ message: "Expected a function" }
|
|
4635
5238
|
),
|
|
4636
5239
|
/** Get JWK for a key */
|
|
4637
|
-
getJWK:
|
|
5240
|
+
getJWK: z4.unknown().refine(
|
|
4638
5241
|
(val) => typeof val === "function",
|
|
4639
5242
|
{ message: "Expected a function" }
|
|
4640
5243
|
),
|
|
4641
5244
|
/** Get DID for a key */
|
|
4642
|
-
getDID:
|
|
5245
|
+
getDID: z4.unknown().refine(
|
|
4643
5246
|
(val) => typeof val === "function",
|
|
4644
5247
|
{ message: "Expected a function" }
|
|
4645
5248
|
)
|
|
4646
5249
|
});
|
|
4647
|
-
var DelegationApiResponseSchema =
|
|
5250
|
+
var DelegationApiResponseSchema = z4.object({
|
|
4648
5251
|
/** SIWE message content */
|
|
4649
|
-
siwe:
|
|
5252
|
+
siwe: z4.string(),
|
|
4650
5253
|
/** Signature of the SIWE message */
|
|
4651
|
-
signature:
|
|
5254
|
+
signature: z4.string(),
|
|
4652
5255
|
/** Delegation version */
|
|
4653
|
-
version:
|
|
5256
|
+
version: z4.number(),
|
|
4654
5257
|
/** CID of the created delegation */
|
|
4655
|
-
cid:
|
|
5258
|
+
cid: z4.string().optional()
|
|
4656
5259
|
});
|
|
4657
|
-
var DelegatedResourceSchema =
|
|
5260
|
+
var DelegatedResourceSchema = z4.object({
|
|
4658
5261
|
/** Short-form service name, e.g. "kv", "sql", "duckdb", "capabilities", "hooks". */
|
|
4659
|
-
service:
|
|
5262
|
+
service: z4.string(),
|
|
4660
5263
|
/** Full space id string, e.g. "tinycloud:pkh:eip155:1:0x....:default". */
|
|
4661
|
-
space:
|
|
5264
|
+
space: z4.string(),
|
|
4662
5265
|
/** Resource path; empty string when the resource URI had no path segment. */
|
|
4663
|
-
path:
|
|
5266
|
+
path: z4.string(),
|
|
4664
5267
|
/** Full-URN ability strings, e.g. ["tinycloud.kv/get", "tinycloud.kv/put"]. */
|
|
4665
|
-
actions:
|
|
5268
|
+
actions: z4.array(z4.string()),
|
|
4666
5269
|
/** Exact ReCap caveats that constrain every action in this scope. */
|
|
4667
|
-
caveats:
|
|
5270
|
+
caveats: z4.array(z4.record(z4.string(), z4.unknown())).optional()
|
|
4668
5271
|
});
|
|
4669
|
-
var CreateDelegationWasmParamsSchema =
|
|
5272
|
+
var CreateDelegationWasmParamsSchema = z4.object({
|
|
4670
5273
|
/** The session containing delegation credentials */
|
|
4671
|
-
session:
|
|
5274
|
+
session: z4.unknown().refine(
|
|
4672
5275
|
(val) => val !== null && typeof val === "object",
|
|
4673
5276
|
{ message: "Expected a ServiceSession object" }
|
|
4674
5277
|
),
|
|
4675
5278
|
/** DID of the delegate */
|
|
4676
|
-
delegateDID:
|
|
5279
|
+
delegateDID: z4.string(),
|
|
4677
5280
|
/** Space ID this delegation applies to */
|
|
4678
|
-
spaceId:
|
|
5281
|
+
spaceId: z4.string(),
|
|
4679
5282
|
/**
|
|
4680
5283
|
* Multi-resource abilities map: short-service → path → full-URN actions.
|
|
4681
5284
|
* Matches the shape accepted by `prepareSession`.
|
|
@@ -4692,26 +5295,26 @@ var CreateDelegationWasmParamsSchema = z3.object({
|
|
|
4692
5295
|
* }
|
|
4693
5296
|
* ```
|
|
4694
5297
|
*/
|
|
4695
|
-
abilities:
|
|
5298
|
+
abilities: z4.record(z4.string(), z4.record(z4.string(), z4.array(z4.string()))),
|
|
4696
5299
|
/** Expiration time in seconds since Unix epoch */
|
|
4697
|
-
expirationSecs:
|
|
5300
|
+
expirationSecs: z4.number(),
|
|
4698
5301
|
/** Optional not-before time in seconds since Unix epoch */
|
|
4699
|
-
notBeforeSecs:
|
|
5302
|
+
notBeforeSecs: z4.number().optional()
|
|
4700
5303
|
});
|
|
4701
|
-
var CreateDelegationWasmResultSchema =
|
|
5304
|
+
var CreateDelegationWasmResultSchema = z4.object({
|
|
4702
5305
|
/** Base64url-encoded UCAN delegation */
|
|
4703
|
-
delegation:
|
|
5306
|
+
delegation: z4.string(),
|
|
4704
5307
|
/** CID of the delegation */
|
|
4705
|
-
cid:
|
|
5308
|
+
cid: z4.string(),
|
|
4706
5309
|
/** DID of the delegate */
|
|
4707
|
-
delegateDID:
|
|
5310
|
+
delegateDID: z4.string(),
|
|
4708
5311
|
/** Expiration time */
|
|
4709
|
-
expiry:
|
|
5312
|
+
expiry: z4.coerce.date(),
|
|
4710
5313
|
/**
|
|
4711
5314
|
* All (service, space, path, actions) entries granted by this delegation.
|
|
4712
5315
|
* Always non-empty on success.
|
|
4713
5316
|
*/
|
|
4714
|
-
resources:
|
|
5317
|
+
resources: z4.array(DelegatedResourceSchema)
|
|
4715
5318
|
});
|
|
4716
5319
|
|
|
4717
5320
|
// src/expiry.ts
|
|
@@ -5406,66 +6009,66 @@ var DelegationManager = class {
|
|
|
5406
6009
|
};
|
|
5407
6010
|
|
|
5408
6011
|
// src/delegations/SharingService.schema.ts
|
|
5409
|
-
import { z as
|
|
5410
|
-
var EncodedShareDataSchema =
|
|
6012
|
+
import { z as z5 } from "zod";
|
|
6013
|
+
var EncodedShareDataSchema = z5.object({
|
|
5411
6014
|
/** Private key in JWK format (must include d parameter) */
|
|
5412
6015
|
key: JWKSchema.refine(
|
|
5413
6016
|
(jwk) => typeof jwk.d === "string" && jwk.d.length > 0,
|
|
5414
6017
|
{ message: "JWK must include private key (d parameter)" }
|
|
5415
6018
|
),
|
|
5416
6019
|
/** DID of the key */
|
|
5417
|
-
keyDid:
|
|
6020
|
+
keyDid: z5.string().min(1, "keyDid is required"),
|
|
5418
6021
|
/** The delegation granting access */
|
|
5419
6022
|
delegation: DelegationSchema,
|
|
5420
6023
|
/** Resource path this link grants access to */
|
|
5421
|
-
path:
|
|
6024
|
+
path: z5.string().min(1, "path is required"),
|
|
5422
6025
|
/** TinyCloud host URL */
|
|
5423
|
-
host:
|
|
6026
|
+
host: z5.string().url("host must be a valid URL"),
|
|
5424
6027
|
/** Space ID */
|
|
5425
|
-
spaceId:
|
|
6028
|
+
spaceId: z5.string().min(1, "spaceId is required"),
|
|
5426
6029
|
/** Schema version (must be 1) */
|
|
5427
|
-
version:
|
|
6030
|
+
version: z5.literal(1)
|
|
5428
6031
|
});
|
|
5429
|
-
var ReceiveOptionsSchema =
|
|
6032
|
+
var ReceiveOptionsSchema = z5.object({
|
|
5430
6033
|
/**
|
|
5431
6034
|
* Whether to automatically create a sub-delegation to the current session key.
|
|
5432
6035
|
* Default: true
|
|
5433
6036
|
*/
|
|
5434
|
-
autoSubdelegate:
|
|
6037
|
+
autoSubdelegate: z5.boolean().optional(),
|
|
5435
6038
|
/**
|
|
5436
6039
|
* Whether to use the current session key for operations (requires autoSubdelegate).
|
|
5437
6040
|
* Default: true
|
|
5438
6041
|
*/
|
|
5439
|
-
useSessionKey:
|
|
6042
|
+
useSessionKey: z5.boolean().optional(),
|
|
5440
6043
|
/**
|
|
5441
6044
|
* Ingestion options passed to CapabilityKeyRegistry.
|
|
5442
6045
|
*/
|
|
5443
6046
|
ingestOptions: IngestOptionsSchema.optional()
|
|
5444
6047
|
});
|
|
5445
|
-
var SharingServiceConfigSchema =
|
|
6048
|
+
var SharingServiceConfigSchema = z5.object({
|
|
5446
6049
|
/** TinyCloud host URLs */
|
|
5447
|
-
hosts:
|
|
6050
|
+
hosts: z5.array(z5.string().url()).min(1, "At least one host URL is required"),
|
|
5448
6051
|
/**
|
|
5449
6052
|
* Active session for authentication.
|
|
5450
6053
|
* Required for generate(), optional for receive().
|
|
5451
6054
|
*/
|
|
5452
|
-
session:
|
|
6055
|
+
session: z5.unknown().refine(
|
|
5453
6056
|
(val) => val === void 0 || val !== null && typeof val === "object",
|
|
5454
6057
|
{ message: "Expected a ServiceSession object or undefined" }
|
|
5455
6058
|
).optional(),
|
|
5456
6059
|
/** Platform-specific invoke function */
|
|
5457
|
-
invoke:
|
|
6060
|
+
invoke: z5.unknown().refine((val) => typeof val === "function", {
|
|
5458
6061
|
message: "Expected an invoke function"
|
|
5459
6062
|
}),
|
|
5460
6063
|
/** Optional custom fetch implementation */
|
|
5461
|
-
fetch:
|
|
6064
|
+
fetch: z5.unknown().refine(
|
|
5462
6065
|
(val) => val === void 0 || typeof val === "function",
|
|
5463
6066
|
{ message: "Expected a fetch function or undefined" }
|
|
5464
6067
|
).optional(),
|
|
5465
6068
|
/** Key provider for cryptographic operations */
|
|
5466
6069
|
keyProvider: KeyProviderSchema,
|
|
5467
6070
|
/** Capability key registry for key/delegation management */
|
|
5468
|
-
registry:
|
|
6071
|
+
registry: z5.unknown().refine(
|
|
5469
6072
|
(val) => val !== null && typeof val === "object",
|
|
5470
6073
|
{ message: "Expected an ICapabilityKeyRegistry object" }
|
|
5471
6074
|
),
|
|
@@ -5473,47 +6076,47 @@ var SharingServiceConfigSchema = z4.object({
|
|
|
5473
6076
|
* Delegation manager for creating delegations.
|
|
5474
6077
|
* Required for generate(), optional for receive().
|
|
5475
6078
|
*/
|
|
5476
|
-
delegationManager:
|
|
6079
|
+
delegationManager: z5.unknown().refine(
|
|
5477
6080
|
(val) => val === void 0 || val !== null && typeof val === "object",
|
|
5478
6081
|
{ message: "Expected a DelegationManager object or undefined" }
|
|
5479
6082
|
).optional(),
|
|
5480
6083
|
/** Factory for creating KV service instances */
|
|
5481
|
-
createKVService:
|
|
6084
|
+
createKVService: z5.unknown().refine(
|
|
5482
6085
|
(val) => typeof val === "function",
|
|
5483
6086
|
{ message: "Expected a createKVService factory function" }
|
|
5484
6087
|
),
|
|
5485
6088
|
/** Base URL for sharing links (e.g., "https://share.myapp.com") */
|
|
5486
|
-
baseUrl:
|
|
6089
|
+
baseUrl: z5.string().optional(),
|
|
5487
6090
|
/**
|
|
5488
6091
|
* Custom delegation creation function.
|
|
5489
6092
|
*/
|
|
5490
|
-
createDelegation:
|
|
6093
|
+
createDelegation: z5.unknown().refine((val) => val === void 0 || typeof val === "function", {
|
|
5491
6094
|
message: "Expected a createDelegation function or undefined"
|
|
5492
6095
|
}).optional(),
|
|
5493
6096
|
/**
|
|
5494
6097
|
* WASM function for client-side delegation creation.
|
|
5495
6098
|
*/
|
|
5496
|
-
createDelegationWasm:
|
|
6099
|
+
createDelegationWasm: z5.unknown().refine((val) => val === void 0 || typeof val === "function", {
|
|
5497
6100
|
message: "Expected a createDelegationWasm function or undefined"
|
|
5498
6101
|
}).optional(),
|
|
5499
6102
|
/** CID computation used to verify transportable child delegations. */
|
|
5500
|
-
computeCid:
|
|
6103
|
+
computeCid: z5.unknown().refine((val) => val === void 0 || typeof val === "function", {
|
|
5501
6104
|
message: "Expected a computeCid function or undefined"
|
|
5502
6105
|
}).optional(),
|
|
5503
6106
|
/**
|
|
5504
6107
|
* Path prefix for KV operations.
|
|
5505
6108
|
*/
|
|
5506
|
-
pathPrefix:
|
|
6109
|
+
pathPrefix: z5.string().optional(),
|
|
5507
6110
|
/**
|
|
5508
6111
|
* Session expiry time.
|
|
5509
6112
|
*/
|
|
5510
|
-
sessionExpiry:
|
|
6113
|
+
sessionExpiry: z5.date().optional(),
|
|
5511
6114
|
/**
|
|
5512
6115
|
* Callback to create a DIRECT delegation from wallet to share key.
|
|
5513
6116
|
* This is the preferred method for long-lived share links because it
|
|
5514
6117
|
* bypasses the session delegation chain entirely.
|
|
5515
6118
|
*/
|
|
5516
|
-
onRootDelegationNeeded:
|
|
6119
|
+
onRootDelegationNeeded: z5.unknown().refine((val) => val === void 0 || typeof val === "function", {
|
|
5517
6120
|
message: "Expected an onRootDelegationNeeded function or undefined"
|
|
5518
6121
|
}).optional()
|
|
5519
6122
|
});
|
|
@@ -5535,6 +6138,7 @@ function validateEncodedShareData(data) {
|
|
|
5535
6138
|
|
|
5536
6139
|
// src/manifest.ts
|
|
5537
6140
|
import ms from "ms";
|
|
6141
|
+
import { ACCOUNT_MANIFEST_PERMISSIONS } from "@tinycloud/bootstrap";
|
|
5538
6142
|
import { resolveSecretPath, SECRET_NAME_RE } from "@tinycloud/sdk-services";
|
|
5539
6143
|
var DEFAULT_KNOWLEDGE_ROOT = "knowledge/index.md";
|
|
5540
6144
|
var ManifestValidationError = class extends Error {
|
|
@@ -6193,30 +6797,6 @@ function withCapabilitiesReadForSpaces(resources) {
|
|
|
6193
6797
|
...[...spaces].map(capabilitiesReadPermission)
|
|
6194
6798
|
]);
|
|
6195
6799
|
}
|
|
6196
|
-
function accountRegistryPermissions() {
|
|
6197
|
-
return [
|
|
6198
|
-
...[ACCOUNT_REGISTRY_PATH, "spaces/"].map((path) => ({
|
|
6199
|
-
service: "tinycloud.kv",
|
|
6200
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
6201
|
-
path,
|
|
6202
|
-
actions: ["tinycloud.kv/get", "tinycloud.kv/put", "tinycloud.kv/list"]
|
|
6203
|
-
})),
|
|
6204
|
-
{
|
|
6205
|
-
service: "tinycloud.delegation",
|
|
6206
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
6207
|
-
path: "",
|
|
6208
|
-
actions: ["tinycloud.delegation/list"]
|
|
6209
|
-
}
|
|
6210
|
-
];
|
|
6211
|
-
}
|
|
6212
|
-
function accountRegistryIndexPermission() {
|
|
6213
|
-
return {
|
|
6214
|
-
service: "tinycloud.sql",
|
|
6215
|
-
space: ACCOUNT_REGISTRY_SPACE,
|
|
6216
|
-
path: "account",
|
|
6217
|
-
actions: ["tinycloud.sql/read", "tinycloud.sql/write", "tinycloud.sql/schema"]
|
|
6218
|
-
};
|
|
6219
|
-
}
|
|
6220
6800
|
function composeManifestRequest(inputs, options2 = {}) {
|
|
6221
6801
|
if (!Array.isArray(inputs) || inputs.length === 0) {
|
|
6222
6802
|
throw new ManifestValidationError(
|
|
@@ -6234,8 +6814,12 @@ function composeManifestRequest(inputs, options2 = {}) {
|
|
|
6234
6814
|
}))
|
|
6235
6815
|
);
|
|
6236
6816
|
if (includeAccountRegistryPermissions) {
|
|
6237
|
-
resources.push(
|
|
6238
|
-
|
|
6817
|
+
resources.push(
|
|
6818
|
+
...ACCOUNT_MANIFEST_PERMISSIONS.map((resource) => ({
|
|
6819
|
+
...resource,
|
|
6820
|
+
actions: [...resource.actions]
|
|
6821
|
+
}))
|
|
6822
|
+
);
|
|
6239
6823
|
}
|
|
6240
6824
|
const resourcesWithImplicitCapabilities = withCapabilitiesReadForSpaces(resources);
|
|
6241
6825
|
const manifestsByAppId = /* @__PURE__ */ new Map();
|
|
@@ -6360,15 +6944,28 @@ function normalizeSpace(space) {
|
|
|
6360
6944
|
function isCapabilitySubset(requested, granted) {
|
|
6361
6945
|
const missing = [];
|
|
6362
6946
|
for (const req of requested) {
|
|
6363
|
-
const
|
|
6364
|
-
|
|
6947
|
+
const matchingScope = granted.filter(
|
|
6948
|
+
(entry) => canonicalizeEntryScopeMatches(req, entry)
|
|
6949
|
+
);
|
|
6950
|
+
const requestedActions = expandActionShortNames(
|
|
6951
|
+
req.service,
|
|
6952
|
+
req.actions
|
|
6953
|
+
);
|
|
6954
|
+
const grantedActions = matchingScope.flatMap(
|
|
6955
|
+
(entry) => expandActionShortNames(entry.service, entry.actions)
|
|
6956
|
+
);
|
|
6957
|
+
const covered = requestedActions.every(
|
|
6958
|
+
(requestedAction) => grantedActions.some(
|
|
6959
|
+
(grantedAction) => actionContains(grantedAction, requestedAction)
|
|
6960
|
+
)
|
|
6961
|
+
);
|
|
6962
|
+
if (!covered) {
|
|
6365
6963
|
missing.push(cloneEntry(req));
|
|
6366
|
-
continue;
|
|
6367
6964
|
}
|
|
6368
6965
|
}
|
|
6369
6966
|
return { subset: missing.length === 0, missing };
|
|
6370
6967
|
}
|
|
6371
|
-
function
|
|
6968
|
+
function canonicalizeEntryScopeMatches(requested, granted) {
|
|
6372
6969
|
if (requested.service !== granted.service) {
|
|
6373
6970
|
return false;
|
|
6374
6971
|
}
|
|
@@ -6378,15 +6975,6 @@ function canonicalizeEntryMatches(requested, granted) {
|
|
|
6378
6975
|
if (!pathContains2(granted.path, requested.path)) {
|
|
6379
6976
|
return false;
|
|
6380
6977
|
}
|
|
6381
|
-
const reqActions = new Set(
|
|
6382
|
-
expandActionShortNames(requested.service, requested.actions)
|
|
6383
|
-
);
|
|
6384
|
-
const grantedActions = expandActionShortNames(granted.service, granted.actions);
|
|
6385
|
-
for (const a of reqActions) {
|
|
6386
|
-
if (!grantedActions.some((grantedAction) => actionContains(grantedAction, a))) {
|
|
6387
|
-
return false;
|
|
6388
|
-
}
|
|
6389
|
-
}
|
|
6390
6978
|
if (!recapCaveatsEqual(requested.caveats, granted.caveats)) {
|
|
6391
6979
|
return false;
|
|
6392
6980
|
}
|
|
@@ -6406,13 +6994,13 @@ function canonicalizeRecapCaveats(caveats) {
|
|
|
6406
6994
|
}
|
|
6407
6995
|
if (Array.isArray(value)) return `[${value.map(canonicalize).join(",")}]`;
|
|
6408
6996
|
if (typeof value === "object") {
|
|
6409
|
-
const
|
|
6410
|
-
const prototype = Object.getPrototypeOf(
|
|
6997
|
+
const object2 = value;
|
|
6998
|
+
const prototype = Object.getPrototypeOf(object2);
|
|
6411
6999
|
if (prototype !== Object.prototype && prototype !== null) {
|
|
6412
7000
|
throw new Error("ReCap caveats must contain only JSON values.");
|
|
6413
7001
|
}
|
|
6414
|
-
return `{${Object.keys(
|
|
6415
|
-
(key) => `${JSON.stringify(key)}:${canonicalize(
|
|
7002
|
+
return `{${Object.keys(object2).sort().map(
|
|
7003
|
+
(key) => `${JSON.stringify(key)}:${canonicalize(object2[key])}`
|
|
6416
7004
|
).join(",")}}`;
|
|
6417
7005
|
}
|
|
6418
7006
|
throw new Error("ReCap caveats must contain only JSON values.");
|
|
@@ -6484,7 +7072,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
|
|
|
6484
7072
|
}
|
|
6485
7073
|
|
|
6486
7074
|
// src/delegations/SharingService.ts
|
|
6487
|
-
import { ed25519 as
|
|
7075
|
+
import { ed25519 as ed255195 } from "@noble/curves/ed25519";
|
|
6488
7076
|
|
|
6489
7077
|
// src/delegations/ShareRecipientClient.ts
|
|
6490
7078
|
import {
|
|
@@ -6492,13 +7080,13 @@ import {
|
|
|
6492
7080
|
KVService,
|
|
6493
7081
|
ServiceContext
|
|
6494
7082
|
} from "@tinycloud/sdk-services";
|
|
6495
|
-
import { ed25519 as
|
|
6496
|
-
import { sha256 as
|
|
7083
|
+
import { ed25519 as ed255194 } from "@noble/curves/ed25519";
|
|
7084
|
+
import { sha256 as sha2568 } from "@noble/hashes/sha256";
|
|
6497
7085
|
|
|
6498
7086
|
// src/delegations/share-envelope.ts
|
|
6499
|
-
import { ed25519 as
|
|
6500
|
-
import { blake3 as
|
|
6501
|
-
import { sha256 as
|
|
7087
|
+
import { ed25519 as ed255193 } from "@noble/curves/ed25519";
|
|
7088
|
+
import { blake3 as blake33 } from "@noble/hashes/blake3";
|
|
7089
|
+
import { sha256 as sha2566 } from "@noble/hashes/sha256";
|
|
6502
7090
|
var ENVELOPE_SCHEMA = "xyz.tinycloud.share/envelope";
|
|
6503
7091
|
var INLINE_PREFIX = "tc2:";
|
|
6504
7092
|
var RAW_CID_CODEC = 85;
|
|
@@ -6547,8 +7135,8 @@ function canonicalJson(value) {
|
|
|
6547
7135
|
}
|
|
6548
7136
|
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
6549
7137
|
if (typeof value === "object") {
|
|
6550
|
-
const
|
|
6551
|
-
return `{${Object.keys(
|
|
7138
|
+
const object2 = value;
|
|
7139
|
+
return `{${Object.keys(object2).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(object2[key])}`).join(",")}}`;
|
|
6552
7140
|
}
|
|
6553
7141
|
throw new ShareEnvelopeError("invalid-envelope", "unsupported JSON value");
|
|
6554
7142
|
}
|
|
@@ -6654,6 +7242,10 @@ function normalizeRecipient(recipient) {
|
|
|
6654
7242
|
}
|
|
6655
7243
|
return { kind: recipient.kind, value: domain };
|
|
6656
7244
|
}
|
|
7245
|
+
if (recipient.kind === "recipientDid") {
|
|
7246
|
+
if (!isCanonicalRecipientDid(recipient.value)) throw new ShareEnvelopeError("invalid-envelope", "recipient DID is invalid");
|
|
7247
|
+
return { kind: recipient.kind, value: recipient.value };
|
|
7248
|
+
}
|
|
6657
7249
|
const exact = recipient.value.trim();
|
|
6658
7250
|
const at = exact.lastIndexOf("@");
|
|
6659
7251
|
const normalizedExact = at > 0 ? `${exact.slice(0, at)}@${exact.slice(at + 1).toLowerCase()}` : exact;
|
|
@@ -6662,6 +7254,28 @@ function normalizeRecipient(recipient) {
|
|
|
6662
7254
|
}
|
|
6663
7255
|
return { kind: recipient.kind, value: normalizedExact };
|
|
6664
7256
|
}
|
|
7257
|
+
function isCanonicalRecipientDid(value) {
|
|
7258
|
+
if (value.length === 0 || value.length > 2048 || /[\u0000-\u0020\u007f]/.test(value)) return false;
|
|
7259
|
+
const parts = value.split(":");
|
|
7260
|
+
if (parts.length < 3 || parts[0] !== "did" || !/^[a-z0-9]+$/.test(parts[1] ?? "")) return false;
|
|
7261
|
+
const identifier = parts.slice(2);
|
|
7262
|
+
if (identifier.some((part) => part.length === 0)) return false;
|
|
7263
|
+
if (parts[1] === "web") {
|
|
7264
|
+
const host = identifier[0] ?? "";
|
|
7265
|
+
if (host.length > 253 || host.split(".").some((label) => !label || label.length > 63 || !/^[A-Za-z0-9-]+$/.test(label) || label.startsWith("-") || label.endsWith("-"))) return false;
|
|
7266
|
+
return identifier.slice(1).every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
|
|
7267
|
+
}
|
|
7268
|
+
if (parts[1] === "pkh") return identifier.length >= 3 && identifier.every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
|
|
7269
|
+
if (parts[1] === "key") {
|
|
7270
|
+
try {
|
|
7271
|
+
const bytes2 = base58btc.decode(identifier.join(":"));
|
|
7272
|
+
return bytes2.length === 34 && bytes2[0] === 237 && bytes2[1] === 1;
|
|
7273
|
+
} catch {
|
|
7274
|
+
return false;
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
return false;
|
|
7278
|
+
}
|
|
6665
7279
|
function normalizeShareRecipientTarget(recipient) {
|
|
6666
7280
|
const normalized = normalizeRecipient(recipient);
|
|
6667
7281
|
if (normalized === void 0) throw new ShareEnvelopeError("invalid-envelope", "recipient matcher is required");
|
|
@@ -6691,17 +7305,17 @@ function createSharePolicy(input) {
|
|
|
6691
7305
|
};
|
|
6692
7306
|
}
|
|
6693
7307
|
function contentDigest(bytes2) {
|
|
6694
|
-
return bytesToBase64Url(
|
|
7308
|
+
return bytesToBase64Url(sha2566(bytes2));
|
|
6695
7309
|
}
|
|
6696
7310
|
function computeShareCid(bytes2) {
|
|
6697
|
-
const digest4 = create(BLAKE3_256_CODE,
|
|
7311
|
+
const digest4 = create(BLAKE3_256_CODE, blake33(bytes2));
|
|
6698
7312
|
return CID.createV1(RAW_CID_CODEC, digest4).toString();
|
|
6699
7313
|
}
|
|
6700
7314
|
function verifyShareCid(cid2, bytes2) {
|
|
6701
7315
|
try {
|
|
6702
7316
|
const parsed = CID.parse(cid2);
|
|
6703
7317
|
if (parsed.toString() !== cid2 || parsed.multihash.code !== BLAKE3_256_CODE) return false;
|
|
6704
|
-
return parsed.equals(CID.createV1(parsed.code, create(parsed.multihash.code,
|
|
7318
|
+
return parsed.equals(CID.createV1(parsed.code, create(parsed.multihash.code, blake33(bytes2))));
|
|
6705
7319
|
} catch {
|
|
6706
7320
|
return false;
|
|
6707
7321
|
}
|
|
@@ -6711,7 +7325,7 @@ function envelopeSigningBytes(envelope) {
|
|
|
6711
7325
|
}
|
|
6712
7326
|
function signShareEnvelope(input) {
|
|
6713
7327
|
if (input.signerPrivateKey.length !== 32) throw new ShareEnvelopeError("invalid-envelope", "Ed25519 private key must be 32 bytes");
|
|
6714
|
-
const publicKey =
|
|
7328
|
+
const publicKey = ed255193.getPublicKey(input.signerPrivateKey);
|
|
6715
7329
|
const unsigned = {
|
|
6716
7330
|
schema: ENVELOPE_SCHEMA,
|
|
6717
7331
|
version: 2,
|
|
@@ -6726,7 +7340,7 @@ function signShareEnvelope(input) {
|
|
|
6726
7340
|
expiresAt: new Date(input.expiresAt).toISOString(),
|
|
6727
7341
|
signer: { did: input.signerDid, publicKey: bytesToBase64Url(publicKey) }
|
|
6728
7342
|
};
|
|
6729
|
-
return { ...unsigned, signature: bytesToBase64Url(
|
|
7343
|
+
return { ...unsigned, signature: bytesToBase64Url(ed255193.sign(envelopeSigningBytes(unsigned), input.signerPrivateKey)) };
|
|
6730
7344
|
}
|
|
6731
7345
|
function verifyShareEnvelope(envelope, options2 = {}) {
|
|
6732
7346
|
try {
|
|
@@ -6748,9 +7362,9 @@ function verifyShareEnvelope(envelope, options2 = {}) {
|
|
|
6748
7362
|
const recipient = normalizeRecipient(envelope.recipient);
|
|
6749
7363
|
if (recipient !== void 0 && JSON.stringify(recipient) !== JSON.stringify(envelope.recipient)) throw new ShareEnvelopeError("invalid-envelope", "recipient is not canonical");
|
|
6750
7364
|
if (recipient?.kind === "exactEmail" || recipient?.kind === "emailDomain") throw new ShareEnvelopeError("unsafe-plaintext", "recipient matchers are not public envelope fields");
|
|
6751
|
-
if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
|
|
7365
|
+
if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "recipientDid", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
|
|
6752
7366
|
if (envelope.recipientKind === "bearer" && recipient?.kind !== void 0 && recipient.kind !== "bearer") throw new ShareEnvelopeError("invalid-envelope", "recipient mode does not match recipient");
|
|
6753
|
-
if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "
|
|
7367
|
+
if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.recipientKind === "recipientDid") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "addressed shares require encryption");
|
|
6754
7368
|
if (typeof envelope.spaceId !== "string" || envelope.spaceId.length === 0 || typeof envelope.content.mimeType !== "string" || envelope.content.mimeType.length === 0 || typeof envelope.content.digest !== "string" || !/^[A-Za-z0-9_-]+$/.test(envelope.content.digest)) throw new ShareEnvelopeError("invalid-envelope", "content metadata is invalid");
|
|
6755
7369
|
const maxContentBytes = envelope.encrypted ? options2.maxSealedContentBytes ?? MAX_SEALED_SHARE_CONTENT_BYTES : options2.maxContentBytes ?? MAX_SHARE_CONTENT_BYTES;
|
|
6756
7370
|
if (!Number.isInteger(envelope.content.size) || envelope.content.size < 0 || envelope.content.size > maxContentBytes) throw new ShareEnvelopeError("content-too-large", "share content exceeds the configured limit");
|
|
@@ -6758,7 +7372,7 @@ function verifyShareEnvelope(envelope, options2 = {}) {
|
|
|
6758
7372
|
const signature = base64UrlToBytes(envelope.signature);
|
|
6759
7373
|
const unsigned = { ...envelope };
|
|
6760
7374
|
delete unsigned.signature;
|
|
6761
|
-
if (publicKey.length !== 32 || signature.length !== 64 || !
|
|
7375
|
+
if (publicKey.length !== 32 || signature.length !== 64 || !ed255193.verify(signature, envelopeSigningBytes(unsigned), publicKey)) throw new ShareEnvelopeError("signature-invalid", "share envelope signature is invalid");
|
|
6762
7376
|
if (options2.trustedSignerDids !== void 0 && envelope.recipientKind !== void 0 && !options2.trustedSignerDids.includes(envelope.signer.did)) throw new ShareEnvelopeError("signature-invalid", "share signer is not trusted");
|
|
6763
7377
|
return envelope;
|
|
6764
7378
|
} catch (error) {
|
|
@@ -6806,7 +7420,7 @@ function encodeInlineShareUrl(input) {
|
|
|
6806
7420
|
}
|
|
6807
7421
|
var PUBLISHED_AAD = new TextEncoder().encode("tinycloud-share-envelope-v1");
|
|
6808
7422
|
function publishedCid(bytes2) {
|
|
6809
|
-
return CID.create(1, code, create(sha2562.code,
|
|
7423
|
+
return CID.create(1, code, create(sha2562.code, sha2566(bytes2))).toString();
|
|
6810
7424
|
}
|
|
6811
7425
|
function isPublishedCid(value) {
|
|
6812
7426
|
try {
|
|
@@ -6846,7 +7460,7 @@ function publishedArtifact(envelope, plaintext, policy) {
|
|
|
6846
7460
|
content: {
|
|
6847
7461
|
mimeType: "application/octet-stream",
|
|
6848
7462
|
size: plaintext.byteLength,
|
|
6849
|
-
digest: bytesToBase64Url(
|
|
7463
|
+
digest: bytesToBase64Url(sha2566(plaintext))
|
|
6850
7464
|
},
|
|
6851
7465
|
// Addressed policy metadata is confidential even though this function
|
|
6852
7466
|
// is called after the outer envelope has been opened. Keep the
|
|
@@ -6889,7 +7503,7 @@ function parsePolicyMetadata(policyBytes, target, expectedExpiry) {
|
|
|
6889
7503
|
assertKeys(policy, ["type", "version", "issuerDid", "recipientMatcher", "target", "delegation", "authority", "actions", "resource", "content-source", "expiresAt"], "published canonical policy material");
|
|
6890
7504
|
if (typeof policy.issuerDid !== "string" || typeof policy.expiresAt !== "string" || policy.expiresAt !== expectedExpiry) throw new ShareEnvelopeError("invalid-envelope", "policy expiry is not bound to the envelope");
|
|
6891
7505
|
const matcherValue = policy.recipientMatcher;
|
|
6892
|
-
if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
7506
|
+
if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" && matcherValue.kind !== "recipientDid" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
6893
7507
|
const matcher2 = normalizeRecipient(matcherValue);
|
|
6894
7508
|
if (matcher2 === void 0 || matcher2.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
6895
7509
|
if (!isPlainObject(policy.target)) throw new ShareEnvelopeError("invalid-envelope", "policy target is invalid");
|
|
@@ -6950,9 +7564,9 @@ function parsePolicyMetadata(policyBytes, target, expectedExpiry) {
|
|
|
6950
7564
|
assertKeys(source, ["kind", "space", "database", "path", "statement", "arguments", "argumentsDigest", "action"], "published SQL content source");
|
|
6951
7565
|
if (typeof source.space !== "string" || typeof source.database !== "string" || typeof source.path !== "string" || typeof source.statement !== "string" || !source.arguments || typeof source.arguments !== "object" || Array.isArray(source.arguments) || typeof source.argumentsDigest !== "string" || source.action !== "tinycloud.sql/read") throw new ShareEnvelopeError("invalid-envelope", "published SQL content source is invalid");
|
|
6952
7566
|
for (const argument of Object.values(source.arguments)) if (!Number.isSafeInteger(argument)) throw new ShareEnvelopeError("invalid-envelope", "published SQL arguments are invalid");
|
|
6953
|
-
if (bytesToBase64Url(
|
|
7567
|
+
if (bytesToBase64Url(sha2566(new TextEncoder().encode(canonicalJson(source.arguments)))) !== source.argumentsDigest) throw new ShareEnvelopeError("invalid-envelope", "published SQL argument digest is invalid");
|
|
6954
7568
|
} else throw new ShareEnvelopeError("invalid-envelope", "policy content source kind is invalid");
|
|
6955
|
-
if (typeof policy.contentSourceDigest !== "string" || bytesToBase64Url(
|
|
7569
|
+
if (typeof policy.contentSourceDigest !== "string" || bytesToBase64Url(sha2566(new TextEncoder().encode(canonicalJson(source)))) !== policy.contentSourceDigest) throw new ShareEnvelopeError("invalid-envelope", "policy content source digest is invalid");
|
|
6956
7570
|
return { recipientKind, actions, resource };
|
|
6957
7571
|
}
|
|
6958
7572
|
function parseCanonicalPublishedV2(value, options2) {
|
|
@@ -6976,7 +7590,7 @@ function parseCanonicalPublishedV2(value, options2) {
|
|
|
6976
7590
|
if (!Number.isFinite(expiry) || expiry <= (options2.now ?? /* @__PURE__ */ new Date()).getTime() || new Date(expiry).toISOString() !== value.expiry) throw new ShareEnvelopeError("expired", "published share envelope has expired");
|
|
6977
7591
|
if (typeof delegation.cid !== "string" || typeof delegation.issuerDid !== "string" || typeof delegation.audience !== "string" || typeof delegation.expiresAt !== "string" || Date.parse(delegation.expiresAt) > expiry) throw new ShareEnvelopeError("invalid-envelope", "published v2 delegation is invalid");
|
|
6978
7592
|
const matcher = value.recipientMatcher;
|
|
6979
|
-
if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
7593
|
+
if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" && matcher.kind !== "recipientDid" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
6980
7594
|
const normalizedMatcher = normalizeRecipient(matcher);
|
|
6981
7595
|
if (normalizedMatcher === void 0 || normalizedMatcher.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
6982
7596
|
if (!Array.isArray(value.actions)) throw new ShareEnvelopeError("invalid-envelope", "published v2 actions are invalid");
|
|
@@ -7000,7 +7614,7 @@ function parseCanonicalPublishedV2(value, options2) {
|
|
|
7000
7614
|
const signingBytes = new Uint8Array(domain.length + body.length);
|
|
7001
7615
|
signingBytes.set(domain);
|
|
7002
7616
|
signingBytes.set(body, domain.length);
|
|
7003
|
-
if (signatureBytes.length !== 64 || !
|
|
7617
|
+
if (signatureBytes.length !== 64 || !ed255193.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v2 envelope signature is invalid");
|
|
7004
7618
|
const content = options2.plaintext ?? new Uint8Array();
|
|
7005
7619
|
const normalized = {
|
|
7006
7620
|
schema: ENVELOPE_SCHEMA,
|
|
@@ -7010,7 +7624,7 @@ function parseCanonicalPublishedV2(value, options2) {
|
|
|
7010
7624
|
recipientKind: normalizedMatcher.kind,
|
|
7011
7625
|
resource,
|
|
7012
7626
|
actions,
|
|
7013
|
-
content: { mimeType: typeof contentSource.mimeType === "string" ? contentSource.mimeType : "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(
|
|
7627
|
+
content: { mimeType: typeof contentSource.mimeType === "string" ? contentSource.mimeType : "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(sha2566(content)) },
|
|
7014
7628
|
encrypted: true,
|
|
7015
7629
|
expiresAt: value.expiry,
|
|
7016
7630
|
signer: { did: signature.signerDid, publicKey: bytesToBase64Url(signerKey) },
|
|
@@ -7109,7 +7723,7 @@ function parsePublishedShareEnvelope(bytes2, options2 = {}) {
|
|
|
7109
7723
|
if (envelope.authorizationTarget.kind !== "bearerKey" && (options2.trustedSignerDids === void 0 || !options2.trustedSignerDids.includes(envelope.signature.signerDid))) throw new ShareEnvelopeError("signature-invalid", "a trusted authority is required for addressed shares");
|
|
7110
7724
|
const signature = base64UrlToBytes(envelope.signature.value);
|
|
7111
7725
|
const publicKey = publishedPublicKey(envelope.signature.signerDid);
|
|
7112
|
-
if (signature.length !== 64 || !
|
|
7726
|
+
if (signature.length !== 64 || !ed255193.verify(signature, publishedEnvelopeSigningBytes(envelope), publicKey)) throw new ShareEnvelopeError("signature-invalid", "published envelope signature is invalid");
|
|
7113
7727
|
return { envelope, artifact: publishedArtifact(envelope, options2.plaintext ?? new Uint8Array(), policy) };
|
|
7114
7728
|
}
|
|
7115
7729
|
function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
|
|
@@ -7148,7 +7762,7 @@ function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
|
|
|
7148
7762
|
const signingBytes = new Uint8Array(domain.length + body.length);
|
|
7149
7763
|
signingBytes.set(domain);
|
|
7150
7764
|
signingBytes.set(body, domain.length);
|
|
7151
|
-
if (signatureBytes.length !== 64 || !
|
|
7765
|
+
if (signatureBytes.length !== 64 || !ed255193.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v1 envelope signature is invalid");
|
|
7152
7766
|
const content = options2.plaintext ?? new Uint8Array();
|
|
7153
7767
|
const artifact = {
|
|
7154
7768
|
envelope: {
|
|
@@ -7159,7 +7773,7 @@ function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
|
|
|
7159
7773
|
resource: { kind: resource.kind, path: resource.path },
|
|
7160
7774
|
recipientKind: authorizationTarget.kind === "bearer" ? "bearer" : authorizationTarget.kind === "exact-email" ? "exactEmail" : authorizationTarget.kind === "email-domain" ? "emailDomain" : void 0,
|
|
7161
7775
|
actions: ["read"],
|
|
7162
|
-
content: { mimeType: "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(
|
|
7776
|
+
content: { mimeType: "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(sha2566(content)) },
|
|
7163
7777
|
encrypted: true,
|
|
7164
7778
|
expiresAt: envelope.expiry,
|
|
7165
7779
|
signer: { did: signature.signerDid, publicKey: bytesToBase64Url(signerKey) },
|
|
@@ -7346,15 +7960,15 @@ function shareCapabilityAllows(capability, action, path) {
|
|
|
7346
7960
|
}
|
|
7347
7961
|
|
|
7348
7962
|
// src/delegations/ShareCache.ts
|
|
7349
|
-
import { sha256 as
|
|
7963
|
+
import { sha256 as sha2567 } from "@noble/hashes/sha256";
|
|
7350
7964
|
function cacheKey(key) {
|
|
7351
7965
|
if (!key.cid || !key.expiresAt) throw new Error("share cache keys require CID and expiry");
|
|
7352
7966
|
return `${key.cid}\0${key.expiresAt}`;
|
|
7353
7967
|
}
|
|
7354
7968
|
function digest2(bytes2) {
|
|
7355
|
-
return
|
|
7969
|
+
return sha2567(bytes2);
|
|
7356
7970
|
}
|
|
7357
|
-
function
|
|
7971
|
+
function equalBytes2(left, right) {
|
|
7358
7972
|
if (left.byteLength !== right.byteLength) return false;
|
|
7359
7973
|
return left.every((byte, index) => byte === right[index]);
|
|
7360
7974
|
}
|
|
@@ -7367,7 +7981,7 @@ var MemoryShareCache = class {
|
|
|
7367
7981
|
const mapKey = cacheKey(key);
|
|
7368
7982
|
const entry = this.entries.get(mapKey);
|
|
7369
7983
|
if (entry === void 0) return void 0;
|
|
7370
|
-
if (Date.parse(entry.key.expiresAt) <= now.getTime() || !
|
|
7984
|
+
if (Date.parse(entry.key.expiresAt) <= now.getTime() || !equalBytes2(entry.digest, digest2(entry.bytes))) {
|
|
7371
7985
|
this.entries.delete(mapKey);
|
|
7372
7986
|
return void 0;
|
|
7373
7987
|
}
|
|
@@ -7376,7 +7990,7 @@ var MemoryShareCache = class {
|
|
|
7376
7990
|
async getByCid(cid2, now = /* @__PURE__ */ new Date()) {
|
|
7377
7991
|
const entries = [...this.entries.values()].filter((entry) => entry.key.cid === cid2);
|
|
7378
7992
|
for (const entry of entries) {
|
|
7379
|
-
if (Date.parse(entry.key.expiresAt) <= now.getTime() || !
|
|
7993
|
+
if (Date.parse(entry.key.expiresAt) <= now.getTime() || !equalBytes2(entry.digest, digest2(entry.bytes))) {
|
|
7380
7994
|
this.entries.delete(cacheKey(entry.key));
|
|
7381
7995
|
continue;
|
|
7382
7996
|
}
|
|
@@ -7417,144 +8031,243 @@ var ShareConflict = class extends Error {
|
|
|
7417
8031
|
}
|
|
7418
8032
|
};
|
|
7419
8033
|
var ShareAccessError = class extends Error {
|
|
7420
|
-
constructor(code3, message) {
|
|
8034
|
+
constructor(code3, message, details) {
|
|
7421
8035
|
super(message ?? "shared access could not be completed");
|
|
7422
8036
|
this.name = "ShareAccessError";
|
|
7423
8037
|
this.code = code3;
|
|
8038
|
+
this.details = details;
|
|
7424
8039
|
}
|
|
7425
8040
|
};
|
|
7426
8041
|
|
|
7427
8042
|
// src/delegations/recipient-types.schema.ts
|
|
7428
|
-
import { z as
|
|
7429
|
-
var ShareRecipientTargetSchema =
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
8043
|
+
import { z as z6 } from "zod";
|
|
8044
|
+
var ShareRecipientTargetSchema = z6.discriminatedUnion("kind", [
|
|
8045
|
+
z6.object({ kind: z6.literal("exactEmail"), value: z6.string().min(1) }).strict(),
|
|
8046
|
+
z6.object({ kind: z6.literal("emailDomain"), value: z6.string().min(1) }).strict(),
|
|
8047
|
+
z6.object({ kind: z6.literal("recipientDid"), value: z6.string().regex(/^did:[a-z0-9]+:.+$/) }).strict(),
|
|
8048
|
+
z6.object({ kind: z6.literal("bearer") }).strict()
|
|
7433
8049
|
]);
|
|
7434
|
-
var ShareResourceSchema =
|
|
7435
|
-
|
|
7436
|
-
|
|
8050
|
+
var ShareResourceSchema = z6.discriminatedUnion("kind", [
|
|
8051
|
+
z6.object({ kind: z6.literal("exact"), path: z6.string().min(1) }).strict(),
|
|
8052
|
+
z6.object({ kind: z6.literal("prefix"), path: z6.string().min(1) }).strict()
|
|
7437
8053
|
]);
|
|
7438
|
-
var ShareActionSchema =
|
|
7439
|
-
var ShareRecipientPolicySchema =
|
|
8054
|
+
var ShareActionSchema = z6.enum(["read", "list", "edit"]);
|
|
8055
|
+
var ShareRecipientPolicySchema = z6.object({
|
|
7440
8056
|
recipientMatcher: ShareRecipientTargetSchema,
|
|
7441
|
-
spaceId:
|
|
8057
|
+
spaceId: z6.string().min(1),
|
|
7442
8058
|
resource: ShareResourceSchema,
|
|
7443
|
-
actions:
|
|
7444
|
-
expiresAt:
|
|
8059
|
+
actions: z6.array(ShareActionSchema).min(1),
|
|
8060
|
+
expiresAt: z6.date()
|
|
7445
8061
|
}).strict();
|
|
7446
|
-
var ShareRecipientClientOptionsSchema =
|
|
7447
|
-
trustedOrigins:
|
|
7448
|
-
maxInlineBytes:
|
|
7449
|
-
maxArtifactBytes:
|
|
7450
|
-
maxContentBytes:
|
|
7451
|
-
maxSealedContentBytes:
|
|
8062
|
+
var ShareRecipientClientOptionsSchema = z6.object({
|
|
8063
|
+
trustedOrigins: z6.array(z6.string().url()).min(1),
|
|
8064
|
+
maxInlineBytes: z6.number().int().positive().optional(),
|
|
8065
|
+
maxArtifactBytes: z6.number().int().positive().optional(),
|
|
8066
|
+
maxContentBytes: z6.number().int().positive().optional(),
|
|
8067
|
+
maxSealedContentBytes: z6.number().int().positive().optional()
|
|
7452
8068
|
}).strict();
|
|
7453
|
-
var ShareNativeActionSchema =
|
|
7454
|
-
var ShareWireActionSchema =
|
|
7455
|
-
var ShareContentSourceSchema =
|
|
7456
|
-
|
|
7457
|
-
kind:
|
|
8069
|
+
var ShareNativeActionSchema = z6.enum(["tinycloud.kv/get", "tinycloud.kv/metadata", "tinycloud.kv/list", "tinycloud.kv/put"]);
|
|
8070
|
+
var ShareWireActionSchema = z6.enum(["tinycloud.kv/get", "tinycloud.kv/metadata", "tinycloud.kv/list", "tinycloud.kv/put", "tinycloud.sql/read"]);
|
|
8071
|
+
var ShareContentSourceSchema = z6.discriminatedUnion("kind", [
|
|
8072
|
+
z6.object({
|
|
8073
|
+
kind: z6.literal("kv"),
|
|
7458
8074
|
action: ShareNativeActionSchema,
|
|
7459
|
-
space:
|
|
7460
|
-
path:
|
|
8075
|
+
space: z6.string().min(1),
|
|
8076
|
+
path: z6.string().min(1)
|
|
7461
8077
|
}).strict(),
|
|
7462
|
-
|
|
7463
|
-
kind:
|
|
7464
|
-
action:
|
|
7465
|
-
space:
|
|
7466
|
-
database:
|
|
7467
|
-
path:
|
|
7468
|
-
statement:
|
|
7469
|
-
arguments:
|
|
7470
|
-
argumentsDigest:
|
|
8078
|
+
z6.object({
|
|
8079
|
+
kind: z6.literal("sql"),
|
|
8080
|
+
action: z6.literal("tinycloud.sql/read"),
|
|
8081
|
+
space: z6.string().min(1),
|
|
8082
|
+
database: z6.string().min(1),
|
|
8083
|
+
path: z6.string().min(1),
|
|
8084
|
+
statement: z6.string().min(1),
|
|
8085
|
+
arguments: z6.record(z6.number().int().safe()),
|
|
8086
|
+
argumentsDigest: z6.string().min(1)
|
|
7471
8087
|
}).strict()
|
|
7472
8088
|
]);
|
|
7473
|
-
var ShareAddressedRecipientSchema =
|
|
7474
|
-
|
|
7475
|
-
|
|
8089
|
+
var ShareAddressedRecipientSchema = z6.discriminatedUnion("kind", [
|
|
8090
|
+
z6.object({ kind: z6.literal("exactEmail"), value: z6.string().min(1) }).strict(),
|
|
8091
|
+
z6.object({ kind: z6.literal("emailDomain"), value: z6.string().min(1) }).strict(),
|
|
8092
|
+
z6.object({ kind: z6.literal("recipientDid"), value: z6.string().regex(/^did:[a-z0-9]+:.+$/) }).strict()
|
|
7476
8093
|
]);
|
|
7477
|
-
var ShareAddressedDelegationRequestV2Schema =
|
|
7478
|
-
version:
|
|
7479
|
-
nonce:
|
|
7480
|
-
jti:
|
|
7481
|
-
senderDid:
|
|
8094
|
+
var ShareAddressedDelegationRequestV2Schema = z6.object({
|
|
8095
|
+
version: z6.literal(2),
|
|
8096
|
+
nonce: z6.string().min(1),
|
|
8097
|
+
jti: z6.string().min(1),
|
|
8098
|
+
senderDid: z6.string().min(1),
|
|
7482
8099
|
recipientMatcher: ShareAddressedRecipientSchema,
|
|
7483
|
-
targetOrigin:
|
|
7484
|
-
nodeAudience:
|
|
7485
|
-
shareCid:
|
|
7486
|
-
shareId:
|
|
7487
|
-
delegationCid:
|
|
7488
|
-
authorityMaterialHandle:
|
|
7489
|
-
authorityMaterialDigest:
|
|
8100
|
+
targetOrigin: z6.string().url(),
|
|
8101
|
+
nodeAudience: z6.string().min(1),
|
|
8102
|
+
shareCid: z6.string().min(1),
|
|
8103
|
+
shareId: z6.string().min(1),
|
|
8104
|
+
delegationCid: z6.string().min(1),
|
|
8105
|
+
authorityMaterialHandle: z6.string().min(1),
|
|
8106
|
+
authorityMaterialDigest: z6.string().min(1),
|
|
7490
8107
|
contentSource: ShareContentSourceSchema,
|
|
7491
|
-
contentSourceDigest:
|
|
7492
|
-
actions:
|
|
7493
|
-
resource:
|
|
7494
|
-
expiresAt:
|
|
7495
|
-
requestBodyDigest:
|
|
8108
|
+
contentSourceDigest: z6.string().min(1),
|
|
8109
|
+
actions: z6.array(ShareWireActionSchema).min(1).refine((actions) => new Set(actions).size === actions.length),
|
|
8110
|
+
resource: z6.object({ kind: z6.enum(["exact", "prefix"]), value: z6.string().min(1) }).strict(),
|
|
8111
|
+
expiresAt: z6.string().datetime({ offset: true }),
|
|
8112
|
+
requestBodyDigest: z6.string().min(1)
|
|
7496
8113
|
}).strict();
|
|
7497
|
-
var ShareAddressedDelegationEnvelopeV2Schema =
|
|
8114
|
+
var ShareAddressedDelegationEnvelopeV2Schema = z6.object({
|
|
7498
8115
|
request: ShareAddressedDelegationRequestV2Schema,
|
|
7499
|
-
proof:
|
|
8116
|
+
proof: z6.object({ alg: z6.literal("EdDSA"), kid: z6.string().min(1), signature: z6.string().min(1) }).strict()
|
|
7500
8117
|
}).strict();
|
|
7501
|
-
var ShareAddressedDelegationResponseV2Schema =
|
|
7502
|
-
type:
|
|
7503
|
-
version:
|
|
7504
|
-
nonce:
|
|
7505
|
-
jti:
|
|
7506
|
-
policyCid:
|
|
7507
|
-
policyBytes:
|
|
7508
|
-
policyDigest:
|
|
7509
|
-
delegationCid:
|
|
7510
|
-
delegationBytes:
|
|
7511
|
-
delegationDigest:
|
|
7512
|
-
authorityMaterialHandle:
|
|
7513
|
-
authorityMaterialDigest:
|
|
7514
|
-
actions:
|
|
7515
|
-
resource:
|
|
7516
|
-
expiresAt:
|
|
7517
|
-
proof:
|
|
8118
|
+
var ShareAddressedDelegationResponseV2Schema = z6.object({
|
|
8119
|
+
type: z6.literal("TinyCloudShareAddressedDelegation"),
|
|
8120
|
+
version: z6.literal(2),
|
|
8121
|
+
nonce: z6.string().min(1),
|
|
8122
|
+
jti: z6.string().min(1),
|
|
8123
|
+
policyCid: z6.string().min(1),
|
|
8124
|
+
policyBytes: z6.string().min(1),
|
|
8125
|
+
policyDigest: z6.string().min(1),
|
|
8126
|
+
delegationCid: z6.string().min(1),
|
|
8127
|
+
delegationBytes: z6.string().min(1),
|
|
8128
|
+
delegationDigest: z6.string().min(1),
|
|
8129
|
+
authorityMaterialHandle: z6.string().min(1),
|
|
8130
|
+
authorityMaterialDigest: z6.string().min(1),
|
|
8131
|
+
actions: z6.array(ShareWireActionSchema).min(1).refine((actions) => new Set(actions).size === actions.length),
|
|
8132
|
+
resource: z6.object({ kind: z6.enum(["exact", "prefix"]), value: z6.string().min(1) }).strict(),
|
|
8133
|
+
expiresAt: z6.string().datetime({ offset: true }),
|
|
8134
|
+
proof: z6.object({ alg: z6.literal("EdDSA"), kid: z6.string().min(1), signature: z6.string().min(1) }).strict()
|
|
7518
8135
|
}).strict();
|
|
7519
|
-
var ShareNativeResponseEntrySchema =
|
|
7520
|
-
path:
|
|
7521
|
-
kind:
|
|
8136
|
+
var ShareNativeResponseEntrySchema = z6.object({
|
|
8137
|
+
path: z6.string().min(1),
|
|
8138
|
+
kind: z6.enum(["file", "folder"])
|
|
7522
8139
|
}).strict();
|
|
7523
8140
|
var ShareNativeResponseBase = {
|
|
7524
|
-
type:
|
|
7525
|
-
version:
|
|
7526
|
-
resource:
|
|
8141
|
+
type: z6.literal("TinyCloudShareInvokeResponse"),
|
|
8142
|
+
version: z6.literal(2),
|
|
8143
|
+
resource: z6.string().min(1)
|
|
7527
8144
|
};
|
|
7528
|
-
var ShareNativeResponseSchema =
|
|
7529
|
-
|
|
8145
|
+
var ShareNativeResponseSchema = z6.discriminatedUnion("action", [
|
|
8146
|
+
z6.object({
|
|
7530
8147
|
...ShareNativeResponseBase,
|
|
7531
|
-
action:
|
|
7532
|
-
metadata:
|
|
7533
|
-
etag:
|
|
8148
|
+
action: z6.literal("tinycloud.kv/metadata"),
|
|
8149
|
+
metadata: z6.record(z6.string()),
|
|
8150
|
+
etag: z6.string().min(1).nullable()
|
|
7534
8151
|
}).strict(),
|
|
7535
|
-
|
|
8152
|
+
z6.object({
|
|
7536
8153
|
...ShareNativeResponseBase,
|
|
7537
|
-
action:
|
|
7538
|
-
mediaType:
|
|
7539
|
-
content:
|
|
7540
|
-
bodyDigest:
|
|
7541
|
-
etag:
|
|
8154
|
+
action: z6.literal("tinycloud.kv/get"),
|
|
8155
|
+
mediaType: z6.string().min(1),
|
|
8156
|
+
content: z6.string(),
|
|
8157
|
+
bodyDigest: z6.string().min(1),
|
|
8158
|
+
etag: z6.string().min(1).nullable()
|
|
7542
8159
|
}).strict(),
|
|
7543
|
-
|
|
8160
|
+
z6.object({
|
|
7544
8161
|
...ShareNativeResponseBase,
|
|
7545
|
-
action:
|
|
7546
|
-
entries:
|
|
7547
|
-
nextCursor:
|
|
8162
|
+
action: z6.literal("tinycloud.kv/list"),
|
|
8163
|
+
entries: z6.array(ShareNativeResponseEntrySchema),
|
|
8164
|
+
nextCursor: z6.string().min(1).nullable()
|
|
7548
8165
|
}).strict(),
|
|
7549
|
-
|
|
8166
|
+
z6.object({
|
|
7550
8167
|
...ShareNativeResponseBase,
|
|
7551
|
-
action:
|
|
7552
|
-
etag:
|
|
7553
|
-
bodyDigest:
|
|
7554
|
-
contentType:
|
|
8168
|
+
action: z6.literal("tinycloud.kv/put"),
|
|
8169
|
+
etag: z6.string().min(1),
|
|
8170
|
+
bodyDigest: z6.string().min(1),
|
|
8171
|
+
contentType: z6.string().min(1)
|
|
7555
8172
|
}).strict()
|
|
7556
8173
|
]);
|
|
7557
8174
|
|
|
8175
|
+
// src/delegations/portable.ts
|
|
8176
|
+
import { z as z7 } from "zod";
|
|
8177
|
+
var ResourceSchema = z7.object({
|
|
8178
|
+
service: z7.string().min(1),
|
|
8179
|
+
space: z7.string().min(1),
|
|
8180
|
+
path: z7.string(),
|
|
8181
|
+
actions: z7.array(z7.string().min(1)).min(1),
|
|
8182
|
+
caveats: z7.array(z7.record(z7.unknown())).optional()
|
|
8183
|
+
}).strict();
|
|
8184
|
+
var PortableDelegationSchema = z7.object({
|
|
8185
|
+
cid: z7.string().min(1),
|
|
8186
|
+
delegationHeader: z7.object({ Authorization: z7.string().min(1) }).strict(),
|
|
8187
|
+
ownerAddress: z7.string().min(1),
|
|
8188
|
+
chainId: z7.number().int().nonnegative(),
|
|
8189
|
+
host: z7.string().url().optional(),
|
|
8190
|
+
spaceId: z7.string().min(1),
|
|
8191
|
+
path: z7.string(),
|
|
8192
|
+
actions: z7.array(z7.string().min(1)).min(1),
|
|
8193
|
+
caveats: z7.array(z7.record(z7.unknown())).optional(),
|
|
8194
|
+
expiry: z7.coerce.date(),
|
|
8195
|
+
delegateDID: z7.string().min(1),
|
|
8196
|
+
delegatorDID: z7.string().min(1).optional(),
|
|
8197
|
+
parentCid: z7.string().min(1).optional(),
|
|
8198
|
+
disableSubDelegation: z7.boolean().optional(),
|
|
8199
|
+
resources: z7.array(ResourceSchema).min(1).optional()
|
|
8200
|
+
}).strict();
|
|
8201
|
+
function parsePortableDelegation(input) {
|
|
8202
|
+
const parsed = PortableDelegationSchema.parse(input);
|
|
8203
|
+
if (parsed.resources !== void 0 && parsed.resources.length === 0)
|
|
8204
|
+
throw new Error("portable delegation resources must not be empty");
|
|
8205
|
+
return parsed;
|
|
8206
|
+
}
|
|
8207
|
+
function serializePortableDelegation(delegation) {
|
|
8208
|
+
return JSON.stringify({
|
|
8209
|
+
...delegation,
|
|
8210
|
+
expiry: delegation.expiry.toISOString()
|
|
8211
|
+
});
|
|
8212
|
+
}
|
|
8213
|
+
async function importPortableDelegation(fetchFn, host, delegation) {
|
|
8214
|
+
const parsed = parsePortableDelegation(delegation);
|
|
8215
|
+
const response = await fetchFn(`${host.replace(/\/+$/, "")}/delegate`, {
|
|
8216
|
+
method: "POST",
|
|
8217
|
+
headers: { Authorization: parsed.delegationHeader.Authorization }
|
|
8218
|
+
});
|
|
8219
|
+
if (!response.ok)
|
|
8220
|
+
throw new Error(`node rejected delegation import (${response.status})`);
|
|
8221
|
+
const body = await response.json().catch(() => ({}));
|
|
8222
|
+
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
8223
|
+
return {};
|
|
8224
|
+
return body;
|
|
8225
|
+
}
|
|
8226
|
+
async function delegatePortablePolicySession(input) {
|
|
8227
|
+
const parent = parsePortableDelegation(input.parent);
|
|
8228
|
+
const descendant = createCompactPolicyDescendant({
|
|
8229
|
+
parentAuthorization: parent.delegationHeader.Authorization.replace(/^Bearer\s+/i, ""),
|
|
8230
|
+
parentCid: parent.cid,
|
|
8231
|
+
issuerDid: parent.delegateDID,
|
|
8232
|
+
audienceDid: input.delegateDID,
|
|
8233
|
+
attenuation: input.attenuation,
|
|
8234
|
+
privateKey: input.issuerPrivateKey,
|
|
8235
|
+
...input.now === void 0 ? {} : { now: input.now },
|
|
8236
|
+
...input.expiresAt === void 0 ? {} : { expiresAt: input.expiresAt },
|
|
8237
|
+
...input.nonce === void 0 ? {} : { nonce: input.nonce }
|
|
8238
|
+
});
|
|
8239
|
+
const resources = Object.entries(descendant.payload.att).map(([resource, abilities]) => {
|
|
8240
|
+
const actions = Object.keys(abilities);
|
|
8241
|
+
if (resource.startsWith("urn:tinycloud:encryption:")) {
|
|
8242
|
+
return { service: "encryption", space: "encryption", path: resource, actions };
|
|
8243
|
+
}
|
|
8244
|
+
const match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
|
|
8245
|
+
if (match === null) throw new Error("policy descendant resource is invalid");
|
|
8246
|
+
const caveats = Object.values(abilities).flat().filter((value) => value !== null && typeof value === "object" && !Array.isArray(value));
|
|
8247
|
+
return { service: "kv", space: match[1], path: match[2], actions, ...caveats.length === 0 ? {} : { caveats } };
|
|
8248
|
+
});
|
|
8249
|
+
const primary = resources.find((resource) => resource.service === "kv") ?? resources[0];
|
|
8250
|
+
if (primary === void 0) throw new Error("policy descendant attenuation is empty");
|
|
8251
|
+
const portable = {
|
|
8252
|
+
cid: descendant.cid,
|
|
8253
|
+
delegationHeader: { Authorization: descendant.authorization },
|
|
8254
|
+
ownerAddress: parent.ownerAddress,
|
|
8255
|
+
chainId: parent.chainId,
|
|
8256
|
+
host: input.host,
|
|
8257
|
+
spaceId: primary.space,
|
|
8258
|
+
path: primary.path,
|
|
8259
|
+
actions: primary.actions,
|
|
8260
|
+
expiry: new Date(descendant.payload.exp * 1e3),
|
|
8261
|
+
delegateDID: input.delegateDID,
|
|
8262
|
+
delegatorDID: parent.delegateDID,
|
|
8263
|
+
parentCid: parent.cid,
|
|
8264
|
+
disableSubDelegation: descendant.payload.fct[0]?.remainingRedelegationDepth === 0,
|
|
8265
|
+
resources
|
|
8266
|
+
};
|
|
8267
|
+
await importPortableDelegation(input.fetch, input.host, portable);
|
|
8268
|
+
return portable;
|
|
8269
|
+
}
|
|
8270
|
+
|
|
7558
8271
|
// src/delegations/ShareRecipientClient.ts
|
|
7559
8272
|
var DEFAULT_MAX_ARTIFACT_BYTES2 = MAX_SHARE_ARTIFACT_BYTES;
|
|
7560
8273
|
var DEFAULT_MAX_CONTENT_BYTES = MAX_SHARE_CONTENT_BYTES;
|
|
@@ -7605,8 +8318,8 @@ function canonicalJsonForProof(value) {
|
|
|
7605
8318
|
}
|
|
7606
8319
|
if (Array.isArray(value)) return `[${value.map(canonicalJsonForProof).join(",")}]`;
|
|
7607
8320
|
if (typeof value === "object") {
|
|
7608
|
-
const
|
|
7609
|
-
return `{${Object.keys(
|
|
8321
|
+
const object2 = value;
|
|
8322
|
+
return `{${Object.keys(object2).sort().map((key) => `${JSON.stringify(key)}:${canonicalJsonForProof(object2[key])}`).join(",")}}`;
|
|
7610
8323
|
}
|
|
7611
8324
|
throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
7612
8325
|
}
|
|
@@ -7630,7 +8343,7 @@ function randomJti() {
|
|
|
7630
8343
|
return bytesToBase64Url2(bytes2);
|
|
7631
8344
|
}
|
|
7632
8345
|
function digestCanonical(value) {
|
|
7633
|
-
return bytesToBase64Url2(
|
|
8346
|
+
return bytesToBase64Url2(sha2568(new TextEncoder().encode(canonicalJsonForProof(value))));
|
|
7634
8347
|
}
|
|
7635
8348
|
function actionWire(action) {
|
|
7636
8349
|
return action === "get" ? "tinycloud.kv/get" : action === "metadata" ? "tinycloud.kv/metadata" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put";
|
|
@@ -7727,15 +8440,46 @@ var ShareRecipientClient = class {
|
|
|
7727
8440
|
const { envelope } = resolved.artifact;
|
|
7728
8441
|
const { location } = resolved;
|
|
7729
8442
|
const bearer = isBearerEnvelope(envelope);
|
|
7730
|
-
const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain";
|
|
8443
|
+
const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.authorizationTargetKind === "recipientDid";
|
|
7731
8444
|
const legacyBearer = !policy && envelope.recipientKind === void 0;
|
|
7732
|
-
|
|
8445
|
+
let recipientDidSession;
|
|
8446
|
+
if (envelope.authorizationTargetKind === "recipientDid") {
|
|
8447
|
+
if (this.options.establishRecipientDidSession === void 0) throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required");
|
|
8448
|
+
const authorization = await this.options.establishRecipientDidSession({ envelope, recipientDid: envelope.recipient?.kind === "recipientDid" ? envelope.recipient.value : "" });
|
|
8449
|
+
if ("state" in authorization) {
|
|
8450
|
+
if (authorization.state === "authorization-required") throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required", authorization);
|
|
8451
|
+
throw new ShareAccessError("SHARE_DENIED", "recipient DID authorization was denied", authorization);
|
|
8452
|
+
}
|
|
8453
|
+
recipientDidSession = authorization;
|
|
8454
|
+
}
|
|
7733
8455
|
if (policy && this.options.bearerSession !== void 0) throw new ShareAccessError("SHARE_POLICY_BEARER_MISMATCH");
|
|
7734
8456
|
if (bearer && this.options.presentation !== void 0) throw new ShareAccessError("SHARE_BEARER_PRESENTATION_MISMATCH");
|
|
7735
|
-
const session = bearer || legacyBearer ? this.options.bearerSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
|
|
7736
|
-
const kv = bearer || legacyBearer ? session === void 0 ? void 0 : this.createKV(envelope.origin, session) : void 0;
|
|
8457
|
+
const session = bearer || legacyBearer ? this.options.bearerSession : recipientDidSession ? recipientDidSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
|
|
7737
8458
|
const policySession = policy ? session : void 0;
|
|
7738
8459
|
if (policySession !== void 0) this.assertProvidedPolicySession(policySession, envelope);
|
|
8460
|
+
const portableDelegation = policySession === void 0 ? void 0 : this.policySessionDelegation(policySession, envelope.origin);
|
|
8461
|
+
const portableInvoke = portableDelegation === void 0 ? void 0 : this.policyInvocationSigner(portableDelegation);
|
|
8462
|
+
if (portableDelegation !== void 0) {
|
|
8463
|
+
if (this.options.importDelegation === void 0) {
|
|
8464
|
+
await importPortableDelegation(this.fetchFn, envelope.origin, portableDelegation);
|
|
8465
|
+
} else {
|
|
8466
|
+
const imported = await this.options.importDelegation(portableDelegation);
|
|
8467
|
+
if (imported !== void 0) {
|
|
8468
|
+
const normalized = parsePortableDelegation(imported);
|
|
8469
|
+
if (normalized.delegationHeader.Authorization !== portableDelegation.delegationHeader.Authorization) {
|
|
8470
|
+
throw new ShareAccessError("SHARE_SESSION_INVALID", "delegation importer changed authorization bytes");
|
|
8471
|
+
}
|
|
8472
|
+
}
|
|
8473
|
+
}
|
|
8474
|
+
}
|
|
8475
|
+
const ordinarySession = portableDelegation === void 0 ? void 0 : {
|
|
8476
|
+
delegationHeader: portableDelegation.delegationHeader,
|
|
8477
|
+
delegationCid: portableDelegation.cid,
|
|
8478
|
+
spaceId: this.policySessionProjection(portableDelegation).spaceId,
|
|
8479
|
+
verificationMethod: portableDelegation.delegateDID,
|
|
8480
|
+
jwk: this.options.bearerSession?.jwk ?? {}
|
|
8481
|
+
};
|
|
8482
|
+
const kv = bearer || legacyBearer || ordinarySession !== void 0 ? session === void 0 && ordinarySession === void 0 ? void 0 : this.createKV(envelope.origin, ordinarySession ?? session, portableInvoke) : void 0;
|
|
7739
8483
|
const advertisedCapability = { spaceId: envelope.spaceId, resource: envelope.resource, actions: envelope.actions };
|
|
7740
8484
|
const capability = policySession?.capability === void 0 ? advertisedCapability : intersectShareCapabilities(advertisedCapability, policySession.capability);
|
|
7741
8485
|
if (capability === void 0) throw new ShareAccessError("SHARE_CAPABILITY_EMPTY");
|
|
@@ -7760,6 +8504,11 @@ var ShareRecipientClient = class {
|
|
|
7760
8504
|
const scope = normalizePath2(input.path ?? envelope.resource.path);
|
|
7761
8505
|
this.assertAllowed(capability, "list", scope);
|
|
7762
8506
|
if (kv === void 0 && policySession === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
8507
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
8508
|
+
const result2 = await kv.list({ path: scope, limit: input.limit, cursor: input.cursor });
|
|
8509
|
+
if (!result2.ok) throw result2.error;
|
|
8510
|
+
return { keys: result2.data.keys, truncated: result2.data.truncated, nextCursor: result2.data.nextCursor };
|
|
8511
|
+
}
|
|
7763
8512
|
if (policySession !== void 0) return this.nativeList(envelope, policySession, scope, input.limit, input.cursor);
|
|
7764
8513
|
const result = await kv.list({ path: scope, limit: input.limit, cursor: input.cursor });
|
|
7765
8514
|
if (!result.ok) throw result.error;
|
|
@@ -7773,6 +8522,14 @@ var ShareRecipientClient = class {
|
|
|
7773
8522
|
const resolvedPath = normalizePath2(path);
|
|
7774
8523
|
this.assertAllowed(capability, "save", resolvedPath);
|
|
7775
8524
|
if (kv === void 0 && policySession === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
8525
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
8526
|
+
const result2 = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
|
|
8527
|
+
if (!result2.ok) {
|
|
8528
|
+
if (result2.error.code === ErrorCodes.KV_PRECONDITION_FAILED || result2.error.code === ErrorCodes.KV_CONFLICT) throw new ShareConflict(resolvedPath, result2.error.meta?.etag);
|
|
8529
|
+
throw result2.error;
|
|
8530
|
+
}
|
|
8531
|
+
return { etag: result2.data.headers.etag };
|
|
8532
|
+
}
|
|
7776
8533
|
if (policySession !== void 0) return this.nativeSave(envelope, policySession, resolvedPath, bytes2, input);
|
|
7777
8534
|
const result = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
|
|
7778
8535
|
if (!result.ok) {
|
|
@@ -7788,22 +8545,79 @@ var ShareRecipientClient = class {
|
|
|
7788
8545
|
const metadata = async (path = envelope.resource.kind === "exact" ? envelope.resource.path : "") => {
|
|
7789
8546
|
const resolvedPath = normalizePath2(path);
|
|
7790
8547
|
this.assertAllowed(capability, "metadata", resolvedPath);
|
|
8548
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
8549
|
+
const result2 = await kv.head(resolvedPath);
|
|
8550
|
+
if (!result2.ok) throw result2.error;
|
|
8551
|
+
return { metadata: { "content-type": result2.data.headers.contentType ?? "application/octet-stream", "content-length": String(result2.data.headers.contentLength ?? ""), ...result2.data.headers.lastModified === void 0 ? {} : { "last-modified": result2.data.headers.lastModified } }, etag: result2.data.headers.etag, contentType: result2.data.headers.contentType, size: result2.data.headers.contentLength };
|
|
8552
|
+
}
|
|
7791
8553
|
if (policySession !== void 0) return this.nativeMetadata(envelope, policySession, resolvedPath);
|
|
7792
8554
|
if (kv === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
7793
8555
|
const result = await kv.head(resolvedPath);
|
|
7794
8556
|
if (!result.ok) throw result.error;
|
|
7795
8557
|
return { metadata: { "content-type": result.data.headers.contentType ?? "application/octet-stream", "content-length": String(result.data.headers.contentLength ?? ""), ...result.data.headers.lastModified === void 0 ? {} : { "last-modified": result.data.headers.lastModified } }, etag: result.data.headers.etag, contentType: result.data.headers.contentType, size: result.data.headers.contentLength };
|
|
7796
8558
|
};
|
|
7797
|
-
return { kind: "share-v2", envelope, location: { ...location, key: void 0 }, resource: envelope.resource, actions: envelope.actions, expiresAt: new Date(envelope.expiresAt), kv, get, listChildren, save, metadata };
|
|
8559
|
+
return { kind: "share-v2", envelope, location: { ...location, key: void 0 }, resource: envelope.resource, actions: envelope.actions, expiresAt: new Date(envelope.expiresAt), kv, portableDelegation, get, listChildren, save, metadata };
|
|
7798
8560
|
} catch (error) {
|
|
7799
8561
|
throw asError(error);
|
|
7800
8562
|
}
|
|
7801
8563
|
}
|
|
7802
|
-
|
|
8564
|
+
policySessionDelegation(session, origin) {
|
|
8565
|
+
if (session.runtimeDelegation === void 0) return void 0;
|
|
8566
|
+
const delegation = parsePortableDelegation(session.runtimeDelegation);
|
|
8567
|
+
if (delegation.host !== void 0 && delegation.host.replace(/\/+$/, "") !== origin.replace(/\/+$/, "")) throw new ShareAccessError("SHARE_ORIGIN_MISMATCH", "delegation host does not match the trusted share origin");
|
|
8568
|
+
return delegation;
|
|
8569
|
+
}
|
|
8570
|
+
policyInvocationSigner(delegation) {
|
|
8571
|
+
const privateKey = this.options.policySessionPrivateKey;
|
|
8572
|
+
if (privateKey === void 0) throw new ShareAccessError("SHARE_SESSION_SIGNER_REQUIRED");
|
|
8573
|
+
const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
|
|
8574
|
+
if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID)
|
|
8575
|
+
throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
8576
|
+
return (_serviceSession, service, path, action, facts) => {
|
|
8577
|
+
const serviceName = service.replace(/^tinycloud\./, "");
|
|
8578
|
+
const cleanPath = path.replace(/^\//, "").replace(/\/$/, "");
|
|
8579
|
+
const authority = Object.entries(session.att).find(([parentResource, abilities]) => {
|
|
8580
|
+
if (!(action in abilities)) return false;
|
|
8581
|
+
if (serviceName === "encryption") return parentResource.startsWith("urn:tinycloud:encryption:") && parentResource === cleanPath;
|
|
8582
|
+
const match = /^tinycloud:\/\/[^/]+\/kv\/(.+)$/.exec(parentResource);
|
|
8583
|
+
if (match === null) return false;
|
|
8584
|
+
const parentPath = match[1];
|
|
8585
|
+
const caveats = abilities[action] ?? [];
|
|
8586
|
+
const prefix = caveats.some((value) => isRecord(value) && value.kind === "prefix");
|
|
8587
|
+
return cleanPath === parentPath || prefix && cleanPath.startsWith(`${parentPath}/`);
|
|
8588
|
+
});
|
|
8589
|
+
if (authority === void 0) throw new ShareAccessError("SHARE_OUT_OF_SCOPE");
|
|
8590
|
+
const resource = serviceName === "encryption" ? authority[0] : `${authority[0].slice(0, authority[0].indexOf("/kv/") + 4)}${cleanPath}`;
|
|
8591
|
+
const caveat = serviceName === "encryption" ? {} : { type: "xyz.tinycloud.resource/selector", kind: "exact", value: resource };
|
|
8592
|
+
const invocation = createCompactPolicyInvocation({
|
|
8593
|
+
sessionAuthorization: delegation.delegationHeader.Authorization,
|
|
8594
|
+
sessionCid: delegation.cid,
|
|
8595
|
+
recipientDid: delegation.delegateDID,
|
|
8596
|
+
audienceDid: String(session.fact.nodeAudience),
|
|
8597
|
+
resource,
|
|
8598
|
+
action,
|
|
8599
|
+
caveat,
|
|
8600
|
+
...facts?.length === 1 ? { facts: facts[0] } : {},
|
|
8601
|
+
privateKey,
|
|
8602
|
+
now: Math.floor(this.now().getTime() / 1e3)
|
|
8603
|
+
});
|
|
8604
|
+
return { Authorization: invocation.authorization };
|
|
8605
|
+
};
|
|
8606
|
+
}
|
|
8607
|
+
policySessionProjection(delegation) {
|
|
8608
|
+
const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
|
|
8609
|
+
if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
8610
|
+
const kvResource = Object.keys(session.att).find((resource) => /^tinycloud:\/\/[^/]+\/kv\/.+$/.test(resource));
|
|
8611
|
+
const match = kvResource === void 0 ? void 0 : /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(kvResource);
|
|
8612
|
+
if (match === void 0 || match === null) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
8613
|
+
return { spaceId: match[1] };
|
|
8614
|
+
}
|
|
8615
|
+
createKV(origin, session, invokeOverride) {
|
|
8616
|
+
const invoke = invokeOverride ?? this.options.invoke ?? nativeInvoke;
|
|
7803
8617
|
if (this.options.createKVService !== void 0) {
|
|
7804
|
-
return this.options.createKVService({ hosts: [origin], session, invoke
|
|
8618
|
+
return this.options.createKVService({ hosts: [origin], session, invoke, fetch: this.fetchFn });
|
|
7805
8619
|
}
|
|
7806
|
-
const context = new ServiceContext({ hosts: [origin], session, invoke
|
|
8620
|
+
const context = new ServiceContext({ hosts: [origin], session, invoke, fetch: this.fetchFn });
|
|
7807
8621
|
const service = new KVService({ prefix: "" });
|
|
7808
8622
|
context.registerService("kv", service);
|
|
7809
8623
|
service.initialize(context);
|
|
@@ -7846,7 +8660,7 @@ var ShareRecipientClient = class {
|
|
|
7846
8660
|
if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES)) throw new ShareAccessError("SHARE_TOO_LARGE");
|
|
7847
8661
|
const contentType = input.contentType ?? envelope.content.mimeType;
|
|
7848
8662
|
if (contentType !== envelope.content.mimeType && !/^text\/(?:plain|markdown)(?:;|$)/i.test(contentType)) throw new ShareAccessError("SHARE_CONTENT_TYPE_INVALID");
|
|
7849
|
-
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2(
|
|
8663
|
+
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2(sha2568(bytes2)), contentType, ifMatch: input.etag, mediaType: "application/vnd.tinycloud.share+json" });
|
|
7850
8664
|
if (result.status === 412 || result.status === 409) throw new ShareConflict(path, result.headers?.etag);
|
|
7851
8665
|
if (result.status === 401 || result.status === 403) throw new ShareAccessError("SHARE_DENIED");
|
|
7852
8666
|
if (result.status < 200 || result.status >= 300) throw new ShareAccessError("SHARE_WRITE_FAILED");
|
|
@@ -7968,7 +8782,7 @@ var ShareRecipientClient = class {
|
|
|
7968
8782
|
};
|
|
7969
8783
|
const signed = this.options.signNativeInvoke === void 0 ? void 0 : await this.options.signNativeInvoke({ envelope: input.envelope, session: input.session, request: body });
|
|
7970
8784
|
const transport = this.options.invoke !== void 0 || session.authorization !== void 0 || session.delegationHeader !== void 0 ? this.defaultNativeHeaders(session, input.action, input.resource, body) : void 0;
|
|
7971
|
-
const response = await this.fetchFn(
|
|
8785
|
+
const response = await this.fetchFn(`${base3}/invoke`, {
|
|
7972
8786
|
method: "POST",
|
|
7973
8787
|
headers: { ...headersRecord2(transport), ...headersRecord2(signed), "content-type": input.mediaType, accept: input.mediaType },
|
|
7974
8788
|
body: JSON.stringify(body),
|
|
@@ -8092,7 +8906,7 @@ var ShareRecipientClient = class {
|
|
|
8092
8906
|
}]);
|
|
8093
8907
|
}
|
|
8094
8908
|
digestMatches(value, bytes2) {
|
|
8095
|
-
const digest4 = bytesToBase64Url2(
|
|
8909
|
+
const digest4 = bytesToBase64Url2(sha2568(bytes2));
|
|
8096
8910
|
return value === digest4 || value === `sha-256=:${digest4}:`;
|
|
8097
8911
|
}
|
|
8098
8912
|
assertNativeRequestBounds(envelope, session, operation, path, limit, cursor) {
|
|
@@ -8214,12 +9028,12 @@ var ShareRecipientClient = class {
|
|
|
8214
9028
|
this.assertDetachedProof(request.proof);
|
|
8215
9029
|
}
|
|
8216
9030
|
parseSessionCapability(value) {
|
|
8217
|
-
const
|
|
8218
|
-
if (typeof
|
|
8219
|
-
if (!Array.isArray(
|
|
8220
|
-
const resource = this.requireObject(
|
|
9031
|
+
const object2 = this.requireObject(value, "session capability");
|
|
9032
|
+
if (typeof object2.spaceId !== "string") throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability space is invalid");
|
|
9033
|
+
if (!Array.isArray(object2.actions) || object2.actions.some((action) => !["read", "list", "edit"].includes(action))) throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability actions are invalid");
|
|
9034
|
+
const resource = this.requireObject(object2.resource, "session capability resource");
|
|
8221
9035
|
if (resource.kind !== "exact" && resource.kind !== "prefix" || typeof resource.path !== "string") throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability resource is invalid");
|
|
8222
|
-
return { spaceId:
|
|
9036
|
+
return { spaceId: object2.spaceId, actions: [...new Set(object2.actions)], resource: { kind: resource.kind, path: resource.path } };
|
|
8223
9037
|
}
|
|
8224
9038
|
assertProvidedPolicySession(session, envelope) {
|
|
8225
9039
|
const sessionExpiry = dateValue(session.expiresAt);
|
|
@@ -8310,7 +9124,7 @@ var ShareRecipientClient = class {
|
|
|
8310
9124
|
nodeAudience: binding.nodeAudience,
|
|
8311
9125
|
...isV2 ? {
|
|
8312
9126
|
enforcerDid: challenge.enforcerDid,
|
|
8313
|
-
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2(
|
|
9127
|
+
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2(sha2568(new TextEncoder().encode(credential)))
|
|
8314
9128
|
} : {},
|
|
8315
9129
|
action,
|
|
8316
9130
|
...binding.actions === void 0 ? {} : { actions: [...binding.actions] },
|
|
@@ -8376,7 +9190,7 @@ var ShareRecipientClient = class {
|
|
|
8376
9190
|
}
|
|
8377
9191
|
if (isJwsProof && detached.kid !== `${signerDid}#${encoded}` || isEd25519Proof && detached.signerDid !== signerDid || signature.length !== 64) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof binding is invalid");
|
|
8378
9192
|
const bytes2 = new TextEncoder().encode(`${domain}${canonicalJsonForProof(message)}`);
|
|
8379
|
-
if (!
|
|
9193
|
+
if (!ed255194.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
|
|
8380
9194
|
}
|
|
8381
9195
|
assertChallengeRequestBinding(request, challenge) {
|
|
8382
9196
|
const source = isRecord(request.body) ? request.body : request;
|
|
@@ -9580,7 +10394,7 @@ function shareKeyMatchesDid(key, didUrl) {
|
|
|
9580
10394
|
if (!publicKey) return false;
|
|
9581
10395
|
const jwkBytes = decodeBase64UrlBytes(key.x);
|
|
9582
10396
|
const privateKey = decodeBase64UrlBytes(key.d);
|
|
9583
|
-
const derivedPublicKey =
|
|
10397
|
+
const derivedPublicKey = ed255195.getPublicKey(privateKey);
|
|
9584
10398
|
return privateKey.length === 32 && publicKey.length === jwkBytes.length && publicKey.every((byte, index) => byte === jwkBytes[index]) && derivedPublicKey.length === jwkBytes.length && derivedPublicKey.every((byte, index) => byte === jwkBytes[index]);
|
|
9585
10399
|
} catch {
|
|
9586
10400
|
return false;
|
|
@@ -9630,8 +10444,8 @@ function verifySignedChild(result, expected, computeCid) {
|
|
|
9630
10444
|
}
|
|
9631
10445
|
|
|
9632
10446
|
// src/delegations/owner-policy.ts
|
|
9633
|
-
import { ed25519 as
|
|
9634
|
-
import { sha256 as
|
|
10447
|
+
import { ed25519 as ed255196 } from "@noble/curves/ed25519";
|
|
10448
|
+
import { sha256 as sha2569 } from "@noble/hashes/sha256";
|
|
9635
10449
|
var MAX_CONTENT_BYTES = 100 * 1024 * 1024;
|
|
9636
10450
|
var ENFORCEMENT_DOMAIN = "xyz.tinycloud.share/policy-enforcement/v2\0";
|
|
9637
10451
|
var POLICY_DOMAIN = "xyz.tinycloud.share/policy/v2\0";
|
|
@@ -9658,10 +10472,10 @@ function fromB64(value) {
|
|
|
9658
10472
|
throw new Error("base64url decoding is unavailable");
|
|
9659
10473
|
}
|
|
9660
10474
|
function cid(bytesValue) {
|
|
9661
|
-
return CID.createV1(code, create(sha2562.code,
|
|
10475
|
+
return CID.createV1(code, create(sha2562.code, sha2569(bytesValue))).toString(base32.encoder);
|
|
9662
10476
|
}
|
|
9663
10477
|
function digest3(bytesValue) {
|
|
9664
|
-
return b64(
|
|
10478
|
+
return b64(sha2569(bytesValue));
|
|
9665
10479
|
}
|
|
9666
10480
|
function didKeyFromEd25519PublicKey(publicKey) {
|
|
9667
10481
|
if (publicKey.length !== 32) throw new Error("share key public key must be 32 bytes");
|
|
@@ -9846,7 +10660,7 @@ function validateOwnerSharePolicyRegistration(value, expected) {
|
|
|
9846
10660
|
const publicKey = encodedKid.length === 34 ? encodedKid.slice(2) : encodedKid;
|
|
9847
10661
|
const signatureBytes = fromB64(proof.signature);
|
|
9848
10662
|
const signedBytes = new TextEncoder().encode(`${OWNER_SHARE_REGISTRATION_DOMAIN}${canonicalizeSignedObjectUnsigned(registrationCore)}`);
|
|
9849
|
-
if (signatureBytes.length !== 64 || !
|
|
10663
|
+
if (signatureBytes.length !== 64 || !ed255196.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
|
|
9850
10664
|
return { registration, proof };
|
|
9851
10665
|
}
|
|
9852
10666
|
function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
@@ -9860,7 +10674,7 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
|
9860
10674
|
}
|
|
9861
10675
|
|
|
9862
10676
|
// src/delegations/share-delivery.ts
|
|
9863
|
-
import { ed25519 as
|
|
10677
|
+
import { ed25519 as ed255197 } from "@noble/curves/ed25519";
|
|
9864
10678
|
var SHARE_DELIVERY_AUTHORIZATION_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v2\0";
|
|
9865
10679
|
function isCanonicalHttpsOrigin(value) {
|
|
9866
10680
|
let url;
|
|
@@ -9933,7 +10747,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
|
9933
10747
|
const authorization = assertObject2(root.authorization, AUTHORIZATION_KEYS, "share delivery authorization");
|
|
9934
10748
|
const proof = assertObject2(root.proof, ["alg", "kid", "signature"], "share delivery authorization proof");
|
|
9935
10749
|
const request = expected.request;
|
|
9936
|
-
if (authorization.type !== "TinyCloudShareDeliveryAuthorization" || authorization.version !== 2 || authorization.dataAuthority !== false || authorization.jti !== request.jti || authorization.shareCid !== request.shareCid || authorization.shareId !== request.shareId || authorization.registrationCid !== request.registrationCid || authorization.delegationCid !== request.delegationCid || authorization.enforcementDelegationCid !== request.enforcementDelegationCid || authorization.envelopeCid !== request.envelopeCid || authorization.policyCid !== request.policyCid || authorization.deliveryEmail !== request.recipientEmail || authorization.shareUrl !== request.shareUrl || authorization.documentName !== request.documentName || authorization.requestBodyDigest !== request.requestBodyDigest || authorization.expiresAt !== request.expiresAt || authorization.idempotencyKey !== request.
|
|
10750
|
+
if (authorization.type !== "TinyCloudShareDeliveryAuthorization" || authorization.version !== 2 || authorization.dataAuthority !== false || authorization.jti !== request.jti || authorization.shareCid !== request.shareCid || authorization.shareId !== request.shareId || authorization.registrationCid !== request.registrationCid || authorization.delegationCid !== request.delegationCid || authorization.enforcementDelegationCid !== request.enforcementDelegationCid || authorization.envelopeCid !== request.envelopeCid || authorization.policyCid !== request.policyCid || authorization.deliveryEmail !== request.recipientEmail || authorization.shareUrl !== request.shareUrl || authorization.documentName !== request.documentName || authorization.requestBodyDigest !== request.requestBodyDigest || authorization.expiresAt !== request.expiresAt || authorization.idempotencyKey !== request.idempotencyKey || authorization.reportAbuseToken !== request.jti || authorization.authorityMaterialHandle !== request.registrationCid) {
|
|
9937
10751
|
throw new Error("share delivery authorization is not bound to the submitted request");
|
|
9938
10752
|
}
|
|
9939
10753
|
if (typeof authorization.issuedAt !== "string" || Date.parse(authorization.issuedAt) > Date.now() + 6e4) throw new Error("share delivery authorization issuedAt is invalid");
|
|
@@ -9948,7 +10762,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
|
9948
10762
|
if (publicKey.length !== 32) throw new Error("share delivery authorization proof key is invalid");
|
|
9949
10763
|
const signatureBytes = fromB642(proof.signature);
|
|
9950
10764
|
const signedBytes = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
|
|
9951
|
-
if (signatureBytes.length !== 64 || !
|
|
10765
|
+
if (signatureBytes.length !== 64 || !ed255197.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
|
|
9952
10766
|
return { authorization, proof };
|
|
9953
10767
|
}
|
|
9954
10768
|
function shareDeliveryTrustedKid(publicKey) {
|
|
@@ -10068,6 +10882,32 @@ var SenderShareStore = class {
|
|
|
10068
10882
|
}
|
|
10069
10883
|
};
|
|
10070
10884
|
|
|
10885
|
+
// src/delegations/index.ts
|
|
10886
|
+
import {
|
|
10887
|
+
authorizeShare,
|
|
10888
|
+
authorizationMethodForTarget,
|
|
10889
|
+
notifyShare,
|
|
10890
|
+
revokeShare,
|
|
10891
|
+
listShares,
|
|
10892
|
+
showShare,
|
|
10893
|
+
publishTargetShare,
|
|
10894
|
+
publishPolicyShare,
|
|
10895
|
+
claimShare,
|
|
10896
|
+
resumeShareAuthorization,
|
|
10897
|
+
isLegacyShareLink,
|
|
10898
|
+
receiveLegacyShare,
|
|
10899
|
+
migrateShare,
|
|
10900
|
+
MemoryEncryptedShareHistoryStorage,
|
|
10901
|
+
EncryptedSenderShareHistory
|
|
10902
|
+
} from "@tinycloud/share-sdk";
|
|
10903
|
+
import {
|
|
10904
|
+
inspectShare,
|
|
10905
|
+
receiveShare,
|
|
10906
|
+
ShareReceiveError,
|
|
10907
|
+
toShareErrorInfo,
|
|
10908
|
+
verifyBearerEnvelope
|
|
10909
|
+
} from "@tinycloud/share-sdk";
|
|
10910
|
+
|
|
10071
10911
|
// src/networkId.ts
|
|
10072
10912
|
import {
|
|
10073
10913
|
buildNetworkId,
|
|
@@ -10083,47 +10923,47 @@ function parseCanonicalNetworkId(networkId) {
|
|
|
10083
10923
|
}
|
|
10084
10924
|
|
|
10085
10925
|
// src/storage.schema.ts
|
|
10086
|
-
import { z as
|
|
10926
|
+
import { z as z8 } from "zod";
|
|
10087
10927
|
var ethereumAddressPattern = /^0x[a-fA-F0-9]{40}$/;
|
|
10088
|
-
var EnsDataSchema2 =
|
|
10928
|
+
var EnsDataSchema2 = z8.object({
|
|
10089
10929
|
/** ENS name/domain. */
|
|
10090
|
-
domain:
|
|
10930
|
+
domain: z8.string().nullable().optional(),
|
|
10091
10931
|
/** ENS avatar URL. */
|
|
10092
|
-
avatarUrl:
|
|
10932
|
+
avatarUrl: z8.string().nullable().optional()
|
|
10093
10933
|
});
|
|
10094
|
-
var PersistedTinyCloudSessionSchema =
|
|
10934
|
+
var PersistedTinyCloudSessionSchema = z8.object({
|
|
10095
10935
|
/** The delegation header containing the UCAN */
|
|
10096
|
-
delegationHeader:
|
|
10097
|
-
Authorization:
|
|
10936
|
+
delegationHeader: z8.object({
|
|
10937
|
+
Authorization: z8.string()
|
|
10098
10938
|
}),
|
|
10099
10939
|
/** The delegation CID */
|
|
10100
|
-
delegationCid:
|
|
10940
|
+
delegationCid: z8.string(),
|
|
10101
10941
|
/** The space ID for this session */
|
|
10102
|
-
spaceId:
|
|
10942
|
+
spaceId: z8.string(),
|
|
10103
10943
|
/** Additional spaces included in this session's capabilities. Key is logical name, value is full spaceId URI */
|
|
10104
|
-
spaces:
|
|
10944
|
+
spaces: z8.record(z8.string(), z8.string()).optional(),
|
|
10105
10945
|
/** The verification method DID */
|
|
10106
|
-
verificationMethod:
|
|
10946
|
+
verificationMethod: z8.string()
|
|
10107
10947
|
});
|
|
10108
|
-
var PersistedSessionDataSchema =
|
|
10948
|
+
var PersistedSessionDataSchema = z8.object({
|
|
10109
10949
|
/** User's Ethereum address */
|
|
10110
|
-
address:
|
|
10950
|
+
address: z8.string().regex(ethereumAddressPattern, "Invalid Ethereum address"),
|
|
10111
10951
|
/** EIP-155 Chain ID */
|
|
10112
|
-
chainId:
|
|
10952
|
+
chainId: z8.number().int().positive(),
|
|
10113
10953
|
/** Session key in JWK format (stringified) */
|
|
10114
|
-
sessionKey:
|
|
10954
|
+
sessionKey: z8.string(),
|
|
10115
10955
|
/** The signed SIWE message */
|
|
10116
|
-
siwe:
|
|
10956
|
+
siwe: z8.string(),
|
|
10117
10957
|
/** User's signature of the SIWE message */
|
|
10118
|
-
signature:
|
|
10958
|
+
signature: z8.string(),
|
|
10119
10959
|
/** TinyCloud delegation data if available */
|
|
10120
10960
|
tinycloudSession: PersistedTinyCloudSessionSchema.optional(),
|
|
10121
10961
|
/** Session expiration timestamp (ISO 8601 with timezone offset) */
|
|
10122
|
-
expiresAt:
|
|
10962
|
+
expiresAt: z8.string().datetime({ offset: true }),
|
|
10123
10963
|
/** Session creation timestamp (ISO 8601 with timezone offset) */
|
|
10124
|
-
createdAt:
|
|
10964
|
+
createdAt: z8.string().datetime({ offset: true }),
|
|
10125
10965
|
/** Schema version for migrations */
|
|
10126
|
-
version:
|
|
10966
|
+
version: z8.string(),
|
|
10127
10967
|
/** Optional ENS data */
|
|
10128
10968
|
ens: EnsDataSchema2.optional(),
|
|
10129
10969
|
/**
|
|
@@ -10133,33 +10973,33 @@ var PersistedSessionDataSchema = z6.object({
|
|
|
10133
10973
|
* for backward compatibility with sessions persisted before this field
|
|
10134
10974
|
* existed — those restore and lazily re-resolve their hosts.
|
|
10135
10975
|
*/
|
|
10136
|
-
tinycloudHosts:
|
|
10976
|
+
tinycloudHosts: z8.array(z8.string()).optional()
|
|
10137
10977
|
});
|
|
10138
|
-
var TinyCloudSessionSchema =
|
|
10978
|
+
var TinyCloudSessionSchema = z8.object({
|
|
10139
10979
|
/** User's Ethereum address */
|
|
10140
|
-
address:
|
|
10980
|
+
address: z8.string().regex(ethereumAddressPattern, "Invalid Ethereum address"),
|
|
10141
10981
|
/** EIP-155 Chain ID */
|
|
10142
|
-
chainId:
|
|
10982
|
+
chainId: z8.number().int().positive(),
|
|
10143
10983
|
/** Session key ID */
|
|
10144
|
-
sessionKey:
|
|
10984
|
+
sessionKey: z8.string(),
|
|
10145
10985
|
/** The space ID for this session */
|
|
10146
|
-
spaceId:
|
|
10986
|
+
spaceId: z8.string(),
|
|
10147
10987
|
/** Additional spaces included in this session's capabilities. Key is logical name, value is full spaceId URI */
|
|
10148
|
-
spaces:
|
|
10988
|
+
spaces: z8.record(z8.string(), z8.string()).optional(),
|
|
10149
10989
|
/** The delegation CID */
|
|
10150
|
-
delegationCid:
|
|
10990
|
+
delegationCid: z8.string(),
|
|
10151
10991
|
/** The delegation header for API calls */
|
|
10152
|
-
delegationHeader:
|
|
10153
|
-
Authorization:
|
|
10992
|
+
delegationHeader: z8.object({
|
|
10993
|
+
Authorization: z8.string()
|
|
10154
10994
|
}),
|
|
10155
10995
|
/** The verification method DID */
|
|
10156
|
-
verificationMethod:
|
|
10996
|
+
verificationMethod: z8.string(),
|
|
10157
10997
|
/** The session key JWK (required for invoke operations) */
|
|
10158
|
-
jwk:
|
|
10998
|
+
jwk: z8.object({}).passthrough(),
|
|
10159
10999
|
/** The signed SIWE message */
|
|
10160
|
-
siwe:
|
|
11000
|
+
siwe: z8.string(),
|
|
10161
11001
|
/** User's signature of the SIWE message */
|
|
10162
|
-
signature:
|
|
11002
|
+
signature: z8.string()
|
|
10163
11003
|
});
|
|
10164
11004
|
function validatePersistedSessionData(data) {
|
|
10165
11005
|
const result = PersistedSessionDataSchema.safeParse(data);
|
|
@@ -10272,112 +11112,112 @@ var Space = class {
|
|
|
10272
11112
|
};
|
|
10273
11113
|
|
|
10274
11114
|
// src/spaces/spaces.schema.ts
|
|
10275
|
-
import { z as
|
|
10276
|
-
var SpaceConfigSchema =
|
|
11115
|
+
import { z as z9 } from "zod";
|
|
11116
|
+
var SpaceConfigSchema = z9.object({
|
|
10277
11117
|
/** The space identifier (full URI) */
|
|
10278
|
-
id:
|
|
11118
|
+
id: z9.string(),
|
|
10279
11119
|
/** The short name of the space */
|
|
10280
|
-
name:
|
|
11120
|
+
name: z9.string(),
|
|
10281
11121
|
/** Factory function to create a space-scoped KV service */
|
|
10282
|
-
createKV:
|
|
11122
|
+
createKV: z9.function(),
|
|
10283
11123
|
/** Factory function to create a space-scoped Data Vault service */
|
|
10284
|
-
createVault:
|
|
11124
|
+
createVault: z9.function(),
|
|
10285
11125
|
/** Optional factory function to create a space-scoped secrets service */
|
|
10286
|
-
createSecrets:
|
|
11126
|
+
createSecrets: z9.function().optional(),
|
|
10287
11127
|
/** Factory function to create space-scoped delegations */
|
|
10288
|
-
createDelegations:
|
|
11128
|
+
createDelegations: z9.function(),
|
|
10289
11129
|
/** Factory function to create space-scoped sharing */
|
|
10290
|
-
createSharing:
|
|
11130
|
+
createSharing: z9.function(),
|
|
10291
11131
|
/** Function to get space info */
|
|
10292
|
-
getInfo:
|
|
11132
|
+
getInfo: z9.function()
|
|
10293
11133
|
});
|
|
10294
|
-
var SpaceServiceConfigSchema =
|
|
11134
|
+
var SpaceServiceConfigSchema = z9.object({
|
|
10295
11135
|
/** TinyCloud host URLs */
|
|
10296
|
-
hosts:
|
|
11136
|
+
hosts: z9.array(z9.string()),
|
|
10297
11137
|
/** Active session for authentication */
|
|
10298
|
-
session:
|
|
11138
|
+
session: z9.unknown(),
|
|
10299
11139
|
/** Platform-specific invoke function */
|
|
10300
|
-
invoke:
|
|
11140
|
+
invoke: z9.function(),
|
|
10301
11141
|
/** Optional custom fetch implementation */
|
|
10302
|
-
fetch:
|
|
11142
|
+
fetch: z9.function().optional(),
|
|
10303
11143
|
/** Optional capability key registry for delegated space discovery */
|
|
10304
|
-
capabilityRegistry:
|
|
11144
|
+
capabilityRegistry: z9.unknown().optional(),
|
|
10305
11145
|
/** Factory function to create a space-scoped KV service */
|
|
10306
|
-
createKVService:
|
|
11146
|
+
createKVService: z9.function().optional(),
|
|
10307
11147
|
/** Factory function to create a space-scoped Data Vault service */
|
|
10308
|
-
createVaultService:
|
|
11148
|
+
createVaultService: z9.function().optional(),
|
|
10309
11149
|
/** Factory function to create a space-scoped secrets service */
|
|
10310
|
-
createSecretsService:
|
|
11150
|
+
createSecretsService: z9.function().optional(),
|
|
10311
11151
|
/** User's PKH DID (derived from address or provided explicitly) */
|
|
10312
|
-
userDid:
|
|
11152
|
+
userDid: z9.string().optional(),
|
|
10313
11153
|
/** Optional SharingService for v2 sharing links (client-side) */
|
|
10314
|
-
sharingService:
|
|
11154
|
+
sharingService: z9.unknown().optional(),
|
|
10315
11155
|
/** Factory function to create delegations using SIWE-based flow */
|
|
10316
|
-
createDelegation:
|
|
11156
|
+
createDelegation: z9.function().optional()
|
|
10317
11157
|
});
|
|
10318
11158
|
var SpaceDelegationParamsSchema = CreateDelegationParamsSchema.extend({
|
|
10319
11159
|
/** The space ID to create the delegation for */
|
|
10320
|
-
spaceId:
|
|
11160
|
+
spaceId: z9.string()
|
|
10321
11161
|
});
|
|
10322
|
-
var ServerDelegationInfoSchema =
|
|
11162
|
+
var ServerDelegationInfoSchema = z9.object({
|
|
10323
11163
|
/** DID of the delegator */
|
|
10324
|
-
delegator:
|
|
11164
|
+
delegator: z9.string(),
|
|
10325
11165
|
/** DID of the delegate */
|
|
10326
|
-
delegate:
|
|
11166
|
+
delegate: z9.string(),
|
|
10327
11167
|
/** Parent delegation CIDs - accepts string or byte array format from server */
|
|
10328
|
-
parents:
|
|
11168
|
+
parents: z9.array(z9.union([z9.string(), z9.array(z9.number())])),
|
|
10329
11169
|
/** Expiration time (ISO8601 string) */
|
|
10330
|
-
expiry:
|
|
11170
|
+
expiry: z9.string().optional(),
|
|
10331
11171
|
/** Not-before time (ISO8601 string) */
|
|
10332
|
-
not_before:
|
|
11172
|
+
not_before: z9.string().optional(),
|
|
10333
11173
|
/** Issued-at time (ISO8601 string) */
|
|
10334
|
-
issued_at:
|
|
11174
|
+
issued_at: z9.string().optional(),
|
|
10335
11175
|
/** Capabilities granted by this delegation */
|
|
10336
|
-
capabilities:
|
|
10337
|
-
|
|
10338
|
-
resource:
|
|
10339
|
-
ability:
|
|
11176
|
+
capabilities: z9.array(
|
|
11177
|
+
z9.object({
|
|
11178
|
+
resource: z9.string(),
|
|
11179
|
+
ability: z9.string()
|
|
10340
11180
|
})
|
|
10341
11181
|
)
|
|
10342
11182
|
});
|
|
10343
|
-
var ServerDelegationsResponseSchema =
|
|
10344
|
-
|
|
11183
|
+
var ServerDelegationsResponseSchema = z9.record(
|
|
11184
|
+
z9.string(),
|
|
10345
11185
|
ServerDelegationInfoSchema
|
|
10346
11186
|
);
|
|
10347
|
-
var ServerOwnedSpaceSchema =
|
|
11187
|
+
var ServerOwnedSpaceSchema = z9.object({
|
|
10348
11188
|
/** Space identifier */
|
|
10349
|
-
id:
|
|
11189
|
+
id: z9.string(),
|
|
10350
11190
|
/** Space name (optional, can be derived from id) */
|
|
10351
|
-
name:
|
|
11191
|
+
name: z9.string().optional(),
|
|
10352
11192
|
/** Owner DID */
|
|
10353
|
-
owner:
|
|
11193
|
+
owner: z9.string(),
|
|
10354
11194
|
/** Creation timestamp */
|
|
10355
|
-
createdAt:
|
|
11195
|
+
createdAt: z9.string().optional()
|
|
10356
11196
|
});
|
|
10357
|
-
var ServerOwnedSpacesResponseSchema =
|
|
10358
|
-
var ServerCreateSpaceResponseSchema =
|
|
11197
|
+
var ServerOwnedSpacesResponseSchema = z9.array(ServerOwnedSpaceSchema);
|
|
11198
|
+
var ServerCreateSpaceResponseSchema = z9.object({
|
|
10359
11199
|
/** Space identifier */
|
|
10360
|
-
id:
|
|
11200
|
+
id: z9.string(),
|
|
10361
11201
|
/** Space name */
|
|
10362
|
-
name:
|
|
11202
|
+
name: z9.string(),
|
|
10363
11203
|
/** Owner DID */
|
|
10364
|
-
owner:
|
|
11204
|
+
owner: z9.string(),
|
|
10365
11205
|
/** Creation timestamp */
|
|
10366
|
-
createdAt:
|
|
11206
|
+
createdAt: z9.string().optional()
|
|
10367
11207
|
});
|
|
10368
|
-
var ServerSpaceInfoResponseSchema =
|
|
11208
|
+
var ServerSpaceInfoResponseSchema = z9.object({
|
|
10369
11209
|
/** Space identifier */
|
|
10370
|
-
id:
|
|
11210
|
+
id: z9.string(),
|
|
10371
11211
|
/** Space name (optional) */
|
|
10372
|
-
name:
|
|
11212
|
+
name: z9.string().optional(),
|
|
10373
11213
|
/** Owner DID */
|
|
10374
|
-
owner:
|
|
11214
|
+
owner: z9.string(),
|
|
10375
11215
|
/** Ownership type */
|
|
10376
|
-
type:
|
|
11216
|
+
type: z9.enum(["owned", "delegated"]).optional(),
|
|
10377
11217
|
/** Permissions the user has in this space */
|
|
10378
|
-
permissions:
|
|
11218
|
+
permissions: z9.array(z9.string()).optional(),
|
|
10379
11219
|
/** Expiration for delegated access */
|
|
10380
|
-
expiresAt:
|
|
11220
|
+
expiresAt: z9.string().optional()
|
|
10381
11221
|
});
|
|
10382
11222
|
function validateServerDelegationsResponse(data) {
|
|
10383
11223
|
if (data === null || data === void 0) {
|
|
@@ -11789,7 +12629,8 @@ var TinyCloud = class _TinyCloud {
|
|
|
11789
12629
|
import {
|
|
11790
12630
|
err as err3,
|
|
11791
12631
|
ok as ok3,
|
|
11792
|
-
serviceError as serviceError3
|
|
12632
|
+
serviceError as serviceError3,
|
|
12633
|
+
ErrorCodes as ErrorCodes3
|
|
11793
12634
|
} from "@tinycloud/sdk-services";
|
|
11794
12635
|
import { ACCOUNT_INDEX_SCHEMA } from "@tinycloud/bootstrap";
|
|
11795
12636
|
var SERVICE_NAME2 = "account";
|
|
@@ -11799,6 +12640,22 @@ var ACCOUNT_SPACES_PATH = "spaces/";
|
|
|
11799
12640
|
var AccountService = class {
|
|
11800
12641
|
constructor(config) {
|
|
11801
12642
|
this.config = config;
|
|
12643
|
+
/**
|
|
12644
|
+
* Per-account-space memo for {@link ensureAccountIndex}.
|
|
12645
|
+
*
|
|
12646
|
+
* Applying the index migration is a no-op once the schema exists, but the
|
|
12647
|
+
* SQL service still spends two round trips discovering that (create the
|
|
12648
|
+
* migrations table, then read the applied-migration rows). Account bootstrap
|
|
12649
|
+
* touches the index eight times, so without a memo that is ~14 wasted
|
|
12650
|
+
* requests on the cold sign-in path. The in-flight dedupe inside SQLService
|
|
12651
|
+
* never helps here: the node SDK builds a fresh SQLService per
|
|
12652
|
+
* `getAccountDb()` call, so its lock map is always empty.
|
|
12653
|
+
*
|
|
12654
|
+
* Keyed by account space id, so a different account never reuses this entry.
|
|
12655
|
+
* Failures are evicted so a later call retries instead of inheriting a
|
|
12656
|
+
* permanently poisoned result.
|
|
12657
|
+
*/
|
|
12658
|
+
this.accountIndexReady = /* @__PURE__ */ new Map();
|
|
11802
12659
|
this.applications = {
|
|
11803
12660
|
list: async (options2 = {}) => {
|
|
11804
12661
|
if (options2.preferIndex) {
|
|
@@ -11832,7 +12689,7 @@ var AccountService = class {
|
|
|
11832
12689
|
if (!loaded.ok) return accountErr(loaded.error);
|
|
11833
12690
|
return ok3(applicationFromRecord(key, loaded.data.data));
|
|
11834
12691
|
},
|
|
11835
|
-
register: async (manifest) => {
|
|
12692
|
+
register: async (manifest, options2 = {}) => {
|
|
11836
12693
|
const manifests = Array.isArray(manifest) ? manifest : [manifest];
|
|
11837
12694
|
const request = composeManifestRequest(manifests);
|
|
11838
12695
|
if (request.registryRecords.length === 0) {
|
|
@@ -11850,7 +12707,7 @@ var AccountService = class {
|
|
|
11850
12707
|
let registered;
|
|
11851
12708
|
for (const record of request.registryRecords) {
|
|
11852
12709
|
const manifestHash = hashJson(record.manifests);
|
|
11853
|
-
if (await this.indexHasApplicationHash(record.app_id, manifestHash)) {
|
|
12710
|
+
if (!options2.assumeUnregistered && await this.indexHasApplicationHash(record.app_id, manifestHash)) {
|
|
11854
12711
|
registered = {
|
|
11855
12712
|
appId: record.app_id,
|
|
11856
12713
|
manifests: record.manifests,
|
|
@@ -11925,6 +12782,60 @@ var AccountService = class {
|
|
|
11925
12782
|
await this.upsertSpaceIndexQuietly(registered);
|
|
11926
12783
|
return ok3(registered);
|
|
11927
12784
|
},
|
|
12785
|
+
/**
|
|
12786
|
+
* Register multiple spaces in one KV batch write + one multi-row index
|
|
12787
|
+
* write, instead of one `register()` round trip per space (TC-373).
|
|
12788
|
+
*
|
|
12789
|
+
* The stored records are computed exactly once and reused for both the
|
|
12790
|
+
* batch attempt and any reconciliation below, so a fallback never mints a
|
|
12791
|
+
* fresh timestamp for a space that already has a written record — a
|
|
12792
|
+
* second `spaceRecordFromInput` call would produce a new content hash and
|
|
12793
|
+
* leave the first attempt's blocks orphaned.
|
|
12794
|
+
*/
|
|
12795
|
+
registerBatch: async (spaces) => {
|
|
12796
|
+
if (spaces.length === 0) return ok3({ spaces: [] });
|
|
12797
|
+
await this.config.ensureAccountSpaceHosted?.();
|
|
12798
|
+
const kvResult = this.accountKV();
|
|
12799
|
+
if (!kvResult.ok) return kvResult;
|
|
12800
|
+
const stored = spaces.map((space) => spaceRecordFromInput(space));
|
|
12801
|
+
const registered = stored.map(
|
|
12802
|
+
(record) => spaceFromRecord(spaceKey(record.space_id), record)
|
|
12803
|
+
);
|
|
12804
|
+
const items = stored.map((record) => ({
|
|
12805
|
+
key: spaceKey(record.space_id),
|
|
12806
|
+
value: record
|
|
12807
|
+
}));
|
|
12808
|
+
const batchResult = await kvResult.data.batchPut(items);
|
|
12809
|
+
if (batchResult.ok) {
|
|
12810
|
+
await this.upsertSpacesIndexQuietly(registered);
|
|
12811
|
+
return ok3({ spaces: registered });
|
|
12812
|
+
}
|
|
12813
|
+
if (!isAmbiguousBatchFailure(batchResult.error)) {
|
|
12814
|
+
return accountErr(batchResult.error);
|
|
12815
|
+
}
|
|
12816
|
+
const reconcileFailures = [];
|
|
12817
|
+
for (const record of stored) {
|
|
12818
|
+
const written = await kvResult.data.put(spaceKey(record.space_id), record);
|
|
12819
|
+
if (!written.ok) {
|
|
12820
|
+
reconcileFailures.push(`${record.space_id}: ${written.error.message}`);
|
|
12821
|
+
}
|
|
12822
|
+
}
|
|
12823
|
+
if (reconcileFailures.length > 0) {
|
|
12824
|
+
return err3(
|
|
12825
|
+
serviceError3(
|
|
12826
|
+
"KV_BATCH_RECONCILE_FAILED",
|
|
12827
|
+
`KV batch write for ${items.length} space(s) failed ambiguously (${batchResult.error.message}) and per-space reconciliation also failed for: ${reconcileFailures.join("; ")}`,
|
|
12828
|
+
SERVICE_NAME2,
|
|
12829
|
+
{ cause: batchResult.error.cause, meta: { originalError: batchResult.error } }
|
|
12830
|
+
)
|
|
12831
|
+
);
|
|
12832
|
+
}
|
|
12833
|
+
console.warn(
|
|
12834
|
+
`[AccountService] KV batch write for ${items.length} space(s) returned an ambiguous error and was reconciled via per-space fallback. Original error: ${batchResult.error.message}`
|
|
12835
|
+
);
|
|
12836
|
+
await this.upsertSpacesIndexQuietly(registered);
|
|
12837
|
+
return ok3({ spaces: registered, recoveredFromBatchError: batchResult.error });
|
|
12838
|
+
},
|
|
11928
12839
|
syncAccessible: async () => {
|
|
11929
12840
|
const listed = await this.config.getSpaces().list();
|
|
11930
12841
|
if (!listed.ok) return accountErr(listed.error);
|
|
@@ -12031,6 +12942,7 @@ var AccountService = class {
|
|
|
12031
12942
|
const delegations = await this.delegations.list();
|
|
12032
12943
|
if (!delegations.ok) return delegations;
|
|
12033
12944
|
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12945
|
+
this.invalidateAccountIndexMemo();
|
|
12034
12946
|
const schema = await this.ensureAccountIndex(dbResult.data);
|
|
12035
12947
|
if (!schema.ok) return schema;
|
|
12036
12948
|
const statements = [
|
|
@@ -12310,6 +13222,47 @@ var AccountService = class {
|
|
|
12310
13222
|
if (!written.ok) return accountErr(written.error);
|
|
12311
13223
|
return ok3(void 0);
|
|
12312
13224
|
}
|
|
13225
|
+
async upsertSpacesIndexQuietly(spaces) {
|
|
13226
|
+
await ignoreIndexFailure(() => this.upsertSpacesIndex(spaces));
|
|
13227
|
+
}
|
|
13228
|
+
/**
|
|
13229
|
+
* Upsert multiple space index rows in ONE multi-row `INSERT OR REPLACE`
|
|
13230
|
+
* statement (TC-373), rather than one statement per space. This matters
|
|
13231
|
+
* because `IDatabaseHandle.batch()` executes its statement list as a plain
|
|
13232
|
+
* loop, not a single database transaction — an N-statement batch is not
|
|
13233
|
+
* atomic. A single multi-row INSERT is one SQLite statement, so it applies
|
|
13234
|
+
* atomically: all rows or none.
|
|
13235
|
+
*/
|
|
13236
|
+
async upsertSpacesIndex(spaces) {
|
|
13237
|
+
if (spaces.length === 0) return ok3(void 0);
|
|
13238
|
+
const dbResult = this.accountDb();
|
|
13239
|
+
if (!dbResult.ok) return ok3(void 0);
|
|
13240
|
+
const schema = await this.ensureAccountIndex(dbResult.data);
|
|
13241
|
+
if (!schema.ok) return schema;
|
|
13242
|
+
const placeholders = spaces.map(() => "(?, ?, ?, ?, ?, ?, ?, ?, ?)").join(", ");
|
|
13243
|
+
const params = spaces.flatMap((space) => {
|
|
13244
|
+
const updatedAt = space.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
13245
|
+
return [
|
|
13246
|
+
space.spaceId,
|
|
13247
|
+
space.name,
|
|
13248
|
+
space.ownerDid,
|
|
13249
|
+
space.type,
|
|
13250
|
+
JSON.stringify(space.permissions),
|
|
13251
|
+
space.status,
|
|
13252
|
+
space.registeredAt ?? updatedAt,
|
|
13253
|
+
updatedAt,
|
|
13254
|
+
space.expiresAt?.toISOString() ?? null
|
|
13255
|
+
];
|
|
13256
|
+
});
|
|
13257
|
+
const written = await dbResult.data.batch([
|
|
13258
|
+
{
|
|
13259
|
+
sql: `INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES ${placeholders}`,
|
|
13260
|
+
params
|
|
13261
|
+
}
|
|
13262
|
+
]);
|
|
13263
|
+
if (!written.ok) return accountErr(written.error);
|
|
13264
|
+
return ok3(void 0);
|
|
13265
|
+
}
|
|
12313
13266
|
async deleteSpaceIndexQuietly(spaceId) {
|
|
12314
13267
|
await ignoreIndexFailure(() => this.deleteSpaceIndex(spaceId));
|
|
12315
13268
|
}
|
|
@@ -12430,7 +13383,41 @@ var AccountService = class {
|
|
|
12430
13383
|
]);
|
|
12431
13384
|
});
|
|
12432
13385
|
}
|
|
13386
|
+
/**
|
|
13387
|
+
* Apply the account index schema at most once per account space.
|
|
13388
|
+
*
|
|
13389
|
+
* The index is a cache over canonical KV state, and every caller already
|
|
13390
|
+
* tolerates it being absent (`ignoreIndexFailure` / `isMissingIndexError`),
|
|
13391
|
+
* so a memo that is wrong in the "already applied" direction degrades to a
|
|
13392
|
+
* `no such table` read that the caller handles. A memo that is wrong in the
|
|
13393
|
+
* other direction would be a real bug, so failures are never cached.
|
|
13394
|
+
*/
|
|
12433
13395
|
async ensureAccountIndex(db) {
|
|
13396
|
+
const key = this.config.getAccountSpaceId() ?? "";
|
|
13397
|
+
const cached = this.accountIndexReady.get(key);
|
|
13398
|
+
if (cached) return cached;
|
|
13399
|
+
const pending = this.applyAccountIndex(db);
|
|
13400
|
+
this.accountIndexReady.set(key, pending);
|
|
13401
|
+
const evict = () => {
|
|
13402
|
+
if (this.accountIndexReady.get(key) === pending) {
|
|
13403
|
+
this.accountIndexReady.delete(key);
|
|
13404
|
+
}
|
|
13405
|
+
};
|
|
13406
|
+
let settled;
|
|
13407
|
+
try {
|
|
13408
|
+
settled = await pending;
|
|
13409
|
+
} catch (error) {
|
|
13410
|
+
evict();
|
|
13411
|
+
throw error;
|
|
13412
|
+
}
|
|
13413
|
+
if (!settled.ok) evict();
|
|
13414
|
+
return settled;
|
|
13415
|
+
}
|
|
13416
|
+
/** Drop the memo so the next {@link ensureAccountIndex} re-applies the schema. */
|
|
13417
|
+
invalidateAccountIndexMemo() {
|
|
13418
|
+
this.accountIndexReady.delete(this.config.getAccountSpaceId() ?? "");
|
|
13419
|
+
}
|
|
13420
|
+
async applyAccountIndex(db) {
|
|
12434
13421
|
const migrated = await db.migrations.apply({
|
|
12435
13422
|
namespace: ACCOUNT_INDEX_NAMESPACE,
|
|
12436
13423
|
migrations: [
|
|
@@ -12547,8 +13534,8 @@ function stableJson(value) {
|
|
|
12547
13534
|
if (Array.isArray(value)) {
|
|
12548
13535
|
return `[${value.map(stableJson).join(",")}]`;
|
|
12549
13536
|
}
|
|
12550
|
-
const
|
|
12551
|
-
return `{${Object.keys(
|
|
13537
|
+
const object2 = value;
|
|
13538
|
+
return `{${Object.keys(object2).sort().map((key) => `${JSON.stringify(key)}:${stableJson(object2[key])}`).join(",")}}`;
|
|
12552
13539
|
}
|
|
12553
13540
|
function indexedDelegationFromRow(row) {
|
|
12554
13541
|
const [
|
|
@@ -12602,6 +13589,17 @@ function accountErr(error) {
|
|
|
12602
13589
|
function isMissingIndexError(error) {
|
|
12603
13590
|
return /no such table:/i.test(error.message);
|
|
12604
13591
|
}
|
|
13592
|
+
var AMBIGUOUS_WRITE_STATUSES = /* @__PURE__ */ new Set([500, 502, 503, 504, 520, 522, 524]);
|
|
13593
|
+
function isAmbiguousBatchFailure(error) {
|
|
13594
|
+
if (error.code === ErrorCodes3.NETWORK_ERROR || error.code === ErrorCodes3.TIMEOUT) {
|
|
13595
|
+
return error.meta?.requestMayHaveDispatched === true;
|
|
13596
|
+
}
|
|
13597
|
+
if (error.code === ErrorCodes3.KV_WRITE_FAILED) {
|
|
13598
|
+
const status = error.meta?.status;
|
|
13599
|
+
return typeof status === "number" && AMBIGUOUS_WRITE_STATUSES.has(status);
|
|
13600
|
+
}
|
|
13601
|
+
return false;
|
|
13602
|
+
}
|
|
12605
13603
|
async function ignoreIndexFailure(task) {
|
|
12606
13604
|
try {
|
|
12607
13605
|
await task();
|
|
@@ -12617,7 +13615,7 @@ import {
|
|
|
12617
13615
|
ok as ok5,
|
|
12618
13616
|
err as err5,
|
|
12619
13617
|
serviceError as serviceError5,
|
|
12620
|
-
ErrorCodes as
|
|
13618
|
+
ErrorCodes as ErrorCodes4,
|
|
12621
13619
|
TinyCloudDebugLogger,
|
|
12622
13620
|
tinyCloudDebugLogger,
|
|
12623
13621
|
enableTinyCloudDebug,
|
|
@@ -13291,6 +14289,279 @@ var AutoApproveSpaceCreationHandler = class {
|
|
|
13291
14289
|
};
|
|
13292
14290
|
var defaultSpaceCreationHandler = new AutoApproveSpaceCreationHandler();
|
|
13293
14291
|
|
|
14292
|
+
// src/authorization/openkey-protocol.ts
|
|
14293
|
+
function validateAuthorizationResultV1(value) {
|
|
14294
|
+
if (!value || typeof value !== "object") {
|
|
14295
|
+
return { ok: false, error: "authorization result must be an object" };
|
|
14296
|
+
}
|
|
14297
|
+
const v = value;
|
|
14298
|
+
if (v.protocolVersion !== 1) {
|
|
14299
|
+
return { ok: false, error: `unsupported protocolVersion ${String(v.protocolVersion)}` };
|
|
14300
|
+
}
|
|
14301
|
+
if (typeof v.address !== "string" || !v.address) {
|
|
14302
|
+
return { ok: false, error: "address must be a non-empty string" };
|
|
14303
|
+
}
|
|
14304
|
+
if (typeof v.signature !== "string" || !v.signature) {
|
|
14305
|
+
return { ok: false, error: "signature must be a non-empty string" };
|
|
14306
|
+
}
|
|
14307
|
+
if (typeof v.signedMessage !== "string" || !v.signedMessage) {
|
|
14308
|
+
return { ok: false, error: "signedMessage must be a non-empty string" };
|
|
14309
|
+
}
|
|
14310
|
+
if (!Array.isArray(v.selectedActionKeys) || v.selectedActionKeys.some((k) => typeof k !== "string")) {
|
|
14311
|
+
return { ok: false, error: "selectedActionKeys must be a string[]" };
|
|
14312
|
+
}
|
|
14313
|
+
if (!Array.isArray(v.permissions)) {
|
|
14314
|
+
return { ok: false, error: "permissions must be an array" };
|
|
14315
|
+
}
|
|
14316
|
+
const permissions = [];
|
|
14317
|
+
for (const [index, entry] of v.permissions.entries()) {
|
|
14318
|
+
if (!entry || typeof entry !== "object") {
|
|
14319
|
+
return { ok: false, error: `permissions[${index}] must be an object` };
|
|
14320
|
+
}
|
|
14321
|
+
const e = entry;
|
|
14322
|
+
if (typeof e.service !== "string" || typeof e.space !== "string" || typeof e.path !== "string") {
|
|
14323
|
+
return { ok: false, error: `permissions[${index}] must have string service/space/path` };
|
|
14324
|
+
}
|
|
14325
|
+
if (!Array.isArray(e.actions) || e.actions.some((a) => typeof a !== "string")) {
|
|
14326
|
+
return { ok: false, error: `permissions[${index}].actions must be a string[]` };
|
|
14327
|
+
}
|
|
14328
|
+
permissions.push({
|
|
14329
|
+
service: e.service,
|
|
14330
|
+
space: e.space,
|
|
14331
|
+
path: e.path,
|
|
14332
|
+
actions: e.actions
|
|
14333
|
+
});
|
|
14334
|
+
}
|
|
14335
|
+
return {
|
|
14336
|
+
ok: true,
|
|
14337
|
+
value: {
|
|
14338
|
+
protocolVersion: 1,
|
|
14339
|
+
address: v.address,
|
|
14340
|
+
signature: v.signature,
|
|
14341
|
+
signedMessage: v.signedMessage,
|
|
14342
|
+
selectedActionKeys: v.selectedActionKeys,
|
|
14343
|
+
permissions
|
|
14344
|
+
}
|
|
14345
|
+
};
|
|
14346
|
+
}
|
|
14347
|
+
var OPENKEY_ACTION_ID_SEPARATOR = "\0";
|
|
14348
|
+
function isPlausibleOpenKeyActionId(id) {
|
|
14349
|
+
return typeof id === "string" && id.split(OPENKEY_ACTION_ID_SEPARATOR).length === 4 && id.length > 0;
|
|
14350
|
+
}
|
|
14351
|
+
function parseCanonicalRecapResource(resource) {
|
|
14352
|
+
if (!resource.startsWith("tinycloud:")) {
|
|
14353
|
+
return { space: resource, path: "" };
|
|
14354
|
+
}
|
|
14355
|
+
const firstSlash = resource.indexOf("/");
|
|
14356
|
+
if (firstSlash < 0) {
|
|
14357
|
+
return { space: resource, path: "" };
|
|
14358
|
+
}
|
|
14359
|
+
const space = resource.slice(0, firstSlash);
|
|
14360
|
+
const rest = resource.slice(firstSlash + 1);
|
|
14361
|
+
const secondSlash = rest.indexOf("/");
|
|
14362
|
+
if (secondSlash < 0) {
|
|
14363
|
+
return { space, path: "" };
|
|
14364
|
+
}
|
|
14365
|
+
return { space, path: rest.slice(secondSlash + 1) };
|
|
14366
|
+
}
|
|
14367
|
+
function extractImmutableSiweFields(siwe) {
|
|
14368
|
+
const lines = siwe.split(/\r?\n/);
|
|
14369
|
+
const result = {};
|
|
14370
|
+
const headerLine = lines[0];
|
|
14371
|
+
if (headerLine) {
|
|
14372
|
+
const domainMatch = headerLine.match(/^(.+?)\s+wants you to sign in/);
|
|
14373
|
+
if (domainMatch) {
|
|
14374
|
+
result.domain = domainMatch[1];
|
|
14375
|
+
}
|
|
14376
|
+
}
|
|
14377
|
+
for (let i = 1; i < lines.length && i < 5; i++) {
|
|
14378
|
+
const line = lines[i]?.trim() ?? "";
|
|
14379
|
+
if (/^0x[0-9a-fA-F]{40}$/.test(line)) {
|
|
14380
|
+
result.address = line;
|
|
14381
|
+
break;
|
|
14382
|
+
}
|
|
14383
|
+
}
|
|
14384
|
+
for (const line of lines) {
|
|
14385
|
+
const match = line.match(/^([A-Z][A-Za-z ]*):\s*(.*)$/);
|
|
14386
|
+
if (!match) continue;
|
|
14387
|
+
const [, key, value] = match;
|
|
14388
|
+
switch (key) {
|
|
14389
|
+
case "URI":
|
|
14390
|
+
result.uri = value;
|
|
14391
|
+
break;
|
|
14392
|
+
case "Version":
|
|
14393
|
+
result.version = value;
|
|
14394
|
+
break;
|
|
14395
|
+
case "Chain ID":
|
|
14396
|
+
result.chainId = value;
|
|
14397
|
+
break;
|
|
14398
|
+
case "Nonce":
|
|
14399
|
+
result.nonce = value;
|
|
14400
|
+
break;
|
|
14401
|
+
case "Issued At":
|
|
14402
|
+
result.issuedAt = value;
|
|
14403
|
+
break;
|
|
14404
|
+
// Sol MAJOR-4: complete immutable-field coverage.
|
|
14405
|
+
case "Expiration Time":
|
|
14406
|
+
result.expirationTime = value;
|
|
14407
|
+
break;
|
|
14408
|
+
case "Not Before":
|
|
14409
|
+
result.notBefore = value;
|
|
14410
|
+
break;
|
|
14411
|
+
case "Request ID":
|
|
14412
|
+
result.requestId = value;
|
|
14413
|
+
break;
|
|
14414
|
+
default:
|
|
14415
|
+
break;
|
|
14416
|
+
}
|
|
14417
|
+
}
|
|
14418
|
+
const uriLineIdx = lines.findIndex((l) => /^URI:/.test(l));
|
|
14419
|
+
if (uriLineIdx > 3) {
|
|
14420
|
+
let end = uriLineIdx - 1;
|
|
14421
|
+
while (end > 3 && lines[end] === "") end -= 1;
|
|
14422
|
+
if (end >= 3) {
|
|
14423
|
+
result.statement = lines.slice(3, end + 1).join("\n");
|
|
14424
|
+
} else {
|
|
14425
|
+
result.statement = "";
|
|
14426
|
+
}
|
|
14427
|
+
} else {
|
|
14428
|
+
result.statement = "";
|
|
14429
|
+
}
|
|
14430
|
+
result.nonRecapResources = lines.filter((l) => /^- /.test(l) && !/^- urn:recap:/.test(l)).join("\n");
|
|
14431
|
+
return result;
|
|
14432
|
+
}
|
|
14433
|
+
function diffImmutableSiweFields(original, signed, options2) {
|
|
14434
|
+
const baseKeys = [
|
|
14435
|
+
"domain",
|
|
14436
|
+
"address",
|
|
14437
|
+
"uri",
|
|
14438
|
+
"version",
|
|
14439
|
+
"chainId",
|
|
14440
|
+
"nonce",
|
|
14441
|
+
"issuedAt",
|
|
14442
|
+
"expirationTime",
|
|
14443
|
+
"notBefore",
|
|
14444
|
+
"requestId",
|
|
14445
|
+
"nonRecapResources"
|
|
14446
|
+
];
|
|
14447
|
+
const keys = options2?.originalHasRecap ? baseKeys : [...baseKeys, "statement"];
|
|
14448
|
+
const diffs = [];
|
|
14449
|
+
for (const key of keys) {
|
|
14450
|
+
const a = original[key] ?? "";
|
|
14451
|
+
const b = signed[key] ?? "";
|
|
14452
|
+
if (a !== b) {
|
|
14453
|
+
diffs.push(key);
|
|
14454
|
+
}
|
|
14455
|
+
}
|
|
14456
|
+
return diffs;
|
|
14457
|
+
}
|
|
14458
|
+
function extractRecapAttenuations(siwe) {
|
|
14459
|
+
const merged = {};
|
|
14460
|
+
const lines = siwe.split(/\r?\n/);
|
|
14461
|
+
for (const line of lines) {
|
|
14462
|
+
const match = line.match(/urn:recap:([A-Za-z0-9_-]+=*)/);
|
|
14463
|
+
if (!match) continue;
|
|
14464
|
+
const encoded = match[1];
|
|
14465
|
+
let decodedJson;
|
|
14466
|
+
try {
|
|
14467
|
+
const normalized = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
14468
|
+
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
|
|
14469
|
+
decodedJson = Buffer.from(padded, "base64").toString("utf8");
|
|
14470
|
+
} catch (err6) {
|
|
14471
|
+
throw new Error(
|
|
14472
|
+
`Failed to decode urn:recap: payload: ${err6.message}`
|
|
14473
|
+
);
|
|
14474
|
+
}
|
|
14475
|
+
let parsed;
|
|
14476
|
+
try {
|
|
14477
|
+
parsed = JSON.parse(decodedJson);
|
|
14478
|
+
} catch (err6) {
|
|
14479
|
+
throw new Error(
|
|
14480
|
+
`urn:recap: payload is not valid JSON: ${err6.message}`
|
|
14481
|
+
);
|
|
14482
|
+
}
|
|
14483
|
+
if (!parsed || typeof parsed !== "object") {
|
|
14484
|
+
throw new Error("urn:recap: payload must be an object");
|
|
14485
|
+
}
|
|
14486
|
+
const att = parsed.att;
|
|
14487
|
+
if (att === void 0) {
|
|
14488
|
+
continue;
|
|
14489
|
+
}
|
|
14490
|
+
if (typeof att !== "object" || att === null || Array.isArray(att)) {
|
|
14491
|
+
throw new Error("urn:recap: att must be an object");
|
|
14492
|
+
}
|
|
14493
|
+
for (const [resource, actionMap] of Object.entries(att)) {
|
|
14494
|
+
if (!actionMap || typeof actionMap !== "object" || Array.isArray(actionMap)) {
|
|
14495
|
+
throw new Error(`urn:recap: att[${resource}] must be an object`);
|
|
14496
|
+
}
|
|
14497
|
+
const existing = merged[resource] ?? {};
|
|
14498
|
+
for (const [action, caveats] of Object.entries(actionMap)) {
|
|
14499
|
+
if (!Array.isArray(caveats)) {
|
|
14500
|
+
throw new Error(
|
|
14501
|
+
`urn:recap: att[${resource}][${action}] must be an array`
|
|
14502
|
+
);
|
|
14503
|
+
}
|
|
14504
|
+
const previous = existing[action] ?? [];
|
|
14505
|
+
existing[action] = previous.concat(caveats);
|
|
14506
|
+
}
|
|
14507
|
+
merged[resource] = existing;
|
|
14508
|
+
}
|
|
14509
|
+
}
|
|
14510
|
+
return merged;
|
|
14511
|
+
}
|
|
14512
|
+
function stableStringify(value) {
|
|
14513
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
14514
|
+
if (Array.isArray(value)) {
|
|
14515
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
14516
|
+
}
|
|
14517
|
+
const entries = Object.entries(value).sort(
|
|
14518
|
+
([a], [b]) => a.localeCompare(b)
|
|
14519
|
+
);
|
|
14520
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
14521
|
+
}
|
|
14522
|
+
function caveatsDeepEqual(a, b) {
|
|
14523
|
+
return stableStringify(a) === stableStringify(b);
|
|
14524
|
+
}
|
|
14525
|
+
function unauthorizedRecapCapabilities(child, parent) {
|
|
14526
|
+
const unauthorized = [];
|
|
14527
|
+
for (const [resource, actions] of Object.entries(child)) {
|
|
14528
|
+
const parentActions = parent[resource];
|
|
14529
|
+
for (const [action, childCaveatsRaw] of Object.entries(actions)) {
|
|
14530
|
+
if (!parentActions || parentActions[action] === void 0) {
|
|
14531
|
+
unauthorized.push({ resource, action });
|
|
14532
|
+
continue;
|
|
14533
|
+
}
|
|
14534
|
+
const parentCaveatsRaw = parentActions[action];
|
|
14535
|
+
const parentCaveats = Array.isArray(parentCaveatsRaw) ? parentCaveatsRaw : [];
|
|
14536
|
+
const childCaveats = Array.isArray(childCaveatsRaw) ? childCaveatsRaw : [];
|
|
14537
|
+
const parentCanonCounts = /* @__PURE__ */ new Map();
|
|
14538
|
+
for (const c of parentCaveats) {
|
|
14539
|
+
const k = stableStringify(c);
|
|
14540
|
+
parentCanonCounts.set(k, (parentCanonCounts.get(k) ?? 0) + 1);
|
|
14541
|
+
}
|
|
14542
|
+
const childCanonCounts = /* @__PURE__ */ new Map();
|
|
14543
|
+
for (const c of childCaveats) {
|
|
14544
|
+
const k = stableStringify(c);
|
|
14545
|
+
childCanonCounts.set(k, (childCanonCounts.get(k) ?? 0) + 1);
|
|
14546
|
+
}
|
|
14547
|
+
let equal = parentCanonCounts.size === childCanonCounts.size;
|
|
14548
|
+
if (equal) {
|
|
14549
|
+
for (const [k, n] of parentCanonCounts) {
|
|
14550
|
+
if (childCanonCounts.get(k) !== n) {
|
|
14551
|
+
equal = false;
|
|
14552
|
+
break;
|
|
14553
|
+
}
|
|
14554
|
+
}
|
|
14555
|
+
}
|
|
14556
|
+
if (!equal) {
|
|
14557
|
+
unauthorized.push({ resource, action });
|
|
14558
|
+
}
|
|
14559
|
+
void caveatsDeepEqual;
|
|
14560
|
+
}
|
|
14561
|
+
}
|
|
14562
|
+
return unauthorized;
|
|
14563
|
+
}
|
|
14564
|
+
|
|
13294
14565
|
// src/version.ts
|
|
13295
14566
|
var ProtocolMismatchError = class extends Error {
|
|
13296
14567
|
constructor(sdkProtocol, nodeProtocol, nodeVersion, host) {
|
|
@@ -13355,8 +14626,10 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
|
|
|
13355
14626
|
|
|
13356
14627
|
// src/index.ts
|
|
13357
14628
|
import {
|
|
14629
|
+
ACCOUNT_MANIFEST_PERMISSIONS as ACCOUNT_MANIFEST_PERMISSIONS2,
|
|
13358
14630
|
ACCOUNT_INDEX_SCHEMA as ACCOUNT_INDEX_SCHEMA2,
|
|
13359
14631
|
BOOTSTRAP_ALLOWLIST,
|
|
14632
|
+
BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST,
|
|
13360
14633
|
BOOTSTRAP_DEFAULT_SPACE,
|
|
13361
14634
|
BOOTSTRAP_ENCRYPTION_NETWORK_NAME,
|
|
13362
14635
|
BOOTSTRAP_ENCRYPTION_NETWORK_RESOURCE_TEMPLATE,
|
|
@@ -13402,17 +14675,9 @@ function equals3(a, b) {
|
|
|
13402
14675
|
return true;
|
|
13403
14676
|
}
|
|
13404
14677
|
|
|
13405
|
-
// ../../node_modules/uint8arrays/dist/src/alloc.
|
|
13406
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
13407
|
-
|
|
13408
|
-
// ../../node_modules/uint8arrays/dist/src/util/as-uint8array.node.js
|
|
13409
|
-
function asUint8Array(buf) {
|
|
13410
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
13411
|
-
}
|
|
13412
|
-
|
|
13413
|
-
// ../../node_modules/uint8arrays/dist/src/alloc.node.js
|
|
14678
|
+
// ../../node_modules/uint8arrays/dist/src/alloc.js
|
|
13414
14679
|
function allocUnsafe(size = 0) {
|
|
13415
|
-
return
|
|
14680
|
+
return new Uint8Array(size);
|
|
13416
14681
|
}
|
|
13417
14682
|
|
|
13418
14683
|
// ../../node_modules/uint8-varint/dist/src/index.js
|
|
@@ -13588,14 +14853,24 @@ function decode6(buf, offset = 0) {
|
|
|
13588
14853
|
}
|
|
13589
14854
|
}
|
|
13590
14855
|
|
|
13591
|
-
// ../../node_modules/uint8arrays/dist/src/
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
return asUint8Array(Buffer3.concat(arrays, length2));
|
|
14856
|
+
// ../../node_modules/uint8arrays/dist/src/util/as-uint8array.js
|
|
14857
|
+
function asUint8Array(buf) {
|
|
14858
|
+
return buf;
|
|
13595
14859
|
}
|
|
13596
14860
|
|
|
13597
|
-
// ../../node_modules/uint8arrays/dist/src/
|
|
13598
|
-
|
|
14861
|
+
// ../../node_modules/uint8arrays/dist/src/concat.js
|
|
14862
|
+
function concat(arrays, length2) {
|
|
14863
|
+
if (length2 == null) {
|
|
14864
|
+
length2 = arrays.reduce((acc, curr) => acc + curr.length, 0);
|
|
14865
|
+
}
|
|
14866
|
+
const output = allocUnsafe(length2);
|
|
14867
|
+
let offset = 0;
|
|
14868
|
+
for (const arr of arrays) {
|
|
14869
|
+
output.set(arr, offset);
|
|
14870
|
+
offset += arr.length;
|
|
14871
|
+
}
|
|
14872
|
+
return asUint8Array(output);
|
|
14873
|
+
}
|
|
13599
14874
|
|
|
13600
14875
|
// ../../node_modules/uint8arrays/dist/src/util/bases.js
|
|
13601
14876
|
function createCodec(name2, prefix, encode5, decode7) {
|
|
@@ -13644,28 +14919,21 @@ var BASES = {
|
|
|
13644
14919
|
};
|
|
13645
14920
|
var bases_default = BASES;
|
|
13646
14921
|
|
|
13647
|
-
// ../../node_modules/uint8arrays/dist/src/from-string.
|
|
14922
|
+
// ../../node_modules/uint8arrays/dist/src/from-string.js
|
|
13648
14923
|
function fromString2(string2, encoding = "utf8") {
|
|
13649
14924
|
const base3 = bases_default[encoding];
|
|
13650
14925
|
if (base3 == null) {
|
|
13651
14926
|
throw new Error(`Unsupported encoding "${encoding}"`);
|
|
13652
14927
|
}
|
|
13653
|
-
if (encoding === "utf8" || encoding === "utf-8") {
|
|
13654
|
-
return asUint8Array(Buffer4.from(string2, "utf-8"));
|
|
13655
|
-
}
|
|
13656
14928
|
return base3.decoder.decode(`${base3.prefix}${string2}`);
|
|
13657
14929
|
}
|
|
13658
14930
|
|
|
13659
|
-
// ../../node_modules/uint8arrays/dist/src/to-string.
|
|
13660
|
-
import { Buffer as Buffer5 } from "buffer";
|
|
14931
|
+
// ../../node_modules/uint8arrays/dist/src/to-string.js
|
|
13661
14932
|
function toString2(array, encoding = "utf8") {
|
|
13662
14933
|
const base3 = bases_default[encoding];
|
|
13663
14934
|
if (base3 == null) {
|
|
13664
14935
|
throw new Error(`Unsupported encoding "${encoding}"`);
|
|
13665
14936
|
}
|
|
13666
|
-
if (encoding === "utf8" || encoding === "utf-8") {
|
|
13667
|
-
return Buffer5.from(array.buffer, array.byteOffset, array.byteLength).toString("utf8");
|
|
13668
|
-
}
|
|
13669
14937
|
return base3.encoder.encode(array).substring(1);
|
|
13670
14938
|
}
|
|
13671
14939
|
|
|
@@ -13699,8 +14967,218 @@ var UnknownProtocolError = class extends Error {
|
|
|
13699
14967
|
};
|
|
13700
14968
|
__publicField(UnknownProtocolError, "name", "UnknownProtocolError");
|
|
13701
14969
|
|
|
13702
|
-
// ../../node_modules/@chainsafe/is-ip/lib/
|
|
13703
|
-
|
|
14970
|
+
// ../../node_modules/@chainsafe/is-ip/lib/parser.js
|
|
14971
|
+
var Parser = class {
|
|
14972
|
+
constructor() {
|
|
14973
|
+
__publicField(this, "index", 0);
|
|
14974
|
+
__publicField(this, "input", "");
|
|
14975
|
+
}
|
|
14976
|
+
new(input) {
|
|
14977
|
+
this.index = 0;
|
|
14978
|
+
this.input = input;
|
|
14979
|
+
return this;
|
|
14980
|
+
}
|
|
14981
|
+
/** Run a parser, and restore the pre-parse state if it fails. */
|
|
14982
|
+
readAtomically(fn) {
|
|
14983
|
+
const index = this.index;
|
|
14984
|
+
const result = fn();
|
|
14985
|
+
if (result === void 0) {
|
|
14986
|
+
this.index = index;
|
|
14987
|
+
}
|
|
14988
|
+
return result;
|
|
14989
|
+
}
|
|
14990
|
+
/** Run a parser, but fail if the entire input wasn't consumed. Doesn't run atomically. */
|
|
14991
|
+
parseWith(fn) {
|
|
14992
|
+
const result = fn();
|
|
14993
|
+
if (this.index !== this.input.length) {
|
|
14994
|
+
return void 0;
|
|
14995
|
+
}
|
|
14996
|
+
return result;
|
|
14997
|
+
}
|
|
14998
|
+
/** Peek the next character from the input */
|
|
14999
|
+
peekChar() {
|
|
15000
|
+
if (this.index >= this.input.length) {
|
|
15001
|
+
return void 0;
|
|
15002
|
+
}
|
|
15003
|
+
return this.input[this.index];
|
|
15004
|
+
}
|
|
15005
|
+
/** Read the next character from the input */
|
|
15006
|
+
readChar() {
|
|
15007
|
+
if (this.index >= this.input.length) {
|
|
15008
|
+
return void 0;
|
|
15009
|
+
}
|
|
15010
|
+
return this.input[this.index++];
|
|
15011
|
+
}
|
|
15012
|
+
/** Read the next character from the input if it matches the target. */
|
|
15013
|
+
readGivenChar(target) {
|
|
15014
|
+
return this.readAtomically(() => {
|
|
15015
|
+
const char = this.readChar();
|
|
15016
|
+
if (char !== target) {
|
|
15017
|
+
return void 0;
|
|
15018
|
+
}
|
|
15019
|
+
return char;
|
|
15020
|
+
});
|
|
15021
|
+
}
|
|
15022
|
+
/**
|
|
15023
|
+
* Helper for reading separators in an indexed loop. Reads the separator
|
|
15024
|
+
* character iff index > 0, then runs the parser. When used in a loop,
|
|
15025
|
+
* the separator character will only be read on index > 0 (see
|
|
15026
|
+
* readIPv4Addr for an example)
|
|
15027
|
+
*/
|
|
15028
|
+
readSeparator(sep, index, inner) {
|
|
15029
|
+
return this.readAtomically(() => {
|
|
15030
|
+
if (index > 0) {
|
|
15031
|
+
if (this.readGivenChar(sep) === void 0) {
|
|
15032
|
+
return void 0;
|
|
15033
|
+
}
|
|
15034
|
+
}
|
|
15035
|
+
return inner();
|
|
15036
|
+
});
|
|
15037
|
+
}
|
|
15038
|
+
/**
|
|
15039
|
+
* Read a number off the front of the input in the given radix, stopping
|
|
15040
|
+
* at the first non-digit character or eof. Fails if the number has more
|
|
15041
|
+
* digits than max_digits or if there is no number.
|
|
15042
|
+
*/
|
|
15043
|
+
readNumber(radix, maxDigits, allowZeroPrefix, maxBytes) {
|
|
15044
|
+
return this.readAtomically(() => {
|
|
15045
|
+
let result = 0;
|
|
15046
|
+
let digitCount = 0;
|
|
15047
|
+
const leadingChar = this.peekChar();
|
|
15048
|
+
if (leadingChar === void 0) {
|
|
15049
|
+
return void 0;
|
|
15050
|
+
}
|
|
15051
|
+
const hasLeadingZero = leadingChar === "0";
|
|
15052
|
+
const maxValue2 = 2 ** (8 * maxBytes) - 1;
|
|
15053
|
+
while (true) {
|
|
15054
|
+
const digit = this.readAtomically(() => {
|
|
15055
|
+
const char = this.readChar();
|
|
15056
|
+
if (char === void 0) {
|
|
15057
|
+
return void 0;
|
|
15058
|
+
}
|
|
15059
|
+
const num = Number.parseInt(char, radix);
|
|
15060
|
+
if (Number.isNaN(num)) {
|
|
15061
|
+
return void 0;
|
|
15062
|
+
}
|
|
15063
|
+
return num;
|
|
15064
|
+
});
|
|
15065
|
+
if (digit === void 0) {
|
|
15066
|
+
break;
|
|
15067
|
+
}
|
|
15068
|
+
result *= radix;
|
|
15069
|
+
result += digit;
|
|
15070
|
+
if (result > maxValue2) {
|
|
15071
|
+
return void 0;
|
|
15072
|
+
}
|
|
15073
|
+
digitCount += 1;
|
|
15074
|
+
if (maxDigits !== void 0) {
|
|
15075
|
+
if (digitCount > maxDigits) {
|
|
15076
|
+
return void 0;
|
|
15077
|
+
}
|
|
15078
|
+
}
|
|
15079
|
+
}
|
|
15080
|
+
if (digitCount === 0) {
|
|
15081
|
+
return void 0;
|
|
15082
|
+
} else if (!allowZeroPrefix && hasLeadingZero && digitCount > 1) {
|
|
15083
|
+
return void 0;
|
|
15084
|
+
} else {
|
|
15085
|
+
return result;
|
|
15086
|
+
}
|
|
15087
|
+
});
|
|
15088
|
+
}
|
|
15089
|
+
/** Read an IPv4 address. */
|
|
15090
|
+
readIPv4Addr() {
|
|
15091
|
+
return this.readAtomically(() => {
|
|
15092
|
+
const out = new Uint8Array(4);
|
|
15093
|
+
for (let i = 0; i < out.length; i++) {
|
|
15094
|
+
const ix = this.readSeparator(".", i, () => this.readNumber(10, 3, false, 1));
|
|
15095
|
+
if (ix === void 0) {
|
|
15096
|
+
return void 0;
|
|
15097
|
+
}
|
|
15098
|
+
out[i] = ix;
|
|
15099
|
+
}
|
|
15100
|
+
return out;
|
|
15101
|
+
});
|
|
15102
|
+
}
|
|
15103
|
+
/** Read an IPv6 Address. */
|
|
15104
|
+
readIPv6Addr() {
|
|
15105
|
+
const readGroups = (groups) => {
|
|
15106
|
+
for (let i = 0; i < groups.length / 2; i++) {
|
|
15107
|
+
const ix = i * 2;
|
|
15108
|
+
if (i < groups.length - 3) {
|
|
15109
|
+
const ipv4 = this.readSeparator(":", i, () => this.readIPv4Addr());
|
|
15110
|
+
if (ipv4 !== void 0) {
|
|
15111
|
+
groups[ix] = ipv4[0];
|
|
15112
|
+
groups[ix + 1] = ipv4[1];
|
|
15113
|
+
groups[ix + 2] = ipv4[2];
|
|
15114
|
+
groups[ix + 3] = ipv4[3];
|
|
15115
|
+
return [ix + 4, true];
|
|
15116
|
+
}
|
|
15117
|
+
}
|
|
15118
|
+
const group = this.readSeparator(":", i, () => this.readNumber(16, 4, true, 2));
|
|
15119
|
+
if (group === void 0) {
|
|
15120
|
+
return [ix, false];
|
|
15121
|
+
}
|
|
15122
|
+
groups[ix] = group >> 8;
|
|
15123
|
+
groups[ix + 1] = group & 255;
|
|
15124
|
+
}
|
|
15125
|
+
return [groups.length, false];
|
|
15126
|
+
};
|
|
15127
|
+
return this.readAtomically(() => {
|
|
15128
|
+
const head = new Uint8Array(16);
|
|
15129
|
+
const [headSize, headIp4] = readGroups(head);
|
|
15130
|
+
if (headSize === 16) {
|
|
15131
|
+
return head;
|
|
15132
|
+
}
|
|
15133
|
+
if (headIp4) {
|
|
15134
|
+
return void 0;
|
|
15135
|
+
}
|
|
15136
|
+
if (this.readGivenChar(":") === void 0) {
|
|
15137
|
+
return void 0;
|
|
15138
|
+
}
|
|
15139
|
+
if (this.readGivenChar(":") === void 0) {
|
|
15140
|
+
return void 0;
|
|
15141
|
+
}
|
|
15142
|
+
const tail = new Uint8Array(14);
|
|
15143
|
+
const limit = 16 - (headSize + 2);
|
|
15144
|
+
const [tailSize] = readGroups(tail.subarray(0, limit));
|
|
15145
|
+
head.set(tail.subarray(0, tailSize), 16 - tailSize);
|
|
15146
|
+
return head;
|
|
15147
|
+
});
|
|
15148
|
+
}
|
|
15149
|
+
/** Read an IP Address, either IPv4 or IPv6. */
|
|
15150
|
+
readIPAddr() {
|
|
15151
|
+
return this.readIPv4Addr() ?? this.readIPv6Addr();
|
|
15152
|
+
}
|
|
15153
|
+
};
|
|
15154
|
+
|
|
15155
|
+
// ../../node_modules/@chainsafe/is-ip/lib/parse.js
|
|
15156
|
+
var MAX_IPV6_LENGTH = 45;
|
|
15157
|
+
var MAX_IPV4_LENGTH = 15;
|
|
15158
|
+
var parser = new Parser();
|
|
15159
|
+
function parseIPv4(input) {
|
|
15160
|
+
if (input.length > MAX_IPV4_LENGTH) {
|
|
15161
|
+
return void 0;
|
|
15162
|
+
}
|
|
15163
|
+
return parser.new(input).parseWith(() => parser.readIPv4Addr());
|
|
15164
|
+
}
|
|
15165
|
+
function parseIPv6(input) {
|
|
15166
|
+
if (input.includes("%")) {
|
|
15167
|
+
input = input.split("%")[0];
|
|
15168
|
+
}
|
|
15169
|
+
if (input.length > MAX_IPV6_LENGTH) {
|
|
15170
|
+
return void 0;
|
|
15171
|
+
}
|
|
15172
|
+
return parser.new(input).parseWith(() => parser.readIPv6Addr());
|
|
15173
|
+
}
|
|
15174
|
+
|
|
15175
|
+
// ../../node_modules/@chainsafe/is-ip/lib/is-ip.js
|
|
15176
|
+
function isIPv4(input) {
|
|
15177
|
+
return Boolean(parseIPv4(input));
|
|
15178
|
+
}
|
|
15179
|
+
function isIPv6(input) {
|
|
15180
|
+
return Boolean(parseIPv6(input));
|
|
15181
|
+
}
|
|
13704
15182
|
|
|
13705
15183
|
// ../../node_modules/@multiformats/multiaddr/dist/src/constants.js
|
|
13706
15184
|
var CODE_IP4 = 4;
|
|
@@ -14657,25 +16135,17 @@ ipRegex.v4 = (options2) => options2 && options2.exact ? v4exact : new RegExp(`${
|
|
|
14657
16135
|
ipRegex.v6 = (options2) => options2 && options2.exact ? v6exact : new RegExp(`${boundry(options2)}${v6}${boundry(options2)}`, "g");
|
|
14658
16136
|
var ip_regex_default = ipRegex;
|
|
14659
16137
|
|
|
14660
|
-
// ../../node_modules/function-timeout/
|
|
14661
|
-
|
|
14662
|
-
|
|
14663
|
-
const script = new vm.Script("returnValue = function_()");
|
|
14664
|
-
const wrappedFunction = (...arguments_) => {
|
|
14665
|
-
const context = {
|
|
14666
|
-
function_: () => function_(...arguments_)
|
|
14667
|
-
};
|
|
14668
|
-
script.runInNewContext(context, { timeout });
|
|
14669
|
-
return context.returnValue;
|
|
14670
|
-
};
|
|
16138
|
+
// ../../node_modules/function-timeout/browser.js
|
|
16139
|
+
function functionTimeout(function_) {
|
|
16140
|
+
const wrappedFunction = (...arguments_) => function_(...arguments_);
|
|
14671
16141
|
Object.defineProperty(wrappedFunction, "name", {
|
|
14672
16142
|
value: `functionTimeout(${function_.name || "<anonymous>"})`,
|
|
14673
16143
|
configurable: true
|
|
14674
16144
|
});
|
|
14675
16145
|
return wrappedFunction;
|
|
14676
16146
|
}
|
|
14677
|
-
function isTimeoutError(
|
|
14678
|
-
return
|
|
16147
|
+
function isTimeoutError() {
|
|
16148
|
+
return false;
|
|
14679
16149
|
}
|
|
14680
16150
|
|
|
14681
16151
|
// ../../node_modules/clone-regexp/node_modules/is-regexp/index.js
|
|
@@ -14838,7 +16308,7 @@ function portForProtocol(protocol) {
|
|
|
14838
16308
|
}
|
|
14839
16309
|
|
|
14840
16310
|
// src/location.ts
|
|
14841
|
-
import { ed25519 as
|
|
16311
|
+
import { ed25519 as ed255198 } from "@noble/curves/ed25519";
|
|
14842
16312
|
import { verifyMessage as verifyMessage2 } from "viem";
|
|
14843
16313
|
var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
14844
16314
|
var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
@@ -15077,13 +16547,14 @@ async function discoverLocalTinyCloudNode(options2 = {}) {
|
|
|
15077
16547
|
}
|
|
15078
16548
|
const fetchFn = options2.fetch ?? globalThis.fetch;
|
|
15079
16549
|
const identityStore = options2.identityStore ?? defaultLocalNodeIdentityStore;
|
|
15080
|
-
const staticCandidates = [
|
|
15081
|
-
|
|
16550
|
+
const staticCandidates = [];
|
|
16551
|
+
if (options2.localNodeUrl) {
|
|
16552
|
+
staticCandidates.push({
|
|
15082
16553
|
source: "local-loopback",
|
|
15083
|
-
url: options2.localNodeUrl
|
|
16554
|
+
url: options2.localNodeUrl,
|
|
15084
16555
|
timeoutMs: LOCAL_LOOPBACK_PROBE_TIMEOUT_MS
|
|
15085
|
-
}
|
|
15086
|
-
|
|
16556
|
+
});
|
|
16557
|
+
}
|
|
15087
16558
|
if (options2.localLinkName) {
|
|
15088
16559
|
if (isValidDnsLabel(options2.localLinkName)) {
|
|
15089
16560
|
staticCandidates.push({
|
|
@@ -15403,13 +16874,13 @@ async function verifyPkhSignature(did, payload, signature) {
|
|
|
15403
16874
|
}
|
|
15404
16875
|
function verifyDidKeySignature(did, payload, signature) {
|
|
15405
16876
|
const publicKey = ed25519PublicKeyFromDidKey2(did);
|
|
15406
|
-
const signatureBytes =
|
|
16877
|
+
const signatureBytes = decodeBase64Url2(signature);
|
|
15407
16878
|
if (signatureBytes.length !== 64) {
|
|
15408
16879
|
throw new LocationRecordValidationError(
|
|
15409
16880
|
"did:key signature must be a base64url Ed25519 signature"
|
|
15410
16881
|
);
|
|
15411
16882
|
}
|
|
15412
|
-
return
|
|
16883
|
+
return ed255198.verify(
|
|
15413
16884
|
signatureBytes,
|
|
15414
16885
|
new TextEncoder().encode(payload),
|
|
15415
16886
|
publicKey
|
|
@@ -15417,7 +16888,7 @@ function verifyDidKeySignature(did, payload, signature) {
|
|
|
15417
16888
|
}
|
|
15418
16889
|
function verifyDidKeyEd25519Signature(did, payload, signature) {
|
|
15419
16890
|
const publicKey = ed25519PublicKeyFromDidKey2(did);
|
|
15420
|
-
return
|
|
16891
|
+
return ed255198.verify(signature, payload, publicKey);
|
|
15421
16892
|
}
|
|
15422
16893
|
function ed25519PublicKeyFromDidKey2(did) {
|
|
15423
16894
|
const identifier = did.slice("did:key:".length);
|
|
@@ -15456,7 +16927,7 @@ function base64UrlEncode3(bytes2) {
|
|
|
15456
16927
|
}
|
|
15457
16928
|
return output;
|
|
15458
16929
|
}
|
|
15459
|
-
function
|
|
16930
|
+
function decodeBase64Url2(value) {
|
|
15460
16931
|
const alphabet2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
15461
16932
|
const bytes2 = [];
|
|
15462
16933
|
let buffer = 0;
|
|
@@ -15479,11 +16950,14 @@ function decodeBase64Url(value) {
|
|
|
15479
16950
|
}
|
|
15480
16951
|
export {
|
|
15481
16952
|
ACCOUNT_INDEX_SCHEMA2 as ACCOUNT_INDEX_SCHEMA,
|
|
16953
|
+
ACCOUNT_MANIFEST_PERMISSIONS2 as ACCOUNT_MANIFEST_PERMISSIONS,
|
|
15482
16954
|
ACCOUNT_REGISTRY_PATH,
|
|
15483
16955
|
ACCOUNT_REGISTRY_SPACE,
|
|
16956
|
+
ATTESTED_ENFORCER_BINDING_V2_SCHEMA,
|
|
15484
16957
|
AccountService,
|
|
15485
16958
|
AutoApproveSpaceCreationHandler,
|
|
15486
16959
|
BOOTSTRAP_ALLOWLIST,
|
|
16960
|
+
BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST,
|
|
15487
16961
|
BOOTSTRAP_DEFAULT_SPACE,
|
|
15488
16962
|
BOOTSTRAP_ENCRYPTION_NETWORK_NAME,
|
|
15489
16963
|
BOOTSTRAP_ENCRYPTION_NETWORK_RESOURCE_TEMPLATE,
|
|
@@ -15495,6 +16969,7 @@ export {
|
|
|
15495
16969
|
BOOTSTRAP_SPACE_NAMES,
|
|
15496
16970
|
CAPABILITIES,
|
|
15497
16971
|
CAPABILITY_REGISTRY2 as CAPABILITY_REGISTRY,
|
|
16972
|
+
CONTENT_SOURCE_V1_DOMAIN,
|
|
15498
16973
|
CapabilityKeyRegistry,
|
|
15499
16974
|
CapabilityKeyRegistryErrorCodes,
|
|
15500
16975
|
CaveatedDelegationUnsupportedError,
|
|
@@ -15536,19 +17011,22 @@ export {
|
|
|
15536
17011
|
EXPIRY,
|
|
15537
17012
|
EncryptionService,
|
|
15538
17013
|
EnsDataSchema,
|
|
15539
|
-
|
|
17014
|
+
ErrorCodes4 as ErrorCodes,
|
|
15540
17015
|
HOLDER_KEY_BINDING_PRESENTATION_SCHEMA,
|
|
15541
17016
|
HOOKS,
|
|
15542
17017
|
HooksService2 as HooksService,
|
|
15543
17018
|
IdentityParseError,
|
|
15544
17019
|
KV,
|
|
15545
17020
|
KVService3 as KVService,
|
|
17021
|
+
LAST_V2_CREATE_AT,
|
|
17022
|
+
LAST_V2_READ_AT,
|
|
15546
17023
|
LISTEN_SQL_STATEMENT_CATALOG,
|
|
15547
17024
|
LOCAL_LINK_HOST_SUFFIX,
|
|
15548
17025
|
LOCAL_LINK_PROBE_TIMEOUT_MS,
|
|
15549
17026
|
LOCAL_LOOPBACK_PROBE_TIMEOUT_MS,
|
|
15550
17027
|
LocationRecordValidationError,
|
|
15551
17028
|
MAX_CONTENT_BYTES,
|
|
17029
|
+
MAX_LEGACY_ENVELOPE_EXPIRES_AT,
|
|
15552
17030
|
MAX_SEALED_SHARE_CONTENT_BYTES,
|
|
15553
17031
|
MAX_SHARE_ARTIFACT_BYTES,
|
|
15554
17032
|
MAX_SHARE_CONTENT_BYTES,
|
|
@@ -15556,8 +17034,13 @@ export {
|
|
|
15556
17034
|
MemorySenderShareKeyStorage,
|
|
15557
17035
|
MemorySenderShareRecordStorage,
|
|
15558
17036
|
MemoryShareCache,
|
|
17037
|
+
NATIVE_PROJECTION_V1_DOMAIN,
|
|
15559
17038
|
NETWORK_NAME_PATTERN,
|
|
15560
17039
|
NetworkIdError,
|
|
17040
|
+
OPENKEY_ACTION_ID_SEPARATOR,
|
|
17041
|
+
POLICY_CAPABILITY_V1_DOMAIN,
|
|
17042
|
+
POLICY_CAPABILITY_V1_SCHEMA,
|
|
17043
|
+
POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA,
|
|
15561
17044
|
POLICY_ENGINE_CHALLENGE_REQUEST_SCHEMA,
|
|
15562
17045
|
POLICY_ENGINE_CHALLENGE_RESPONSE_SCHEMA,
|
|
15563
17046
|
POLICY_ENGINE_DENIAL_SCHEMA,
|
|
@@ -15565,7 +17048,10 @@ export {
|
|
|
15565
17048
|
POLICY_ENGINE_RECORD_SCHEMA,
|
|
15566
17049
|
POLICY_ENGINE_RESOLVE_REQUEST_SCHEMA,
|
|
15567
17050
|
POLICY_SCHEMA,
|
|
17051
|
+
POLICY_SESSION_UCAN_V1_PROFILE,
|
|
15568
17052
|
POLICY_STATUS_SCHEMA,
|
|
17053
|
+
POLICY_V1_DOMAIN,
|
|
17054
|
+
POLICY_V1_SCHEMA,
|
|
15569
17055
|
PORTABLE_DELEGATION_SCHEMA,
|
|
15570
17056
|
PermissionNotInManifestError,
|
|
15571
17057
|
PrefixedKVService,
|
|
@@ -15573,6 +17059,11 @@ export {
|
|
|
15573
17059
|
REQUESTER_ENGINE_RETRY_ATTEMPTS,
|
|
15574
17060
|
REQUESTER_ENGINE_RETRY_MAX_DELAY_MS,
|
|
15575
17061
|
REQUESTER_NEAR_EXPIRY_SECONDS,
|
|
17062
|
+
ROOT_REVOCATION_V1_DOMAIN,
|
|
17063
|
+
ROOT_REVOCATION_V1_SCHEMA,
|
|
17064
|
+
ROOT_STATUS_CHECKPOINT_V1_SCHEMA,
|
|
17065
|
+
ROOT_STATUS_RENEWAL_V1_DOMAIN,
|
|
17066
|
+
ROOT_STATUS_V1_DOMAIN,
|
|
15576
17067
|
SECRETS_SPACE,
|
|
15577
17068
|
SECRET_NAME_RE2 as SECRET_NAME_RE,
|
|
15578
17069
|
SECRET_RECORDS_SCHEMA,
|
|
@@ -15650,13 +17141,16 @@ export {
|
|
|
15650
17141
|
canonicalizeRecapCaveats,
|
|
15651
17142
|
canonicalizeSecretScope,
|
|
15652
17143
|
canonicalizeSignedObjectUnsigned,
|
|
17144
|
+
canonicalizeUnifiedPolicyCapability,
|
|
15653
17145
|
checkDecryptInvocationInput,
|
|
15654
17146
|
checkNodeInfo,
|
|
15655
17147
|
clearTinyCloudDebugLogs,
|
|
17148
|
+
compactAttenuationContains,
|
|
15656
17149
|
composeBootstrapSpaceManifest,
|
|
15657
17150
|
composeManifestRequest,
|
|
15658
17151
|
computeOwnerShareRegistrationCid,
|
|
15659
17152
|
computeShareCid,
|
|
17153
|
+
contentSourceDigestHex,
|
|
15660
17154
|
createAndSignPolicy,
|
|
15661
17155
|
createAndSignPolicyEngineRecord,
|
|
15662
17156
|
createAndSignPolicyStatus,
|
|
@@ -15679,11 +17173,13 @@ export {
|
|
|
15679
17173
|
defaultRetryPolicy2 as defaultRetryPolicy,
|
|
15680
17174
|
defaultSignStrategy,
|
|
15681
17175
|
defaultSpaceCreationHandler,
|
|
17176
|
+
delegatePortablePolicySession,
|
|
15682
17177
|
deriveDelegationCid,
|
|
15683
17178
|
deriveSignedObjectMaterial,
|
|
15684
17179
|
deriveSignedReceiverKey,
|
|
15685
17180
|
didCacheKey,
|
|
15686
17181
|
didEquals,
|
|
17182
|
+
diffImmutableSiweFields,
|
|
15687
17183
|
disableTinyCloudDebug,
|
|
15688
17184
|
discoverLocalTinyCloudNode,
|
|
15689
17185
|
discoverNetwork,
|
|
@@ -15704,18 +17200,23 @@ export {
|
|
|
15704
17200
|
expandActionShortNames,
|
|
15705
17201
|
expandPermissionEntries,
|
|
15706
17202
|
expandPermissionEntry,
|
|
17203
|
+
extractImmutableSiweFields,
|
|
17204
|
+
extractRecapAttenuations,
|
|
15707
17205
|
fetchLocationRecord,
|
|
15708
17206
|
fetchPeerId,
|
|
15709
17207
|
generateRandomReceiverKey,
|
|
17208
|
+
getPolicyRootStatusV3,
|
|
15710
17209
|
getTinyCloudDebugLogs,
|
|
15711
17210
|
hexDecode,
|
|
15712
17211
|
hexEncode,
|
|
15713
17212
|
httpUrlToMultiaddr,
|
|
17213
|
+
importPortableDelegation,
|
|
15714
17214
|
installTinyCloudDebugGlobals,
|
|
15715
17215
|
intersectShareCapabilities,
|
|
15716
17216
|
isCapabilitySubset,
|
|
15717
17217
|
isEvmAddress,
|
|
15718
17218
|
isNetworkId,
|
|
17219
|
+
isPlausibleOpenKeyActionId,
|
|
15719
17220
|
isV2ShareLink,
|
|
15720
17221
|
jcsCanonicalize,
|
|
15721
17222
|
loadManifest,
|
|
@@ -15730,21 +17231,32 @@ export {
|
|
|
15730
17231
|
normalizeShareActions,
|
|
15731
17232
|
normalizeShareRecipientTarget,
|
|
15732
17233
|
normalizeShareResource,
|
|
17234
|
+
normalizeUnifiedPolicyCapability,
|
|
15733
17235
|
ok5 as ok,
|
|
15734
17236
|
openWrappedKey,
|
|
15735
17237
|
parseCanonicalNetworkId,
|
|
17238
|
+
parseCanonicalRecapResource,
|
|
17239
|
+
parseCompactUcanAuthorization,
|
|
15736
17240
|
parseExpiry,
|
|
15737
17241
|
parseNetworkId2 as parseNetworkId,
|
|
15738
17242
|
parseNodeNativePortableDelegation,
|
|
15739
17243
|
parsePkhDid,
|
|
17244
|
+
parsePolicySessionUcan,
|
|
17245
|
+
parsePortableDelegation,
|
|
15740
17246
|
parseRecapCapabilities,
|
|
15741
17247
|
parseShareArtifact,
|
|
15742
17248
|
parseShareUrl,
|
|
15743
17249
|
parseSpaceUri,
|
|
15744
17250
|
pkhDid,
|
|
17251
|
+
policyCidFromCanonicalBytes,
|
|
17252
|
+
policyDigestHex,
|
|
17253
|
+
policyIdForDigestHex,
|
|
15745
17254
|
principalDid,
|
|
15746
17255
|
principalDidEquals,
|
|
17256
|
+
projectUnifiedPolicyCapabilities,
|
|
17257
|
+
projectUnifiedPolicyCapability,
|
|
15747
17258
|
recapCaveatsEqual,
|
|
17259
|
+
renewPolicyRootStatusV3,
|
|
15748
17260
|
resolveCloudLocation,
|
|
15749
17261
|
resolveManifest,
|
|
15750
17262
|
resolveManifestKnowledgeRoot,
|
|
@@ -15754,16 +17266,25 @@ export {
|
|
|
15754
17266
|
resourceCapabilitiesToAbilitiesMap,
|
|
15755
17267
|
resourceCapabilitiesToSpaceAbilitiesMap,
|
|
15756
17268
|
restoreDelegatedShareKey,
|
|
17269
|
+
revokePolicyRootV3,
|
|
15757
17270
|
serialize as serializeJcsJson,
|
|
17271
|
+
serializePortableDelegation,
|
|
15758
17272
|
serviceError5 as serviceError,
|
|
15759
17273
|
shareCapabilityAllows,
|
|
15760
17274
|
shareDeliveryTrustedKid,
|
|
17275
|
+
signCompactUcanAuthorization,
|
|
15761
17276
|
signLocationRecord,
|
|
15762
17277
|
signShareEnvelope,
|
|
15763
17278
|
signedObjectIdFor,
|
|
15764
17279
|
submitHostDelegation,
|
|
15765
17280
|
tinyCloudDebugLogger,
|
|
15766
17281
|
toSignedObjectError,
|
|
17282
|
+
unauthorizedRecapCapabilities,
|
|
17283
|
+
unifiedNativeProjectionHashHex,
|
|
17284
|
+
unifiedPolicyCapabilityContains,
|
|
17285
|
+
unifiedPolicyCapabilityDigestHex,
|
|
17286
|
+
unifiedPolicyCapabilityFromNative,
|
|
17287
|
+
validateAuthorizationResultV1,
|
|
15767
17288
|
validateClientSession,
|
|
15768
17289
|
validateEnvelope,
|
|
15769
17290
|
validateLocationRecord,
|
|
@@ -15787,6 +17308,8 @@ export {
|
|
|
15787
17308
|
verifyLocationRecord,
|
|
15788
17309
|
verifyPolicy,
|
|
15789
17310
|
verifyPolicyEngineRecord,
|
|
17311
|
+
verifyPolicyRootRevocationV3,
|
|
17312
|
+
verifyPolicyRootStatusCheckpointV3,
|
|
15790
17313
|
verifyPolicyStatus,
|
|
15791
17314
|
verifyShareCid,
|
|
15792
17315
|
verifyShareEnvelope,
|