@tinycloud/sdk-core 3.0.0-beta.8 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{credential-admission-CFjUChF8.d.cts → credential-admission-BxpkckU0.d.cts} +23 -3
- package/dist/{credential-admission-DIEPgQ0o.d.ts → credential-admission-CO9WMtGs.d.ts} +23 -3
- package/dist/delegations/index.cjs +101 -188
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +3 -3
- package/dist/delegations/index.d.ts +3 -3
- package/dist/delegations/index.js +102 -193
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +381 -218
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -7
- package/dist/index.d.ts +74 -7
- package/dist/index.js +382 -223
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +82 -36
- 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 +82 -36
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-DjmM_yJu.d.cts → recipient-types.schema-D9AI8tjN.d.cts} +42 -105
- package/dist/{recipient-types.schema-DjmM_yJu.d.ts → recipient-types.schema-D9AI8tjN.d.ts} +42 -105
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -311,6 +311,7 @@ var CREDENTIAL_ERROR_CODES = [
|
|
|
311
311
|
"ISSUER_UNREADY",
|
|
312
312
|
"OFFLINE",
|
|
313
313
|
"POPUP_BLOCKED",
|
|
314
|
+
"PROOF_REJECTED",
|
|
314
315
|
"REQUEST_EXPIRED",
|
|
315
316
|
"REQUEST_SUBSTITUTED",
|
|
316
317
|
"SIGNATURE_REJECTED",
|
|
@@ -324,6 +325,7 @@ var RECOVERABLE = /* @__PURE__ */ new Set([
|
|
|
324
325
|
"ISSUER_UNREADY",
|
|
325
326
|
"OFFLINE",
|
|
326
327
|
"POPUP_BLOCKED",
|
|
328
|
+
"PROOF_REJECTED",
|
|
327
329
|
"REQUEST_EXPIRED",
|
|
328
330
|
"SIGNATURE_REJECTED",
|
|
329
331
|
"UNSUPPORTED_PROFILE",
|
|
@@ -392,6 +394,7 @@ function holderBindingSigningBytes(binding) {
|
|
|
392
394
|
|
|
393
395
|
// src/credentials/descriptor.ts
|
|
394
396
|
var ID = /^[a-z0-9][a-z0-9._-]{0,127}(?:\/v1)?$/;
|
|
397
|
+
var CLAIM_NAME = /^[a-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
395
398
|
var STEP_TYPES = /* @__PURE__ */ new Set(["collect_input", "mailbox_otp", "holder_signature"]);
|
|
396
399
|
var ENDPOINTS = {
|
|
397
400
|
request: "request",
|
|
@@ -472,7 +475,7 @@ function validateCredentialFlowDescriptor(value) {
|
|
|
472
475
|
for (const value2 of raw.claims) {
|
|
473
476
|
const claim = object(value2, "claim");
|
|
474
477
|
exact(claim, ["name", "matching", "selectiveDisclosure"], "claim");
|
|
475
|
-
const name2 = text(claim.name, "claim.name",
|
|
478
|
+
const name2 = text(claim.name, "claim.name", CLAIM_NAME);
|
|
476
479
|
if (claimNames.has(name2) || claim.matching !== "normalized_exact" || typeof claim.selectiveDisclosure !== "boolean") fail("claim is invalid");
|
|
477
480
|
claimNames.add(name2);
|
|
478
481
|
}
|
|
@@ -563,9 +566,14 @@ function isDigest(value) {
|
|
|
563
566
|
return typeof value === "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
|
|
564
567
|
}
|
|
565
568
|
|
|
569
|
+
// src/credentials/email-domain.ts
|
|
570
|
+
import { canonicalEmailDomain, canonicalMailbox, isCanonicalEmailDomain, mailboxBelongsToDomain } from "@tinycloud/share-envelope";
|
|
571
|
+
|
|
566
572
|
// src/credentials/requirement.ts
|
|
567
573
|
var ID2 = /^[a-z0-9][a-z0-9._-]{0,127}(?:\/v1)?$/;
|
|
568
574
|
var EMAIL_CREDENTIAL_MAX_AGE_SECONDS = 3600;
|
|
575
|
+
var EMAIL_DOMAIN_CREDENTIAL_MAX_AGE_SECONDS = 300;
|
|
576
|
+
var CLAIM_NAME2 = /^[a-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
569
577
|
function createEmailCredentialRequirement(input) {
|
|
570
578
|
return validateCredentialRequirement({
|
|
571
579
|
type: "TinyCloudCredentialRequirement",
|
|
@@ -576,6 +584,17 @@ function createEmailCredentialRequirement(input) {
|
|
|
576
584
|
maxAgeSeconds: EMAIL_CREDENTIAL_MAX_AGE_SECONDS
|
|
577
585
|
});
|
|
578
586
|
}
|
|
587
|
+
function createEmailDomainCredentialRequirement(input) {
|
|
588
|
+
if (!isCanonicalEmailDomain(input.domain)) throw new CredentialError("UNSUPPORTED_PROFILE", "Email domain is not canonical");
|
|
589
|
+
return validateCredentialRequirement({
|
|
590
|
+
type: "TinyCloudCredentialRequirement",
|
|
591
|
+
version: 1,
|
|
592
|
+
profile: input.profile,
|
|
593
|
+
credentialType: input.credentialType,
|
|
594
|
+
claims: { emailDomain: input.domain },
|
|
595
|
+
maxAgeSeconds: EMAIL_DOMAIN_CREDENTIAL_MAX_AGE_SECONDS
|
|
596
|
+
});
|
|
597
|
+
}
|
|
579
598
|
function validateCredentialRequirement(value) {
|
|
580
599
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential requirement is invalid");
|
|
581
600
|
const raw = value;
|
|
@@ -589,7 +608,7 @@ function validateCredentialRequirement(value) {
|
|
|
589
608
|
if (typeof raw.claims !== "object" || raw.claims === null || Array.isArray(raw.claims)) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential claims are invalid");
|
|
590
609
|
const claims = {};
|
|
591
610
|
for (const [key, value2] of Object.entries(raw.claims).sort(([a], [b]) => a.localeCompare(b))) {
|
|
592
|
-
if (!
|
|
611
|
+
if (!CLAIM_NAME2.test(key) || typeof value2 !== "string" || value2.length === 0 || value2.length > 4096) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential claim is invalid");
|
|
593
612
|
claims[key] = value2;
|
|
594
613
|
}
|
|
595
614
|
if (raw.maxAgeSeconds !== void 0 && (!Number.isSafeInteger(raw.maxAgeSeconds) || raw.maxAgeSeconds < 1)) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential freshness is invalid");
|
|
@@ -4012,8 +4031,9 @@ async function signCompactUcanAuthorization(input) {
|
|
|
4012
4031
|
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
4013
4032
|
return signCompactUcan(input);
|
|
4014
4033
|
}
|
|
4034
|
+
var MAX_POLICY_ROOT_SECONDS = 31 * 24 * 60 * 60;
|
|
4015
4035
|
async function signCompactUcanRootAuthorization(input) {
|
|
4016
|
-
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore >
|
|
4036
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > MAX_POLICY_ROOT_SECONDS)
|
|
4017
4037
|
throw new Error("compact policy root lifetime must be between one second and 31 days");
|
|
4018
4038
|
return signCompactUcan({ ...input, proofs: [] });
|
|
4019
4039
|
}
|
|
@@ -4048,7 +4068,7 @@ function createCompactPolicyInvocation(input) {
|
|
|
4048
4068
|
const signature = ed255193.sign(signingInput, input.privateKey);
|
|
4049
4069
|
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url2(signature)}`);
|
|
4050
4070
|
}
|
|
4051
|
-
function
|
|
4071
|
+
function compactPolicyDescendantClaims(input) {
|
|
4052
4072
|
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
4053
4073
|
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
4054
4074
|
const parentFact = parent.payload.fct[0];
|
|
@@ -4056,29 +4076,53 @@ function createCompactPolicyDescendant(input) {
|
|
|
4056
4076
|
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
4057
4077
|
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
4058
4078
|
throw new Error("policy descendant exceeds the parent attenuation");
|
|
4079
|
+
const now = Math.max(input.now ?? parent.payload.nbf + 1, parent.payload.nbf + 1);
|
|
4080
|
+
const exp = Math.min(input.expiresAt ?? parent.payload.exp - 1, parent.payload.exp - 1);
|
|
4081
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
4082
|
+
return {
|
|
4083
|
+
parentCid: parent.cid,
|
|
4084
|
+
fact: { ...parentFact, remainingRedelegationDepth: depth - 1 },
|
|
4085
|
+
notBefore: now,
|
|
4086
|
+
expiresAt: exp,
|
|
4087
|
+
nonce: input.nonce ?? encodeBase64Url2(crypto.getRandomValues(new Uint8Array(16)))
|
|
4088
|
+
};
|
|
4089
|
+
}
|
|
4090
|
+
function createCompactPolicyDescendant(input) {
|
|
4091
|
+
const claims = compactPolicyDescendantClaims(input);
|
|
4059
4092
|
const principal = input.issuerDid.split("#", 1)[0];
|
|
4060
4093
|
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
4061
4094
|
const publicKey = ed255193.getPublicKey(input.privateKey);
|
|
4062
4095
|
if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
4063
|
-
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
4064
|
-
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
4065
|
-
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
4066
4096
|
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url2(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
4067
4097
|
const payload = {
|
|
4068
4098
|
att: input.attenuation,
|
|
4069
4099
|
aud: input.audienceDid,
|
|
4070
|
-
exp,
|
|
4071
|
-
fct: [
|
|
4100
|
+
exp: claims.expiresAt,
|
|
4101
|
+
fct: [claims.fact],
|
|
4072
4102
|
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
4073
|
-
nbf:
|
|
4074
|
-
nnc:
|
|
4075
|
-
prf: [
|
|
4103
|
+
nbf: claims.notBefore,
|
|
4104
|
+
nnc: claims.nonce,
|
|
4105
|
+
prf: [claims.parentCid]
|
|
4076
4106
|
};
|
|
4077
4107
|
const protectedSegment = encodeBase64Url2(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
4078
4108
|
const payloadSegment = encodeBase64Url2(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
4079
4109
|
const signature = ed255193.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
4080
4110
|
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url2(signature)}`);
|
|
4081
4111
|
}
|
|
4112
|
+
async function signCompactPolicyDescendant(input) {
|
|
4113
|
+
const claims = compactPolicyDescendantClaims(input);
|
|
4114
|
+
return signCompactUcan({
|
|
4115
|
+
issuerDid: input.issuerDid,
|
|
4116
|
+
audienceDid: input.audienceDid,
|
|
4117
|
+
attenuation: input.attenuation,
|
|
4118
|
+
facts: [claims.fact],
|
|
4119
|
+
proofs: [claims.parentCid],
|
|
4120
|
+
notBefore: claims.notBefore,
|
|
4121
|
+
expiresAt: claims.expiresAt,
|
|
4122
|
+
nonce: claims.nonce,
|
|
4123
|
+
sign: input.sign
|
|
4124
|
+
});
|
|
4125
|
+
}
|
|
4082
4126
|
function compactAttenuationContains(parent, child) {
|
|
4083
4127
|
const selector = (value) => {
|
|
4084
4128
|
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
@@ -4148,7 +4192,7 @@ function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
|
4148
4192
|
throw new Error("policy session UCAN fact is incomplete");
|
|
4149
4193
|
if (hasV4AuditFactShape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)))
|
|
4150
4194
|
throw new Error("policy session UCAN v4 audit facts are invalid");
|
|
4151
|
-
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 >
|
|
4195
|
+
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 > MAX_POLICY_ROOT_SECONDS || parsed.payload.iss.split("#", 1)[0] !== fact.nodeAudience || parsed.payload.aud !== fact.recipientDid)
|
|
4152
4196
|
throw new Error("policy session UCAN fact is invalid");
|
|
4153
4197
|
return {
|
|
4154
4198
|
authorization,
|
|
@@ -4572,24 +4616,21 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4572
4616
|
policy,
|
|
4573
4617
|
challenge
|
|
4574
4618
|
});
|
|
4575
|
-
const response = await
|
|
4619
|
+
const response = await postPolicyDelegation(
|
|
4620
|
+
fetchFn,
|
|
4576
4621
|
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
4577
4622
|
{
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
credentialSpaceId,
|
|
4590
|
-
presentation
|
|
4591
|
-
})
|
|
4592
|
-
}
|
|
4623
|
+
policyCid: input.policyCid,
|
|
4624
|
+
challengeId: challenge.challengeId,
|
|
4625
|
+
nonce: challenge.nonce,
|
|
4626
|
+
requirement: validateCredentialRequirement(input.requirement),
|
|
4627
|
+
credential: envelopeFromVerified(input.credential),
|
|
4628
|
+
accountAuthorizationCid,
|
|
4629
|
+
credentialSpaceId,
|
|
4630
|
+
presentation
|
|
4631
|
+
},
|
|
4632
|
+
requestedSessionExpiry(input.requestedExpiresAt, policy),
|
|
4633
|
+
input.signal
|
|
4593
4634
|
);
|
|
4594
4635
|
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
4595
4636
|
const value = record(await response.json(), "policy delegation");
|
|
@@ -4630,20 +4671,20 @@ async function admitPolicyCredentialV4(input) {
|
|
|
4630
4671
|
policy,
|
|
4631
4672
|
challenge
|
|
4632
4673
|
});
|
|
4633
|
-
const response = await
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4638
|
-
body: JSON.stringify({
|
|
4674
|
+
const response = await postPolicyDelegation(
|
|
4675
|
+
fetchFn,
|
|
4676
|
+
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
4677
|
+
{
|
|
4639
4678
|
policyCid: input.policyCid,
|
|
4640
4679
|
challengeId: challenge.challengeId,
|
|
4641
4680
|
nonce: challenge.nonce,
|
|
4642
4681
|
requirement: validateCredentialRequirement(input.requirement),
|
|
4643
4682
|
credential: envelopeFromVerified(input.credential),
|
|
4644
4683
|
presentation
|
|
4645
|
-
}
|
|
4646
|
-
|
|
4684
|
+
},
|
|
4685
|
+
requestedSessionExpiry(input.requestedExpiresAt, policy),
|
|
4686
|
+
input.signal
|
|
4687
|
+
);
|
|
4647
4688
|
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
4648
4689
|
const value = record(await response.json(), "policy delegation");
|
|
4649
4690
|
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") throw new Error("policy delegation response is invalid");
|
|
@@ -4667,6 +4708,27 @@ async function admitPolicyCredentialV4(input) {
|
|
|
4667
4708
|
input.signal?.throwIfAborted();
|
|
4668
4709
|
return Object.freeze({ challenge, presentation, session, delegationImported: true });
|
|
4669
4710
|
}
|
|
4711
|
+
function requestedSessionExpiry(requested, policy) {
|
|
4712
|
+
const value = requested === void 0 ? policy.expiresAt : requested;
|
|
4713
|
+
if (value === null || value === void 0) return void 0;
|
|
4714
|
+
const seconds = Math.floor(Date.parse(value) / 1e3);
|
|
4715
|
+
if (!Number.isFinite(seconds) || seconds <= Math.floor(Date.now() / 1e3) + 60) return void 0;
|
|
4716
|
+
return new Date(seconds * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
4717
|
+
}
|
|
4718
|
+
async function postPolicyDelegation(fetchFn, url, body, requestedExpiresAt, signal) {
|
|
4719
|
+
const send = (payload) => fetchFn(url, {
|
|
4720
|
+
method: "POST",
|
|
4721
|
+
redirect: "error",
|
|
4722
|
+
signal,
|
|
4723
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4724
|
+
body: JSON.stringify(payload)
|
|
4725
|
+
});
|
|
4726
|
+
if (requestedExpiresAt === void 0) return send(body);
|
|
4727
|
+
const response = await send({ ...body, requestedExpiresAt });
|
|
4728
|
+
if (response.status !== 422) return response;
|
|
4729
|
+
await response.body?.cancel().catch(() => void 0);
|
|
4730
|
+
return send(body);
|
|
4731
|
+
}
|
|
4670
4732
|
function policyRuntimeBasePath2(value) {
|
|
4671
4733
|
const path = value ?? "/policy/v3";
|
|
4672
4734
|
if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
|
|
@@ -6042,6 +6104,7 @@ var DelegationErrorSchema = z4.object({
|
|
|
6042
6104
|
});
|
|
6043
6105
|
var DelegationErrorCodes = {
|
|
6044
6106
|
AUTH_REQUIRED: "AUTH_REQUIRED",
|
|
6107
|
+
AUTH_UNAUTHORIZED: "AUTH_UNAUTHORIZED",
|
|
6045
6108
|
AUTH_EXPIRED: "AUTH_EXPIRED",
|
|
6046
6109
|
NOT_INITIALIZED: "NOT_INITIALIZED",
|
|
6047
6110
|
NOT_FOUND: "NOT_FOUND",
|
|
@@ -6406,7 +6469,7 @@ var CreateDelegationWasmResultSchema = z4.object({
|
|
|
6406
6469
|
// src/expiry.ts
|
|
6407
6470
|
var EPHEMERAL_MS = 60 * 60 * 1e3;
|
|
6408
6471
|
var SIGNED_READ_URL_MS = 5 * 60 * 1e3;
|
|
6409
|
-
var SESSION_MS =
|
|
6472
|
+
var SESSION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
6410
6473
|
var SHARE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
6411
6474
|
var APP_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
6412
6475
|
var MAX_MS = 10 * 365 * 24 * 60 * 60 * 1e3;
|
|
@@ -8174,7 +8237,6 @@ import { ed25519 as ed255195 } from "@noble/curves/ed25519";
|
|
|
8174
8237
|
import { blake3 as blake33 } from "@noble/hashes/blake3";
|
|
8175
8238
|
import { sha256 as sha2567 } from "@noble/hashes/sha256";
|
|
8176
8239
|
var ENVELOPE_SCHEMA = "xyz.tinycloud.share/envelope";
|
|
8177
|
-
var INLINE_PREFIX = "tc2:";
|
|
8178
8240
|
var RAW_CID_CODEC = 85;
|
|
8179
8241
|
var BLAKE3_256_CODE = 30;
|
|
8180
8242
|
var DEFAULT_MAX_INLINE_BYTES = 256 * 1024;
|
|
@@ -8879,25 +8941,8 @@ function parsePublishedShareLink(link, options2 = {}) {
|
|
|
8879
8941
|
}
|
|
8880
8942
|
const origin2 = normalizeOrigin(url.origin);
|
|
8881
8943
|
if (options2.trustedOrigins !== void 0 && !options2.trustedOrigins.map(normalizeOrigin).includes(origin2)) throw new ShareEnvelopeError("origin-mismatch", "share link origin is not trusted");
|
|
8882
|
-
if (url.
|
|
8883
|
-
if (url.
|
|
8884
|
-
let payload;
|
|
8885
|
-
try {
|
|
8886
|
-
const bytes2 = base64UrlToBytes(url.hash.slice("#v=2&p=".length));
|
|
8887
|
-
if (bytes2.length > (options2.maxInlineBytes ?? DEFAULT_MAX_INLINE_BYTES) * 2) throw new Error("inline payload too large");
|
|
8888
|
-
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes2));
|
|
8889
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("inline payload shape");
|
|
8890
|
-
payload = value;
|
|
8891
|
-
} catch (error) {
|
|
8892
|
-
throw new ShareEnvelopeError("invalid-link", error instanceof Error ? error.message : "invalid inline payload");
|
|
8893
|
-
}
|
|
8894
|
-
if (payload.v !== 2 || typeof payload.c !== "string" || typeof payload.cid !== "string" || payload.k !== void 0 && typeof payload.k !== "string" || Object.keys(payload).some((key3) => !["v", "c", "cid", "k"].includes(key3))) throw new ShareEnvelopeError("invalid-link", "inline payload fields are invalid");
|
|
8895
|
-
const sealed = base64UrlToBytes(payload.c);
|
|
8896
|
-
if (!verifyPublishedShareCid(payload.cid, sealed)) throw new ShareEnvelopeError("cid-mismatch", "inline payload CID does not match");
|
|
8897
|
-
const key2 = payload.k === void 0 ? void 0 : base64UrlToBytes(payload.k);
|
|
8898
|
-
if (key2 !== void 0 && key2.length !== 32) throw new ShareEnvelopeError("invalid-link", "inline payload key is invalid");
|
|
8899
|
-
return { origin: origin2, cid: payload.cid, ...key2 === void 0 ? {} : { key: key2 }, sealed };
|
|
8900
|
-
}
|
|
8944
|
+
if (url.username !== "" || url.password !== "") throw new ShareEnvelopeError("invalid-link", "share link is not canonical");
|
|
8945
|
+
if (url.search !== "") throw new ShareEnvelopeError("invalid-link", "share link is not canonical");
|
|
8901
8946
|
const match = /^\/s\/([a-z2-7]+)$/.exec(url.pathname);
|
|
8902
8947
|
if (match === null || !url.hash.startsWith("#k=")) throw new ShareEnvelopeError("invalid-link", "published share link is invalid");
|
|
8903
8948
|
const key = base64UrlToBytes(url.hash.slice(3));
|
|
@@ -8917,13 +8962,10 @@ function parseShareUrl(link, options2 = {}) {
|
|
|
8917
8962
|
} catch {
|
|
8918
8963
|
throw new ShareEnvelopeError("invalid-link", "share link must be an absolute URL");
|
|
8919
8964
|
}
|
|
8920
|
-
if (url.search !== "") throw new ShareEnvelopeError("invalid-link", "share links must not contain query parameters");
|
|
8921
8965
|
const origin2 = normalizeOrigin(url.origin);
|
|
8922
8966
|
if (options2.trustedOrigins !== void 0 && !options2.trustedOrigins.map(normalizeOrigin).includes(origin2)) throw new ShareEnvelopeError("origin-mismatch", "share link origin is not trusted");
|
|
8923
|
-
if (url.pathname === "/
|
|
8924
|
-
|
|
8925
|
-
return { kind: "inline", origin: origin2, cid: published.cid, key: published.key, url: `${url.origin}${url.pathname}`, protocol: "share-envelope-v2" };
|
|
8926
|
-
}
|
|
8967
|
+
if (url.pathname === "/viewer") throw new ShareEnvelopeError("invalid-link", "retired viewer links are not accepted");
|
|
8968
|
+
if (url.search !== "") throw new ShareEnvelopeError("invalid-link", "share links must not contain query parameters");
|
|
8927
8969
|
const match = url.pathname.match(/^\/s\/(i\/)?([^/]+)$/);
|
|
8928
8970
|
if (!match) throw new ShareEnvelopeError("invalid-link", "share link path is invalid");
|
|
8929
8971
|
const fragmentParams = url.hash === "" ? void 0 : new URLSearchParams(url.hash.slice(1));
|
|
@@ -8946,9 +8988,10 @@ function parseShareUrl(link, options2 = {}) {
|
|
|
8946
8988
|
}
|
|
8947
8989
|
function isV2ShareLink(link) {
|
|
8948
8990
|
try {
|
|
8949
|
-
|
|
8991
|
+
const url = new URL(link);
|
|
8992
|
+
return url.search === "" && url.pathname.startsWith("/s/");
|
|
8950
8993
|
} catch {
|
|
8951
|
-
return
|
|
8994
|
+
return false;
|
|
8952
8995
|
}
|
|
8953
8996
|
}
|
|
8954
8997
|
async function encryptShareBytes(bytes2, key) {
|
|
@@ -10448,6 +10491,13 @@ var ShareRecipientClient = class {
|
|
|
10448
10491
|
};
|
|
10449
10492
|
|
|
10450
10493
|
// src/delegations/SharingService.ts
|
|
10494
|
+
function spaceIdsEqual(left, right) {
|
|
10495
|
+
const normalizeOwnerAddress = (space) => {
|
|
10496
|
+
const match = /^(tinycloud:pkh:eip155:\d+:)(0x[0-9a-fA-F]{40})(:.+)$/.exec(space);
|
|
10497
|
+
return match === null ? space : `${match[1]}${match[2].toLowerCase()}${match[3]}`;
|
|
10498
|
+
};
|
|
10499
|
+
return normalizeOwnerAddress(left) === normalizeOwnerAddress(right);
|
|
10500
|
+
}
|
|
10451
10501
|
function inferShortServiceFromActionUrns(actions) {
|
|
10452
10502
|
let short;
|
|
10453
10503
|
for (const action of actions) {
|
|
@@ -10683,11 +10733,11 @@ var SharingService = class {
|
|
|
10683
10733
|
}
|
|
10684
10734
|
return result;
|
|
10685
10735
|
};
|
|
10686
|
-
const canSatisfyFromRegistry = this.
|
|
10736
|
+
const canSatisfyFromRegistry = this.classifyDelegationAuthority(
|
|
10687
10737
|
fullPath,
|
|
10688
10738
|
actions,
|
|
10689
10739
|
requestedExpiry
|
|
10690
|
-
);
|
|
10740
|
+
) === "ok";
|
|
10691
10741
|
if (canSatisfyFromRegistry) {
|
|
10692
10742
|
const delegationResult = await this.createSessionDelegation(plainDID, fullPath, actions, expiry);
|
|
10693
10743
|
const childDelegationActiveError = this.retiredGraphError();
|
|
@@ -10757,49 +10807,58 @@ var SharingService = class {
|
|
|
10757
10807
|
return { ok: true, data: shareLink };
|
|
10758
10808
|
}
|
|
10759
10809
|
/**
|
|
10760
|
-
*
|
|
10761
|
-
*
|
|
10762
|
-
*
|
|
10763
|
-
*
|
|
10764
|
-
*
|
|
10765
|
-
*
|
|
10810
|
+
* Report, without side effects, whether this session's registry authority
|
|
10811
|
+
* can issue the child delegation {@link generate} would create for the same
|
|
10812
|
+
* `path`, `actions` and `expiry` (defaults and `pathPrefix` applied the
|
|
10813
|
+
* same way):
|
|
10814
|
+
*
|
|
10815
|
+
* - `"ok"`: an uncaveated entry covers it.
|
|
10816
|
+
* - `"caveated"`: only caveated entries cover it. SharingService cannot
|
|
10817
|
+
* carry signed ReCap caveats into a child delegation.
|
|
10818
|
+
* - `"not-covered"`: no entry covers it, or there is no session.
|
|
10819
|
+
*
|
|
10820
|
+
* It does not consult `onRootDelegationNeeded`, so a signer-backed session
|
|
10821
|
+
* may still generate when this is not `"ok"`.
|
|
10822
|
+
*/
|
|
10823
|
+
preflightGenerate(params) {
|
|
10824
|
+
if (!this.session || !params.path) return "not-covered";
|
|
10825
|
+
const fullPath = this.pathPrefix ? `${this.pathPrefix}/${params.path}`.replace(/\/+/g, "/") : params.path;
|
|
10826
|
+
return this.classifyDelegationAuthority(
|
|
10827
|
+
fullPath,
|
|
10828
|
+
params.actions ?? DEFAULT_READ_ACTIONS,
|
|
10829
|
+
params.expiry ?? new Date(Date.now() + DEFAULT_EXPIRY_MS)
|
|
10830
|
+
);
|
|
10831
|
+
}
|
|
10832
|
+
/**
|
|
10833
|
+
* Classify the registry's authority for a child delegation. An entry
|
|
10834
|
+
* satisfies it when it is in the session space, valid, lasts at least until
|
|
10835
|
+
* `requestedExpiry`, allows sub-delegation, covers `path` (exact or parent)
|
|
10836
|
+
* and grants every action. Satisfying entries with caveats are unusable.
|
|
10766
10837
|
* @internal
|
|
10767
10838
|
*/
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
for (const key of
|
|
10771
|
-
const
|
|
10772
|
-
|
|
10773
|
-
if (delegation.spaceId !== this.session?.spaceId) {
|
|
10774
|
-
continue;
|
|
10775
|
-
}
|
|
10776
|
-
if ((delegation.caveats?.length ?? 0) > 0) {
|
|
10777
|
-
continue;
|
|
10778
|
-
}
|
|
10779
|
-
if (!this.registry.isDelegationValid(delegation)) {
|
|
10839
|
+
classifyDelegationAuthority(path, actions, requestedExpiry) {
|
|
10840
|
+
let coveredOnlyByCaveated = false;
|
|
10841
|
+
for (const key of this.registry.getAllKeys()) {
|
|
10842
|
+
for (const delegation of this.registry.getDelegationsForKey(key.id)) {
|
|
10843
|
+
if (delegation.spaceId === void 0 || !spaceIdsEqual(delegation.spaceId, this.session?.spaceId ?? "")) {
|
|
10780
10844
|
continue;
|
|
10781
10845
|
}
|
|
10782
|
-
if (delegation
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
if (delegation.
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
const delegationPath = delegation.path || "";
|
|
10789
|
-
if (!this.pathMatches(delegationPath, path)) {
|
|
10846
|
+
if (!this.registry.isDelegationValid(delegation)) continue;
|
|
10847
|
+
if (delegation.expiry < requestedExpiry) continue;
|
|
10848
|
+
if (delegation.allowSubDelegation === false) continue;
|
|
10849
|
+
if (!this.pathMatches(delegation.path || "", path)) continue;
|
|
10850
|
+
const delegationActions = delegation.actions || [];
|
|
10851
|
+
if (!actions.every((action) => delegationActions.includes(action) || delegationActions.includes("*"))) {
|
|
10790
10852
|
continue;
|
|
10791
10853
|
}
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
(action) => delegationActions.includes(action) || delegationActions.includes("*")
|
|
10795
|
-
);
|
|
10796
|
-
if (!hasAllActions) {
|
|
10854
|
+
if ((delegation.caveats?.length ?? 0) > 0) {
|
|
10855
|
+
coveredOnlyByCaveated = true;
|
|
10797
10856
|
continue;
|
|
10798
10857
|
}
|
|
10799
|
-
return
|
|
10858
|
+
return "ok";
|
|
10800
10859
|
}
|
|
10801
10860
|
}
|
|
10802
|
-
return
|
|
10861
|
+
return coveredOnlyByCaveated ? "caveated" : "not-covered";
|
|
10803
10862
|
}
|
|
10804
10863
|
retiredGraphError() {
|
|
10805
10864
|
try {
|
|
@@ -10898,11 +10957,23 @@ var SharingService = class {
|
|
|
10898
10957
|
const errorText = await registerRes.text();
|
|
10899
10958
|
const registrationTextActiveError = this.retiredGraphError();
|
|
10900
10959
|
if (registrationTextActiveError) return { ok: false, error: registrationTextActiveError };
|
|
10960
|
+
const message = `Failed to register delegation with server: ${registerRes.status} ${errorText}`;
|
|
10961
|
+
if (registerRes.status === 401 || registerRes.status === 403) {
|
|
10962
|
+
return {
|
|
10963
|
+
ok: false,
|
|
10964
|
+
error: createError2(
|
|
10965
|
+
DelegationErrorCodes.AUTH_UNAUTHORIZED,
|
|
10966
|
+
message,
|
|
10967
|
+
void 0,
|
|
10968
|
+
{ status: registerRes.status }
|
|
10969
|
+
)
|
|
10970
|
+
};
|
|
10971
|
+
}
|
|
10901
10972
|
return {
|
|
10902
10973
|
ok: false,
|
|
10903
10974
|
error: createError2(
|
|
10904
10975
|
DelegationErrorCodes.CREATION_FAILED,
|
|
10905
|
-
|
|
10976
|
+
message
|
|
10906
10977
|
)
|
|
10907
10978
|
};
|
|
10908
10979
|
}
|
|
@@ -11759,114 +11830,13 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
|
11759
11830
|
return validateOwnerSharePolicyRegistration(value, expected);
|
|
11760
11831
|
}
|
|
11761
11832
|
|
|
11762
|
-
// src/delegations/share-delivery.ts
|
|
11763
|
-
import { ed25519 as ed255199 } from "@noble/curves/ed25519";
|
|
11764
|
-
var SHARE_DELIVERY_AUTHORIZATION_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v2\0";
|
|
11765
|
-
function isCanonicalHttpsOrigin(value) {
|
|
11766
|
-
let url;
|
|
11767
|
-
try {
|
|
11768
|
-
url = new URL(value);
|
|
11769
|
-
} catch {
|
|
11770
|
-
return false;
|
|
11771
|
-
}
|
|
11772
|
-
return url.protocol === "https:" && url.origin === value && url.pathname === "/" && url.search === "" && url.hash === "" && url.username === "" && url.password === "";
|
|
11773
|
-
}
|
|
11774
|
-
var AUTHORIZATION_KEYS = [
|
|
11775
|
-
"type",
|
|
11776
|
-
"version",
|
|
11777
|
-
"jti",
|
|
11778
|
-
"shareCid",
|
|
11779
|
-
"shareId",
|
|
11780
|
-
"registrationCid",
|
|
11781
|
-
"delegationCid",
|
|
11782
|
-
"enforcementDelegationCid",
|
|
11783
|
-
"envelopeCid",
|
|
11784
|
-
"policyCid",
|
|
11785
|
-
"nodeAudience",
|
|
11786
|
-
"targetOrigin",
|
|
11787
|
-
"openCredentialsAudience",
|
|
11788
|
-
"holder",
|
|
11789
|
-
"recipientMatcher",
|
|
11790
|
-
"deliveryEmail",
|
|
11791
|
-
"shareUrl",
|
|
11792
|
-
"returnOrigin",
|
|
11793
|
-
"documentName",
|
|
11794
|
-
"senderDid",
|
|
11795
|
-
"senderTrust",
|
|
11796
|
-
"contentSource",
|
|
11797
|
-
"contentSourceDigest",
|
|
11798
|
-
"shareExpiresAt",
|
|
11799
|
-
"issuedAt",
|
|
11800
|
-
"reportAbuseToken",
|
|
11801
|
-
"actions",
|
|
11802
|
-
"resource",
|
|
11803
|
-
"authorityMaterialHandle",
|
|
11804
|
-
"authorityMaterialDigest",
|
|
11805
|
-
"requestBodyDigest",
|
|
11806
|
-
"idempotencyKey",
|
|
11807
|
-
"expiresAt",
|
|
11808
|
-
"dataAuthority"
|
|
11809
|
-
];
|
|
11810
|
-
function assertObject2(value, keys, label) {
|
|
11811
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
|
|
11812
|
-
const record2 = value;
|
|
11813
|
-
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`);
|
|
11814
|
-
return record2;
|
|
11815
|
-
}
|
|
11816
|
-
function fromB642(value) {
|
|
11817
|
-
if (!/^[A-Za-z0-9_-]+$/.test(value)) throw new Error("share delivery value is not canonical base64url");
|
|
11818
|
-
if (typeof atob === "function") {
|
|
11819
|
-
const padded = value.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - value.length % 4) % 4);
|
|
11820
|
-
return Uint8Array.from(atob(padded), (character) => character.charCodeAt(0));
|
|
11821
|
-
}
|
|
11822
|
-
if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(value, "base64url"));
|
|
11823
|
-
throw new Error("base64url decoding is unavailable");
|
|
11824
|
-
}
|
|
11825
|
-
function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
11826
|
-
let value;
|
|
11827
|
-
try {
|
|
11828
|
-
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytesValue));
|
|
11829
|
-
} catch {
|
|
11830
|
-
throw new Error("share delivery authorization response is not valid UTF-8 JSON");
|
|
11831
|
-
}
|
|
11832
|
-
const root = assertObject2(value, ["authorization", "proof"], "share delivery authorization response");
|
|
11833
|
-
const authorization = assertObject2(root.authorization, AUTHORIZATION_KEYS, "share delivery authorization");
|
|
11834
|
-
const proof = assertObject2(root.proof, ["alg", "kid", "signature"], "share delivery authorization proof");
|
|
11835
|
-
const request = expected.request;
|
|
11836
|
-
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) {
|
|
11837
|
-
throw new Error("share delivery authorization is not bound to the submitted request");
|
|
11838
|
-
}
|
|
11839
|
-
if (typeof authorization.issuedAt !== "string" || Date.parse(authorization.issuedAt) > Date.now() + 6e4) throw new Error("share delivery authorization issuedAt is invalid");
|
|
11840
|
-
if (new Date(authorization.expiresAt).toISOString() !== authorization.expiresAt) throw new Error("share delivery authorization expiresAt is non-canonical");
|
|
11841
|
-
if (typeof authorization.openCredentialsAudience !== "string" || !isCanonicalHttpsOrigin(authorization.openCredentialsAudience) || authorization.openCredentialsAudience !== expected.credentialsAudience || authorization.openCredentialsAudience === authorization.nodeAudience || authorization.openCredentialsAudience === authorization.returnOrigin) {
|
|
11842
|
-
throw new Error("share delivery authorization openCredentialsAudience is missing or untrusted");
|
|
11843
|
-
}
|
|
11844
|
-
if (proof.alg !== "EdDSA" || typeof proof.kid !== "string" || typeof proof.signature !== "string") throw new Error("share delivery authorization proof is invalid");
|
|
11845
|
-
if (proof.kid !== expected.nodeProof.kid) throw new Error("share delivery authorization proof key is not trusted");
|
|
11846
|
-
const encodedKid = expected.nodeProof.publicKey;
|
|
11847
|
-
const publicKey = encodedKid.length === 34 && encodedKid[0] === 237 && encodedKid[1] === 1 ? encodedKid.slice(2) : encodedKid;
|
|
11848
|
-
if (publicKey.length !== 32) throw new Error("share delivery authorization proof key is invalid");
|
|
11849
|
-
const signatureBytes = fromB642(proof.signature);
|
|
11850
|
-
const signedBytes = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
|
|
11851
|
-
if (signatureBytes.length !== 64 || !ed255199.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
|
|
11852
|
-
return { authorization, proof };
|
|
11853
|
-
}
|
|
11854
|
-
function shareDeliveryTrustedKid(publicKey) {
|
|
11855
|
-
if (publicKey.length !== 32) throw new Error("share delivery node key must be a raw 32-byte Ed25519 public key");
|
|
11856
|
-
const prefixed = new Uint8Array(34);
|
|
11857
|
-
prefixed.set([237, 1]);
|
|
11858
|
-
prefixed.set(publicKey, 2);
|
|
11859
|
-
const did = `did:key:${base58btc.encode(prefixed)}`;
|
|
11860
|
-
return `${did}#${did.slice("did:key:".length)}`;
|
|
11861
|
-
}
|
|
11862
|
-
|
|
11863
11833
|
// src/delegations/share-delivery-v3.ts
|
|
11864
|
-
import { ed25519 as
|
|
11834
|
+
import { ed25519 as ed255199 } from "@noble/curves/ed25519";
|
|
11865
11835
|
import { sha256 as sha25611 } from "@noble/hashes/sha256";
|
|
11866
11836
|
var CREDENTIAL_INVITATION_REQUEST_DOMAIN = "xyz.tinycloud.credentials/invitation-request/v1\0";
|
|
11867
11837
|
var DELIVERY_ADMISSION_DOMAIN = "xyz.tinycloud.policy/delivery-admission/v0\0";
|
|
11868
|
-
var REQUEST_KEYS = ["schema", "policyId", "recipient", "resource", "credentialType", "returnLink", "envelopeRef", "audience", "issuedAt", "expiresAt", "nonce"];
|
|
11869
|
-
var ADMISSION_KEYS = ["schema", "policyId", "ownerDid", "recipient", "resource", "actions", "credentialType", "returnLink", "envelopeRef", "senderKeyDid", "audience", "issuedAt", "expiresAt", "nonce", "signature"];
|
|
11838
|
+
var REQUEST_KEYS = ["schema", "policyId", "recipient", "resource", "credentialType", "returnLink", "envelopeRef", "label", "shareExpiresAt", "audience", "issuedAt", "expiresAt", "nonce"];
|
|
11839
|
+
var ADMISSION_KEYS = ["schema", "policyId", "ownerDid", "recipient", "resource", "actions", "credentialType", "returnLink", "envelopeRef", "label", "shareExpiresAt", "senderKeyDid", "audience", "issuedAt", "expiresAt", "nonce", "signature"];
|
|
11870
11840
|
function exactObject2(value, keys, label) {
|
|
11871
11841
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
|
|
11872
11842
|
const record2 = value;
|
|
@@ -11910,15 +11880,16 @@ function validateShareDeliveryAuthorizationV3Bytes(bytes2, expected) {
|
|
|
11910
11880
|
const contentSource = object3(envelope.contentSource, "v3 content source");
|
|
11911
11881
|
const envelopeSignature = object3(envelope.signature, "v3 envelope signature");
|
|
11912
11882
|
const target = object3(envelope.target, "v3 target");
|
|
11913
|
-
const
|
|
11914
|
-
|
|
11883
|
+
const binding = object3(envelope.attestedEnforcerBinding, "v3 attested enforcer binding");
|
|
11884
|
+
const fields = ["policyId", "recipient", "resource", "credentialType", "returnLink", "envelopeRef", "label", "shareExpiresAt", "audience", "issuedAt", "expiresAt", "nonce"];
|
|
11885
|
+
if (request.schema !== "xyz.tinycloud.credentials/invitation-request/v1" || admission.schema !== "xyz.tinycloud.policy/delivery-admission/v0" || fields.some((field) => request[field] !== admission[field]) || request.policyId !== envelope.policyCid || request.recipient !== expected.request.recipientEmail || request.resource !== contentSource.kvResource || request.credentialType !== credentialType.id || request.credentialType !== "opencredentials.email/v1" || request.returnLink !== expected.request.shareUrl || request.envelopeRef !== expected.request.shareCid || request.label !== expected.request.documentName || request.shareExpiresAt !== envelope.expiry || request.audience !== expected.deliveryAudience || request.expiresAt !== expected.request.expiresAt || request.nonce !== expected.request.jti || admission.ownerDid !== envelopeSignature.signerDid || admission.senderKeyDid !== expected.senderKeyDid || canonicalizeSignedObjectUnsigned(admission.actions) !== canonicalizeSignedObjectUnsigned(["tinycloud.kv/get"]) || signature.suite !== "eddsa-ed25519-sha256-jcs-v1" || target.nodeAudience !== binding.nodeAudience || signature.signerDid !== binding.nodeAudience) throw new Error("v3 share delivery authorization is not bound to the submitted request");
|
|
11915
11886
|
const issuedAt = Date.parse(String(request.issuedAt));
|
|
11916
11887
|
const expiresAt = Date.parse(String(request.expiresAt));
|
|
11917
11888
|
if (!Number.isFinite(issuedAt) || !Number.isFinite(expiresAt) || expiresAt <= issuedAt || expiresAt - issuedAt > 15 * 6e4) throw new Error("v3 share delivery authorization time is invalid");
|
|
11918
11889
|
const admissionSignature = decodeBase64Url3(signature.value);
|
|
11919
11890
|
const { signature: _signature, ...unsignedAdmission } = admission;
|
|
11920
11891
|
const digest4 = sha25611(new TextEncoder().encode(`${DELIVERY_ADMISSION_DOMAIN}${canonicalizeSignedObjectUnsigned(unsignedAdmission)}`));
|
|
11921
|
-
if (admissionSignature.length !== 64 || !
|
|
11892
|
+
if (admissionSignature.length !== 64 || !ed255199.verify(admissionSignature, digest4, didKeyBytes2(String(signature.signerDid)))) throw new Error("v3 share delivery admission signature is invalid");
|
|
11922
11893
|
return { request, admission };
|
|
11923
11894
|
}
|
|
11924
11895
|
|
|
@@ -12042,9 +12013,6 @@ import {
|
|
|
12042
12013
|
publishPolicyShare,
|
|
12043
12014
|
claimShare,
|
|
12044
12015
|
resumeShareAuthorization,
|
|
12045
|
-
isLegacyShareLink,
|
|
12046
|
-
receiveLegacyShare,
|
|
12047
|
-
migrateShare,
|
|
12048
12016
|
MemoryEncryptedShareHistoryStorage,
|
|
12049
12017
|
EncryptedSenderShareHistory
|
|
12050
12018
|
} from "@tinycloud/share-sdk";
|
|
@@ -12052,8 +12020,7 @@ import {
|
|
|
12052
12020
|
inspectShare,
|
|
12053
12021
|
receiveShare,
|
|
12054
12022
|
ShareReceiveError,
|
|
12055
|
-
toShareErrorInfo
|
|
12056
|
-
verifyBearerEnvelope
|
|
12023
|
+
toShareErrorInfo
|
|
12057
12024
|
} from "@tinycloud/share-sdk";
|
|
12058
12025
|
|
|
12059
12026
|
// src/networkId.ts
|
|
@@ -17689,7 +17656,7 @@ function portForProtocol(protocol) {
|
|
|
17689
17656
|
}
|
|
17690
17657
|
|
|
17691
17658
|
// src/location.ts
|
|
17692
|
-
import { ed25519 as
|
|
17659
|
+
import { ed25519 as ed2551910 } from "@noble/curves/ed25519";
|
|
17693
17660
|
import { verifyMessage as verifyMessage2 } from "viem";
|
|
17694
17661
|
var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
17695
17662
|
var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
@@ -17697,6 +17664,7 @@ var DEFAULT_LOCAL_NODE_URL = "http://127.0.0.1:8000";
|
|
|
17697
17664
|
var LOCAL_LOOPBACK_PROBE_TIMEOUT_MS = 250;
|
|
17698
17665
|
var LOCAL_LINK_PROBE_TIMEOUT_MS = 750;
|
|
17699
17666
|
var LOCAL_LINK_HOST_SUFFIX = ".local.tinycloud.link";
|
|
17667
|
+
var OWNER_NODE_BINDING_TIMEOUT_MS = 5e3;
|
|
17700
17668
|
function createInMemoryLocalNodeIdentityStore() {
|
|
17701
17669
|
const pins = /* @__PURE__ */ new Map();
|
|
17702
17670
|
return {
|
|
@@ -17747,6 +17715,13 @@ var LocationRecordValidationError = class extends Error {
|
|
|
17747
17715
|
this.name = "LocationRecordValidationError";
|
|
17748
17716
|
}
|
|
17749
17717
|
};
|
|
17718
|
+
var LocationRegistryHttpError = class extends Error {
|
|
17719
|
+
constructor(message, status) {
|
|
17720
|
+
super(message);
|
|
17721
|
+
this.status = status;
|
|
17722
|
+
this.name = "LocationRegistryHttpError";
|
|
17723
|
+
}
|
|
17724
|
+
};
|
|
17750
17725
|
var CloudLocationResolutionError = class extends Error {
|
|
17751
17726
|
constructor(subject, attempts) {
|
|
17752
17727
|
super(`Unable to resolve TinyCloud location for ${subject}`);
|
|
@@ -17829,21 +17804,80 @@ async function verifyLocationRecord(input) {
|
|
|
17829
17804
|
}
|
|
17830
17805
|
return false;
|
|
17831
17806
|
}
|
|
17832
|
-
async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fetch) {
|
|
17807
|
+
async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fetch, signal) {
|
|
17833
17808
|
const url = `${registryUrl.replace(/\/$/, "")}/v1/locations/${encodeURIComponent(subject)}`;
|
|
17834
|
-
const response = await fetchFn(url
|
|
17809
|
+
const response = await fetchFn(url, {
|
|
17810
|
+
redirect: "error",
|
|
17811
|
+
headers: { accept: "application/json" },
|
|
17812
|
+
...signal === void 0 ? {} : { signal }
|
|
17813
|
+
});
|
|
17835
17814
|
if (response.status === 404) {
|
|
17836
17815
|
return null;
|
|
17837
17816
|
}
|
|
17838
17817
|
if (!response.ok) {
|
|
17839
|
-
throw new
|
|
17818
|
+
throw new LocationRegistryHttpError(`location registry returned HTTP ${response.status}`, response.status);
|
|
17819
|
+
}
|
|
17820
|
+
const text2 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
17821
|
+
let body;
|
|
17822
|
+
try {
|
|
17823
|
+
body = JSON.parse(text2);
|
|
17824
|
+
} catch {
|
|
17825
|
+
throw new LocationRecordValidationError("registry response is not JSON");
|
|
17840
17826
|
}
|
|
17841
|
-
const body = await response.json();
|
|
17842
17827
|
if (body.record === void 0) {
|
|
17843
17828
|
throw new LocationRecordValidationError("registry response missing record");
|
|
17844
17829
|
}
|
|
17845
17830
|
return validateLocationRecord(body.record);
|
|
17846
17831
|
}
|
|
17832
|
+
async function publishLocationRecord(options2) {
|
|
17833
|
+
validateSubject(options2.subject);
|
|
17834
|
+
const registryUrl = exactHttpOrigin(options2.registryUrl, "registry URL");
|
|
17835
|
+
const nodeOrigin = exactHttpOrigin(options2.nodeOrigin, "node origin");
|
|
17836
|
+
const fetchFn = options2.fetch ?? globalThis.fetch.bind(globalThis);
|
|
17837
|
+
const current = await fetchLocationRecord(registryUrl, options2.subject, fetchFn);
|
|
17838
|
+
if (current !== null) {
|
|
17839
|
+
if (current.subject !== options2.subject || !await verifyLocationRecord(current)) {
|
|
17840
|
+
throw new LocationRecordValidationError("existing location record signature is invalid");
|
|
17841
|
+
}
|
|
17842
|
+
if (publishedHttpOrigins(current).includes(nodeOrigin)) {
|
|
17843
|
+
return current;
|
|
17844
|
+
}
|
|
17845
|
+
}
|
|
17846
|
+
const record2 = await signLocationRecord({
|
|
17847
|
+
version: 1,
|
|
17848
|
+
subject: options2.subject,
|
|
17849
|
+
multiaddrs: [...current?.multiaddrs ?? [], httpUrlToMultiaddr(nodeOrigin)],
|
|
17850
|
+
updated_at: (options2.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
17851
|
+
sequence: (current?.sequence ?? -1) + 1
|
|
17852
|
+
}, options2.signer);
|
|
17853
|
+
const response = await fetchFn(
|
|
17854
|
+
`${registryUrl}/v1/locations/${encodeURIComponent(options2.subject)}`,
|
|
17855
|
+
{
|
|
17856
|
+
method: "PUT",
|
|
17857
|
+
redirect: "error",
|
|
17858
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
17859
|
+
body: JSON.stringify(record2)
|
|
17860
|
+
}
|
|
17861
|
+
);
|
|
17862
|
+
if (!response.ok) {
|
|
17863
|
+
throw new LocationRegistryHttpError(`location registry publish returned HTTP ${response.status}`, response.status);
|
|
17864
|
+
}
|
|
17865
|
+
const text2 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
17866
|
+
let body;
|
|
17867
|
+
try {
|
|
17868
|
+
body = JSON.parse(text2);
|
|
17869
|
+
} catch {
|
|
17870
|
+
throw new LocationRecordValidationError("registry publish response is not JSON");
|
|
17871
|
+
}
|
|
17872
|
+
if (body.record === void 0) {
|
|
17873
|
+
throw new LocationRecordValidationError("registry publish response missing record");
|
|
17874
|
+
}
|
|
17875
|
+
const published = validateLocationRecord(body.record);
|
|
17876
|
+
if (canonicalLocationPayload(locationPayloadForRecord(published)) !== canonicalLocationPayload(locationPayloadForRecord(record2)) || published.signature !== record2.signature || !await verifyLocationRecord(published)) {
|
|
17877
|
+
throw new LocationRecordValidationError("registry publish response does not match the signed record");
|
|
17878
|
+
}
|
|
17879
|
+
return published;
|
|
17880
|
+
}
|
|
17847
17881
|
async function resolveCloudLocation(subject, options2 = {}) {
|
|
17848
17882
|
validateSubject(subject);
|
|
17849
17883
|
const verifyRecords = options2.verifyRecords ?? true;
|
|
@@ -18094,6 +18128,123 @@ function multiaddrToHttpUrl(input) {
|
|
|
18094
18128
|
}
|
|
18095
18129
|
return uri;
|
|
18096
18130
|
}
|
|
18131
|
+
function exactHttpOrigin(value, label) {
|
|
18132
|
+
let url;
|
|
18133
|
+
try {
|
|
18134
|
+
url = new URL(value);
|
|
18135
|
+
} catch {
|
|
18136
|
+
throw new LocationRecordValidationError(`${label} must be an absolute URL origin`);
|
|
18137
|
+
}
|
|
18138
|
+
const loopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
18139
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) {
|
|
18140
|
+
throw new LocationRecordValidationError(`${label} must use HTTPS (or loopback HTTP)`);
|
|
18141
|
+
}
|
|
18142
|
+
if (url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "") {
|
|
18143
|
+
throw new LocationRecordValidationError(`${label} must be an origin without credentials, path, query, or fragment`);
|
|
18144
|
+
}
|
|
18145
|
+
return url.origin;
|
|
18146
|
+
}
|
|
18147
|
+
function publishedHttpOrigins(record2) {
|
|
18148
|
+
const origins = [];
|
|
18149
|
+
for (const address of record2.multiaddrs) {
|
|
18150
|
+
try {
|
|
18151
|
+
origins.push(exactHttpOrigin(multiaddrToHttpUrl(address), "published node URL"));
|
|
18152
|
+
} catch {
|
|
18153
|
+
}
|
|
18154
|
+
}
|
|
18155
|
+
return origins;
|
|
18156
|
+
}
|
|
18157
|
+
async function boundedResponseText(response, label, maxBytes) {
|
|
18158
|
+
const declaredLength = response.headers.get("content-length");
|
|
18159
|
+
if (declaredLength !== null && (!/^\d+$/.test(declaredLength) || Number(declaredLength) > maxBytes)) {
|
|
18160
|
+
throw new LocationRecordValidationError(`${label} response is too large`);
|
|
18161
|
+
}
|
|
18162
|
+
if (response.body === null) return "";
|
|
18163
|
+
const reader = response.body.getReader();
|
|
18164
|
+
const chunks = [];
|
|
18165
|
+
let total = 0;
|
|
18166
|
+
try {
|
|
18167
|
+
while (true) {
|
|
18168
|
+
const { done, value } = await reader.read();
|
|
18169
|
+
if (done) break;
|
|
18170
|
+
if (value === void 0) continue;
|
|
18171
|
+
total += value.byteLength;
|
|
18172
|
+
if (total > maxBytes) {
|
|
18173
|
+
await reader.cancel().catch(() => void 0);
|
|
18174
|
+
throw new LocationRecordValidationError(`${label} response is too large`);
|
|
18175
|
+
}
|
|
18176
|
+
chunks.push(value);
|
|
18177
|
+
}
|
|
18178
|
+
} finally {
|
|
18179
|
+
reader.releaseLock();
|
|
18180
|
+
}
|
|
18181
|
+
const bytes2 = new Uint8Array(total);
|
|
18182
|
+
let offset = 0;
|
|
18183
|
+
for (const chunk of chunks) {
|
|
18184
|
+
bytes2.set(chunk, offset);
|
|
18185
|
+
offset += chunk.byteLength;
|
|
18186
|
+
}
|
|
18187
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes2);
|
|
18188
|
+
}
|
|
18189
|
+
function boundedSignal(parent, timeoutMs) {
|
|
18190
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
18191
|
+
throw new LocationRecordValidationError("owner-node binding timeout must be positive");
|
|
18192
|
+
}
|
|
18193
|
+
const controller = new AbortController();
|
|
18194
|
+
const abortFromParent = () => controller.abort(parent?.reason);
|
|
18195
|
+
if (parent?.aborted) abortFromParent();
|
|
18196
|
+
else parent?.addEventListener("abort", abortFromParent, { once: true });
|
|
18197
|
+
const timer = setTimeout(() => controller.abort(new DOMException("owner-node binding timed out", "TimeoutError")), timeoutMs);
|
|
18198
|
+
return {
|
|
18199
|
+
signal: controller.signal,
|
|
18200
|
+
dispose() {
|
|
18201
|
+
clearTimeout(timer);
|
|
18202
|
+
parent?.removeEventListener("abort", abortFromParent);
|
|
18203
|
+
}
|
|
18204
|
+
};
|
|
18205
|
+
}
|
|
18206
|
+
async function verifyOwnerNodeBinding(options2) {
|
|
18207
|
+
validateSubject(options2.ownerDid);
|
|
18208
|
+
validateSubject(options2.nodeDid);
|
|
18209
|
+
const registryUrl = exactHttpOrigin(options2.registryUrl, "registry URL");
|
|
18210
|
+
const nodeOrigin = exactHttpOrigin(options2.nodeOrigin, "node origin");
|
|
18211
|
+
const fetchFn = options2.fetch ?? globalThis.fetch.bind(globalThis);
|
|
18212
|
+
const lookup = boundedSignal(options2.signal, options2.timeoutMs ?? OWNER_NODE_BINDING_TIMEOUT_MS);
|
|
18213
|
+
try {
|
|
18214
|
+
const record2 = await fetchLocationRecord(registryUrl, options2.ownerDid, fetchFn, lookup.signal);
|
|
18215
|
+
if (record2 === null) {
|
|
18216
|
+
throw new LocationRecordValidationError("owner has no published location record");
|
|
18217
|
+
}
|
|
18218
|
+
if (record2.subject !== options2.ownerDid || !await verifyLocationRecord(record2)) {
|
|
18219
|
+
throw new LocationRecordValidationError("owner location record signature is invalid");
|
|
18220
|
+
}
|
|
18221
|
+
const publishedOrigins = publishedHttpOrigins(record2);
|
|
18222
|
+
if (!publishedOrigins.includes(nodeOrigin)) {
|
|
18223
|
+
throw new LocationRecordValidationError("share target is not in the owner's signed location record");
|
|
18224
|
+
}
|
|
18225
|
+
const response = await fetchFn(new URL("/info", nodeOrigin), {
|
|
18226
|
+
redirect: "error",
|
|
18227
|
+
headers: { accept: "application/json" },
|
|
18228
|
+
signal: lookup.signal
|
|
18229
|
+
});
|
|
18230
|
+
if (!response.ok) {
|
|
18231
|
+
throw new LocationRecordValidationError(`target node /info returned HTTP ${response.status}`);
|
|
18232
|
+
}
|
|
18233
|
+
const text2 = await boundedResponseText(response, "target node /info", 16 * 1024);
|
|
18234
|
+
let body;
|
|
18235
|
+
try {
|
|
18236
|
+
body = JSON.parse(text2);
|
|
18237
|
+
} catch {
|
|
18238
|
+
throw new LocationRecordValidationError("target node /info response is not JSON");
|
|
18239
|
+
}
|
|
18240
|
+
if (body === null || typeof body !== "object" || Array.isArray(body) || body.nodeId !== options2.nodeDid) {
|
|
18241
|
+
throw new LocationRecordValidationError("target node identity does not match the share attestation");
|
|
18242
|
+
}
|
|
18243
|
+
return Object.freeze({ record: record2, nodeOrigin, nodeDid: options2.nodeDid });
|
|
18244
|
+
} finally {
|
|
18245
|
+
lookup.dispose();
|
|
18246
|
+
}
|
|
18247
|
+
}
|
|
18097
18248
|
function httpUrlToMultiaddr(input) {
|
|
18098
18249
|
const url = new URL(input);
|
|
18099
18250
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
@@ -18261,7 +18412,7 @@ function verifyDidKeySignature(did, payload, signature) {
|
|
|
18261
18412
|
"did:key signature must be a base64url Ed25519 signature"
|
|
18262
18413
|
);
|
|
18263
18414
|
}
|
|
18264
|
-
return
|
|
18415
|
+
return ed2551910.verify(
|
|
18265
18416
|
signatureBytes,
|
|
18266
18417
|
new TextEncoder().encode(payload),
|
|
18267
18418
|
publicKey
|
|
@@ -18269,7 +18420,7 @@ function verifyDidKeySignature(did, payload, signature) {
|
|
|
18269
18420
|
}
|
|
18270
18421
|
function verifyDidKeyEd25519Signature(did, payload, signature) {
|
|
18271
18422
|
const publicKey = ed25519PublicKeyFromDidKey2(did);
|
|
18272
|
-
return
|
|
18423
|
+
return ed2551910.verify(signature, payload, publicKey);
|
|
18273
18424
|
}
|
|
18274
18425
|
function ed25519PublicKeyFromDidKey2(did) {
|
|
18275
18426
|
const identifier = did.slice("did:key:".length);
|
|
@@ -18392,6 +18543,7 @@ export {
|
|
|
18392
18543
|
ED25519_JCS_SIGNATURE_SUITE,
|
|
18393
18544
|
EIP191_JCS_SIGNATURE_SUITE,
|
|
18394
18545
|
EMAIL_CREDENTIAL_MAX_AGE_SECONDS,
|
|
18546
|
+
EMAIL_DOMAIN_CREDENTIAL_MAX_AGE_SECONDS,
|
|
18395
18547
|
ENCRYPTION,
|
|
18396
18548
|
ENCRYPTION_MANIFEST_SPACE,
|
|
18397
18549
|
ENCRYPTION_NETWORK_URN_PREFIX,
|
|
@@ -18417,6 +18569,7 @@ export {
|
|
|
18417
18569
|
LOCAL_LINK_PROBE_TIMEOUT_MS,
|
|
18418
18570
|
LOCAL_LOOPBACK_PROBE_TIMEOUT_MS,
|
|
18419
18571
|
LocationRecordValidationError,
|
|
18572
|
+
LocationRegistryHttpError,
|
|
18420
18573
|
MAX_CONTENT_BYTES,
|
|
18421
18574
|
MAX_LEGACY_ENVELOPE_EXPIRES_AT,
|
|
18422
18575
|
MAX_SEALED_SHARE_CONTENT_BYTES,
|
|
@@ -18430,6 +18583,7 @@ export {
|
|
|
18430
18583
|
NETWORK_NAME_PATTERN,
|
|
18431
18584
|
NetworkIdError,
|
|
18432
18585
|
OPENKEY_ACTION_ID_SEPARATOR,
|
|
18586
|
+
OWNER_NODE_BINDING_TIMEOUT_MS,
|
|
18433
18587
|
OpenKeyManageKeyError,
|
|
18434
18588
|
POLICY_CAPABILITY_V1_DOMAIN,
|
|
18435
18589
|
POLICY_CAPABILITY_V1_SCHEMA,
|
|
@@ -18469,7 +18623,6 @@ export {
|
|
|
18469
18623
|
SECRET_RECORDS_SCHEMA,
|
|
18470
18624
|
SERVICE_LONG_TO_SHORT,
|
|
18471
18625
|
SERVICE_SHORT_TO_LONG,
|
|
18472
|
-
SHARE_DELIVERY_AUTHORIZATION_DOMAIN,
|
|
18473
18626
|
SPACE,
|
|
18474
18627
|
SQL,
|
|
18475
18628
|
SQLAction,
|
|
@@ -18536,8 +18689,10 @@ export {
|
|
|
18536
18689
|
buildPolicyCredentialPresentationV4,
|
|
18537
18690
|
buildSpaceUri,
|
|
18538
18691
|
canonicalDigest,
|
|
18692
|
+
canonicalEmailDomain,
|
|
18539
18693
|
canonicalHashHex,
|
|
18540
18694
|
canonicalLocationPayload,
|
|
18695
|
+
canonicalMailbox,
|
|
18541
18696
|
canonicalOwnerSharePolicy,
|
|
18542
18697
|
canonicalSignedResponse,
|
|
18543
18698
|
canonicalizeAddress,
|
|
@@ -18565,6 +18720,7 @@ export {
|
|
|
18565
18720
|
createCapabilityKeyRegistry,
|
|
18566
18721
|
createDelegatedShareKey,
|
|
18567
18722
|
createEmailCredentialRequirement,
|
|
18723
|
+
createEmailDomainCredentialRequirement,
|
|
18568
18724
|
createHolderBinding,
|
|
18569
18725
|
createInMemoryLocalNodeIdentityStore,
|
|
18570
18726
|
createLocalStorageLocalNodeIdentityStore,
|
|
@@ -18637,6 +18793,7 @@ export {
|
|
|
18637
18793
|
importPortableDelegation,
|
|
18638
18794
|
installTinyCloudDebugGlobals,
|
|
18639
18795
|
intersectShareCapabilities,
|
|
18796
|
+
isCanonicalEmailDomain,
|
|
18640
18797
|
isCapabilitySubset,
|
|
18641
18798
|
isDigest,
|
|
18642
18799
|
isEvmAddress,
|
|
@@ -18647,6 +18804,7 @@ export {
|
|
|
18647
18804
|
jcsCanonicalize,
|
|
18648
18805
|
loadManifest,
|
|
18649
18806
|
locationPayloadForRecord,
|
|
18807
|
+
mailboxBelongsToDomain,
|
|
18650
18808
|
makePkhSpaceId,
|
|
18651
18809
|
makePublicSpaceId,
|
|
18652
18810
|
manifestAbilitiesUnion,
|
|
@@ -18685,6 +18843,7 @@ export {
|
|
|
18685
18843
|
principalDidEquals,
|
|
18686
18844
|
projectUnifiedPolicyCapabilities,
|
|
18687
18845
|
projectUnifiedPolicyCapability,
|
|
18846
|
+
publishLocationRecord,
|
|
18688
18847
|
recapCaveatsEqual,
|
|
18689
18848
|
registerPolicyV3,
|
|
18690
18849
|
renewPolicyRootStatusV3,
|
|
@@ -18704,7 +18863,7 @@ export {
|
|
|
18704
18863
|
serviceError5 as serviceError,
|
|
18705
18864
|
sha256Base64Url,
|
|
18706
18865
|
shareCapabilityAllows,
|
|
18707
|
-
|
|
18866
|
+
signCompactPolicyDescendant,
|
|
18708
18867
|
signCompactUcanAuthorization,
|
|
18709
18868
|
signCompactUcanRootAuthorization,
|
|
18710
18869
|
signLocationRecord,
|
|
@@ -18741,7 +18900,6 @@ export {
|
|
|
18741
18900
|
validatePolicyStatusSignedShape,
|
|
18742
18901
|
validatePolicyStatusUnsigned,
|
|
18743
18902
|
validatePolicyUnsigned,
|
|
18744
|
-
validateShareDeliveryAuthorizationBytes,
|
|
18745
18903
|
validateShareDeliveryAuthorizationV3Bytes,
|
|
18746
18904
|
validateUnifiedPolicyV2,
|
|
18747
18905
|
verifyDecryptResponse,
|
|
@@ -18749,6 +18907,7 @@ export {
|
|
|
18749
18907
|
verifyEip191MessageSignature,
|
|
18750
18908
|
verifyIssuedCredential,
|
|
18751
18909
|
verifyLocationRecord,
|
|
18910
|
+
verifyOwnerNodeBinding,
|
|
18752
18911
|
verifyPolicy,
|
|
18753
18912
|
verifyPolicyEngineRecord,
|
|
18754
18913
|
verifyPolicyRootRevocationV3,
|