@tinycloud/sdk-core 2.11.0 → 3.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{unified-BlXXf3l7.d.cts → credential-admission-C_cO1QqB.d.cts} +353 -1
- package/dist/{unified-HWqC-h7O.d.ts → credential-admission-cvHe-HUC.d.ts} +353 -1
- package/dist/delegations/index.cjs +10 -10
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +2 -2
- package/dist/delegations/index.d.ts +2 -2
- package/dist/delegations/index.js +10 -10
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +534 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -242
- package/dist/index.d.ts +6 -242
- package/dist/index.js +536 -169
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +420 -14
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.d.cts +2 -2
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +420 -14
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-CieclU3Z.d.cts → recipient-types.schema-G8NEKRoo.d.cts} +8 -8
- package/dist/{recipient-types.schema-CieclU3Z.d.ts → recipient-types.schema-G8NEKRoo.d.ts} +8 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -315,6 +315,7 @@ var CREDENTIAL_ERROR_CODES = [
|
|
|
315
315
|
"REQUEST_SUBSTITUTED",
|
|
316
316
|
"SIGNATURE_REJECTED",
|
|
317
317
|
"UNSUPPORTED_PROFILE",
|
|
318
|
+
"UNSUPPORTED_VERSION",
|
|
318
319
|
"VERIFICATION_FAILED",
|
|
319
320
|
"VERIFIED_NOT_SAVED"
|
|
320
321
|
];
|
|
@@ -326,6 +327,7 @@ var RECOVERABLE = /* @__PURE__ */ new Set([
|
|
|
326
327
|
"REQUEST_EXPIRED",
|
|
327
328
|
"SIGNATURE_REJECTED",
|
|
328
329
|
"UNSUPPORTED_PROFILE",
|
|
330
|
+
"UNSUPPORTED_VERSION",
|
|
329
331
|
"VERIFIED_NOT_SAVED"
|
|
330
332
|
]);
|
|
331
333
|
var CredentialError = class extends Error {
|
|
@@ -613,11 +615,11 @@ async function createStoredCredentialRecord(input) {
|
|
|
613
615
|
const recordId = await canonicalDigest({ credentialDigest: input.verified.credentialDigest, holderDid: input.ownerDid });
|
|
614
616
|
return Object.freeze({ type: "TinyCloudStoredCredential", version: 1, ownerDid: input.ownerDid, recordId, requirementDigest: input.requirementDigest, descriptorDigest: input.verified.descriptorDigest, profile: input.verified.profile, credentialType: input.verified.credentialType, issuerDid: input.verified.issuerDid, issuerKid: input.verified.issuerKid, holderDid: input.verified.holderDid, claims: input.verified.claims, claimsDigest: input.verified.claimsDigest, credentialDigest: input.verified.credentialDigest, credential: input.verified.credential, schema: input.verified.schema, credentialId: input.verified.credentialId, issuedAt: input.verified.issuedAt, notBefore: input.verified.notBefore, expiresAt: input.verified.expiresAt, status: input.verified.status, verifiedAt: input.verified.verifiedAt, storedAt });
|
|
615
617
|
}
|
|
616
|
-
async function createStorageReceipt(
|
|
617
|
-
return Object.freeze({ type: "TinyCloudCredentialStorageReceipt", version: 1, ownerDid:
|
|
618
|
+
async function createStorageReceipt(record2, etag) {
|
|
619
|
+
return Object.freeze({ type: "TinyCloudCredentialStorageReceipt", version: 1, ownerDid: record2.ownerDid, recordId: record2.recordId, recordDigest: await canonicalDigest(record2), storedAt: record2.storedAt, ...etag === void 0 ? {} : { etag } });
|
|
618
620
|
}
|
|
619
|
-
async function verifyStorageReceipt(
|
|
620
|
-
return receipt.type === "TinyCloudCredentialStorageReceipt" && receipt.version === 1 && receipt.ownerDid === activeOwnerDid &&
|
|
621
|
+
async function verifyStorageReceipt(record2, receipt, activeOwnerDid, activeHolderDid) {
|
|
622
|
+
return receipt.type === "TinyCloudCredentialStorageReceipt" && receipt.version === 1 && receipt.ownerDid === activeOwnerDid && record2.ownerDid === activeOwnerDid && record2.holderDid === activeHolderDid && receipt.recordId === record2.recordId && receipt.storedAt === record2.storedAt && receipt.recordDigest === await canonicalDigest(record2);
|
|
621
623
|
}
|
|
622
624
|
|
|
623
625
|
// src/credentials/verification.ts
|
|
@@ -806,7 +808,7 @@ function makePkhSpaceId(address, chainId, name2) {
|
|
|
806
808
|
}
|
|
807
809
|
|
|
808
810
|
// src/requester/index.ts
|
|
809
|
-
import { bytesToHex as bytesToHex3, sha256 as
|
|
811
|
+
import { bytesToHex as bytesToHex3, sha256 as sha2566 } from "viem";
|
|
810
812
|
import { blake3 as blake32 } from "@noble/hashes/blake3";
|
|
811
813
|
|
|
812
814
|
// ../../node_modules/multiformats/dist/src/bases/base32.js
|
|
@@ -3176,13 +3178,13 @@ function base64UrlDecode(value) {
|
|
|
3176
3178
|
return decoded;
|
|
3177
3179
|
}
|
|
3178
3180
|
function hexToBytes(value) {
|
|
3179
|
-
const
|
|
3180
|
-
if (
|
|
3181
|
+
const hex3 = value.slice(2);
|
|
3182
|
+
if (hex3.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex3)) {
|
|
3181
3183
|
throw new SignatureMaterialError("hex signature must have even length");
|
|
3182
3184
|
}
|
|
3183
|
-
const output = new Uint8Array(
|
|
3185
|
+
const output = new Uint8Array(hex3.length / 2);
|
|
3184
3186
|
for (let index = 0; index < output.length; index++) {
|
|
3185
|
-
output[index] = Number.parseInt(
|
|
3187
|
+
output[index] = Number.parseInt(hex3.slice(index * 2, index * 2 + 2), 16);
|
|
3186
3188
|
}
|
|
3187
3189
|
return output;
|
|
3188
3190
|
}
|
|
@@ -3422,6 +3424,34 @@ var ROOT_REVOCATION_V1_DOMAIN = "xyz.tinycloud.policy/RootRevocation/v1\0";
|
|
|
3422
3424
|
var LAST_V2_CREATE_AT = "2026-09-30T00:00:00Z";
|
|
3423
3425
|
var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
|
|
3424
3426
|
var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
|
|
3427
|
+
async function requestPolicyChallengeV3(input) {
|
|
3428
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3429
|
+
const response = await fetchFn(new URL("/share/v3/policy/challenges", input.nodeOrigin), {
|
|
3430
|
+
method: "POST",
|
|
3431
|
+
redirect: "error",
|
|
3432
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3433
|
+
body: JSON.stringify({ policyCid: input.policyCid, recipientDid: input.recipientDid, requestedCapabilities: input.requestedCapabilities.map(normalizeUnifiedPolicyCapability) })
|
|
3434
|
+
});
|
|
3435
|
+
if (!response.ok) throw new Error(`policy challenge rejected (${response.status})`);
|
|
3436
|
+
const value = object2(await response.json(), "policy challenge");
|
|
3437
|
+
if (typeof value.challengeId !== "string" || typeof value.nonce !== "string" || value.policyCid !== input.policyCid || value.recipientDid !== input.recipientDid)
|
|
3438
|
+
throw new Error("policy challenge binding is invalid");
|
|
3439
|
+
return value;
|
|
3440
|
+
}
|
|
3441
|
+
function compactAttenuationForPolicyCapabilities(input) {
|
|
3442
|
+
const attenuation = {};
|
|
3443
|
+
for (const raw of input) {
|
|
3444
|
+
const capability = normalizeUnifiedPolicyCapability(raw);
|
|
3445
|
+
if (attenuation[capability.resource] !== void 0)
|
|
3446
|
+
throw new Error("policy capabilities contain a duplicate resource");
|
|
3447
|
+
attenuation[capability.resource] = capability.kind === "encryption" ? { [capability.action]: [{}] } : Object.fromEntries(capability.actions.map((action) => [action, [{
|
|
3448
|
+
type: "xyz.tinycloud.resource/selector",
|
|
3449
|
+
kind: capability.selector,
|
|
3450
|
+
value: capability.resource
|
|
3451
|
+
}]]));
|
|
3452
|
+
}
|
|
3453
|
+
return attenuation;
|
|
3454
|
+
}
|
|
3425
3455
|
function verifyPolicyRootStatusCheckpointV3(input) {
|
|
3426
3456
|
const checkpoint = input.checkpoint;
|
|
3427
3457
|
const allowed = /* @__PURE__ */ new Set(["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "state", "sequence", "checkedAt", "freshUntil", "revokedAt", "revocationCid", "previousCheckpointDigestHex", "issuerDid", "signature"]);
|
|
@@ -3591,11 +3621,15 @@ function nonEmptyString(value, label) {
|
|
|
3591
3621
|
return value;
|
|
3592
3622
|
}
|
|
3593
3623
|
function parseKvResource(resource) {
|
|
3594
|
-
const
|
|
3595
|
-
|
|
3624
|
+
const marker = resource.indexOf("/kv/");
|
|
3625
|
+
const encodedSpace = marker < 1 ? "" : resource.slice(0, marker);
|
|
3626
|
+
const legacy = encodedSpace.startsWith("tinycloud://");
|
|
3627
|
+
const space = legacy ? encodedSpace.slice("tinycloud://".length) : encodedSpace;
|
|
3628
|
+
const path = marker < 1 ? "" : resource.slice(marker + 4);
|
|
3629
|
+
if (marker < 1 || (legacy ? /[:/?#%]/.test(space) : !encodedSpace.startsWith("tinycloud:") || /[/?#%]/.test(encodedSpace)) || path.startsWith("/") || path.endsWith("/") || path.includes("//") || path.split("/").some((part) => part === "." || part === ".." || part.length === 0)) {
|
|
3596
3630
|
throw new Error("KV resource is not canonical");
|
|
3597
3631
|
}
|
|
3598
|
-
return { space
|
|
3632
|
+
return { space, path };
|
|
3599
3633
|
}
|
|
3600
3634
|
function parseEncryptionResource(resource) {
|
|
3601
3635
|
if (!resource.startsWith("urn:tinycloud:encryption:")) throw new Error("encryption capability is invalid");
|
|
@@ -3740,7 +3774,7 @@ function unifiedPolicyCapabilityFromNative(input) {
|
|
|
3740
3774
|
throw new Error("native capability is not supported");
|
|
3741
3775
|
const caveat = object2(value.caveat, "native.caveat");
|
|
3742
3776
|
exactKeys(caveat, ["type", "kind", "value"], "native selector caveat");
|
|
3743
|
-
if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `tinycloud://${value.space}/kv/${value.path}`)
|
|
3777
|
+
if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `${value.space.startsWith("tinycloud:") ? value.space : `tinycloud://${value.space}`}/kv/${value.path}`)
|
|
3744
3778
|
throw new Error("native selector caveat does not match capability");
|
|
3745
3779
|
return normalizeUnifiedPolicyCapability({
|
|
3746
3780
|
kind: "kv",
|
|
@@ -3799,9 +3833,7 @@ var CompactPayloadSchema = z2.object({
|
|
|
3799
3833
|
nnc: z2.string().min(1),
|
|
3800
3834
|
prf: z2.array(z2.string().min(1))
|
|
3801
3835
|
}).strict();
|
|
3802
|
-
async function
|
|
3803
|
-
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
|
|
3804
|
-
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
3836
|
+
async function signCompactUcan(input) {
|
|
3805
3837
|
const principal = input.issuerDid.split("#", 1)[0];
|
|
3806
3838
|
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3807
3839
|
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
@@ -3823,6 +3855,16 @@ async function signCompactUcanAuthorization(input) {
|
|
|
3823
3855
|
if (signature.length !== 64) throw new Error("compact Authorization signature must be Ed25519");
|
|
3824
3856
|
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url2(signature)}`);
|
|
3825
3857
|
}
|
|
3858
|
+
async function signCompactUcanAuthorization(input) {
|
|
3859
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
|
|
3860
|
+
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
3861
|
+
return signCompactUcan(input);
|
|
3862
|
+
}
|
|
3863
|
+
async function signCompactUcanRootAuthorization(input) {
|
|
3864
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 31 * 24 * 60 * 60)
|
|
3865
|
+
throw new Error("compact policy root lifetime must be between one second and 31 days");
|
|
3866
|
+
return signCompactUcan({ ...input, proofs: [] });
|
|
3867
|
+
}
|
|
3826
3868
|
function createCompactPolicyInvocation(input) {
|
|
3827
3869
|
const session = parsePolicySessionUcan(input.sessionAuthorization);
|
|
3828
3870
|
if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
|
|
@@ -3969,14 +4011,14 @@ function decodeBase64Url2(value) {
|
|
|
3969
4011
|
if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
|
|
3970
4012
|
throw new Error("value is not canonical base64url");
|
|
3971
4013
|
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
3972
|
-
const binary = typeof
|
|
4014
|
+
const binary = typeof atob === "function" ? atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=")) : Buffer.from(normalized, "base64").toString("binary");
|
|
3973
4015
|
const bytes2 = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
3974
|
-
const encoded = typeof
|
|
4016
|
+
const encoded = typeof btoa === "function" ? btoa(String.fromCharCode(...bytes2)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(bytes2).toString("base64url");
|
|
3975
4017
|
if (encoded !== value) throw new Error("value is not canonical base64url");
|
|
3976
4018
|
return bytes2;
|
|
3977
4019
|
}
|
|
3978
4020
|
function encodeBase64Url2(value) {
|
|
3979
|
-
return typeof
|
|
4021
|
+
return typeof btoa === "function" ? btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(value).toString("base64url");
|
|
3980
4022
|
}
|
|
3981
4023
|
function equalBytes(left, right) {
|
|
3982
4024
|
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
@@ -4001,6 +4043,320 @@ function base32Lower(bytes2) {
|
|
|
4001
4043
|
return output;
|
|
4002
4044
|
}
|
|
4003
4045
|
|
|
4046
|
+
// src/policy/credential-admission.ts
|
|
4047
|
+
import { ed25519 as ed255194 } from "@noble/curves/ed25519";
|
|
4048
|
+
import { sha256 as sha2565 } from "@noble/hashes/sha256";
|
|
4049
|
+
var POLICY_V2_SCHEMA = "xyz.tinycloud.policy/policy/v2";
|
|
4050
|
+
var POLICY_V2_DOMAIN = "xyz.tinycloud.policy/policy/v2\0";
|
|
4051
|
+
var POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE = "TinyCloudPolicyCredentialRequirement";
|
|
4052
|
+
var POLICY_PRESENTATION_V3_SCHEMA = "xyz.tinycloud.policy/presentation/v3";
|
|
4053
|
+
var POLICY_PRESENTATION_V3_DOMAIN = "xyz.tinycloud.policy/Presentation/v3\0";
|
|
4054
|
+
function record(value, label) {
|
|
4055
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4056
|
+
throw new Error(`${label} must be an object`);
|
|
4057
|
+
}
|
|
4058
|
+
return value;
|
|
4059
|
+
}
|
|
4060
|
+
function exactKeys2(value, keys, label) {
|
|
4061
|
+
const expected = [...keys].sort();
|
|
4062
|
+
const actual = Object.keys(value).sort();
|
|
4063
|
+
if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index])) {
|
|
4064
|
+
throw new Error(`${label} contains an unknown or missing field`);
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
function nonEmpty(value, label) {
|
|
4068
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
4069
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
4070
|
+
}
|
|
4071
|
+
return value;
|
|
4072
|
+
}
|
|
4073
|
+
function policyNodeOrigin(value) {
|
|
4074
|
+
let url;
|
|
4075
|
+
try {
|
|
4076
|
+
url = new URL(value);
|
|
4077
|
+
} catch {
|
|
4078
|
+
throw new Error("policy node origin is invalid");
|
|
4079
|
+
}
|
|
4080
|
+
if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "") {
|
|
4081
|
+
throw new Error("policy node origin is invalid");
|
|
4082
|
+
}
|
|
4083
|
+
return url.origin;
|
|
4084
|
+
}
|
|
4085
|
+
function versionPair(value, label) {
|
|
4086
|
+
const item = record(value, label);
|
|
4087
|
+
exactKeys2(item, ["id", "version"], label);
|
|
4088
|
+
if (item.version !== 1) throw new Error(`${label} version is unsupported`);
|
|
4089
|
+
return Object.freeze({ id: nonEmpty(item.id, `${label}.id`), version: 1 });
|
|
4090
|
+
}
|
|
4091
|
+
function validatePolicyCredentialRequirementV1(value) {
|
|
4092
|
+
const item = record(value, "policy credential requirement");
|
|
4093
|
+
exactKeys2(
|
|
4094
|
+
item,
|
|
4095
|
+
[
|
|
4096
|
+
"type",
|
|
4097
|
+
"version",
|
|
4098
|
+
"requirementDigest",
|
|
4099
|
+
"descriptorDigest",
|
|
4100
|
+
"issuerDid",
|
|
4101
|
+
"issuerKid",
|
|
4102
|
+
"profile",
|
|
4103
|
+
"credentialType"
|
|
4104
|
+
],
|
|
4105
|
+
"policy credential requirement"
|
|
4106
|
+
);
|
|
4107
|
+
if (item.type !== POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE || item.version !== 1 || !isDigest(item.requirementDigest) || !isDigest(item.descriptorDigest)) {
|
|
4108
|
+
throw new Error("policy credential requirement is invalid");
|
|
4109
|
+
}
|
|
4110
|
+
return Object.freeze({
|
|
4111
|
+
type: POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE,
|
|
4112
|
+
version: 1,
|
|
4113
|
+
requirementDigest: item.requirementDigest,
|
|
4114
|
+
descriptorDigest: item.descriptorDigest,
|
|
4115
|
+
issuerDid: nonEmpty(item.issuerDid, "policy credential issuer"),
|
|
4116
|
+
issuerKid: nonEmpty(item.issuerKid, "policy credential issuer key"),
|
|
4117
|
+
profile: versionPair(item.profile, "policy credential profile"),
|
|
4118
|
+
credentialType: versionPair(
|
|
4119
|
+
item.credentialType,
|
|
4120
|
+
"policy credential type"
|
|
4121
|
+
)
|
|
4122
|
+
});
|
|
4123
|
+
}
|
|
4124
|
+
function hex2(bytes2) {
|
|
4125
|
+
return [...bytes2].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
4126
|
+
}
|
|
4127
|
+
function policyV2DigestHex(input) {
|
|
4128
|
+
const canonicalPolicy = {
|
|
4129
|
+
...input,
|
|
4130
|
+
credentialRequirement: validatePolicyCredentialRequirementV1(
|
|
4131
|
+
input.credentialRequirement
|
|
4132
|
+
),
|
|
4133
|
+
capabilityCeiling: input.capabilityCeiling.map(
|
|
4134
|
+
normalizeUnifiedPolicyCapability
|
|
4135
|
+
)
|
|
4136
|
+
};
|
|
4137
|
+
return hex2(
|
|
4138
|
+
sha2565(
|
|
4139
|
+
new TextEncoder().encode(
|
|
4140
|
+
POLICY_V2_DOMAIN + jcsCanonicalize(canonicalPolicy)
|
|
4141
|
+
)
|
|
4142
|
+
)
|
|
4143
|
+
);
|
|
4144
|
+
}
|
|
4145
|
+
function date(value, label) {
|
|
4146
|
+
const text2 = nonEmpty(value, label);
|
|
4147
|
+
if (!Number.isFinite(Date.parse(text2))) throw new Error(`${label} is invalid`);
|
|
4148
|
+
return text2;
|
|
4149
|
+
}
|
|
4150
|
+
function rfc3339Seconds(value) {
|
|
4151
|
+
return new Date(Math.floor(value.getTime() / 1e3) * 1e3).toISOString().replace(/\.000Z$/, "Z");
|
|
4152
|
+
}
|
|
4153
|
+
function validateUnifiedPolicyV2(value, expectedPolicyCid) {
|
|
4154
|
+
const item = record(value, "Policy/v2");
|
|
4155
|
+
const allowed = [
|
|
4156
|
+
"schema",
|
|
4157
|
+
"policyId",
|
|
4158
|
+
"ownerDid",
|
|
4159
|
+
"createdAt",
|
|
4160
|
+
"contentSource",
|
|
4161
|
+
"capabilityCeiling",
|
|
4162
|
+
"credentialRequirement",
|
|
4163
|
+
"signature",
|
|
4164
|
+
...item.expiresAt === void 0 ? [] : ["expiresAt"]
|
|
4165
|
+
];
|
|
4166
|
+
exactKeys2(item, allowed, "Policy/v2");
|
|
4167
|
+
if (item.schema !== POLICY_V2_SCHEMA || !Array.isArray(item.capabilityCeiling)) {
|
|
4168
|
+
throw new Error("Policy/v2 is invalid");
|
|
4169
|
+
}
|
|
4170
|
+
const ownerDid = nonEmpty(item.ownerDid, "Policy/v2 ownerDid");
|
|
4171
|
+
const signature = record(item.signature, "Policy/v2 signature");
|
|
4172
|
+
exactKeys2(signature, ["suite", "signerDid", "value"], "Policy/v2 signature");
|
|
4173
|
+
if (signature.suite !== "Ed25519" || signature.signerDid !== ownerDid || typeof signature.value !== "string" || signature.value.length === 0) {
|
|
4174
|
+
throw new Error("Policy/v2 signature binding is invalid");
|
|
4175
|
+
}
|
|
4176
|
+
const policy = Object.freeze({
|
|
4177
|
+
schema: POLICY_V2_SCHEMA,
|
|
4178
|
+
policyId: nonEmpty(item.policyId, "Policy/v2 policyId"),
|
|
4179
|
+
ownerDid,
|
|
4180
|
+
createdAt: date(item.createdAt, "Policy/v2 createdAt"),
|
|
4181
|
+
...item.expiresAt === void 0 ? {} : { expiresAt: date(item.expiresAt, "Policy/v2 expiresAt") },
|
|
4182
|
+
contentSource: item.contentSource,
|
|
4183
|
+
capabilityCeiling: Object.freeze(
|
|
4184
|
+
item.capabilityCeiling.map(normalizeUnifiedPolicyCapability)
|
|
4185
|
+
),
|
|
4186
|
+
credentialRequirement: validatePolicyCredentialRequirementV1(
|
|
4187
|
+
item.credentialRequirement
|
|
4188
|
+
),
|
|
4189
|
+
signature: Object.freeze({
|
|
4190
|
+
suite: "Ed25519",
|
|
4191
|
+
signerDid: ownerDid,
|
|
4192
|
+
value: signature.value
|
|
4193
|
+
})
|
|
4194
|
+
});
|
|
4195
|
+
const unsigned = { ...policy };
|
|
4196
|
+
delete unsigned.policyId;
|
|
4197
|
+
delete unsigned.signature;
|
|
4198
|
+
const digestHex = policyV2DigestHex(unsigned);
|
|
4199
|
+
if (policy.policyId !== policyIdForDigestHex(digestHex)) {
|
|
4200
|
+
throw new Error("Policy/v2 policyId binding is invalid");
|
|
4201
|
+
}
|
|
4202
|
+
if (expectedPolicyCid !== void 0) {
|
|
4203
|
+
const cid2 = policyCidFromCanonicalBytes(
|
|
4204
|
+
new TextEncoder().encode(jcsCanonicalize(policy))
|
|
4205
|
+
);
|
|
4206
|
+
if (cid2 !== expectedPolicyCid) throw new Error("Policy/v2 CID binding is invalid");
|
|
4207
|
+
}
|
|
4208
|
+
return policy;
|
|
4209
|
+
}
|
|
4210
|
+
function didKeyBytes(did) {
|
|
4211
|
+
const principal = did.split("#", 1)[0];
|
|
4212
|
+
if (!principal.startsWith("did:key:")) throw new Error("holder DID must be did:key");
|
|
4213
|
+
const material = base58btc.decode(principal.slice("did:key:".length));
|
|
4214
|
+
if (material.length !== 34 || material[0] !== 237 || material[1] !== 1) {
|
|
4215
|
+
throw new Error("holder DID must contain an Ed25519 key");
|
|
4216
|
+
}
|
|
4217
|
+
return material.slice(2);
|
|
4218
|
+
}
|
|
4219
|
+
function envelopeFromVerified(verified) {
|
|
4220
|
+
const {
|
|
4221
|
+
verifiedAt: _verifiedAt,
|
|
4222
|
+
credentialDigest: _credentialDigest,
|
|
4223
|
+
statusCheckedAt: _statusCheckedAt,
|
|
4224
|
+
...envelope
|
|
4225
|
+
} = verified;
|
|
4226
|
+
return envelope;
|
|
4227
|
+
}
|
|
4228
|
+
async function buildPolicyCredentialPresentationV3(input) {
|
|
4229
|
+
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4230
|
+
const requirement = validateCredentialRequirement(input.requirement);
|
|
4231
|
+
const commitment = policy.credentialRequirement;
|
|
4232
|
+
const requirementDigest = await credentialRequirementDigest(requirement);
|
|
4233
|
+
const credentialDigest = await sha256Base64Url(input.credential.credential);
|
|
4234
|
+
if (requirementDigest !== commitment.requirementDigest || input.credential.descriptorDigest !== commitment.descriptorDigest || input.credential.credentialDigest !== credentialDigest || input.credential.issuerDid !== commitment.issuerDid || input.credential.issuerKid !== commitment.issuerKid || jcsCanonicalize(input.credential.profile) !== jcsCanonicalize(commitment.profile) || jcsCanonicalize(input.credential.credentialType) !== jcsCanonicalize(commitment.credentialType)) {
|
|
4235
|
+
throw new Error("credential does not match the signed Policy/v2 requirement");
|
|
4236
|
+
}
|
|
4237
|
+
const requestedCapabilities = input.requestedCapabilities.map(
|
|
4238
|
+
normalizeUnifiedPolicyCapability
|
|
4239
|
+
);
|
|
4240
|
+
if (requestedCapabilities.length === 0 || requestedCapabilities.some(
|
|
4241
|
+
(requested) => !policy.capabilityCeiling.some(
|
|
4242
|
+
(authority) => unifiedPolicyCapabilityContains(authority, requested)
|
|
4243
|
+
)
|
|
4244
|
+
)) {
|
|
4245
|
+
throw new Error("requested capabilities exceed the signed Policy/v2 ceiling");
|
|
4246
|
+
}
|
|
4247
|
+
const challenge = input.challenge;
|
|
4248
|
+
const holderDid = input.credential.holderDid;
|
|
4249
|
+
if (challenge.policyCid !== input.policyCid || challenge.recipientDid !== holderDid || input.credential.subjectDid !== holderDid || typeof challenge.nodeAudience !== "string" || challenge.nodeAudience.length === 0 || typeof challenge.expiresAt !== "string" || !Number.isFinite(Date.parse(challenge.expiresAt))) {
|
|
4250
|
+
throw new Error("policy challenge binding is invalid");
|
|
4251
|
+
}
|
|
4252
|
+
didKeyBytes(holderDid);
|
|
4253
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
4254
|
+
const challengeExpiry = Date.parse(challenge.expiresAt);
|
|
4255
|
+
const credentialExpiry = Date.parse(input.credential.expiresAt);
|
|
4256
|
+
const expiresAtMs = Math.min(
|
|
4257
|
+
now.getTime() + 6e4,
|
|
4258
|
+
challengeExpiry,
|
|
4259
|
+
credentialExpiry
|
|
4260
|
+
);
|
|
4261
|
+
if (expiresAtMs <= now.getTime()) throw new Error("policy challenge is expired");
|
|
4262
|
+
const unsigned = Object.freeze({
|
|
4263
|
+
schema: POLICY_PRESENTATION_V3_SCHEMA,
|
|
4264
|
+
jti: input.jti ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
4265
|
+
challengeId: challenge.challengeId,
|
|
4266
|
+
nonce: challenge.nonce,
|
|
4267
|
+
policyCid: input.policyCid,
|
|
4268
|
+
nodeAudience: challenge.nodeAudience,
|
|
4269
|
+
holderDid,
|
|
4270
|
+
subjectDid: input.credential.subjectDid,
|
|
4271
|
+
credentialSpaceOwnerDid: nonEmpty(
|
|
4272
|
+
input.credentialSpaceOwnerDid,
|
|
4273
|
+
"credential space owner DID"
|
|
4274
|
+
),
|
|
4275
|
+
credentialDigest,
|
|
4276
|
+
requirementDigest,
|
|
4277
|
+
descriptorDigest: input.credential.descriptorDigest,
|
|
4278
|
+
requestedCapabilities: Object.freeze(requestedCapabilities),
|
|
4279
|
+
issuedAt: rfc3339Seconds(now),
|
|
4280
|
+
expiresAt: rfc3339Seconds(new Date(expiresAtMs))
|
|
4281
|
+
});
|
|
4282
|
+
const digest4 = sha2565(
|
|
4283
|
+
new TextEncoder().encode(
|
|
4284
|
+
POLICY_PRESENTATION_V3_DOMAIN + jcsCanonicalize(unsigned)
|
|
4285
|
+
)
|
|
4286
|
+
);
|
|
4287
|
+
const signature = await input.sign(digest4);
|
|
4288
|
+
if (signature.length !== 64 || !ed255194.verify(signature, digest4, didKeyBytes(holderDid))) {
|
|
4289
|
+
throw new Error("policy presentation signature is invalid");
|
|
4290
|
+
}
|
|
4291
|
+
return Object.freeze({
|
|
4292
|
+
...unsigned,
|
|
4293
|
+
signature: Object.freeze({
|
|
4294
|
+
suite: "Ed25519",
|
|
4295
|
+
signerDid: holderDid,
|
|
4296
|
+
value: encodeBase64Url(signature)
|
|
4297
|
+
})
|
|
4298
|
+
});
|
|
4299
|
+
}
|
|
4300
|
+
async function admitPolicyCredentialV3(input) {
|
|
4301
|
+
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4302
|
+
const nodeOrigin = policyNodeOrigin(input.nodeOrigin);
|
|
4303
|
+
const accountAuthorizationCid = nonEmpty(
|
|
4304
|
+
input.accountAuthorizationCid,
|
|
4305
|
+
"account authorization CID"
|
|
4306
|
+
);
|
|
4307
|
+
const credentialSpaceId = nonEmpty(
|
|
4308
|
+
input.credentialSpaceId,
|
|
4309
|
+
"credential space ID"
|
|
4310
|
+
);
|
|
4311
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
4312
|
+
const challenge = await requestPolicyChallengeV3({
|
|
4313
|
+
nodeOrigin,
|
|
4314
|
+
policyCid: input.policyCid,
|
|
4315
|
+
recipientDid: input.credential.holderDid,
|
|
4316
|
+
requestedCapabilities: input.requestedCapabilities,
|
|
4317
|
+
fetch: fetchFn
|
|
4318
|
+
});
|
|
4319
|
+
const presentation = await buildPolicyCredentialPresentationV3({
|
|
4320
|
+
...input,
|
|
4321
|
+
policy,
|
|
4322
|
+
challenge
|
|
4323
|
+
});
|
|
4324
|
+
const response = await fetchFn(
|
|
4325
|
+
new URL("/share/v3/policy/delegations", nodeOrigin),
|
|
4326
|
+
{
|
|
4327
|
+
method: "POST",
|
|
4328
|
+
redirect: "error",
|
|
4329
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4330
|
+
body: JSON.stringify({
|
|
4331
|
+
policyCid: input.policyCid,
|
|
4332
|
+
challengeId: challenge.challengeId,
|
|
4333
|
+
nonce: challenge.nonce,
|
|
4334
|
+
requirement: validateCredentialRequirement(input.requirement),
|
|
4335
|
+
credential: envelopeFromVerified(input.credential),
|
|
4336
|
+
accountAuthorizationCid,
|
|
4337
|
+
credentialSpaceId,
|
|
4338
|
+
presentation
|
|
4339
|
+
})
|
|
4340
|
+
}
|
|
4341
|
+
);
|
|
4342
|
+
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
4343
|
+
const value = record(await response.json(), "policy delegation");
|
|
4344
|
+
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") {
|
|
4345
|
+
throw new Error("policy delegation response is invalid");
|
|
4346
|
+
}
|
|
4347
|
+
const session = parsePolicySessionUcan(value.authorization, [
|
|
4348
|
+
input.policyRootCid,
|
|
4349
|
+
input.enforcementRootCid
|
|
4350
|
+
]);
|
|
4351
|
+
const expectedAttenuation = compactAttenuationForPolicyCapabilities(
|
|
4352
|
+
input.requestedCapabilities
|
|
4353
|
+
);
|
|
4354
|
+
if (session.cid !== value.sessionCid || session.aud !== input.credential.holderDid || session.fact.policyCid !== input.policyCid || session.fact.recipientDid !== input.credential.holderDid || session.fact.policyDelegationCid !== input.policyRootCid || session.fact.enforcementDelegationCid !== input.enforcementRootCid || jcsCanonicalize(session.att) !== jcsCanonicalize(expectedAttenuation)) {
|
|
4355
|
+
throw new Error("policy delegation signed binding is invalid");
|
|
4356
|
+
}
|
|
4357
|
+
return Object.freeze({ challenge, presentation, session });
|
|
4358
|
+
}
|
|
4359
|
+
|
|
4004
4360
|
// src/requester/index.ts
|
|
4005
4361
|
var REQUESTER_NEAR_EXPIRY_SECONDS = 30;
|
|
4006
4362
|
var REQUESTER_ENGINE_RETRY_ATTEMPTS = 3;
|
|
@@ -4252,15 +4608,15 @@ var TranscriptRequester = class _TranscriptRequester {
|
|
|
4252
4608
|
"bootstrap owner-node binding does not match trusted discovery/config"
|
|
4253
4609
|
);
|
|
4254
4610
|
}
|
|
4255
|
-
const
|
|
4256
|
-
if (
|
|
4611
|
+
const record2 = await verifyRecordBeforeEgress(bootstrap, options2);
|
|
4612
|
+
if (record2.endpoint !== bootstrap.policyEngine.endpoint) {
|
|
4257
4613
|
throw new TranscriptRequesterError(
|
|
4258
4614
|
"requester-engine-record-endpoint-mismatch",
|
|
4259
4615
|
"policy engine record endpoint does not match bootstrap endpoint",
|
|
4260
4616
|
"bootstrap-invalid"
|
|
4261
4617
|
);
|
|
4262
4618
|
}
|
|
4263
|
-
if (
|
|
4619
|
+
if (record2.audience !== bootstrap.policyEngine.audience) {
|
|
4264
4620
|
throw new TranscriptRequesterError(
|
|
4265
4621
|
"requester-engine-record-audience-mismatch",
|
|
4266
4622
|
"policy engine record audience does not match bootstrap audience",
|
|
@@ -4291,7 +4647,7 @@ var TranscriptRequester = class _TranscriptRequester {
|
|
|
4291
4647
|
requestedCapabilities,
|
|
4292
4648
|
nativeAuthorityCeiling,
|
|
4293
4649
|
requestedCapabilitiesHash(requestedCapabilities),
|
|
4294
|
-
parseStrictRfc33392(
|
|
4650
|
+
parseStrictRfc33392(record2.expiresAt),
|
|
4295
4651
|
policyEngineAddresses,
|
|
4296
4652
|
ownerNodeAddresses,
|
|
4297
4653
|
options2
|
|
@@ -4914,7 +5270,7 @@ function requestedCapabilitiesHash(capabilities) {
|
|
|
4914
5270
|
const bytes2 = new Uint8Array(domain.length + body.length);
|
|
4915
5271
|
bytes2.set(domain, 0);
|
|
4916
5272
|
bytes2.set(body, domain.length);
|
|
4917
|
-
return bytesToHex3(
|
|
5273
|
+
return bytesToHex3(sha2566(bytes2, "bytes")).slice(2);
|
|
4918
5274
|
}
|
|
4919
5275
|
function normalizeWireDelegation(delegation) {
|
|
4920
5276
|
const signed = delegationAuthorityFromCompactJws(delegation.encoded);
|
|
@@ -5160,9 +5516,9 @@ function parseNodeDataResponse(response, schema, label) {
|
|
|
5160
5516
|
function nodeErrorMessage(body) {
|
|
5161
5517
|
if (typeof body === "string") return body;
|
|
5162
5518
|
if (body !== null && typeof body === "object") {
|
|
5163
|
-
const
|
|
5164
|
-
const code3 = typeof
|
|
5165
|
-
const message = typeof
|
|
5519
|
+
const record2 = body;
|
|
5520
|
+
const code3 = typeof record2.code === "string" ? record2.code : void 0;
|
|
5521
|
+
const message = typeof record2.message === "string" ? record2.message : void 0;
|
|
5166
5522
|
if (code3 !== void 0)
|
|
5167
5523
|
return message === void 0 ? code3 : `${code3}: ${message}`;
|
|
5168
5524
|
}
|
|
@@ -7484,7 +7840,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
|
|
|
7484
7840
|
}
|
|
7485
7841
|
|
|
7486
7842
|
// src/delegations/SharingService.ts
|
|
7487
|
-
import { ed25519 as
|
|
7843
|
+
import { ed25519 as ed255197 } from "@noble/curves/ed25519";
|
|
7488
7844
|
|
|
7489
7845
|
// src/delegations/ShareRecipientClient.ts
|
|
7490
7846
|
import {
|
|
@@ -7492,13 +7848,13 @@ import {
|
|
|
7492
7848
|
KVService,
|
|
7493
7849
|
ServiceContext
|
|
7494
7850
|
} from "@tinycloud/sdk-services";
|
|
7495
|
-
import { ed25519 as
|
|
7496
|
-
import { sha256 as
|
|
7851
|
+
import { ed25519 as ed255196 } from "@noble/curves/ed25519";
|
|
7852
|
+
import { sha256 as sha2569 } from "@noble/hashes/sha256";
|
|
7497
7853
|
|
|
7498
7854
|
// src/delegations/share-envelope.ts
|
|
7499
|
-
import { ed25519 as
|
|
7855
|
+
import { ed25519 as ed255195 } from "@noble/curves/ed25519";
|
|
7500
7856
|
import { blake3 as blake33 } from "@noble/hashes/blake3";
|
|
7501
|
-
import { sha256 as
|
|
7857
|
+
import { sha256 as sha2567 } from "@noble/hashes/sha256";
|
|
7502
7858
|
var ENVELOPE_SCHEMA = "xyz.tinycloud.share/envelope";
|
|
7503
7859
|
var INLINE_PREFIX = "tc2:";
|
|
7504
7860
|
var RAW_CID_CODEC = 85;
|
|
@@ -7717,7 +8073,7 @@ function createSharePolicy(input) {
|
|
|
7717
8073
|
};
|
|
7718
8074
|
}
|
|
7719
8075
|
function contentDigest(bytes2) {
|
|
7720
|
-
return bytesToBase64Url(
|
|
8076
|
+
return bytesToBase64Url(sha2567(bytes2));
|
|
7721
8077
|
}
|
|
7722
8078
|
function computeShareCid(bytes2) {
|
|
7723
8079
|
const digest4 = create(BLAKE3_256_CODE, blake33(bytes2));
|
|
@@ -7737,7 +8093,7 @@ function envelopeSigningBytes(envelope) {
|
|
|
7737
8093
|
}
|
|
7738
8094
|
function signShareEnvelope(input) {
|
|
7739
8095
|
if (input.signerPrivateKey.length !== 32) throw new ShareEnvelopeError("invalid-envelope", "Ed25519 private key must be 32 bytes");
|
|
7740
|
-
const publicKey =
|
|
8096
|
+
const publicKey = ed255195.getPublicKey(input.signerPrivateKey);
|
|
7741
8097
|
const unsigned = {
|
|
7742
8098
|
schema: ENVELOPE_SCHEMA,
|
|
7743
8099
|
version: 2,
|
|
@@ -7752,7 +8108,7 @@ function signShareEnvelope(input) {
|
|
|
7752
8108
|
expiresAt: new Date(input.expiresAt).toISOString(),
|
|
7753
8109
|
signer: { did: input.signerDid, publicKey: bytesToBase64Url(publicKey) }
|
|
7754
8110
|
};
|
|
7755
|
-
return { ...unsigned, signature: bytesToBase64Url(
|
|
8111
|
+
return { ...unsigned, signature: bytesToBase64Url(ed255195.sign(envelopeSigningBytes(unsigned), input.signerPrivateKey)) };
|
|
7756
8112
|
}
|
|
7757
8113
|
function verifyShareEnvelope(envelope, options2 = {}) {
|
|
7758
8114
|
try {
|
|
@@ -7784,7 +8140,7 @@ function verifyShareEnvelope(envelope, options2 = {}) {
|
|
|
7784
8140
|
const signature = base64UrlToBytes(envelope.signature);
|
|
7785
8141
|
const unsigned = { ...envelope };
|
|
7786
8142
|
delete unsigned.signature;
|
|
7787
|
-
if (publicKey.length !== 32 || signature.length !== 64 || !
|
|
8143
|
+
if (publicKey.length !== 32 || signature.length !== 64 || !ed255195.verify(signature, envelopeSigningBytes(unsigned), publicKey)) throw new ShareEnvelopeError("signature-invalid", "share envelope signature is invalid");
|
|
7788
8144
|
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");
|
|
7789
8145
|
return envelope;
|
|
7790
8146
|
} catch (error) {
|
|
@@ -7832,7 +8188,7 @@ function encodeInlineShareUrl(input) {
|
|
|
7832
8188
|
}
|
|
7833
8189
|
var PUBLISHED_AAD = new TextEncoder().encode("tinycloud-share-envelope-v1");
|
|
7834
8190
|
function publishedCid(bytes2) {
|
|
7835
|
-
return CID.create(1, code, create(sha2562.code,
|
|
8191
|
+
return CID.create(1, code, create(sha2562.code, sha2567(bytes2))).toString();
|
|
7836
8192
|
}
|
|
7837
8193
|
function isPublishedCid(value) {
|
|
7838
8194
|
try {
|
|
@@ -7872,7 +8228,7 @@ function publishedArtifact(envelope, plaintext, policy) {
|
|
|
7872
8228
|
content: {
|
|
7873
8229
|
mimeType: "application/octet-stream",
|
|
7874
8230
|
size: plaintext.byteLength,
|
|
7875
|
-
digest: bytesToBase64Url(
|
|
8231
|
+
digest: bytesToBase64Url(sha2567(plaintext))
|
|
7876
8232
|
},
|
|
7877
8233
|
// Addressed policy metadata is confidential even though this function
|
|
7878
8234
|
// is called after the outer envelope has been opened. Keep the
|
|
@@ -7976,9 +8332,9 @@ function parsePolicyMetadata(policyBytes, target, expectedExpiry) {
|
|
|
7976
8332
|
assertKeys(source, ["kind", "space", "database", "path", "statement", "arguments", "argumentsDigest", "action"], "published SQL content source");
|
|
7977
8333
|
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");
|
|
7978
8334
|
for (const argument of Object.values(source.arguments)) if (!Number.isSafeInteger(argument)) throw new ShareEnvelopeError("invalid-envelope", "published SQL arguments are invalid");
|
|
7979
|
-
if (bytesToBase64Url(
|
|
8335
|
+
if (bytesToBase64Url(sha2567(new TextEncoder().encode(canonicalJson(source.arguments)))) !== source.argumentsDigest) throw new ShareEnvelopeError("invalid-envelope", "published SQL argument digest is invalid");
|
|
7980
8336
|
} else throw new ShareEnvelopeError("invalid-envelope", "policy content source kind is invalid");
|
|
7981
|
-
if (typeof policy.contentSourceDigest !== "string" || bytesToBase64Url(
|
|
8337
|
+
if (typeof policy.contentSourceDigest !== "string" || bytesToBase64Url(sha2567(new TextEncoder().encode(canonicalJson(source)))) !== policy.contentSourceDigest) throw new ShareEnvelopeError("invalid-envelope", "policy content source digest is invalid");
|
|
7982
8338
|
return { recipientKind, actions, resource };
|
|
7983
8339
|
}
|
|
7984
8340
|
function parseCanonicalPublishedV2(value, options2) {
|
|
@@ -8026,7 +8382,7 @@ function parseCanonicalPublishedV2(value, options2) {
|
|
|
8026
8382
|
const signingBytes = new Uint8Array(domain.length + body.length);
|
|
8027
8383
|
signingBytes.set(domain);
|
|
8028
8384
|
signingBytes.set(body, domain.length);
|
|
8029
|
-
if (signatureBytes.length !== 64 || !
|
|
8385
|
+
if (signatureBytes.length !== 64 || !ed255195.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v2 envelope signature is invalid");
|
|
8030
8386
|
const content = options2.plaintext ?? new Uint8Array();
|
|
8031
8387
|
const normalized = {
|
|
8032
8388
|
schema: ENVELOPE_SCHEMA,
|
|
@@ -8036,7 +8392,7 @@ function parseCanonicalPublishedV2(value, options2) {
|
|
|
8036
8392
|
recipientKind: normalizedMatcher.kind,
|
|
8037
8393
|
resource,
|
|
8038
8394
|
actions,
|
|
8039
|
-
content: { mimeType: typeof contentSource.mimeType === "string" ? contentSource.mimeType : "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(
|
|
8395
|
+
content: { mimeType: typeof contentSource.mimeType === "string" ? contentSource.mimeType : "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(sha2567(content)) },
|
|
8040
8396
|
encrypted: true,
|
|
8041
8397
|
expiresAt: value.expiry,
|
|
8042
8398
|
signer: { did: signature.signerDid, publicKey: bytesToBase64Url(signerKey) },
|
|
@@ -8135,7 +8491,7 @@ function parsePublishedShareEnvelope(bytes2, options2 = {}) {
|
|
|
8135
8491
|
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");
|
|
8136
8492
|
const signature = base64UrlToBytes(envelope.signature.value);
|
|
8137
8493
|
const publicKey = publishedPublicKey(envelope.signature.signerDid);
|
|
8138
|
-
if (signature.length !== 64 || !
|
|
8494
|
+
if (signature.length !== 64 || !ed255195.verify(signature, publishedEnvelopeSigningBytes(envelope), publicKey)) throw new ShareEnvelopeError("signature-invalid", "published envelope signature is invalid");
|
|
8139
8495
|
return { envelope, artifact: publishedArtifact(envelope, options2.plaintext ?? new Uint8Array(), policy) };
|
|
8140
8496
|
}
|
|
8141
8497
|
function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
|
|
@@ -8174,7 +8530,7 @@ function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
|
|
|
8174
8530
|
const signingBytes = new Uint8Array(domain.length + body.length);
|
|
8175
8531
|
signingBytes.set(domain);
|
|
8176
8532
|
signingBytes.set(body, domain.length);
|
|
8177
|
-
if (signatureBytes.length !== 64 || !
|
|
8533
|
+
if (signatureBytes.length !== 64 || !ed255195.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v1 envelope signature is invalid");
|
|
8178
8534
|
const content = options2.plaintext ?? new Uint8Array();
|
|
8179
8535
|
const artifact = {
|
|
8180
8536
|
envelope: {
|
|
@@ -8185,7 +8541,7 @@ function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
|
|
|
8185
8541
|
resource: { kind: resource.kind, path: resource.path },
|
|
8186
8542
|
recipientKind: authorizationTarget.kind === "bearer" ? "bearer" : authorizationTarget.kind === "exact-email" ? "exactEmail" : authorizationTarget.kind === "email-domain" ? "emailDomain" : void 0,
|
|
8187
8543
|
actions: ["read"],
|
|
8188
|
-
content: { mimeType: "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(
|
|
8544
|
+
content: { mimeType: "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url(sha2567(content)) },
|
|
8189
8545
|
encrypted: true,
|
|
8190
8546
|
expiresAt: envelope.expiry,
|
|
8191
8547
|
signer: { did: signature.signerDid, publicKey: bytesToBase64Url(signerKey) },
|
|
@@ -8372,13 +8728,13 @@ function shareCapabilityAllows(capability, action, path) {
|
|
|
8372
8728
|
}
|
|
8373
8729
|
|
|
8374
8730
|
// src/delegations/ShareCache.ts
|
|
8375
|
-
import { sha256 as
|
|
8731
|
+
import { sha256 as sha2568 } from "@noble/hashes/sha256";
|
|
8376
8732
|
function cacheKey(key) {
|
|
8377
8733
|
if (!key.cid || !key.expiresAt) throw new Error("share cache keys require CID and expiry");
|
|
8378
8734
|
return `${key.cid}\0${key.expiresAt}`;
|
|
8379
8735
|
}
|
|
8380
8736
|
function digest2(bytes2) {
|
|
8381
|
-
return
|
|
8737
|
+
return sha2568(bytes2);
|
|
8382
8738
|
}
|
|
8383
8739
|
function equalBytes2(left, right) {
|
|
8384
8740
|
if (left.byteLength !== right.byteLength) return false;
|
|
@@ -8755,7 +9111,7 @@ function randomJti() {
|
|
|
8755
9111
|
return bytesToBase64Url2(bytes2);
|
|
8756
9112
|
}
|
|
8757
9113
|
function digestCanonical(value) {
|
|
8758
|
-
return bytesToBase64Url2(
|
|
9114
|
+
return bytesToBase64Url2(sha2569(new TextEncoder().encode(canonicalJsonForProof(value))));
|
|
8759
9115
|
}
|
|
8760
9116
|
function actionWire(action) {
|
|
8761
9117
|
return action === "get" ? "tinycloud.kv/get" : action === "metadata" ? "tinycloud.kv/metadata" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put";
|
|
@@ -8991,9 +9347,9 @@ var ShareRecipientClient = class {
|
|
|
8991
9347
|
const authority = Object.entries(session.att).find(([parentResource, abilities]) => {
|
|
8992
9348
|
if (!(action in abilities)) return false;
|
|
8993
9349
|
if (serviceName === "encryption") return parentResource.startsWith("urn:tinycloud:encryption:") && parentResource === cleanPath;
|
|
8994
|
-
const
|
|
8995
|
-
if (
|
|
8996
|
-
const parentPath =
|
|
9350
|
+
const marker = parentResource.indexOf("/kv/");
|
|
9351
|
+
if (marker < 1) return false;
|
|
9352
|
+
const parentPath = parentResource.slice(marker + 4);
|
|
8997
9353
|
const caveats = abilities[action] ?? [];
|
|
8998
9354
|
const prefix = caveats.some((value) => isRecord(value) && value.kind === "prefix");
|
|
8999
9355
|
return cleanPath === parentPath || prefix && cleanPath.startsWith(`${parentPath}/`);
|
|
@@ -9019,10 +9375,10 @@ var ShareRecipientClient = class {
|
|
|
9019
9375
|
policySessionProjection(delegation) {
|
|
9020
9376
|
const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
|
|
9021
9377
|
if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
9022
|
-
const kvResource = Object.keys(session.att).find((resource) =>
|
|
9023
|
-
const
|
|
9024
|
-
if (
|
|
9025
|
-
return { spaceId:
|
|
9378
|
+
const kvResource = Object.keys(session.att).find((resource) => resource.indexOf("/kv/") > 0);
|
|
9379
|
+
const marker = kvResource?.indexOf("/kv/") ?? -1;
|
|
9380
|
+
if (kvResource === void 0 || marker < 1) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
9381
|
+
return { spaceId: kvResource.slice(0, marker) };
|
|
9026
9382
|
}
|
|
9027
9383
|
createKV(origin2, session, invokeOverride) {
|
|
9028
9384
|
const invoke = invokeOverride ?? this.options.invoke ?? nativeInvoke;
|
|
@@ -9072,7 +9428,7 @@ var ShareRecipientClient = class {
|
|
|
9072
9428
|
if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES)) throw new ShareAccessError("SHARE_TOO_LARGE");
|
|
9073
9429
|
const contentType = input.contentType ?? envelope.content.mimeType;
|
|
9074
9430
|
if (contentType !== envelope.content.mimeType && !/^text\/(?:plain|markdown)(?:;|$)/i.test(contentType)) throw new ShareAccessError("SHARE_CONTENT_TYPE_INVALID");
|
|
9075
|
-
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2(
|
|
9431
|
+
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2(sha2569(bytes2)), contentType, ifMatch: input.etag, mediaType: "application/vnd.tinycloud.share+json" });
|
|
9076
9432
|
if (result.status === 412 || result.status === 409) throw new ShareConflict(path, result.headers?.etag);
|
|
9077
9433
|
if (result.status === 401 || result.status === 403) throw new ShareAccessError("SHARE_DENIED");
|
|
9078
9434
|
if (result.status < 200 || result.status >= 300) throw new ShareAccessError("SHARE_WRITE_FAILED");
|
|
@@ -9224,44 +9580,44 @@ var ShareRecipientClient = class {
|
|
|
9224
9580
|
}
|
|
9225
9581
|
const parsed = ShareNativeResponseSchema.safeParse(value);
|
|
9226
9582
|
if (!parsed.success) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
|
|
9227
|
-
const
|
|
9583
|
+
const record2 = parsed.data;
|
|
9228
9584
|
const expectedAction = actionWire(input.action);
|
|
9229
|
-
if (
|
|
9585
|
+
if (record2.action !== expectedAction || record2.version !== 2 || record2.resource !== input.resource) {
|
|
9230
9586
|
throw new ShareAccessError("SHARE_RESPONSE_MISMATCH");
|
|
9231
9587
|
}
|
|
9232
|
-
if (
|
|
9233
|
-
if (
|
|
9588
|
+
if (record2.etag !== void 0 && record2.etag !== null && headers.etag !== void 0 && record2.etag !== headers.etag) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
|
|
9589
|
+
if (record2.etag !== void 0 && record2.etag !== null) headers.etag = record2.etag;
|
|
9234
9590
|
if (input.action === "list") {
|
|
9235
|
-
if (
|
|
9236
|
-
const rawEntries =
|
|
9591
|
+
if (record2.entries === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
|
|
9592
|
+
const rawEntries = record2.entries;
|
|
9237
9593
|
if (rawEntries.length > MAX_NATIVE_ENTRIES) throw new ShareAccessError("SHARE_TOO_LARGE");
|
|
9238
9594
|
const entries = [...rawEntries];
|
|
9239
9595
|
const headerCursor = response.headers.get("x-tinycloud-next-cursor");
|
|
9240
|
-
if (
|
|
9241
|
-
const nextCursor =
|
|
9596
|
+
if (record2.nextCursor !== void 0 && record2.nextCursor !== null && headerCursor !== null && record2.nextCursor !== headerCursor) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
|
|
9597
|
+
const nextCursor = record2.nextCursor ?? headerCursor ?? void 0;
|
|
9242
9598
|
if (nextCursor !== void 0 && new TextEncoder().encode(nextCursor).byteLength > MAX_NATIVE_CURSOR_BYTES) throw new ShareAccessError("SHARE_TOO_LARGE");
|
|
9243
|
-
return { status: response.status, headers, type:
|
|
9599
|
+
return { status: response.status, headers, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource, keys: entries.map((entry) => entry.path), entries, truncated: nextCursor !== void 0, nextCursor };
|
|
9244
9600
|
}
|
|
9245
9601
|
if (input.action === "get") {
|
|
9246
|
-
if (
|
|
9602
|
+
if (record2.content === void 0 || record2.bodyDigest === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
|
|
9247
9603
|
let bytes2;
|
|
9248
9604
|
try {
|
|
9249
|
-
bytes2 = base64UrlToBytes2(
|
|
9605
|
+
bytes2 = base64UrlToBytes2(record2.content);
|
|
9250
9606
|
} catch {
|
|
9251
9607
|
throw new ShareAccessError("SHARE_RESPONSE_INVALID");
|
|
9252
9608
|
}
|
|
9253
|
-
if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES) || !this.digestMatches(
|
|
9254
|
-
return { status: response.status, headers, bytes: bytes2, bodyDigest:
|
|
9609
|
+
if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES) || !this.digestMatches(record2.bodyDigest, bytes2)) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
|
|
9610
|
+
return { status: response.status, headers, bytes: bytes2, bodyDigest: record2.bodyDigest, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource };
|
|
9255
9611
|
}
|
|
9256
9612
|
if (input.action === "metadata") {
|
|
9257
|
-
if (
|
|
9258
|
-
return { status: response.status, headers, metadata:
|
|
9613
|
+
if (record2.metadata === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
|
|
9614
|
+
return { status: response.status, headers, metadata: record2.metadata, etag: record2.etag ?? void 0, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource };
|
|
9259
9615
|
}
|
|
9260
|
-
const responseEtag =
|
|
9261
|
-
const responseBodyDigest =
|
|
9616
|
+
const responseEtag = record2.etag;
|
|
9617
|
+
const responseBodyDigest = record2.bodyDigest;
|
|
9262
9618
|
if (responseEtag === void 0 || responseEtag === null || responseEtag.length === 0 || headers.etag !== void 0 && responseEtag !== headers.etag) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
|
|
9263
9619
|
if (input.bodyDigest === void 0 || responseBodyDigest === void 0 || responseBodyDigest !== input.bodyDigest || !this.digestMatches(responseBodyDigest, input.body ?? new Uint8Array())) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
|
|
9264
|
-
return { status: response.status, headers, bodyDigest: responseBodyDigest, type:
|
|
9620
|
+
return { status: response.status, headers, bodyDigest: responseBodyDigest, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource };
|
|
9265
9621
|
}
|
|
9266
9622
|
validateNativeResult(input, result) {
|
|
9267
9623
|
if (!isNativeSuccess(result)) throw new ShareAccessError("SHARE_RESPONSE_MISMATCH");
|
|
@@ -9318,7 +9674,7 @@ var ShareRecipientClient = class {
|
|
|
9318
9674
|
}]);
|
|
9319
9675
|
}
|
|
9320
9676
|
digestMatches(value, bytes2) {
|
|
9321
|
-
const digest4 = bytesToBase64Url2(
|
|
9677
|
+
const digest4 = bytesToBase64Url2(sha2569(bytes2));
|
|
9322
9678
|
return value === digest4 || value === `sha-256=:${digest4}:`;
|
|
9323
9679
|
}
|
|
9324
9680
|
assertNativeRequestBounds(envelope, session, operation, path, limit, cursor) {
|
|
@@ -9536,7 +9892,7 @@ var ShareRecipientClient = class {
|
|
|
9536
9892
|
nodeAudience: binding.nodeAudience,
|
|
9537
9893
|
...isV2 ? {
|
|
9538
9894
|
enforcerDid: challenge.enforcerDid,
|
|
9539
|
-
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2(
|
|
9895
|
+
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2(sha2569(new TextEncoder().encode(credential)))
|
|
9540
9896
|
} : {},
|
|
9541
9897
|
action,
|
|
9542
9898
|
...binding.actions === void 0 ? {} : { actions: [...binding.actions] },
|
|
@@ -9602,7 +9958,7 @@ var ShareRecipientClient = class {
|
|
|
9602
9958
|
}
|
|
9603
9959
|
if (isJwsProof && detached.kid !== `${signerDid}#${encoded}` || isEd25519Proof && detached.signerDid !== signerDid || signature.length !== 64) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof binding is invalid");
|
|
9604
9960
|
const bytes2 = new TextEncoder().encode(`${domain}${canonicalJsonForProof(message)}`);
|
|
9605
|
-
if (!
|
|
9961
|
+
if (!ed255196.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
|
|
9606
9962
|
}
|
|
9607
9963
|
assertChallengeRequestBinding(request, challenge) {
|
|
9608
9964
|
const source = isRecord(request.body) ? request.body : request;
|
|
@@ -10806,7 +11162,7 @@ function shareKeyMatchesDid(key, didUrl) {
|
|
|
10806
11162
|
if (!publicKey) return false;
|
|
10807
11163
|
const jwkBytes = decodeBase64UrlBytes(key.x);
|
|
10808
11164
|
const privateKey = decodeBase64UrlBytes(key.d);
|
|
10809
|
-
const derivedPublicKey =
|
|
11165
|
+
const derivedPublicKey = ed255197.getPublicKey(privateKey);
|
|
10810
11166
|
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]);
|
|
10811
11167
|
} catch {
|
|
10812
11168
|
return false;
|
|
@@ -10856,8 +11212,8 @@ function verifySignedChild(result, expected, computeCid) {
|
|
|
10856
11212
|
}
|
|
10857
11213
|
|
|
10858
11214
|
// src/delegations/owner-policy.ts
|
|
10859
|
-
import { ed25519 as
|
|
10860
|
-
import { sha256 as
|
|
11215
|
+
import { ed25519 as ed255198 } from "@noble/curves/ed25519";
|
|
11216
|
+
import { sha256 as sha25610 } from "@noble/hashes/sha256";
|
|
10861
11217
|
var MAX_CONTENT_BYTES = 100 * 1024 * 1024;
|
|
10862
11218
|
var ENFORCEMENT_DOMAIN = "xyz.tinycloud.share/policy-enforcement/v2\0";
|
|
10863
11219
|
var POLICY_DOMAIN = "xyz.tinycloud.share/policy/v2\0";
|
|
@@ -10884,10 +11240,10 @@ function fromB64(value) {
|
|
|
10884
11240
|
throw new Error("base64url decoding is unavailable");
|
|
10885
11241
|
}
|
|
10886
11242
|
function cid(bytesValue) {
|
|
10887
|
-
return CID.createV1(code, create(sha2562.code,
|
|
11243
|
+
return CID.createV1(code, create(sha2562.code, sha25610(bytesValue))).toString(base32.encoder);
|
|
10888
11244
|
}
|
|
10889
11245
|
function digest3(bytesValue) {
|
|
10890
|
-
return b64(
|
|
11246
|
+
return b64(sha25610(bytesValue));
|
|
10891
11247
|
}
|
|
10892
11248
|
function didKeyFromEd25519PublicKey(publicKey) {
|
|
10893
11249
|
if (publicKey.length !== 32) throw new Error("share key public key must be 32 bytes");
|
|
@@ -10959,9 +11315,9 @@ function dagCborEncode(value) {
|
|
|
10959
11315
|
}
|
|
10960
11316
|
function assertObject(value, keys, label) {
|
|
10961
11317
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
|
|
10962
|
-
const
|
|
10963
|
-
if (Object.keys(
|
|
10964
|
-
return
|
|
11318
|
+
const record2 = value;
|
|
11319
|
+
if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) throw new Error(`${label} has unknown or missing fields`);
|
|
11320
|
+
return record2;
|
|
10965
11321
|
}
|
|
10966
11322
|
async function createDelegatedShareKey(options2) {
|
|
10967
11323
|
if (!globalThis.crypto?.subtle) throw new Error("WebCrypto Ed25519 is required for delegated share keys");
|
|
@@ -11072,7 +11428,7 @@ function validateOwnerSharePolicyRegistration(value, expected) {
|
|
|
11072
11428
|
const publicKey = encodedKid.length === 34 ? encodedKid.slice(2) : encodedKid;
|
|
11073
11429
|
const signatureBytes = fromB64(proof.signature);
|
|
11074
11430
|
const signedBytes = new TextEncoder().encode(`${OWNER_SHARE_REGISTRATION_DOMAIN}${canonicalizeSignedObjectUnsigned(registrationCore)}`);
|
|
11075
|
-
if (signatureBytes.length !== 64 || !
|
|
11431
|
+
if (signatureBytes.length !== 64 || !ed255198.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
|
|
11076
11432
|
return { registration, proof };
|
|
11077
11433
|
}
|
|
11078
11434
|
function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
@@ -11086,7 +11442,7 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
|
11086
11442
|
}
|
|
11087
11443
|
|
|
11088
11444
|
// src/delegations/share-delivery.ts
|
|
11089
|
-
import { ed25519 as
|
|
11445
|
+
import { ed25519 as ed255199 } from "@noble/curves/ed25519";
|
|
11090
11446
|
var SHARE_DELIVERY_AUTHORIZATION_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v2\0";
|
|
11091
11447
|
function isCanonicalHttpsOrigin(value) {
|
|
11092
11448
|
let url;
|
|
@@ -11135,9 +11491,9 @@ var AUTHORIZATION_KEYS = [
|
|
|
11135
11491
|
];
|
|
11136
11492
|
function assertObject2(value, keys, label) {
|
|
11137
11493
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
|
|
11138
|
-
const
|
|
11139
|
-
if (Object.keys(
|
|
11140
|
-
return
|
|
11494
|
+
const record2 = value;
|
|
11495
|
+
if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) throw new Error(`${label} has unknown or missing fields`);
|
|
11496
|
+
return record2;
|
|
11141
11497
|
}
|
|
11142
11498
|
function fromB642(value) {
|
|
11143
11499
|
if (!/^[A-Za-z0-9_-]+$/.test(value)) throw new Error("share delivery value is not canonical base64url");
|
|
@@ -11174,7 +11530,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
|
11174
11530
|
if (publicKey.length !== 32) throw new Error("share delivery authorization proof key is invalid");
|
|
11175
11531
|
const signatureBytes = fromB642(proof.signature);
|
|
11176
11532
|
const signedBytes = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
|
|
11177
|
-
if (signatureBytes.length !== 64 || !
|
|
11533
|
+
if (signatureBytes.length !== 64 || !ed255199.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
|
|
11178
11534
|
return { authorization, proof };
|
|
11179
11535
|
}
|
|
11180
11536
|
function shareDeliveryTrustedKid(publicKey) {
|
|
@@ -11191,8 +11547,8 @@ var MemorySenderShareRecordStorage = class {
|
|
|
11191
11547
|
constructor() {
|
|
11192
11548
|
this.records = /* @__PURE__ */ new Map();
|
|
11193
11549
|
}
|
|
11194
|
-
async put(
|
|
11195
|
-
this.records.set(
|
|
11550
|
+
async put(record2) {
|
|
11551
|
+
this.records.set(record2.shareId, record2);
|
|
11196
11552
|
}
|
|
11197
11553
|
async list() {
|
|
11198
11554
|
return [...this.records.values()];
|
|
@@ -11228,7 +11584,7 @@ var SenderShareStore = class {
|
|
|
11228
11584
|
async save(receipt, key) {
|
|
11229
11585
|
const registration = receipt.registration;
|
|
11230
11586
|
if (registration.shareKeyDid !== key.did) throw new Error("share key does not match the registered receipt");
|
|
11231
|
-
const
|
|
11587
|
+
const record2 = {
|
|
11232
11588
|
shareId: registration.shareId,
|
|
11233
11589
|
registrationCid: registration.registrationCid,
|
|
11234
11590
|
policyCid: registration.policyCid,
|
|
@@ -11244,15 +11600,15 @@ var SenderShareStore = class {
|
|
|
11244
11600
|
registeredAt: registration.registeredAt,
|
|
11245
11601
|
expiresAt: registration.expiresAt
|
|
11246
11602
|
};
|
|
11247
|
-
await this.records.put(
|
|
11248
|
-
await this.keys.put(
|
|
11249
|
-
return
|
|
11603
|
+
await this.records.put(record2);
|
|
11604
|
+
await this.keys.put(record2.shareId, { cryptoKey: key.cryptoKey, publicKey: key.publicKey, extractable: key.extractable });
|
|
11605
|
+
return record2;
|
|
11250
11606
|
}
|
|
11251
11607
|
/** List shares created in any session, most recent first. */
|
|
11252
11608
|
async list(options2) {
|
|
11253
11609
|
const now = this.now().getTime();
|
|
11254
11610
|
const records = await this.records.list();
|
|
11255
|
-
return records.filter((
|
|
11611
|
+
return records.filter((record2) => (options2?.includeRevoked ?? false) || record2.revokedAt === void 0).filter((record2) => (options2?.includeExpired ?? false) || Date.parse(record2.expiresAt) > now).sort((left, right) => Date.parse(right.registeredAt) - Date.parse(left.registeredAt));
|
|
11256
11612
|
}
|
|
11257
11613
|
async get(shareId) {
|
|
11258
11614
|
return this.records.get(shareId);
|
|
@@ -11275,15 +11631,15 @@ var SenderShareStore = class {
|
|
|
11275
11631
|
* returned CID, then call {@link markRevoked} once that succeeds.
|
|
11276
11632
|
*/
|
|
11277
11633
|
async revocationTarget(shareId, scope) {
|
|
11278
|
-
const
|
|
11279
|
-
if (
|
|
11280
|
-
return scope === "direct" ?
|
|
11634
|
+
const record2 = await this.records.get(shareId);
|
|
11635
|
+
if (record2 === void 0) throw new Error(`Unknown share: ${shareId}`);
|
|
11636
|
+
return scope === "direct" ? record2.enforcementDelegationCid : record2.ownerDelegationCid;
|
|
11281
11637
|
}
|
|
11282
11638
|
/** Mark a share revoked locally after the caller's node-side revoke call succeeds. */
|
|
11283
11639
|
async markRevoked(shareId, revokedAt = this.now().toISOString()) {
|
|
11284
|
-
const
|
|
11285
|
-
if (
|
|
11286
|
-
const revoked = { ...
|
|
11640
|
+
const record2 = await this.records.get(shareId);
|
|
11641
|
+
if (record2 === void 0) throw new Error(`Unknown share: ${shareId}`);
|
|
11642
|
+
const revoked = { ...record2, revokedAt };
|
|
11287
11643
|
await this.records.put(revoked);
|
|
11288
11644
|
return revoked;
|
|
11289
11645
|
}
|
|
@@ -13117,27 +13473,27 @@ var AccountService = class {
|
|
|
13117
13473
|
const kvResult = this.accountKV();
|
|
13118
13474
|
if (!kvResult.ok) return kvResult;
|
|
13119
13475
|
let registered;
|
|
13120
|
-
for (const
|
|
13121
|
-
const manifestHash = hashJson(
|
|
13122
|
-
if (!options2.assumeUnregistered && await this.indexHasApplicationHash(
|
|
13476
|
+
for (const record2 of request.registryRecords) {
|
|
13477
|
+
const manifestHash = hashJson(record2.manifests);
|
|
13478
|
+
if (!options2.assumeUnregistered && await this.indexHasApplicationHash(record2.app_id, manifestHash)) {
|
|
13123
13479
|
registered = {
|
|
13124
|
-
appId:
|
|
13125
|
-
manifests:
|
|
13480
|
+
appId: record2.app_id,
|
|
13481
|
+
manifests: record2.manifests,
|
|
13126
13482
|
manifestHash,
|
|
13127
|
-
name:
|
|
13128
|
-
description:
|
|
13483
|
+
name: record2.manifests[0]?.name,
|
|
13484
|
+
description: record2.manifests[0]?.description
|
|
13129
13485
|
};
|
|
13130
13486
|
continue;
|
|
13131
13487
|
}
|
|
13132
13488
|
const stored = {
|
|
13133
|
-
app_id:
|
|
13134
|
-
manifests:
|
|
13489
|
+
app_id: record2.app_id,
|
|
13490
|
+
manifests: record2.manifests,
|
|
13135
13491
|
manifest_hash: manifestHash,
|
|
13136
13492
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
13137
13493
|
};
|
|
13138
|
-
const written = await kvResult.data.put(
|
|
13494
|
+
const written = await kvResult.data.put(record2.key, stored);
|
|
13139
13495
|
if (!written.ok) return accountErr(written.error);
|
|
13140
|
-
registered = applicationFromRecord(
|
|
13496
|
+
registered = applicationFromRecord(record2.key, stored);
|
|
13141
13497
|
await this.upsertApplicationIndexQuietly(registered);
|
|
13142
13498
|
}
|
|
13143
13499
|
return ok3(registered);
|
|
@@ -13211,11 +13567,11 @@ var AccountService = class {
|
|
|
13211
13567
|
if (!kvResult.ok) return kvResult;
|
|
13212
13568
|
const stored = spaces.map((space) => spaceRecordFromInput(space));
|
|
13213
13569
|
const registered = stored.map(
|
|
13214
|
-
(
|
|
13570
|
+
(record2) => spaceFromRecord(spaceKey(record2.space_id), record2)
|
|
13215
13571
|
);
|
|
13216
|
-
const items = stored.map((
|
|
13217
|
-
key: spaceKey(
|
|
13218
|
-
value:
|
|
13572
|
+
const items = stored.map((record2) => ({
|
|
13573
|
+
key: spaceKey(record2.space_id),
|
|
13574
|
+
value: record2
|
|
13219
13575
|
}));
|
|
13220
13576
|
const batchResult = await kvResult.data.batchPut(items);
|
|
13221
13577
|
if (batchResult.ok) {
|
|
@@ -13226,10 +13582,10 @@ var AccountService = class {
|
|
|
13226
13582
|
return accountErr(batchResult.error);
|
|
13227
13583
|
}
|
|
13228
13584
|
const reconcileFailures = [];
|
|
13229
|
-
for (const
|
|
13230
|
-
const written = await kvResult.data.put(spaceKey(
|
|
13585
|
+
for (const record2 of stored) {
|
|
13586
|
+
const written = await kvResult.data.put(spaceKey(record2.space_id), record2);
|
|
13231
13587
|
if (!written.ok) {
|
|
13232
|
-
reconcileFailures.push(`${
|
|
13588
|
+
reconcileFailures.push(`${record2.space_id}: ${written.error.message}`);
|
|
13233
13589
|
}
|
|
13234
13590
|
}
|
|
13235
13591
|
if (reconcileFailures.length > 0) {
|
|
@@ -13849,16 +14205,16 @@ function applicationKey(appId) {
|
|
|
13849
14205
|
function appIdFromKey(key) {
|
|
13850
14206
|
return key.startsWith(ACCOUNT_REGISTRY_PATH) ? key.slice(ACCOUNT_REGISTRY_PATH.length) : key;
|
|
13851
14207
|
}
|
|
13852
|
-
function applicationFromRecord(key,
|
|
13853
|
-
const manifests = Array.isArray(
|
|
14208
|
+
function applicationFromRecord(key, record2) {
|
|
14209
|
+
const manifests = Array.isArray(record2.manifests) ? record2.manifests : [];
|
|
13854
14210
|
const first = manifests[0];
|
|
13855
14211
|
return {
|
|
13856
|
-
appId:
|
|
14212
|
+
appId: record2.app_id ?? record2.appId ?? first?.app_id ?? appIdFromKey(key),
|
|
13857
14213
|
manifests,
|
|
13858
|
-
updatedAt:
|
|
14214
|
+
updatedAt: record2.updated_at ?? record2.updatedAt,
|
|
13859
14215
|
name: first?.name,
|
|
13860
14216
|
description: first?.description,
|
|
13861
|
-
manifestHash:
|
|
14217
|
+
manifestHash: record2.manifest_hash ?? record2.manifestHash ?? hashJson(manifests)
|
|
13862
14218
|
};
|
|
13863
14219
|
}
|
|
13864
14220
|
function indexedApplicationFromRow(row) {
|
|
@@ -13901,17 +14257,17 @@ function spaceRecordFromInput(space) {
|
|
|
13901
14257
|
expires_at: accountSpace.expiresAt instanceof Date ? accountSpace.expiresAt.toISOString() : accountSpace.expiresAt
|
|
13902
14258
|
};
|
|
13903
14259
|
}
|
|
13904
|
-
function spaceFromRecord(key,
|
|
13905
|
-
const expiresAt =
|
|
14260
|
+
function spaceFromRecord(key, record2) {
|
|
14261
|
+
const expiresAt = record2.expires_at ?? record2.expiresAt;
|
|
13906
14262
|
return {
|
|
13907
|
-
spaceId:
|
|
13908
|
-
name:
|
|
13909
|
-
ownerDid:
|
|
13910
|
-
type:
|
|
13911
|
-
permissions: Array.isArray(
|
|
13912
|
-
status:
|
|
13913
|
-
registeredAt:
|
|
13914
|
-
updatedAt:
|
|
14263
|
+
spaceId: record2.space_id ?? record2.spaceId ?? spaceIdFromKey(key),
|
|
14264
|
+
name: record2.name ?? spaceIdFromKey(key).split(":").pop() ?? spaceIdFromKey(key),
|
|
14265
|
+
ownerDid: record2.owner_did ?? record2.ownerDid ?? record2.owner ?? "",
|
|
14266
|
+
type: record2.type ?? "discovered",
|
|
14267
|
+
permissions: Array.isArray(record2.permissions) ? record2.permissions : [],
|
|
14268
|
+
status: record2.status ?? "active",
|
|
14269
|
+
registeredAt: record2.registered_at ?? record2.registeredAt,
|
|
14270
|
+
updatedAt: record2.updated_at ?? record2.updatedAt,
|
|
13915
14271
|
expiresAt: expiresAt ? new Date(expiresAt) : void 0
|
|
13916
14272
|
};
|
|
13917
14273
|
}
|
|
@@ -16722,7 +17078,7 @@ function portForProtocol(protocol) {
|
|
|
16722
17078
|
}
|
|
16723
17079
|
|
|
16724
17080
|
// src/location.ts
|
|
16725
|
-
import { ed25519 as
|
|
17081
|
+
import { ed25519 as ed2551910 } from "@noble/curves/ed25519";
|
|
16726
17082
|
import { verifyMessage as verifyMessage2 } from "viem";
|
|
16727
17083
|
var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
16728
17084
|
var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
@@ -16787,13 +17143,13 @@ var CloudLocationResolutionError = class extends Error {
|
|
|
16787
17143
|
this.attempts = attempts;
|
|
16788
17144
|
}
|
|
16789
17145
|
};
|
|
16790
|
-
function locationPayloadForRecord(
|
|
17146
|
+
function locationPayloadForRecord(record2) {
|
|
16791
17147
|
return {
|
|
16792
|
-
version:
|
|
16793
|
-
subject:
|
|
16794
|
-
multiaddrs: [...
|
|
16795
|
-
updated_at:
|
|
16796
|
-
sequence:
|
|
17148
|
+
version: record2.version,
|
|
17149
|
+
subject: record2.subject,
|
|
17150
|
+
multiaddrs: [...record2.multiaddrs],
|
|
17151
|
+
updated_at: record2.updated_at,
|
|
17152
|
+
sequence: record2.sequence
|
|
16797
17153
|
};
|
|
16798
17154
|
}
|
|
16799
17155
|
function canonicalLocationPayload(payload) {
|
|
@@ -16852,13 +17208,13 @@ function validateLocationRecord(input) {
|
|
|
16852
17208
|
return { ...payload, signature };
|
|
16853
17209
|
}
|
|
16854
17210
|
async function verifyLocationRecord(input) {
|
|
16855
|
-
const
|
|
16856
|
-
const payload = canonicalLocationPayload(locationPayloadForRecord(
|
|
16857
|
-
if (
|
|
16858
|
-
return verifyPkhSignature(
|
|
17211
|
+
const record2 = validateLocationRecord(input);
|
|
17212
|
+
const payload = canonicalLocationPayload(locationPayloadForRecord(record2));
|
|
17213
|
+
if (record2.subject.startsWith("did:pkh:")) {
|
|
17214
|
+
return verifyPkhSignature(record2.subject, payload, record2.signature);
|
|
16859
17215
|
}
|
|
16860
|
-
if (
|
|
16861
|
-
return verifyDidKeySignature(
|
|
17216
|
+
if (record2.subject.startsWith("did:key:")) {
|
|
17217
|
+
return verifyDidKeySignature(record2.subject, payload, record2.signature);
|
|
16862
17218
|
}
|
|
16863
17219
|
return false;
|
|
16864
17220
|
}
|
|
@@ -17044,18 +17400,18 @@ async function fetchRegistryLocalLinkCandidates(options2, fetchFn, existingCandi
|
|
|
17044
17400
|
}
|
|
17045
17401
|
const registryUrl = options2.registryUrl ?? DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL;
|
|
17046
17402
|
try {
|
|
17047
|
-
const
|
|
17048
|
-
if (!
|
|
17403
|
+
const record2 = await fetchLocationRecord(registryUrl, options2.subject, fetchFn);
|
|
17404
|
+
if (!record2) {
|
|
17049
17405
|
return [];
|
|
17050
17406
|
}
|
|
17051
17407
|
const shouldVerify = options2.verifyRecords ?? true;
|
|
17052
|
-
if (shouldVerify && !await verifyLocationRecord(
|
|
17408
|
+
if (shouldVerify && !await verifyLocationRecord(record2)) {
|
|
17053
17409
|
debugLog(
|
|
17054
17410
|
`registry record signature invalid for ${options2.subject}; skipping local-link lookup`
|
|
17055
17411
|
);
|
|
17056
17412
|
return [];
|
|
17057
17413
|
}
|
|
17058
|
-
return extractLocalLinkUrls(
|
|
17414
|
+
return extractLocalLinkUrls(record2).filter((url) => !existingCandidates.some((c) => c.url === url)).map((url) => ({
|
|
17059
17415
|
source: "local-link",
|
|
17060
17416
|
url,
|
|
17061
17417
|
timeoutMs: LOCAL_LINK_PROBE_TIMEOUT_MS
|
|
@@ -17064,12 +17420,12 @@ async function fetchRegistryLocalLinkCandidates(options2, fetchFn, existingCandi
|
|
|
17064
17420
|
return [];
|
|
17065
17421
|
}
|
|
17066
17422
|
}
|
|
17067
|
-
function extractLocalLinkUrls(
|
|
17068
|
-
if (!
|
|
17423
|
+
function extractLocalLinkUrls(record2) {
|
|
17424
|
+
if (!record2) {
|
|
17069
17425
|
return [];
|
|
17070
17426
|
}
|
|
17071
17427
|
const urls = [];
|
|
17072
|
-
for (const addr of
|
|
17428
|
+
for (const addr of record2.multiaddrs) {
|
|
17073
17429
|
let url;
|
|
17074
17430
|
try {
|
|
17075
17431
|
url = multiaddrToHttpUrl(addr);
|
|
@@ -17168,12 +17524,12 @@ async function resolveCentralized(subject, options2, verifyRecords) {
|
|
|
17168
17524
|
if (!options2.centralizedRegistryUrl) {
|
|
17169
17525
|
return null;
|
|
17170
17526
|
}
|
|
17171
|
-
const
|
|
17527
|
+
const record2 = await fetchLocationRecord(
|
|
17172
17528
|
options2.centralizedRegistryUrl,
|
|
17173
17529
|
subject,
|
|
17174
17530
|
options2.fetch
|
|
17175
17531
|
);
|
|
17176
|
-
return toCandidate(subject, "centralized",
|
|
17532
|
+
return toCandidate(subject, "centralized", record2, verifyRecords);
|
|
17177
17533
|
});
|
|
17178
17534
|
}
|
|
17179
17535
|
async function resolveFallback(subject, multiaddrs) {
|
|
@@ -17205,18 +17561,18 @@ async function toCandidate(subject, source, input, verifyRecord) {
|
|
|
17205
17561
|
}
|
|
17206
17562
|
const maybeRecord = input;
|
|
17207
17563
|
if (maybeRecord.version === 1 && maybeRecord.signature !== void 0) {
|
|
17208
|
-
const
|
|
17209
|
-
if (
|
|
17564
|
+
const record2 = validateLocationRecord(input);
|
|
17565
|
+
if (record2.subject !== subject) {
|
|
17210
17566
|
throw new LocationRecordValidationError(
|
|
17211
17567
|
"location record subject does not match requested subject"
|
|
17212
17568
|
);
|
|
17213
17569
|
}
|
|
17214
|
-
if (verifyRecord && !await verifyLocationRecord(
|
|
17570
|
+
if (verifyRecord && !await verifyLocationRecord(record2)) {
|
|
17215
17571
|
throw new LocationRecordValidationError(
|
|
17216
17572
|
"location record signature is invalid"
|
|
17217
17573
|
);
|
|
17218
17574
|
}
|
|
17219
|
-
return { source, multiaddrs: [...
|
|
17575
|
+
return { source, multiaddrs: [...record2.multiaddrs], record: record2 };
|
|
17220
17576
|
}
|
|
17221
17577
|
const candidateInput = input;
|
|
17222
17578
|
if (!Array.isArray(candidateInput.multiaddrs)) {
|
|
@@ -17226,18 +17582,18 @@ async function toCandidate(subject, source, input, verifyRecord) {
|
|
|
17226
17582
|
}
|
|
17227
17583
|
validateMultiaddrs(candidateInput.multiaddrs);
|
|
17228
17584
|
if (candidateInput.record !== void 0) {
|
|
17229
|
-
const
|
|
17230
|
-
if (
|
|
17585
|
+
const record2 = validateLocationRecord(candidateInput.record);
|
|
17586
|
+
if (record2.subject !== subject) {
|
|
17231
17587
|
throw new LocationRecordValidationError(
|
|
17232
17588
|
"location record subject does not match requested subject"
|
|
17233
17589
|
);
|
|
17234
17590
|
}
|
|
17235
|
-
if (verifyRecord && !await verifyLocationRecord(
|
|
17591
|
+
if (verifyRecord && !await verifyLocationRecord(record2)) {
|
|
17236
17592
|
throw new LocationRecordValidationError(
|
|
17237
17593
|
"location record signature is invalid"
|
|
17238
17594
|
);
|
|
17239
17595
|
}
|
|
17240
|
-
return { source, multiaddrs: [...candidateInput.multiaddrs], record };
|
|
17596
|
+
return { source, multiaddrs: [...candidateInput.multiaddrs], record: record2 };
|
|
17241
17597
|
}
|
|
17242
17598
|
return { source, multiaddrs: [...candidateInput.multiaddrs] };
|
|
17243
17599
|
}
|
|
@@ -17294,7 +17650,7 @@ function verifyDidKeySignature(did, payload, signature) {
|
|
|
17294
17650
|
"did:key signature must be a base64url Ed25519 signature"
|
|
17295
17651
|
);
|
|
17296
17652
|
}
|
|
17297
|
-
return
|
|
17653
|
+
return ed2551910.verify(
|
|
17298
17654
|
signatureBytes,
|
|
17299
17655
|
new TextEncoder().encode(payload),
|
|
17300
17656
|
publicKey
|
|
@@ -17302,7 +17658,7 @@ function verifyDidKeySignature(did, payload, signature) {
|
|
|
17302
17658
|
}
|
|
17303
17659
|
function verifyDidKeyEd25519Signature(did, payload, signature) {
|
|
17304
17660
|
const publicKey = ed25519PublicKeyFromDidKey2(did);
|
|
17305
|
-
return
|
|
17661
|
+
return ed2551910.verify(signature, payload, publicKey);
|
|
17306
17662
|
}
|
|
17307
17663
|
function ed25519PublicKeyFromDidKey2(did) {
|
|
17308
17664
|
const identifier = did.slice("did:key:".length);
|
|
@@ -17462,6 +17818,7 @@ export {
|
|
|
17462
17818
|
OPENKEY_ACTION_ID_SEPARATOR,
|
|
17463
17819
|
POLICY_CAPABILITY_V1_DOMAIN,
|
|
17464
17820
|
POLICY_CAPABILITY_V1_SCHEMA,
|
|
17821
|
+
POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE,
|
|
17465
17822
|
POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA,
|
|
17466
17823
|
POLICY_ENGINE_CHALLENGE_REQUEST_SCHEMA,
|
|
17467
17824
|
POLICY_ENGINE_CHALLENGE_RESPONSE_SCHEMA,
|
|
@@ -17469,11 +17826,15 @@ export {
|
|
|
17469
17826
|
POLICY_ENGINE_GRANT_PRESENTATION_DENIAL_CODES,
|
|
17470
17827
|
POLICY_ENGINE_RECORD_SCHEMA,
|
|
17471
17828
|
POLICY_ENGINE_RESOLVE_REQUEST_SCHEMA,
|
|
17829
|
+
POLICY_PRESENTATION_V3_DOMAIN,
|
|
17830
|
+
POLICY_PRESENTATION_V3_SCHEMA,
|
|
17472
17831
|
POLICY_SCHEMA,
|
|
17473
17832
|
POLICY_SESSION_UCAN_V1_PROFILE,
|
|
17474
17833
|
POLICY_STATUS_SCHEMA,
|
|
17475
17834
|
POLICY_V1_DOMAIN,
|
|
17476
17835
|
POLICY_V1_SCHEMA,
|
|
17836
|
+
POLICY_V2_DOMAIN,
|
|
17837
|
+
POLICY_V2_SCHEMA,
|
|
17477
17838
|
PORTABLE_DELEGATION_SCHEMA,
|
|
17478
17839
|
PermissionNotInManifestError,
|
|
17479
17840
|
PrefixedKVService,
|
|
@@ -17541,6 +17902,7 @@ export {
|
|
|
17541
17902
|
actionContains,
|
|
17542
17903
|
activateSessionWithHost,
|
|
17543
17904
|
addressStorageKey,
|
|
17905
|
+
admitPolicyCredentialV3,
|
|
17544
17906
|
applyPrefix,
|
|
17545
17907
|
bootstrapEncryptionNetworkId,
|
|
17546
17908
|
bootstrapSpaceId,
|
|
@@ -17550,6 +17912,7 @@ export {
|
|
|
17550
17912
|
buildDecryptFacts,
|
|
17551
17913
|
buildDecryptInvocation,
|
|
17552
17914
|
buildNetworkId2 as buildNetworkId,
|
|
17915
|
+
buildPolicyCredentialPresentationV3,
|
|
17553
17916
|
buildSpaceUri,
|
|
17554
17917
|
canonicalDigest,
|
|
17555
17918
|
canonicalHashHex,
|
|
@@ -17689,6 +18052,7 @@ export {
|
|
|
17689
18052
|
policyCidFromCanonicalBytes,
|
|
17690
18053
|
policyDigestHex,
|
|
17691
18054
|
policyIdForDigestHex,
|
|
18055
|
+
policyV2DigestHex,
|
|
17692
18056
|
principalDid,
|
|
17693
18057
|
principalDidEquals,
|
|
17694
18058
|
projectUnifiedPolicyCapabilities,
|
|
@@ -17712,6 +18076,7 @@ export {
|
|
|
17712
18076
|
shareCapabilityAllows,
|
|
17713
18077
|
shareDeliveryTrustedKid,
|
|
17714
18078
|
signCompactUcanAuthorization,
|
|
18079
|
+
signCompactUcanRootAuthorization,
|
|
17715
18080
|
signLocationRecord,
|
|
17716
18081
|
signShareEnvelope,
|
|
17717
18082
|
signedObjectIdFor,
|
|
@@ -17735,6 +18100,7 @@ export {
|
|
|
17735
18100
|
validateOwnerSharePolicyRegistration,
|
|
17736
18101
|
validateOwnerSharePolicyRegistrationBytes,
|
|
17737
18102
|
validatePersistedSessionData,
|
|
18103
|
+
validatePolicyCredentialRequirementV1,
|
|
17738
18104
|
validatePolicyEngineRecordSigned,
|
|
17739
18105
|
validatePolicyEngineRecordSignedShape,
|
|
17740
18106
|
validatePolicyEngineRecordUnsigned,
|
|
@@ -17745,6 +18111,7 @@ export {
|
|
|
17745
18111
|
validatePolicyStatusUnsigned,
|
|
17746
18112
|
validatePolicyUnsigned,
|
|
17747
18113
|
validateShareDeliveryAuthorizationBytes,
|
|
18114
|
+
validateUnifiedPolicyV2,
|
|
17748
18115
|
verifyDecryptResponse,
|
|
17749
18116
|
verifyDidKeyEd25519Signature,
|
|
17750
18117
|
verifyEip191MessageSignature,
|