@tinycloud/cli 0.9.1-beta.1 → 0.9.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +149 -45
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +24 -18
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -17725,7 +17725,7 @@ function validateV3Invariants(value, ctx) {
|
|
|
17725
17725
|
if (value.contentSource.encryptionNetwork !== value.encryptionNetwork) {
|
|
17726
17726
|
ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["encryptionNetwork"], message: "encryption network is not bound to the source" });
|
|
17727
17727
|
}
|
|
17728
|
-
if (value.attestedEnforcerBinding.enforcerDid !== value.target.nodeAudience || value.attestedEnforcerBinding.
|
|
17728
|
+
if (value.attestedEnforcerBinding.enforcerDid !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
|
|
17729
17729
|
ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
|
|
17730
17730
|
}
|
|
17731
17731
|
if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
|
|
@@ -18077,7 +18077,7 @@ async function signCompactUcanAuthorization(input) {
|
|
|
18077
18077
|
const publicKey = ed25519PublicKeyFromDidKey(principal);
|
|
18078
18078
|
const header = {
|
|
18079
18079
|
alg: "EdDSA",
|
|
18080
|
-
jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x:
|
|
18080
|
+
jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: toBase64Url(publicKey) },
|
|
18081
18081
|
typ: "JWT",
|
|
18082
18082
|
ucv: "0.10.0"
|
|
18083
18083
|
};
|
|
@@ -18091,13 +18091,13 @@ async function signCompactUcanAuthorization(input) {
|
|
|
18091
18091
|
nnc: input.nonce,
|
|
18092
18092
|
prf: input.proofs
|
|
18093
18093
|
};
|
|
18094
|
-
const protectedSegment =
|
|
18095
|
-
const payloadSegment =
|
|
18094
|
+
const protectedSegment = toBase64Url(new TextEncoder().encode(canonicalize2(header)));
|
|
18095
|
+
const payloadSegment = toBase64Url(new TextEncoder().encode(canonicalize2(payload)));
|
|
18096
18096
|
const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
|
|
18097
18097
|
const signature = await input.sign(signingInput);
|
|
18098
18098
|
if (signature.length !== 64) throw new TypeError("compact Authorization signature must be Ed25519");
|
|
18099
18099
|
return verifyCompactUcanAuthorization(
|
|
18100
|
-
`${protectedSegment}.${payloadSegment}.${
|
|
18100
|
+
`${protectedSegment}.${payloadSegment}.${toBase64Url(signature)}`
|
|
18101
18101
|
);
|
|
18102
18102
|
}
|
|
18103
18103
|
function verifyCompactUcanAuthorization(authorization, expectedCid) {
|
|
@@ -18105,9 +18105,9 @@ function verifyCompactUcanAuthorization(authorization, expectedCid) {
|
|
|
18105
18105
|
const segments = authorization.split(".");
|
|
18106
18106
|
if (segments.length !== 3 || segments.some((segment) => segment.length === 0)) throw new TypeError("compact Authorization must contain three segments");
|
|
18107
18107
|
const [headerSegment, payloadSegment, signatureSegment] = segments;
|
|
18108
|
-
const headerBytes =
|
|
18109
|
-
const payloadBytes =
|
|
18110
|
-
const signature =
|
|
18108
|
+
const headerBytes = fromBase64Url(headerSegment);
|
|
18109
|
+
const payloadBytes = fromBase64Url(payloadSegment);
|
|
18110
|
+
const signature = fromBase64Url(signatureSegment);
|
|
18111
18111
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
18112
18112
|
const header = JSON.parse(decoder.decode(headerBytes));
|
|
18113
18113
|
const payload = JSON.parse(decoder.decode(payloadBytes));
|
|
@@ -18120,7 +18120,7 @@ function verifyCompactUcanAuthorization(authorization, expectedCid) {
|
|
|
18120
18120
|
if (typeof payload.iss !== "string" || typeof payload.aud !== "string" || typeof payload.nnc !== "string" || !Number.isInteger(payload.nbf) || !Number.isInteger(payload.exp) || payload.nbf >= payload.exp || !Array.isArray(payload.prf) || payload.prf.some((proof) => typeof proof !== "string") || !Array.isArray(payload.fct) || payload.fct.length !== 1) throw new TypeError("compact Authorization payload is invalid");
|
|
18121
18121
|
const principal = payload.iss.split("#", 1)[0];
|
|
18122
18122
|
const publicKey = ed25519PublicKeyFromDidKey(principal);
|
|
18123
|
-
if (!equal(publicKey,
|
|
18123
|
+
if (!equal(publicKey, fromBase64Url(jwk.x))) throw new TypeError("compact Authorization JWK does not bind issuer");
|
|
18124
18124
|
if (!ed25519.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey, { zip215: false })) throw new TypeError("compact Authorization signature is invalid");
|
|
18125
18125
|
const cid2 = CID.createV1(85, create(30, blake3(new TextEncoder().encode(authorization)))).toString();
|
|
18126
18126
|
if (expectedCid !== void 0 && cid2 !== expectedCid) throw new TypeError("compact Authorization CID mismatch");
|
|
@@ -18133,16 +18133,6 @@ function object(value, label) {
|
|
|
18133
18133
|
function assertExactKeys(value, keys, label) {
|
|
18134
18134
|
if (Object.keys(value).length !== keys.length || Object.keys(value).some((key) => !keys.includes(key))) throw new TypeError(`${label} has unknown or missing fields`);
|
|
18135
18135
|
}
|
|
18136
|
-
function decodeBase64Url(value) {
|
|
18137
|
-
if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1) throw new TypeError("compact Authorization segment is not base64url");
|
|
18138
|
-
const bytes3 = typeof Buffer !== "undefined" ? new Uint8Array(Buffer.from(value, "base64url")) : Uint8Array.from(atob(value.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(value.length / 4) * 4, "=")), (character) => character.charCodeAt(0));
|
|
18139
|
-
const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes3).toString("base64url") : btoa(String.fromCharCode(...bytes3)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
18140
|
-
if (encoded !== value) throw new TypeError("compact Authorization segment is not canonical");
|
|
18141
|
-
return bytes3;
|
|
18142
|
-
}
|
|
18143
|
-
function encodeBase64Url(value) {
|
|
18144
|
-
return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
18145
|
-
}
|
|
18146
18136
|
function equal(left, right) {
|
|
18147
18137
|
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
18148
18138
|
}
|
|
@@ -18262,10 +18252,10 @@ async function verifyEnvelopeV3(envelope, options) {
|
|
|
18262
18252
|
const binding = parsed.attestedEnforcerBinding;
|
|
18263
18253
|
const { signature: bindingSignature, ...unsignedBinding } = binding;
|
|
18264
18254
|
const expectedBindingDigestHex = hex(sha2562(new TextEncoder().encode(canonicalize2({ enforcerDid: binding.enforcerDid, nodeAudience: binding.nodeAudience }))));
|
|
18265
|
-
if (binding.enforcerDid !== parsed.target.nodeAudience || binding.
|
|
18255
|
+
if (binding.enforcerDid !== parsed.target.nodeAudience || binding.attestationBindingDigestHex !== expectedBindingDigestHex || bindingSignature.signerDid !== binding.nodeAudience || bindingSignature.suite !== "Ed25519" || Date.parse(binding.issuedAt) > Date.now() || Date.parse(binding.expiresAt) <= Date.now() || Date.parse(binding.expiresAt) < Date.parse(parsed.expiry)) return false;
|
|
18266
18256
|
try {
|
|
18267
18257
|
const digest4 = sha2562(new TextEncoder().encode(`${ATTESTED_ENFORCER_V2_DOMAIN}${canonicalize2(unsignedBinding)}`));
|
|
18268
|
-
if (!ed25519.verify(fromBase64Url(bindingSignature.value), digest4, ed25519PublicKeyFromDidKey(binding.
|
|
18258
|
+
if (!ed25519.verify(fromBase64Url(bindingSignature.value), digest4, ed25519PublicKeyFromDidKey(binding.nodeAudience), ED25519_VERIFY_OPTS2)) return false;
|
|
18269
18259
|
} catch {
|
|
18270
18260
|
return false;
|
|
18271
18261
|
}
|
|
@@ -18278,7 +18268,7 @@ async function verifyEnvelopeV3(envelope, options) {
|
|
|
18278
18268
|
const common = ["ownerDid", "policyId", "policyDigestHex", "policyCid", "contentSourceDigestHex", "capabilityCeilingHashHex", "nativeProjectionHashHex", "nodeAudience"];
|
|
18279
18269
|
const policyKeys = [...common, "role", "mode"];
|
|
18280
18270
|
const enforcementKeys = [...policyKeys, "enforcerDid"];
|
|
18281
|
-
if (Object.keys(policyFact).length !== policyKeys.length || policyKeys.some((key) => !(key in policyFact)) || Object.keys(enforcementFact).length !== enforcementKeys.length || enforcementKeys.some((key) => !(key in enforcementFact)) || policyRoot.payload.prf.length !== 0 || enforcementRoot.payload.prf.length !== 0 || policyRoot.payload.iss.split("#", 1)[0] !== policy.ownerDid || enforcementRoot.payload.iss.split("#", 1)[0] !== policy.ownerDid || policyRoot.payload.nbf !== enforcementRoot.payload.nbf || policyRoot.payload.exp !== enforcementRoot.payload.exp || canonicalize2(policyRoot.payload.att) !== canonicalize2(expectedAttenuation) || canonicalize2(enforcementRoot.payload.att) !== canonicalize2(expectedAttenuation) || policyFact.role !== "policy-authority" || policyFact.mode !== "policy-source" || "enforcerDid" in policyFact || enforcementFact.role !== "policy-enforcement" || enforcementFact.mode !== "conditional-mint" || policyRoot.payload.aud !== `did:tinycloud:policy:${hex(policyIdDigest)}` || enforcementRoot.payload.aud !==
|
|
18271
|
+
if (Object.keys(policyFact).length !== policyKeys.length || policyKeys.some((key) => !(key in policyFact)) || Object.keys(enforcementFact).length !== enforcementKeys.length || enforcementKeys.some((key) => !(key in enforcementFact)) || policyRoot.payload.prf.length !== 0 || enforcementRoot.payload.prf.length !== 0 || policyRoot.payload.iss.split("#", 1)[0] !== policy.ownerDid || enforcementRoot.payload.iss.split("#", 1)[0] !== policy.ownerDid || policyRoot.payload.nbf !== enforcementRoot.payload.nbf || policyRoot.payload.exp !== enforcementRoot.payload.exp || canonicalize2(policyRoot.payload.att) !== canonicalize2(expectedAttenuation) || canonicalize2(enforcementRoot.payload.att) !== canonicalize2(expectedAttenuation) || policyFact.role !== "policy-authority" || policyFact.mode !== "policy-source" || "enforcerDid" in policyFact || enforcementFact.role !== "policy-enforcement" || enforcementFact.mode !== "conditional-mint" || policyRoot.payload.aud !== `did:tinycloud:policy:${hex(policyIdDigest)}` || enforcementRoot.payload.aud !== binding.enforcerDid || enforcementFact.enforcerDid !== binding.enforcerDid || common.some((key) => policyFact[key] !== enforcementFact[key]) || policyFact.ownerDid !== policy.ownerDid || policyFact.policyId !== policy.policyId || policyFact.policyDigestHex !== hex(policyIdDigest) || policyFact.policyCid !== parsed.policyCid || policyFact.contentSourceDigestHex !== parsed.contentSourceDigestHex || policyFact.capabilityCeilingHashHex !== capabilityCeilingHashHex || policyFact.nativeProjectionHashHex !== nativeProjectionHashHex || policyFact.nodeAudience !== binding.nodeAudience || policyRoot.payload.exp * 1e3 < Date.parse(parsed.expiry)) return false;
|
|
18282
18272
|
} catch {
|
|
18283
18273
|
return false;
|
|
18284
18274
|
}
|
|
@@ -18460,8 +18450,12 @@ async function readResponseBytes(response, limit, tooLargeCode) {
|
|
|
18460
18450
|
function registryFetcher(options, limit, tooLargeCode = "max-bytes-exceeded", stage = "envelope") {
|
|
18461
18451
|
if (options.fetchBlob !== void 0) return async (input) => {
|
|
18462
18452
|
try {
|
|
18463
|
-
|
|
18453
|
+
options.signal?.throwIfAborted();
|
|
18454
|
+
const bytes3 = await options.fetchBlob({ ...input, ...options.signal === void 0 ? {} : { signal: options.signal } });
|
|
18455
|
+
options.signal?.throwIfAborted();
|
|
18456
|
+
return boundedBytes(bytes3, limit, tooLargeCode);
|
|
18464
18457
|
} catch (error) {
|
|
18458
|
+
if (options.signal?.aborted) throw options.signal.reason ?? error;
|
|
18465
18459
|
if (error instanceof ShareReceiveError) throw error;
|
|
18466
18460
|
throw new ShareReceiveError("fetch-failed", "registry unavailable", { stage });
|
|
18467
18461
|
}
|
|
@@ -18471,10 +18465,19 @@ function registryFetcher(options, limit, tooLargeCode = "max-bytes-exceeded", st
|
|
|
18471
18465
|
const base33 = options.registryBaseUrl.replace(/\/+$/, "");
|
|
18472
18466
|
return async ({ cid: cid2 }) => {
|
|
18473
18467
|
try {
|
|
18474
|
-
|
|
18468
|
+
options.signal?.throwIfAborted();
|
|
18469
|
+
const response = await fetchFn(`${base33}/ipfs/${cid2}?format=raw`, {
|
|
18470
|
+
headers: { accept: "application/vnd.ipld.raw" },
|
|
18471
|
+
redirect: "error",
|
|
18472
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
18473
|
+
});
|
|
18474
|
+
options.signal?.throwIfAborted();
|
|
18475
18475
|
if (!response.ok) throw new ShareReceiveError("fetch-failed", `registry returned ${response.status}`, { stage });
|
|
18476
|
-
|
|
18476
|
+
const bytes3 = await readResponseBytes(response, limit, tooLargeCode);
|
|
18477
|
+
options.signal?.throwIfAborted();
|
|
18478
|
+
return bytes3;
|
|
18477
18479
|
} catch (error) {
|
|
18480
|
+
if (options.signal?.aborted) throw options.signal.reason ?? error;
|
|
18478
18481
|
if (error instanceof ShareReceiveError) throw error;
|
|
18479
18482
|
throw new ShareReceiveError("fetch-failed", "registry unavailable", { stage });
|
|
18480
18483
|
}
|
|
@@ -20265,6 +20268,39 @@ function uiAction(action) {
|
|
|
20265
20268
|
function selectedAction(envelope) {
|
|
20266
20269
|
return envelope.actions.includes("list") ? "tinycloud.kv/list" : envelope.actions.includes("edit") ? "tinycloud.kv/put" : "tinycloud.kv/get";
|
|
20267
20270
|
}
|
|
20271
|
+
function policyAttenuationForV3(envelope) {
|
|
20272
|
+
const policy = object2(envelope.policy, "v3 policy");
|
|
20273
|
+
if (!Array.isArray(policy.capabilityCeiling)) throw new Error("v3 policy capability ceiling is invalid");
|
|
20274
|
+
const attenuation = {};
|
|
20275
|
+
for (const raw of policy.capabilityCeiling) {
|
|
20276
|
+
const capability = object2(raw, "v3 policy capability");
|
|
20277
|
+
if (typeof capability.resource !== "string" || attenuation[capability.resource] !== void 0) throw new Error("v3 policy capability is invalid");
|
|
20278
|
+
if (capability.kind === "encryption") {
|
|
20279
|
+
if (capability.action !== "tinycloud.encryption/decrypt") throw new Error("v3 policy capability is invalid");
|
|
20280
|
+
attenuation[capability.resource] = { [capability.action]: [{}] };
|
|
20281
|
+
continue;
|
|
20282
|
+
}
|
|
20283
|
+
if (capability.kind !== "kv" || capability.selector !== "exact" && capability.selector !== "prefix" || !Array.isArray(capability.actions) || capability.actions.length === 0 || capability.actions.some((action) => typeof action !== "string")) throw new Error("v3 policy capability is invalid");
|
|
20284
|
+
attenuation[capability.resource] = Object.fromEntries(capability.actions.map((action) => [action, [{
|
|
20285
|
+
type: "xyz.tinycloud.resource/selector",
|
|
20286
|
+
kind: capability.selector,
|
|
20287
|
+
value: capability.resource
|
|
20288
|
+
}]]));
|
|
20289
|
+
}
|
|
20290
|
+
return attenuation;
|
|
20291
|
+
}
|
|
20292
|
+
function verifyV3PolicyAuthorization(input) {
|
|
20293
|
+
const compact = verifyCompactUcanAuthorization(input.authorization, input.cid);
|
|
20294
|
+
const fact = compact.payload.fct[0];
|
|
20295
|
+
const factKeys = Object.keys(fact);
|
|
20296
|
+
const legacyShape = factKeys.length === POLICY_SESSION_FACT_KEYS.length && factKeys.every((key) => POLICY_SESSION_FACT_KEYS.includes(key)) && POLICY_SESSION_FACT_KEYS.every((key) => key in fact);
|
|
20297
|
+
const v4Shape = factKeys.length === POLICY_SESSION_FACT_KEYS.length + POLICY_SESSION_V4_AUDIT_FACT_KEYS.length && factKeys.every((key) => POLICY_SESSION_FACT_KEYS.includes(key) || POLICY_SESSION_V4_AUDIT_FACT_KEYS.includes(key)) && POLICY_SESSION_FACT_KEYS.every((key) => key in fact) && POLICY_SESSION_V4_AUDIT_FACT_KEYS.every((key) => key in fact);
|
|
20298
|
+
const binding = object2(input.envelope.attestedEnforcerBinding, "v3 attested enforcer binding");
|
|
20299
|
+
const policy = object2(input.envelope.policy, "v3 policy");
|
|
20300
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
20301
|
+
if (!legacyShape && !v4Shape || POLICY_SESSION_DIGEST_FACT_KEYS.some((key) => !LOWER_SHA256_HEX.test(fact[key])) || v4Shape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)) || compact.payload.aud !== input.holderDid || compact.payload.iss.split("#", 1)[0] !== fact.nodeAudience || fact.profile !== "policy-session-ucan/v1" || fact.ownerDid !== policy.ownerDid || fact.policyId !== policy.policyId || fact.policyCid !== input.envelope.policyCid || fact.contentSourceDigestHex !== input.envelope.contentSourceDigestHex || fact.enforcerDid !== binding.enforcerDid || fact.nodeAudience !== binding.nodeAudience || fact.recipientDid !== input.holderDid || fact.policyDelegationCid !== input.envelope.policyRoot.cid || fact.enforcementDelegationCid !== input.envelope.enforcementRoot.cid || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || compact.payload.prf.length !== 2 || compact.payload.prf[0] !== input.envelope.policyRoot.cid || compact.payload.prf[1] !== input.envelope.enforcementRoot.cid || compact.payload.nbf > now || compact.payload.exp <= now || compact.payload.exp - compact.payload.nbf > 60 || canonicalize2(compact.payload.att) !== canonicalize2(policyAttenuationForV3(input.envelope))) throw new Error("v3 policy delegation signed binding mismatch");
|
|
20302
|
+
return compact;
|
|
20303
|
+
}
|
|
20268
20304
|
function hex2(value) {
|
|
20269
20305
|
return [...value].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
20270
20306
|
}
|
|
@@ -20355,7 +20391,7 @@ function createAddressedAuthorization(input) {
|
|
|
20355
20391
|
}
|
|
20356
20392
|
};
|
|
20357
20393
|
}
|
|
20358
|
-
var __defProp2, __export2, external_exports2, util2, objectUtil2, ZodParsedType2, getParsedType2, ZodIssueCode2, quotelessJson2, ZodError2, errorMap2, en_default2, overrideErrorMap2, makeIssue2, EMPTY_PATH2, ParseStatus2, INVALID2, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, errorUtil2, ParseInputLazyPath2, handleResult2, ZodType2, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString2, ZodNumber2, ZodBigInt2, ZodBoolean2, ZodDate2, ZodSymbol2, ZodUndefined2, ZodNull2, ZodAny2, ZodUnknown2, ZodNever2, ZodVoid2, ZodArray2, ZodObject2, ZodUnion2, getDiscriminator2, ZodDiscriminatedUnion2, ZodIntersection2, ZodTuple2, ZodRecord2, ZodMap2, ZodSet2, ZodFunction2, ZodLazy2, ZodLiteral2, ZodEnum2, ZodNativeEnum2, ZodPromise2, ZodEffects2, ZodOptional2, ZodNullable2, ZodDefault2, ZodCatch2, ZodNaN2, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly2, late2, ZodFirstPartyTypeKind2, instanceOfType2, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, ostring2, onumber2, oboolean2, coerce2, NEVER2, empty, src, _brrp__multiformats_scope_baseX, base_x_default, Encoder, Decoder, ComposedDecoder, Codec, base32, base32upper, base32pad, base32padupper, base32hex, base32hexupper, base32hexpad, base32hexpadupper, base32z, base36, base36upper, base58btc, base58flickr, encode_1, MSB, REST, MSBALL, INT, decode2, MSB$1, REST$1, N1, N2, N3, N4, N5, N6, N7, N8, N9, length, varint, _brrp_varint, varint_default, Digest, cache, CID, DAG_PB_CODE, SHA_256_CODE, cidSymbol, code, SHA256_CODE, base64, base64pad, base64url, base64urlpad, ED25519_MULTICODEC_PREFIX, PUBLIC_KEY_LENGTH, base64UrlString, sessionJwkCommonFields, okpPrivateJwkSchema, ecPrivateJwkSchema, sessionJwkSchema, policyTargetSchema, bearerKeyTargetSchema, recipientDidTargetSchema, authorizationTargetSchema, resourceSelectorSchema, targetSchema, displaySchema, contentPointerSchema, signatureSchema, unsignedShareEnvelopeSchema, shareEnvelopeSchema, recipientMatcherSchema, shareActionSchema, kvContentSourceSchema, sqlContentSourceSchema, contentSourceSchema, v2TargetSchema, shareDecryptionSchema, ownerAuthoritySchema, contentMetadataSchema, unsignedShareEnvelopeV2BaseSchema, unsignedShareEnvelopeV2Schema, shareEnvelopeV2Schema, unifiedResourceSchema, unifiedEncryptionNetworkSchema, unifiedKvCapabilitySchema, unifiedEncryptionCapabilitySchema, unifiedCapabilitySchema, unifiedContentSourceSchema, unifiedPolicyV1Schema, policyCredentialRequirementV1Schema, unifiedPolicyV2Schema, unifiedPolicySchema, unifiedRootSchema, attestedEnforcerBindingV2Schema, v3TargetSchema, unsignedShareEnvelopeV3BaseSchema, unsignedShareEnvelopeV3Schema, shareEnvelopeV3Schema, BEARER_READ_ABILITY, READ_ABILITIES, ED25519_VERIFY_OPTS, ENVELOPE_AAD_LABEL, SEALED_BLOB_VERSION, AAD, KEY_LENGTH, NONCE_LENGTH, TAG_LENGTH, HEADER_LENGTH, ED25519_VERIFY_OPTS2, ENVELOPE_SIGNATURE_DOMAIN, ENVELOPE_V2_SIGNATURE_DOMAIN, ENVELOPE_V3_SIGNATURE_DOMAIN, POLICY_V1_SIGNATURE_DOMAIN, POLICY_V2_SIGNATURE_DOMAIN, CONTENT_SOURCE_V1_DOMAIN, POLICY_CAPABILITY_V1_DOMAIN, NATIVE_PROJECTION_V1_DOMAIN, ATTESTED_ENFORCER_V2_DOMAIN, KEY_LENGTH2, INLINE_PREFIX, MAX_INLINE_BYTES, SHARE_RESULT_VERSION, DEFAULT_MAX_SEALED_BLOB_BYTES, DEFAULT_MAX_CONTENT_BLOB_BYTES, CONTENT_SEALED_OVERHEAD, ShareReceiveError, SHARE_CONTENT_LIMIT, SHARE_SEALED_OVERHEAD, SHARE_PUBLISH_RESULT_VERSION, DEFAULT_SHARE_LIFETIME_MS, SharePublishError, empty2, src2, _brrp__multiformats_scope_baseX2, base_x_default2, Encoder2, Decoder2, ComposedDecoder2, Codec2, base322, base32upper2, base32pad2, base32padupper2, base32hex2, base32hexupper2, base32hexpad2, base32hexpadupper2, base32z2, base362, base36upper2, base58btc2, base58flickr2, encode_12, MSB2, REST2, MSBALL2, INT2, decode6, MSB$12, REST$12, N12, N22, N32, N42, N52, N62, N72, N82, N92, length2, varint2, _brrp_varint2, varint_default2, Digest2, cache2, CID2, DAG_PB_CODE2, SHA_256_CODE2, cidSymbol2, code2, SHA256_CODE2, MAX_CONTENT_BYTES, POLICY_ENFORCEMENT_DOMAIN, POLICY_DOMAIN, OWNER_SHARE_REGISTRATION_DOMAIN, ENVELOPE_DOMAIN, ENVELOPE_DOMAIN2, ShareNotifyError, SHARE_V2_PROTOCOL, DOMAIN, PRESENTATION_DOMAIN, SESSION_DOMAIN, INVOCATION_DOMAIN, BASE64_ALPHABET, ShareRecipientClient;
|
|
20394
|
+
var __defProp2, __export2, external_exports2, util2, objectUtil2, ZodParsedType2, getParsedType2, ZodIssueCode2, quotelessJson2, ZodError2, errorMap2, en_default2, overrideErrorMap2, makeIssue2, EMPTY_PATH2, ParseStatus2, INVALID2, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, errorUtil2, ParseInputLazyPath2, handleResult2, ZodType2, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString2, ZodNumber2, ZodBigInt2, ZodBoolean2, ZodDate2, ZodSymbol2, ZodUndefined2, ZodNull2, ZodAny2, ZodUnknown2, ZodNever2, ZodVoid2, ZodArray2, ZodObject2, ZodUnion2, getDiscriminator2, ZodDiscriminatedUnion2, ZodIntersection2, ZodTuple2, ZodRecord2, ZodMap2, ZodSet2, ZodFunction2, ZodLazy2, ZodLiteral2, ZodEnum2, ZodNativeEnum2, ZodPromise2, ZodEffects2, ZodOptional2, ZodNullable2, ZodDefault2, ZodCatch2, ZodNaN2, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly2, late2, ZodFirstPartyTypeKind2, instanceOfType2, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, ostring2, onumber2, oboolean2, coerce2, NEVER2, empty, src, _brrp__multiformats_scope_baseX, base_x_default, Encoder, Decoder, ComposedDecoder, Codec, base32, base32upper, base32pad, base32padupper, base32hex, base32hexupper, base32hexpad, base32hexpadupper, base32z, base36, base36upper, base58btc, base58flickr, encode_1, MSB, REST, MSBALL, INT, decode2, MSB$1, REST$1, N1, N2, N3, N4, N5, N6, N7, N8, N9, length, varint, _brrp_varint, varint_default, Digest, cache, CID, DAG_PB_CODE, SHA_256_CODE, cidSymbol, code, SHA256_CODE, base64, base64pad, base64url, base64urlpad, ED25519_MULTICODEC_PREFIX, PUBLIC_KEY_LENGTH, base64UrlString, sessionJwkCommonFields, okpPrivateJwkSchema, ecPrivateJwkSchema, sessionJwkSchema, policyTargetSchema, bearerKeyTargetSchema, recipientDidTargetSchema, authorizationTargetSchema, resourceSelectorSchema, targetSchema, displaySchema, contentPointerSchema, signatureSchema, unsignedShareEnvelopeSchema, shareEnvelopeSchema, recipientMatcherSchema, shareActionSchema, kvContentSourceSchema, sqlContentSourceSchema, contentSourceSchema, v2TargetSchema, shareDecryptionSchema, ownerAuthoritySchema, contentMetadataSchema, unsignedShareEnvelopeV2BaseSchema, unsignedShareEnvelopeV2Schema, shareEnvelopeV2Schema, unifiedResourceSchema, unifiedEncryptionNetworkSchema, unifiedKvCapabilitySchema, unifiedEncryptionCapabilitySchema, unifiedCapabilitySchema, unifiedContentSourceSchema, unifiedPolicyV1Schema, policyCredentialRequirementV1Schema, unifiedPolicyV2Schema, unifiedPolicySchema, unifiedRootSchema, attestedEnforcerBindingV2Schema, v3TargetSchema, unsignedShareEnvelopeV3BaseSchema, unsignedShareEnvelopeV3Schema, shareEnvelopeV3Schema, BEARER_READ_ABILITY, READ_ABILITIES, ED25519_VERIFY_OPTS, ENVELOPE_AAD_LABEL, SEALED_BLOB_VERSION, AAD, KEY_LENGTH, NONCE_LENGTH, TAG_LENGTH, HEADER_LENGTH, ED25519_VERIFY_OPTS2, ENVELOPE_SIGNATURE_DOMAIN, ENVELOPE_V2_SIGNATURE_DOMAIN, ENVELOPE_V3_SIGNATURE_DOMAIN, POLICY_V1_SIGNATURE_DOMAIN, POLICY_V2_SIGNATURE_DOMAIN, CONTENT_SOURCE_V1_DOMAIN, POLICY_CAPABILITY_V1_DOMAIN, NATIVE_PROJECTION_V1_DOMAIN, ATTESTED_ENFORCER_V2_DOMAIN, KEY_LENGTH2, INLINE_PREFIX, MAX_INLINE_BYTES, SHARE_RESULT_VERSION, DEFAULT_MAX_SEALED_BLOB_BYTES, DEFAULT_MAX_CONTENT_BLOB_BYTES, CONTENT_SEALED_OVERHEAD, ShareReceiveError, SHARE_CONTENT_LIMIT, SHARE_SEALED_OVERHEAD, SHARE_PUBLISH_RESULT_VERSION, DEFAULT_SHARE_LIFETIME_MS, SharePublishError, empty2, src2, _brrp__multiformats_scope_baseX2, base_x_default2, Encoder2, Decoder2, ComposedDecoder2, Codec2, base322, base32upper2, base32pad2, base32padupper2, base32hex2, base32hexupper2, base32hexpad2, base32hexpadupper2, base32z2, base362, base36upper2, base58btc2, base58flickr2, encode_12, MSB2, REST2, MSBALL2, INT2, decode6, MSB$12, REST$12, N12, N22, N32, N42, N52, N62, N72, N82, N92, length2, varint2, _brrp_varint2, varint_default2, Digest2, cache2, CID2, DAG_PB_CODE2, SHA_256_CODE2, cidSymbol2, code2, SHA256_CODE2, MAX_CONTENT_BYTES, POLICY_ENFORCEMENT_DOMAIN, POLICY_DOMAIN, OWNER_SHARE_REGISTRATION_DOMAIN, ENVELOPE_DOMAIN, ENVELOPE_DOMAIN2, ShareNotifyError, SHARE_V2_PROTOCOL, DOMAIN, PRESENTATION_DOMAIN, SESSION_DOMAIN, INVOCATION_DOMAIN, BASE64_ALPHABET, POLICY_SESSION_FACT_KEYS, POLICY_SESSION_V4_AUDIT_FACT_KEYS, POLICY_SESSION_DIGEST_FACT_KEYS, LOWER_SHA256_HEX, ShareRecipientClient;
|
|
20359
20395
|
var init_dist3 = __esm({
|
|
20360
20396
|
"../share-sdk/dist/index.js"() {
|
|
20361
20397
|
"use strict";
|
|
@@ -25518,11 +25554,61 @@ var init_dist3 = __esm({
|
|
|
25518
25554
|
SESSION_DOMAIN = SHARE_V2_PROTOCOL.sessionDomain;
|
|
25519
25555
|
INVOCATION_DOMAIN = SHARE_V2_PROTOCOL.invocationDomain;
|
|
25520
25556
|
BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
25557
|
+
POLICY_SESSION_FACT_KEYS = [
|
|
25558
|
+
"profile",
|
|
25559
|
+
"ownerDid",
|
|
25560
|
+
"policyId",
|
|
25561
|
+
"policyDigestHex",
|
|
25562
|
+
"policyCid",
|
|
25563
|
+
"policyDelegationCid",
|
|
25564
|
+
"enforcementDelegationCid",
|
|
25565
|
+
"contentSourceDigestHex",
|
|
25566
|
+
"capabilityCeilingHashHex",
|
|
25567
|
+
"nativeProjectionHashHex",
|
|
25568
|
+
"enforcerDid",
|
|
25569
|
+
"nodeAudience",
|
|
25570
|
+
"recipientDid",
|
|
25571
|
+
"challengeId",
|
|
25572
|
+
"claimDigestHex",
|
|
25573
|
+
"claimJti",
|
|
25574
|
+
"vpDigestHex",
|
|
25575
|
+
"credentialEvidenceDigestHex",
|
|
25576
|
+
"decisionContextDigestHex",
|
|
25577
|
+
"issuanceAuditDigestHex",
|
|
25578
|
+
"remainingRedelegationDepth"
|
|
25579
|
+
];
|
|
25580
|
+
POLICY_SESSION_V4_AUDIT_FACT_KEYS = ["credentialIdAuditDigestHex", "presentationJtiAuditDigestHex"];
|
|
25581
|
+
POLICY_SESSION_DIGEST_FACT_KEYS = [
|
|
25582
|
+
"policyDigestHex",
|
|
25583
|
+
"contentSourceDigestHex",
|
|
25584
|
+
"capabilityCeilingHashHex",
|
|
25585
|
+
"nativeProjectionHashHex",
|
|
25586
|
+
"claimDigestHex",
|
|
25587
|
+
"vpDigestHex",
|
|
25588
|
+
"credentialEvidenceDigestHex",
|
|
25589
|
+
"decisionContextDigestHex",
|
|
25590
|
+
"issuanceAuditDigestHex"
|
|
25591
|
+
];
|
|
25592
|
+
LOWER_SHA256_HEX = /^[0-9a-f]{64}$/;
|
|
25521
25593
|
ShareRecipientClient = class {
|
|
25522
25594
|
constructor(options) {
|
|
25523
25595
|
this.options = options;
|
|
25524
25596
|
this.fetchFn = options.fetchFn ?? globalThis.fetch.bind(globalThis);
|
|
25525
25597
|
this.signer = options.sign;
|
|
25598
|
+
if (options.policyAuthorization !== void 0) {
|
|
25599
|
+
if (options.envelope.version !== 3) throw new Error("policy delegation fast path requires a v3 envelope");
|
|
25600
|
+
const compact = verifyV3PolicyAuthorization({ ...options.policyAuthorization, envelope: options.envelope, holderDid: options.holderDid });
|
|
25601
|
+
const nodeAudience = compact.payload.fct[0].nodeAudience;
|
|
25602
|
+
this.v3Authorization = options.policyAuthorization.authorization;
|
|
25603
|
+
this.v3NodeAudience = nodeAudience;
|
|
25604
|
+
this.nativeSigner = options.sign;
|
|
25605
|
+
this.session = {
|
|
25606
|
+
sessionId: options.policyAuthorization.cid,
|
|
25607
|
+
expiresAt: new Date(compact.payload.exp * 1e3).toISOString(),
|
|
25608
|
+
actions: options.envelope.actions,
|
|
25609
|
+
resource: options.envelope.resource
|
|
25610
|
+
};
|
|
25611
|
+
}
|
|
25526
25612
|
}
|
|
25527
25613
|
fetchFn;
|
|
25528
25614
|
session;
|
|
@@ -25530,6 +25616,7 @@ var init_dist3 = __esm({
|
|
|
25530
25616
|
nativeSigner;
|
|
25531
25617
|
holderProof;
|
|
25532
25618
|
v3Authorization;
|
|
25619
|
+
v3NodeAudience;
|
|
25533
25620
|
v3ContentKey;
|
|
25534
25621
|
v3ContentEnvelope;
|
|
25535
25622
|
async beginChallenge(envelope) {
|
|
@@ -25619,37 +25706,52 @@ var init_dist3 = __esm({
|
|
|
25619
25706
|
}
|
|
25620
25707
|
async establishV3(envelope) {
|
|
25621
25708
|
if (this.options.buildPresentation === void 0) throw new Error("share presentation builder is required");
|
|
25709
|
+
const attestedEnforcer = object2(envelope.attestedEnforcerBinding, "v3 attested enforcer binding");
|
|
25710
|
+
if (attestedEnforcer.enforcerDid !== envelope.target.nodeAudience || typeof attestedEnforcer.nodeAudience !== "string") throw new Error("v3 attested enforcer binding mismatch");
|
|
25711
|
+
try {
|
|
25712
|
+
ed25519PublicKeyFromDidKey(attestedEnforcer.nodeAudience);
|
|
25713
|
+
} catch {
|
|
25714
|
+
throw new Error("v3 attested Node audience is invalid");
|
|
25715
|
+
}
|
|
25622
25716
|
const challengeResponse = await this.fetchFn(new URL("/share/v3/policy/challenges", this.options.nodeOrigin), {
|
|
25623
25717
|
method: "POST",
|
|
25624
25718
|
redirect: "error",
|
|
25625
25719
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
25626
|
-
body: JSON.stringify({ policyCid: envelope.policyCid, recipientDid: this.options.holderDid, requestedCapabilities: envelope.policy.capabilityCeiling })
|
|
25720
|
+
body: JSON.stringify({ policyCid: envelope.policyCid, recipientDid: this.options.holderDid, requestedCapabilities: envelope.policy.capabilityCeiling }),
|
|
25721
|
+
...this.options.signal === void 0 ? {} : { signal: this.options.signal }
|
|
25627
25722
|
});
|
|
25628
25723
|
if (!challengeResponse.ok) throw new Error(`v3 policy challenge rejected (${challengeResponse.status})`);
|
|
25629
25724
|
const challenge2 = object2(await challengeResponse.json(), "v3 policy challenge");
|
|
25630
|
-
if (typeof challenge2.challengeId !== "string" || typeof challenge2.nonce !== "string" || challenge2.policyCid !== envelope.policyCid || challenge2.recipientDid !== this.options.holderDid) throw new Error("v3 policy challenge binding mismatch");
|
|
25725
|
+
if (typeof challenge2.challengeId !== "string" || typeof challenge2.nonce !== "string" || challenge2.policyCid !== envelope.policyCid || challenge2.recipientDid !== this.options.holderDid || challenge2.nodeAudience !== attestedEnforcer.nodeAudience || challenge2.enforcerDid !== void 0 && challenge2.enforcerDid !== attestedEnforcer.enforcerDid || typeof challenge2.expiresAt !== "string" || !Number.isFinite(Date.parse(challenge2.expiresAt)) || Date.parse(challenge2.expiresAt) <= Date.now()) throw new Error("v3 policy challenge binding mismatch");
|
|
25631
25726
|
const material = await this.options.buildPresentation({
|
|
25632
25727
|
challenge: challenge2,
|
|
25633
25728
|
envelope,
|
|
25634
25729
|
policy: envelope.policy
|
|
25635
25730
|
});
|
|
25636
|
-
if (material.sign === void 0 || material.
|
|
25731
|
+
if (material.sign === void 0 || material.presentation === void 0) throw new Error("v3 ceremony requires a recipient signer and presentation");
|
|
25732
|
+
const accountless = material.presentation.schema === "xyz.tinycloud.policy/presentation/v4";
|
|
25733
|
+
if (accountless ? material.credentialEnvelope === void 0 || material.requirement === void 0 : material.claim === void 0) {
|
|
25734
|
+
throw new Error(accountless ? "v4 ceremony requires a verified credential and requirement" : "v3 ceremony requires a claim");
|
|
25735
|
+
}
|
|
25736
|
+
this.options.onStage?.("policy-admission");
|
|
25637
25737
|
const delegationResponse = await this.fetchFn(new URL("/share/v3/policy/delegations", this.options.nodeOrigin), {
|
|
25638
25738
|
method: "POST",
|
|
25639
25739
|
redirect: "error",
|
|
25640
25740
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
25641
|
-
body: JSON.stringify({ policyCid: envelope.policyCid, challengeId: challenge2.challengeId, nonce: challenge2.nonce, claim: material.claim, presentation: material.presentation })
|
|
25741
|
+
body: JSON.stringify(accountless ? { policyCid: envelope.policyCid, challengeId: challenge2.challengeId, nonce: challenge2.nonce, requirement: material.requirement, credential: material.credentialEnvelope, presentation: material.presentation } : { policyCid: envelope.policyCid, challengeId: challenge2.challengeId, nonce: challenge2.nonce, claim: material.claim, presentation: material.presentation }),
|
|
25742
|
+
...this.options.signal === void 0 ? {} : { signal: this.options.signal }
|
|
25642
25743
|
});
|
|
25643
25744
|
if (!delegationResponse.ok) throw new Error(`v3 policy delegation rejected (${delegationResponse.status})`);
|
|
25644
25745
|
const delegation = object2(await delegationResponse.json(), "v3 policy delegation");
|
|
25645
25746
|
if (delegation.admitted !== true || typeof delegation.sessionCid !== "string" || typeof delegation.authorization !== "string") throw new Error("v3 policy delegation response is not admitted");
|
|
25646
|
-
const compact =
|
|
25747
|
+
const compact = verifyV3PolicyAuthorization({ authorization: delegation.authorization, cid: delegation.sessionCid, envelope, holderDid: this.options.holderDid });
|
|
25647
25748
|
const fact = compact.payload.fct[0];
|
|
25648
|
-
|
|
25649
|
-
const imported = await this.fetchFn(new URL("/delegate", this.options.nodeOrigin), { method: "POST", redirect: "error", headers: { Authorization: delegation.authorization } });
|
|
25749
|
+
this.options.onStage?.("delegation-import");
|
|
25750
|
+
const imported = await this.fetchFn(new URL("/delegate", this.options.nodeOrigin), { method: "POST", redirect: "error", headers: { Authorization: delegation.authorization }, ...this.options.signal === void 0 ? {} : { signal: this.options.signal } });
|
|
25650
25751
|
if (!imported.ok) throw new Error(`ordinary delegation import rejected (${imported.status})`);
|
|
25651
25752
|
this.signer = material.sign;
|
|
25652
25753
|
this.v3Authorization = delegation.authorization;
|
|
25754
|
+
this.v3NodeAudience = fact.nodeAudience;
|
|
25653
25755
|
this.session = { sessionId: delegation.sessionCid, expiresAt: new Date(compact.payload.exp * 1e3).toISOString(), actions: envelope.actions, resource: envelope.resource };
|
|
25654
25756
|
return this.session;
|
|
25655
25757
|
}
|
|
@@ -25657,18 +25759,18 @@ var init_dist3 = __esm({
|
|
|
25657
25759
|
async decryptV3Content(bytes3) {
|
|
25658
25760
|
const envelope = this.options.envelope;
|
|
25659
25761
|
const signer = this.nativeSigner ?? this.signer;
|
|
25660
|
-
if (envelope.version !== 3 || this.session === void 0 || this.v3Authorization === void 0 || signer === void 0) throw new Error("v3 policy session signer is required");
|
|
25762
|
+
if (envelope.version !== 3 || this.session === void 0 || this.v3Authorization === void 0 || this.v3NodeAudience === void 0 || signer === void 0) throw new Error("v3 policy session signer is required");
|
|
25661
25763
|
const encrypted = parseV3InlineEncryptedEnvelope(bytes3, envelope);
|
|
25662
25764
|
const receiverPrivateKey = crypto.getRandomValues(new Uint8Array(32));
|
|
25663
|
-
const receiverPublicKey =
|
|
25765
|
+
const receiverPublicKey = toBase64(x25519.getPublicKey(receiverPrivateKey));
|
|
25664
25766
|
const receiverPublicKeyHash = canonicalHashHex2(receiverPublicKey);
|
|
25665
|
-
const body = { type: "tinycloud.encryption.decrypt/v1", targetNode:
|
|
25767
|
+
const body = { type: "tinycloud.encryption.decrypt/v1", targetNode: this.v3NodeAudience, networkId: encrypted.networkId, alg: encrypted.alg, keyVersion: encrypted.keyVersion, encryptedSymmetricKey: encrypted.encryptedSymmetricKey, encryptedSymmetricKeyHash: encrypted.encryptedSymmetricKeyHash, receiverPublicKey, receiverPublicKeyHash };
|
|
25666
25768
|
const bodyHash = hex2(sha2562(new TextEncoder().encode(canonicalize2(body))));
|
|
25667
25769
|
const session = verifyCompactUcanAuthorization(this.v3Authorization, this.session.sessionId);
|
|
25668
25770
|
const now = Math.floor(Date.now() / 1e3);
|
|
25669
25771
|
const invocation = await signCompactUcanAuthorization({
|
|
25670
25772
|
issuerDid: this.options.holderDid,
|
|
25671
|
-
audienceDid:
|
|
25773
|
+
audienceDid: this.v3NodeAudience,
|
|
25672
25774
|
attenuation: { [encrypted.networkId]: { "tinycloud.encryption/decrypt": [{}] } },
|
|
25673
25775
|
facts: [{ type: body.type, targetNode: body.targetNode, networkId: body.networkId, bodyHash, encryptedSymmetricKeyHash: body.encryptedSymmetricKeyHash, receiverPublicKeyHash, alg: body.alg, keyVersion: body.keyVersion }],
|
|
25674
25776
|
proofs: [session.cid],
|
|
@@ -25678,7 +25780,8 @@ var init_dist3 = __esm({
|
|
|
25678
25780
|
sign: signer
|
|
25679
25781
|
});
|
|
25680
25782
|
try {
|
|
25681
|
-
|
|
25783
|
+
this.options.onStage?.("decryption");
|
|
25784
|
+
const response = await this.fetchFn(new URL("/invoke", this.options.nodeOrigin), { method: "POST", redirect: "error", headers: { accept: "application/json", "content-type": "application/json", Authorization: invocation.authorization }, body: JSON.stringify(body), ...this.options.signal === void 0 ? {} : { signal: this.options.signal } });
|
|
25682
25785
|
if (!response.ok) throw new Error(`v3 decrypt invocation rejected (${response.status})`);
|
|
25683
25786
|
const value = object2(await response.json(), "v3 decrypt response");
|
|
25684
25787
|
const allowed = ["type", "targetNode", "networkId", "invocationCid", "encryptedSymmetricKeyHash", "receiverPublicKeyHash", "wrappedKey", "alg", "keyVersion", "requestHash", "nodeId", "nodeSignature"];
|
|
@@ -25688,12 +25791,12 @@ var init_dist3 = __esm({
|
|
|
25688
25791
|
const signature = fromBase64(value.nodeSignature, "v3 decrypt response signature");
|
|
25689
25792
|
if (signature.length !== 64 || !ed25519.verify(signature, new TextEncoder().encode(canonicalize2(unsigned)), ed25519PublicKeyFromDidKey(body.targetNode), { zip215: false })) throw new Error("v3 decrypt response signature is invalid");
|
|
25690
25793
|
const wrapped = fromBase64(value.wrappedKey, "v3 wrapped content key");
|
|
25691
|
-
if (wrapped.length <
|
|
25794
|
+
if (wrapped.length < 61 || wrapped[32] !== 1) throw new Error("v3 wrapped content key is malformed");
|
|
25692
25795
|
const shared = x25519.getSharedSecret(receiverPrivateKey, wrapped.slice(0, 32));
|
|
25693
|
-
const symmetricKey = await aesGcmDecrypt(shared, wrapped.slice(
|
|
25796
|
+
const symmetricKey = await aesGcmDecrypt(shared, wrapped.slice(33));
|
|
25694
25797
|
shared.fill(0);
|
|
25695
25798
|
if (symmetricKey.length !== 32) throw new Error("v3 content key is malformed");
|
|
25696
|
-
const plaintext = await aesGcmDecrypt(symmetricKey,
|
|
25799
|
+
const plaintext = await aesGcmDecrypt(symmetricKey, fromBase64(encrypted.ciphertext, "v3 encrypted content"));
|
|
25697
25800
|
this.v3ContentKey?.fill(0);
|
|
25698
25801
|
this.v3ContentKey = symmetricKey;
|
|
25699
25802
|
this.v3ContentEnvelope = encrypted;
|
|
@@ -25752,7 +25855,7 @@ var init_dist3 = __esm({
|
|
|
25752
25855
|
}
|
|
25753
25856
|
async nativeInvokeV3(request, envelope) {
|
|
25754
25857
|
const signer = this.nativeSigner ?? this.signer;
|
|
25755
|
-
if (this.session === void 0 || this.v3Authorization === void 0 || signer === void 0) throw new Error("v3 policy session signer is required");
|
|
25858
|
+
if (this.session === void 0 || this.v3Authorization === void 0 || this.v3NodeAudience === void 0 || signer === void 0) throw new Error("v3 policy session signer is required");
|
|
25756
25859
|
const session = verifyCompactUcanAuthorization(this.v3Authorization, this.session.sessionId);
|
|
25757
25860
|
if (session.payload.aud !== this.options.holderDid) throw new Error("v3 session recipient mismatch");
|
|
25758
25861
|
const action = request.action === "list" ? "tinycloud.kv/list" : request.action === "put" ? "tinycloud.kv/put" : request.action === "metadata" ? "tinycloud.kv/metadata" : "tinycloud.kv/get";
|
|
@@ -25766,7 +25869,7 @@ var init_dist3 = __esm({
|
|
|
25766
25869
|
if (path !== root && !(capability.selector === "prefix" && path.startsWith(`${root}/`))) throw new Error("v3 KV request is outside the signed selector");
|
|
25767
25870
|
const resource = `${capability.resource.slice(0, split2 + marker.length)}${path}`;
|
|
25768
25871
|
const now = Math.floor(Date.now() / 1e3);
|
|
25769
|
-
const invocation = await signCompactUcanAuthorization({ issuerDid: this.options.holderDid, audienceDid:
|
|
25872
|
+
const invocation = await signCompactUcanAuthorization({ issuerDid: this.options.holderDid, audienceDid: this.v3NodeAudience, attenuation: { [resource]: { [action]: [{ type: "xyz.tinycloud.resource/selector", kind: capability.selector, value: resource }] } }, facts: [{ type: "tinycloud.policy.invocation/v1", policyCid: envelope.policyCid, sessionCid: session.cid }], proofs: [session.cid], notBefore: now, expiresAt: Math.min(now + 60, session.payload.exp), nonce: toBase64Url(crypto.getRandomValues(new Uint8Array(16))), sign: signer });
|
|
25770
25873
|
const headers = new Headers({ accept: "application/json", Authorization: invocation.authorization });
|
|
25771
25874
|
let body;
|
|
25772
25875
|
if (action === "tinycloud.kv/put") {
|
|
@@ -25775,7 +25878,8 @@ var init_dist3 = __esm({
|
|
|
25775
25878
|
headers.set("content-type", request.contentType ?? "application/octet-stream");
|
|
25776
25879
|
if (request.ifMatch !== void 0) headers.set("if-match", request.ifMatch);
|
|
25777
25880
|
}
|
|
25778
|
-
|
|
25881
|
+
this.options.onStage?.("invocation");
|
|
25882
|
+
return this.fetchFn(new URL("/invoke", this.options.nodeOrigin), { method: "POST", redirect: "error", headers, ...body === void 0 ? {} : { body }, ...this.options.signal === void 0 ? {} : { signal: this.options.signal } });
|
|
25779
25883
|
}
|
|
25780
25884
|
};
|
|
25781
25885
|
}
|
|
@@ -32445,7 +32549,7 @@ function validateV3Invariants2(value, ctx) {
|
|
|
32445
32549
|
if (value.contentSource.encryptionNetwork !== value.encryptionNetwork) {
|
|
32446
32550
|
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["encryptionNetwork"], message: "encryption network is not bound to the source" });
|
|
32447
32551
|
}
|
|
32448
|
-
if (value.attestedEnforcerBinding.enforcerDid !== value.target.nodeAudience || value.attestedEnforcerBinding.
|
|
32552
|
+
if (value.attestedEnforcerBinding.enforcerDid !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
|
|
32449
32553
|
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
|
|
32450
32554
|
}
|
|
32451
32555
|
if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
|