@tinycloud/sdk-core 2.11.0-beta.0 → 2.11.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap/index.cjs +0 -4
- package/dist/delegations/index.cjs +93 -112
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +3 -2
- package/dist/delegations/index.d.ts +3 -2
- package/dist/delegations/index.js +119 -51
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +775 -399
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +338 -12
- package/dist/index.d.ts +338 -12
- package/dist/index.js +798 -83
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +10 -74
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.js +10 -8
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-B2wH53_t.d.cts → recipient-types.schema-D5pDlIqn.d.cts} +116 -5
- package/dist/{recipient-types.schema-B2wH53_t.d.ts → recipient-types.schema-D5pDlIqn.d.ts} +116 -5
- package/dist/requester/index.cjs +10 -38
- package/dist/requester/index.cjs.map +1 -1
- package/dist/requester/index.js +10 -8
- package/dist/requester/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -1858,13 +1858,12 @@ function digest(input, options2) {
|
|
|
1858
1858
|
}
|
|
1859
1859
|
var identity2 = { code: code2, name, encode: encode4, digest };
|
|
1860
1860
|
|
|
1861
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
1862
|
-
var
|
|
1863
|
-
__export(
|
|
1861
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
1862
|
+
var sha2_browser_exports = {};
|
|
1863
|
+
__export(sha2_browser_exports, {
|
|
1864
1864
|
sha256: () => sha2562,
|
|
1865
1865
|
sha512: () => sha512
|
|
1866
1866
|
});
|
|
1867
|
-
import crypto2 from "crypto";
|
|
1868
1867
|
|
|
1869
1868
|
// ../../node_modules/multiformats/dist/src/hashes/hasher.js
|
|
1870
1869
|
var DEFAULT_MIN_DIGEST_LENGTH = 20;
|
|
@@ -1914,21 +1913,24 @@ function createDigest(digest4, code3, truncate) {
|
|
|
1914
1913
|
return create(code3, digest4);
|
|
1915
1914
|
}
|
|
1916
1915
|
|
|
1917
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
1916
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
1917
|
+
function sha(name2) {
|
|
1918
|
+
return async (data) => new Uint8Array(await crypto.subtle.digest(name2, data));
|
|
1919
|
+
}
|
|
1918
1920
|
var sha2562 = from2({
|
|
1919
1921
|
name: "sha2-256",
|
|
1920
1922
|
code: 18,
|
|
1921
|
-
encode: (
|
|
1923
|
+
encode: sha("SHA-256")
|
|
1922
1924
|
});
|
|
1923
1925
|
var sha512 = from2({
|
|
1924
1926
|
name: "sha2-512",
|
|
1925
1927
|
code: 19,
|
|
1926
|
-
encode: (
|
|
1928
|
+
encode: sha("SHA-512")
|
|
1927
1929
|
});
|
|
1928
1930
|
|
|
1929
1931
|
// ../../node_modules/multiformats/dist/src/basics.js
|
|
1930
1932
|
var bases = { ...identity_exports, ...base2_exports, ...base8_exports, ...base10_exports, ...base16_exports, ...base32_exports, ...base36_exports, ...base58_exports, ...base64_exports, ...base256emoji_exports };
|
|
1931
|
-
var hashes = { ...
|
|
1933
|
+
var hashes = { ...sha2_browser_exports, ...identity_exports2 };
|
|
1932
1934
|
|
|
1933
1935
|
// src/policy/signed-object.ts
|
|
1934
1936
|
import { bytesToHex as bytesToHex2, sha256 as sha2563, verifyMessage } from "viem";
|
|
@@ -6360,15 +6362,28 @@ function normalizeSpace(space) {
|
|
|
6360
6362
|
function isCapabilitySubset(requested, granted) {
|
|
6361
6363
|
const missing = [];
|
|
6362
6364
|
for (const req of requested) {
|
|
6363
|
-
const
|
|
6364
|
-
|
|
6365
|
+
const matchingScope = granted.filter(
|
|
6366
|
+
(entry) => canonicalizeEntryScopeMatches(req, entry)
|
|
6367
|
+
);
|
|
6368
|
+
const requestedActions = expandActionShortNames(
|
|
6369
|
+
req.service,
|
|
6370
|
+
req.actions
|
|
6371
|
+
);
|
|
6372
|
+
const grantedActions = matchingScope.flatMap(
|
|
6373
|
+
(entry) => expandActionShortNames(entry.service, entry.actions)
|
|
6374
|
+
);
|
|
6375
|
+
const covered = requestedActions.every(
|
|
6376
|
+
(requestedAction) => grantedActions.some(
|
|
6377
|
+
(grantedAction) => actionContains(grantedAction, requestedAction)
|
|
6378
|
+
)
|
|
6379
|
+
);
|
|
6380
|
+
if (!covered) {
|
|
6365
6381
|
missing.push(cloneEntry(req));
|
|
6366
|
-
continue;
|
|
6367
6382
|
}
|
|
6368
6383
|
}
|
|
6369
6384
|
return { subset: missing.length === 0, missing };
|
|
6370
6385
|
}
|
|
6371
|
-
function
|
|
6386
|
+
function canonicalizeEntryScopeMatches(requested, granted) {
|
|
6372
6387
|
if (requested.service !== granted.service) {
|
|
6373
6388
|
return false;
|
|
6374
6389
|
}
|
|
@@ -6378,15 +6393,6 @@ function canonicalizeEntryMatches(requested, granted) {
|
|
|
6378
6393
|
if (!pathContains2(granted.path, requested.path)) {
|
|
6379
6394
|
return false;
|
|
6380
6395
|
}
|
|
6381
|
-
const reqActions = new Set(
|
|
6382
|
-
expandActionShortNames(requested.service, requested.actions)
|
|
6383
|
-
);
|
|
6384
|
-
const grantedActions = expandActionShortNames(granted.service, granted.actions);
|
|
6385
|
-
for (const a of reqActions) {
|
|
6386
|
-
if (!grantedActions.some((grantedAction) => actionContains(grantedAction, a))) {
|
|
6387
|
-
return false;
|
|
6388
|
-
}
|
|
6389
|
-
}
|
|
6390
6396
|
if (!recapCaveatsEqual(requested.caveats, granted.caveats)) {
|
|
6391
6397
|
return false;
|
|
6392
6398
|
}
|
|
@@ -6654,6 +6660,10 @@ function normalizeRecipient(recipient) {
|
|
|
6654
6660
|
}
|
|
6655
6661
|
return { kind: recipient.kind, value: domain };
|
|
6656
6662
|
}
|
|
6663
|
+
if (recipient.kind === "recipientDid") {
|
|
6664
|
+
if (!isCanonicalRecipientDid(recipient.value)) throw new ShareEnvelopeError("invalid-envelope", "recipient DID is invalid");
|
|
6665
|
+
return { kind: recipient.kind, value: recipient.value };
|
|
6666
|
+
}
|
|
6657
6667
|
const exact = recipient.value.trim();
|
|
6658
6668
|
const at = exact.lastIndexOf("@");
|
|
6659
6669
|
const normalizedExact = at > 0 ? `${exact.slice(0, at)}@${exact.slice(at + 1).toLowerCase()}` : exact;
|
|
@@ -6662,6 +6672,28 @@ function normalizeRecipient(recipient) {
|
|
|
6662
6672
|
}
|
|
6663
6673
|
return { kind: recipient.kind, value: normalizedExact };
|
|
6664
6674
|
}
|
|
6675
|
+
function isCanonicalRecipientDid(value) {
|
|
6676
|
+
if (value.length === 0 || value.length > 2048 || /[\u0000-\u0020\u007f]/.test(value)) return false;
|
|
6677
|
+
const parts = value.split(":");
|
|
6678
|
+
if (parts.length < 3 || parts[0] !== "did" || !/^[a-z0-9]+$/.test(parts[1] ?? "")) return false;
|
|
6679
|
+
const identifier = parts.slice(2);
|
|
6680
|
+
if (identifier.some((part) => part.length === 0)) return false;
|
|
6681
|
+
if (parts[1] === "web") {
|
|
6682
|
+
const host = identifier[0] ?? "";
|
|
6683
|
+
if (host.length > 253 || host.split(".").some((label) => !label || label.length > 63 || !/^[A-Za-z0-9-]+$/.test(label) || label.startsWith("-") || label.endsWith("-"))) return false;
|
|
6684
|
+
return identifier.slice(1).every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
|
|
6685
|
+
}
|
|
6686
|
+
if (parts[1] === "pkh") return identifier.length >= 3 && identifier.every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
|
|
6687
|
+
if (parts[1] === "key") {
|
|
6688
|
+
try {
|
|
6689
|
+
const bytes2 = base58btc.decode(identifier.join(":"));
|
|
6690
|
+
return bytes2.length === 34 && bytes2[0] === 237 && bytes2[1] === 1;
|
|
6691
|
+
} catch {
|
|
6692
|
+
return false;
|
|
6693
|
+
}
|
|
6694
|
+
}
|
|
6695
|
+
return false;
|
|
6696
|
+
}
|
|
6665
6697
|
function normalizeShareRecipientTarget(recipient) {
|
|
6666
6698
|
const normalized = normalizeRecipient(recipient);
|
|
6667
6699
|
if (normalized === void 0) throw new ShareEnvelopeError("invalid-envelope", "recipient matcher is required");
|
|
@@ -6748,9 +6780,9 @@ function verifyShareEnvelope(envelope, options2 = {}) {
|
|
|
6748
6780
|
const recipient = normalizeRecipient(envelope.recipient);
|
|
6749
6781
|
if (recipient !== void 0 && JSON.stringify(recipient) !== JSON.stringify(envelope.recipient)) throw new ShareEnvelopeError("invalid-envelope", "recipient is not canonical");
|
|
6750
6782
|
if (recipient?.kind === "exactEmail" || recipient?.kind === "emailDomain") throw new ShareEnvelopeError("unsafe-plaintext", "recipient matchers are not public envelope fields");
|
|
6751
|
-
if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
|
|
6783
|
+
if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "recipientDid", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
|
|
6752
6784
|
if (envelope.recipientKind === "bearer" && recipient?.kind !== void 0 && recipient.kind !== "bearer") throw new ShareEnvelopeError("invalid-envelope", "recipient mode does not match recipient");
|
|
6753
|
-
if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "
|
|
6785
|
+
if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.recipientKind === "recipientDid") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "addressed shares require encryption");
|
|
6754
6786
|
if (typeof envelope.spaceId !== "string" || envelope.spaceId.length === 0 || typeof envelope.content.mimeType !== "string" || envelope.content.mimeType.length === 0 || typeof envelope.content.digest !== "string" || !/^[A-Za-z0-9_-]+$/.test(envelope.content.digest)) throw new ShareEnvelopeError("invalid-envelope", "content metadata is invalid");
|
|
6755
6787
|
const maxContentBytes = envelope.encrypted ? options2.maxSealedContentBytes ?? MAX_SEALED_SHARE_CONTENT_BYTES : options2.maxContentBytes ?? MAX_SHARE_CONTENT_BYTES;
|
|
6756
6788
|
if (!Number.isInteger(envelope.content.size) || envelope.content.size < 0 || envelope.content.size > maxContentBytes) throw new ShareEnvelopeError("content-too-large", "share content exceeds the configured limit");
|
|
@@ -6889,7 +6921,7 @@ function parsePolicyMetadata(policyBytes, target, expectedExpiry) {
|
|
|
6889
6921
|
assertKeys(policy, ["type", "version", "issuerDid", "recipientMatcher", "target", "delegation", "authority", "actions", "resource", "content-source", "expiresAt"], "published canonical policy material");
|
|
6890
6922
|
if (typeof policy.issuerDid !== "string" || typeof policy.expiresAt !== "string" || policy.expiresAt !== expectedExpiry) throw new ShareEnvelopeError("invalid-envelope", "policy expiry is not bound to the envelope");
|
|
6891
6923
|
const matcherValue = policy.recipientMatcher;
|
|
6892
|
-
if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
6924
|
+
if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" && matcherValue.kind !== "recipientDid" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
6893
6925
|
const matcher2 = normalizeRecipient(matcherValue);
|
|
6894
6926
|
if (matcher2 === void 0 || matcher2.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
6895
6927
|
if (!isPlainObject(policy.target)) throw new ShareEnvelopeError("invalid-envelope", "policy target is invalid");
|
|
@@ -6976,7 +7008,7 @@ function parseCanonicalPublishedV2(value, options2) {
|
|
|
6976
7008
|
if (!Number.isFinite(expiry) || expiry <= (options2.now ?? /* @__PURE__ */ new Date()).getTime() || new Date(expiry).toISOString() !== value.expiry) throw new ShareEnvelopeError("expired", "published share envelope has expired");
|
|
6977
7009
|
if (typeof delegation.cid !== "string" || typeof delegation.issuerDid !== "string" || typeof delegation.audience !== "string" || typeof delegation.expiresAt !== "string" || Date.parse(delegation.expiresAt) > expiry) throw new ShareEnvelopeError("invalid-envelope", "published v2 delegation is invalid");
|
|
6978
7010
|
const matcher = value.recipientMatcher;
|
|
6979
|
-
if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
7011
|
+
if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" && matcher.kind !== "recipientDid" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
6980
7012
|
const normalizedMatcher = normalizeRecipient(matcher);
|
|
6981
7013
|
if (normalizedMatcher === void 0 || normalizedMatcher.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
6982
7014
|
if (!Array.isArray(value.actions)) throw new ShareEnvelopeError("invalid-envelope", "published v2 actions are invalid");
|
|
@@ -7417,10 +7449,11 @@ var ShareConflict = class extends Error {
|
|
|
7417
7449
|
}
|
|
7418
7450
|
};
|
|
7419
7451
|
var ShareAccessError = class extends Error {
|
|
7420
|
-
constructor(code3, message) {
|
|
7452
|
+
constructor(code3, message, details) {
|
|
7421
7453
|
super(message ?? "shared access could not be completed");
|
|
7422
7454
|
this.name = "ShareAccessError";
|
|
7423
7455
|
this.code = code3;
|
|
7456
|
+
this.details = details;
|
|
7424
7457
|
}
|
|
7425
7458
|
};
|
|
7426
7459
|
|
|
@@ -7429,6 +7462,7 @@ import { z as z5 } from "zod";
|
|
|
7429
7462
|
var ShareRecipientTargetSchema = z5.discriminatedUnion("kind", [
|
|
7430
7463
|
z5.object({ kind: z5.literal("exactEmail"), value: z5.string().min(1) }).strict(),
|
|
7431
7464
|
z5.object({ kind: z5.literal("emailDomain"), value: z5.string().min(1) }).strict(),
|
|
7465
|
+
z5.object({ kind: z5.literal("recipientDid"), value: z5.string().regex(/^did:[a-z0-9]+:.+$/) }).strict(),
|
|
7432
7466
|
z5.object({ kind: z5.literal("bearer") }).strict()
|
|
7433
7467
|
]);
|
|
7434
7468
|
var ShareResourceSchema = z5.discriminatedUnion("kind", [
|
|
@@ -7472,7 +7506,8 @@ var ShareContentSourceSchema = z5.discriminatedUnion("kind", [
|
|
|
7472
7506
|
]);
|
|
7473
7507
|
var ShareAddressedRecipientSchema = z5.discriminatedUnion("kind", [
|
|
7474
7508
|
z5.object({ kind: z5.literal("exactEmail"), value: z5.string().min(1) }).strict(),
|
|
7475
|
-
z5.object({ kind: z5.literal("emailDomain"), value: z5.string().min(1) }).strict()
|
|
7509
|
+
z5.object({ kind: z5.literal("emailDomain"), value: z5.string().min(1) }).strict(),
|
|
7510
|
+
z5.object({ kind: z5.literal("recipientDid"), value: z5.string().regex(/^did:[a-z0-9]+:.+$/) }).strict()
|
|
7476
7511
|
]);
|
|
7477
7512
|
var ShareAddressedDelegationRequestV2Schema = z5.object({
|
|
7478
7513
|
version: z5.literal(2),
|
|
@@ -7727,12 +7762,21 @@ var ShareRecipientClient = class {
|
|
|
7727
7762
|
const { envelope } = resolved.artifact;
|
|
7728
7763
|
const { location } = resolved;
|
|
7729
7764
|
const bearer = isBearerEnvelope(envelope);
|
|
7730
|
-
const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain";
|
|
7765
|
+
const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.authorizationTargetKind === "recipientDid";
|
|
7731
7766
|
const legacyBearer = !policy && envelope.recipientKind === void 0;
|
|
7732
|
-
|
|
7767
|
+
let recipientDidSession;
|
|
7768
|
+
if (envelope.authorizationTargetKind === "recipientDid") {
|
|
7769
|
+
if (this.options.establishRecipientDidSession === void 0) throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required");
|
|
7770
|
+
const authorization = await this.options.establishRecipientDidSession({ envelope, recipientDid: envelope.recipient?.kind === "recipientDid" ? envelope.recipient.value : "" });
|
|
7771
|
+
if ("state" in authorization) {
|
|
7772
|
+
if (authorization.state === "authorization-required") throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required", authorization);
|
|
7773
|
+
throw new ShareAccessError("SHARE_DENIED", "recipient DID authorization was denied", authorization);
|
|
7774
|
+
}
|
|
7775
|
+
recipientDidSession = authorization;
|
|
7776
|
+
}
|
|
7733
7777
|
if (policy && this.options.bearerSession !== void 0) throw new ShareAccessError("SHARE_POLICY_BEARER_MISMATCH");
|
|
7734
7778
|
if (bearer && this.options.presentation !== void 0) throw new ShareAccessError("SHARE_BEARER_PRESENTATION_MISMATCH");
|
|
7735
|
-
const session = bearer || legacyBearer ? this.options.bearerSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
|
|
7779
|
+
const session = bearer || legacyBearer ? this.options.bearerSession : recipientDidSession ? recipientDidSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
|
|
7736
7780
|
const kv = bearer || legacyBearer ? session === void 0 ? void 0 : this.createKV(envelope.origin, session) : void 0;
|
|
7737
7781
|
const policySession = policy ? session : void 0;
|
|
7738
7782
|
if (policySession !== void 0) this.assertProvidedPolicySession(policySession, envelope);
|
|
@@ -9788,6 +9832,10 @@ async function createPolicyEnforcementDelegation(input) {
|
|
|
9788
9832
|
spaceId: input.spaceId,
|
|
9789
9833
|
path: input.path,
|
|
9790
9834
|
actions: [...input.actions],
|
|
9835
|
+
...input.decryption === void 0 ? {} : {
|
|
9836
|
+
decryptionNetworkId: input.decryption.networkId,
|
|
9837
|
+
decryptionAction: input.decryption.action
|
|
9838
|
+
},
|
|
9791
9839
|
contentSourceDigest: input.contentSourceDigest,
|
|
9792
9840
|
expiresAt: input.expiresAt
|
|
9793
9841
|
};
|
|
@@ -9807,7 +9855,9 @@ function computeOwnerShareRegistrationCid(registration) {
|
|
|
9807
9855
|
function validateOwnerSharePolicyRegistration(value, expected) {
|
|
9808
9856
|
if (cid(expected.policy.bytes) !== expected.policy.cid) throw new Error("submitted owner-share policy bytes do not match its CID");
|
|
9809
9857
|
const root = assertObject(value, ["registration", "proof"], "owner-share registration response");
|
|
9810
|
-
const
|
|
9858
|
+
const rawRegistration = root.registration;
|
|
9859
|
+
const hasDecryption = typeof rawRegistration === "object" && rawRegistration !== null && Object.prototype.hasOwnProperty.call(rawRegistration, "decryption");
|
|
9860
|
+
const registration = assertObject(root.registration, ["registrationCid", "policyCid", "ownerDelegationCid", "enforcementDelegationCid", "ownerDid", "shareKeyDid", "enforcerDid", "shareId", "recipientMatcher", "target", "resource", "actions", ...hasDecryption ? ["decryption"] : [], "contentSource", "contentSourceDigest", "registeredAt", "expiresAt"], "owner-share registration");
|
|
9811
9861
|
const proof = assertObject(root.proof, ["alg", "kid", "signature"], "owner-share registration proof");
|
|
9812
9862
|
if (registration.policyCid !== expected.policy.cid || registration.ownerDelegationCid !== expected.ownerDelegation.delegationCid || registration.enforcementDelegationCid !== expected.enforcementDelegation.cid || registration.contentSourceDigest !== expected.contentSourceDigest) throw new Error("owner-share registration is not bound to the submitted chain");
|
|
9813
9863
|
let policyValue;
|
|
@@ -9823,7 +9873,9 @@ function validateOwnerSharePolicyRegistration(value, expected) {
|
|
|
9823
9873
|
const registrationTarget = registration.target;
|
|
9824
9874
|
const registrationResource = registration.resource;
|
|
9825
9875
|
const enforcementFacts = expected.enforcementDelegation.facts;
|
|
9826
|
-
|
|
9876
|
+
const decryption = policy.decryption;
|
|
9877
|
+
const decryptionMatches = decryption === void 0 ? registration.decryption === void 0 : registration.decryption !== void 0 && canonicalizeSignedObjectUnsigned(decryption) === canonicalizeSignedObjectUnsigned(registration.decryption);
|
|
9878
|
+
if (typeof target?.origin !== "string" || typeof target.nodeAudience !== "string" || typeof target.enforcerDid !== "string" || typeof target.spaceId !== "string" || typeof resource?.kind !== "string" || !["exact", "prefix"].includes(resource.kind) || typeof resource?.path !== "string" || !Array.isArray(policy.actions) || policy.ownerDid !== registration.ownerDid || policy.shareKeyDid !== registration.shareKeyDid || policy.shareId !== registration.shareId || canonicalizeSignedObjectUnsigned(policy.recipientMatcher) !== canonicalizeSignedObjectUnsigned(registration.recipientMatcher) || target.origin !== registrationTarget.origin || target.nodeAudience !== registrationTarget.nodeAudience || target.enforcerDid !== registration.enforcerDid || target.spaceId !== registrationTarget.spaceId || resource.kind !== registrationResource.kind || resource.path !== registrationResource.path || canonicalizeSignedObjectUnsigned(policy.actions) !== canonicalizeSignedObjectUnsigned(registration.actions) || !decryptionMatches || canonicalizeSignedObjectUnsigned(policy.contentSource) !== canonicalizeSignedObjectUnsigned(registration.contentSource) || policy.expiresAt !== registration.expiresAt || policy.contentSourceDigest !== registration.contentSourceDigest || enforcementFacts.ownerDelegationCid !== registration.ownerDelegationCid || enforcementFacts.policyCid !== registration.policyCid || enforcementFacts.shareKeyDid !== registration.shareKeyDid || enforcementFacts.enforcerDid !== registration.enforcerDid || enforcementFacts.nodeAudience !== registrationTarget.nodeAudience || enforcementFacts.spaceId !== registrationTarget.spaceId || enforcementFacts.path !== registrationResource.path || canonicalizeSignedObjectUnsigned(enforcementFacts.actions) !== canonicalizeSignedObjectUnsigned(registration.actions) || enforcementFacts.decryptionNetworkId !== decryption?.networkId || enforcementFacts.decryptionAction !== decryption?.action || enforcementFacts.expiresAt !== registration.expiresAt) throw new Error("owner-share registration is not bound to the canonical policy");
|
|
9827
9879
|
if (typeof registration.registrationCid !== "string" || typeof registration.expiresAt !== "string" || typeof registration.registeredAt !== "string") throw new Error("owner-share registration timestamps are invalid");
|
|
9828
9880
|
if (new Date(registration.expiresAt).toISOString() !== registration.expiresAt || Date.parse(registration.expiresAt) <= Date.now()) throw new Error("owner-share registration is expired or non-canonical");
|
|
9829
9881
|
const { registrationCid: _registrationCid, ...registrationCore } = registration;
|
|
@@ -9925,7 +9977,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
|
9925
9977
|
const authorization = assertObject2(root.authorization, AUTHORIZATION_KEYS, "share delivery authorization");
|
|
9926
9978
|
const proof = assertObject2(root.proof, ["alg", "kid", "signature"], "share delivery authorization proof");
|
|
9927
9979
|
const request = expected.request;
|
|
9928
|
-
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.
|
|
9980
|
+
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) {
|
|
9929
9981
|
throw new Error("share delivery authorization is not bound to the submitted request");
|
|
9930
9982
|
}
|
|
9931
9983
|
if (typeof authorization.issuedAt !== "string" || Date.parse(authorization.issuedAt) > Date.now() + 6e4) throw new Error("share delivery authorization issuedAt is invalid");
|
|
@@ -10060,6 +10112,32 @@ var SenderShareStore = class {
|
|
|
10060
10112
|
}
|
|
10061
10113
|
};
|
|
10062
10114
|
|
|
10115
|
+
// src/delegations/index.ts
|
|
10116
|
+
import {
|
|
10117
|
+
authorizeShare,
|
|
10118
|
+
authorizationMethodForTarget,
|
|
10119
|
+
notifyShare,
|
|
10120
|
+
revokeShare,
|
|
10121
|
+
listShares,
|
|
10122
|
+
showShare,
|
|
10123
|
+
publishTargetShare,
|
|
10124
|
+
publishPolicyShare,
|
|
10125
|
+
claimShare,
|
|
10126
|
+
resumeShareAuthorization,
|
|
10127
|
+
isLegacyShareLink,
|
|
10128
|
+
receiveLegacyShare,
|
|
10129
|
+
migrateShare,
|
|
10130
|
+
MemoryEncryptedShareHistoryStorage,
|
|
10131
|
+
EncryptedSenderShareHistory
|
|
10132
|
+
} from "@tinycloud/share-sdk";
|
|
10133
|
+
import {
|
|
10134
|
+
inspectShare,
|
|
10135
|
+
receiveShare,
|
|
10136
|
+
ShareReceiveError,
|
|
10137
|
+
toShareErrorInfo,
|
|
10138
|
+
verifyBearerEnvelope
|
|
10139
|
+
} from "@tinycloud/share-sdk";
|
|
10140
|
+
|
|
10063
10141
|
// src/networkId.ts
|
|
10064
10142
|
import {
|
|
10065
10143
|
buildNetworkId,
|
|
@@ -11781,7 +11859,8 @@ var TinyCloud = class _TinyCloud {
|
|
|
11781
11859
|
import {
|
|
11782
11860
|
err as err3,
|
|
11783
11861
|
ok as ok3,
|
|
11784
|
-
serviceError as serviceError3
|
|
11862
|
+
serviceError as serviceError3,
|
|
11863
|
+
ErrorCodes as ErrorCodes3
|
|
11785
11864
|
} from "@tinycloud/sdk-services";
|
|
11786
11865
|
import { ACCOUNT_INDEX_SCHEMA } from "@tinycloud/bootstrap";
|
|
11787
11866
|
var SERVICE_NAME2 = "account";
|
|
@@ -11791,6 +11870,22 @@ var ACCOUNT_SPACES_PATH = "spaces/";
|
|
|
11791
11870
|
var AccountService = class {
|
|
11792
11871
|
constructor(config) {
|
|
11793
11872
|
this.config = config;
|
|
11873
|
+
/**
|
|
11874
|
+
* Per-account-space memo for {@link ensureAccountIndex}.
|
|
11875
|
+
*
|
|
11876
|
+
* Applying the index migration is a no-op once the schema exists, but the
|
|
11877
|
+
* SQL service still spends two round trips discovering that (create the
|
|
11878
|
+
* migrations table, then read the applied-migration rows). Account bootstrap
|
|
11879
|
+
* touches the index eight times, so without a memo that is ~14 wasted
|
|
11880
|
+
* requests on the cold sign-in path. The in-flight dedupe inside SQLService
|
|
11881
|
+
* never helps here: the node SDK builds a fresh SQLService per
|
|
11882
|
+
* `getAccountDb()` call, so its lock map is always empty.
|
|
11883
|
+
*
|
|
11884
|
+
* Keyed by account space id, so a different account never reuses this entry.
|
|
11885
|
+
* Failures are evicted so a later call retries instead of inheriting a
|
|
11886
|
+
* permanently poisoned result.
|
|
11887
|
+
*/
|
|
11888
|
+
this.accountIndexReady = /* @__PURE__ */ new Map();
|
|
11794
11889
|
this.applications = {
|
|
11795
11890
|
list: async (options2 = {}) => {
|
|
11796
11891
|
if (options2.preferIndex) {
|
|
@@ -11824,7 +11919,7 @@ var AccountService = class {
|
|
|
11824
11919
|
if (!loaded.ok) return accountErr(loaded.error);
|
|
11825
11920
|
return ok3(applicationFromRecord(key, loaded.data.data));
|
|
11826
11921
|
},
|
|
11827
|
-
register: async (manifest) => {
|
|
11922
|
+
register: async (manifest, options2 = {}) => {
|
|
11828
11923
|
const manifests = Array.isArray(manifest) ? manifest : [manifest];
|
|
11829
11924
|
const request = composeManifestRequest(manifests);
|
|
11830
11925
|
if (request.registryRecords.length === 0) {
|
|
@@ -11842,7 +11937,7 @@ var AccountService = class {
|
|
|
11842
11937
|
let registered;
|
|
11843
11938
|
for (const record of request.registryRecords) {
|
|
11844
11939
|
const manifestHash = hashJson(record.manifests);
|
|
11845
|
-
if (await this.indexHasApplicationHash(record.app_id, manifestHash)) {
|
|
11940
|
+
if (!options2.assumeUnregistered && await this.indexHasApplicationHash(record.app_id, manifestHash)) {
|
|
11846
11941
|
registered = {
|
|
11847
11942
|
appId: record.app_id,
|
|
11848
11943
|
manifests: record.manifests,
|
|
@@ -11917,6 +12012,60 @@ var AccountService = class {
|
|
|
11917
12012
|
await this.upsertSpaceIndexQuietly(registered);
|
|
11918
12013
|
return ok3(registered);
|
|
11919
12014
|
},
|
|
12015
|
+
/**
|
|
12016
|
+
* Register multiple spaces in one KV batch write + one multi-row index
|
|
12017
|
+
* write, instead of one `register()` round trip per space (TC-373).
|
|
12018
|
+
*
|
|
12019
|
+
* The stored records are computed exactly once and reused for both the
|
|
12020
|
+
* batch attempt and any reconciliation below, so a fallback never mints a
|
|
12021
|
+
* fresh timestamp for a space that already has a written record — a
|
|
12022
|
+
* second `spaceRecordFromInput` call would produce a new content hash and
|
|
12023
|
+
* leave the first attempt's blocks orphaned.
|
|
12024
|
+
*/
|
|
12025
|
+
registerBatch: async (spaces) => {
|
|
12026
|
+
if (spaces.length === 0) return ok3({ spaces: [] });
|
|
12027
|
+
await this.config.ensureAccountSpaceHosted?.();
|
|
12028
|
+
const kvResult = this.accountKV();
|
|
12029
|
+
if (!kvResult.ok) return kvResult;
|
|
12030
|
+
const stored = spaces.map((space) => spaceRecordFromInput(space));
|
|
12031
|
+
const registered = stored.map(
|
|
12032
|
+
(record) => spaceFromRecord(spaceKey(record.space_id), record)
|
|
12033
|
+
);
|
|
12034
|
+
const items = stored.map((record) => ({
|
|
12035
|
+
key: spaceKey(record.space_id),
|
|
12036
|
+
value: record
|
|
12037
|
+
}));
|
|
12038
|
+
const batchResult = await kvResult.data.batchPut(items);
|
|
12039
|
+
if (batchResult.ok) {
|
|
12040
|
+
await this.upsertSpacesIndexQuietly(registered);
|
|
12041
|
+
return ok3({ spaces: registered });
|
|
12042
|
+
}
|
|
12043
|
+
if (!isAmbiguousBatchFailure(batchResult.error)) {
|
|
12044
|
+
return accountErr(batchResult.error);
|
|
12045
|
+
}
|
|
12046
|
+
const reconcileFailures = [];
|
|
12047
|
+
for (const record of stored) {
|
|
12048
|
+
const written = await kvResult.data.put(spaceKey(record.space_id), record);
|
|
12049
|
+
if (!written.ok) {
|
|
12050
|
+
reconcileFailures.push(`${record.space_id}: ${written.error.message}`);
|
|
12051
|
+
}
|
|
12052
|
+
}
|
|
12053
|
+
if (reconcileFailures.length > 0) {
|
|
12054
|
+
return err3(
|
|
12055
|
+
serviceError3(
|
|
12056
|
+
"KV_BATCH_RECONCILE_FAILED",
|
|
12057
|
+
`KV batch write for ${items.length} space(s) failed ambiguously (${batchResult.error.message}) and per-space reconciliation also failed for: ${reconcileFailures.join("; ")}`,
|
|
12058
|
+
SERVICE_NAME2,
|
|
12059
|
+
{ cause: batchResult.error.cause, meta: { originalError: batchResult.error } }
|
|
12060
|
+
)
|
|
12061
|
+
);
|
|
12062
|
+
}
|
|
12063
|
+
console.warn(
|
|
12064
|
+
`[AccountService] KV batch write for ${items.length} space(s) returned an ambiguous error and was reconciled via per-space fallback. Original error: ${batchResult.error.message}`
|
|
12065
|
+
);
|
|
12066
|
+
await this.upsertSpacesIndexQuietly(registered);
|
|
12067
|
+
return ok3({ spaces: registered, recoveredFromBatchError: batchResult.error });
|
|
12068
|
+
},
|
|
11920
12069
|
syncAccessible: async () => {
|
|
11921
12070
|
const listed = await this.config.getSpaces().list();
|
|
11922
12071
|
if (!listed.ok) return accountErr(listed.error);
|
|
@@ -12023,6 +12172,7 @@ var AccountService = class {
|
|
|
12023
12172
|
const delegations = await this.delegations.list();
|
|
12024
12173
|
if (!delegations.ok) return delegations;
|
|
12025
12174
|
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12175
|
+
this.invalidateAccountIndexMemo();
|
|
12026
12176
|
const schema = await this.ensureAccountIndex(dbResult.data);
|
|
12027
12177
|
if (!schema.ok) return schema;
|
|
12028
12178
|
const statements = [
|
|
@@ -12302,6 +12452,47 @@ var AccountService = class {
|
|
|
12302
12452
|
if (!written.ok) return accountErr(written.error);
|
|
12303
12453
|
return ok3(void 0);
|
|
12304
12454
|
}
|
|
12455
|
+
async upsertSpacesIndexQuietly(spaces) {
|
|
12456
|
+
await ignoreIndexFailure(() => this.upsertSpacesIndex(spaces));
|
|
12457
|
+
}
|
|
12458
|
+
/**
|
|
12459
|
+
* Upsert multiple space index rows in ONE multi-row `INSERT OR REPLACE`
|
|
12460
|
+
* statement (TC-373), rather than one statement per space. This matters
|
|
12461
|
+
* because `IDatabaseHandle.batch()` executes its statement list as a plain
|
|
12462
|
+
* loop, not a single database transaction — an N-statement batch is not
|
|
12463
|
+
* atomic. A single multi-row INSERT is one SQLite statement, so it applies
|
|
12464
|
+
* atomically: all rows or none.
|
|
12465
|
+
*/
|
|
12466
|
+
async upsertSpacesIndex(spaces) {
|
|
12467
|
+
if (spaces.length === 0) return ok3(void 0);
|
|
12468
|
+
const dbResult = this.accountDb();
|
|
12469
|
+
if (!dbResult.ok) return ok3(void 0);
|
|
12470
|
+
const schema = await this.ensureAccountIndex(dbResult.data);
|
|
12471
|
+
if (!schema.ok) return schema;
|
|
12472
|
+
const placeholders = spaces.map(() => "(?, ?, ?, ?, ?, ?, ?, ?, ?)").join(", ");
|
|
12473
|
+
const params = spaces.flatMap((space) => {
|
|
12474
|
+
const updatedAt = space.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
12475
|
+
return [
|
|
12476
|
+
space.spaceId,
|
|
12477
|
+
space.name,
|
|
12478
|
+
space.ownerDid,
|
|
12479
|
+
space.type,
|
|
12480
|
+
JSON.stringify(space.permissions),
|
|
12481
|
+
space.status,
|
|
12482
|
+
space.registeredAt ?? updatedAt,
|
|
12483
|
+
updatedAt,
|
|
12484
|
+
space.expiresAt?.toISOString() ?? null
|
|
12485
|
+
];
|
|
12486
|
+
});
|
|
12487
|
+
const written = await dbResult.data.batch([
|
|
12488
|
+
{
|
|
12489
|
+
sql: `INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES ${placeholders}`,
|
|
12490
|
+
params
|
|
12491
|
+
}
|
|
12492
|
+
]);
|
|
12493
|
+
if (!written.ok) return accountErr(written.error);
|
|
12494
|
+
return ok3(void 0);
|
|
12495
|
+
}
|
|
12305
12496
|
async deleteSpaceIndexQuietly(spaceId) {
|
|
12306
12497
|
await ignoreIndexFailure(() => this.deleteSpaceIndex(spaceId));
|
|
12307
12498
|
}
|
|
@@ -12422,7 +12613,41 @@ var AccountService = class {
|
|
|
12422
12613
|
]);
|
|
12423
12614
|
});
|
|
12424
12615
|
}
|
|
12616
|
+
/**
|
|
12617
|
+
* Apply the account index schema at most once per account space.
|
|
12618
|
+
*
|
|
12619
|
+
* The index is a cache over canonical KV state, and every caller already
|
|
12620
|
+
* tolerates it being absent (`ignoreIndexFailure` / `isMissingIndexError`),
|
|
12621
|
+
* so a memo that is wrong in the "already applied" direction degrades to a
|
|
12622
|
+
* `no such table` read that the caller handles. A memo that is wrong in the
|
|
12623
|
+
* other direction would be a real bug, so failures are never cached.
|
|
12624
|
+
*/
|
|
12425
12625
|
async ensureAccountIndex(db) {
|
|
12626
|
+
const key = this.config.getAccountSpaceId() ?? "";
|
|
12627
|
+
const cached = this.accountIndexReady.get(key);
|
|
12628
|
+
if (cached) return cached;
|
|
12629
|
+
const pending = this.applyAccountIndex(db);
|
|
12630
|
+
this.accountIndexReady.set(key, pending);
|
|
12631
|
+
const evict = () => {
|
|
12632
|
+
if (this.accountIndexReady.get(key) === pending) {
|
|
12633
|
+
this.accountIndexReady.delete(key);
|
|
12634
|
+
}
|
|
12635
|
+
};
|
|
12636
|
+
let settled;
|
|
12637
|
+
try {
|
|
12638
|
+
settled = await pending;
|
|
12639
|
+
} catch (error) {
|
|
12640
|
+
evict();
|
|
12641
|
+
throw error;
|
|
12642
|
+
}
|
|
12643
|
+
if (!settled.ok) evict();
|
|
12644
|
+
return settled;
|
|
12645
|
+
}
|
|
12646
|
+
/** Drop the memo so the next {@link ensureAccountIndex} re-applies the schema. */
|
|
12647
|
+
invalidateAccountIndexMemo() {
|
|
12648
|
+
this.accountIndexReady.delete(this.config.getAccountSpaceId() ?? "");
|
|
12649
|
+
}
|
|
12650
|
+
async applyAccountIndex(db) {
|
|
12426
12651
|
const migrated = await db.migrations.apply({
|
|
12427
12652
|
namespace: ACCOUNT_INDEX_NAMESPACE,
|
|
12428
12653
|
migrations: [
|
|
@@ -12594,6 +12819,17 @@ function accountErr(error) {
|
|
|
12594
12819
|
function isMissingIndexError(error) {
|
|
12595
12820
|
return /no such table:/i.test(error.message);
|
|
12596
12821
|
}
|
|
12822
|
+
var AMBIGUOUS_WRITE_STATUSES = /* @__PURE__ */ new Set([500, 502, 503, 504, 520, 522, 524]);
|
|
12823
|
+
function isAmbiguousBatchFailure(error) {
|
|
12824
|
+
if (error.code === ErrorCodes3.NETWORK_ERROR || error.code === ErrorCodes3.TIMEOUT) {
|
|
12825
|
+
return error.meta?.requestMayHaveDispatched === true;
|
|
12826
|
+
}
|
|
12827
|
+
if (error.code === ErrorCodes3.KV_WRITE_FAILED) {
|
|
12828
|
+
const status = error.meta?.status;
|
|
12829
|
+
return typeof status === "number" && AMBIGUOUS_WRITE_STATUSES.has(status);
|
|
12830
|
+
}
|
|
12831
|
+
return false;
|
|
12832
|
+
}
|
|
12597
12833
|
async function ignoreIndexFailure(task) {
|
|
12598
12834
|
try {
|
|
12599
12835
|
await task();
|
|
@@ -12609,7 +12845,7 @@ import {
|
|
|
12609
12845
|
ok as ok5,
|
|
12610
12846
|
err as err5,
|
|
12611
12847
|
serviceError as serviceError5,
|
|
12612
|
-
ErrorCodes as
|
|
12848
|
+
ErrorCodes as ErrorCodes4,
|
|
12613
12849
|
TinyCloudDebugLogger,
|
|
12614
12850
|
tinyCloudDebugLogger,
|
|
12615
12851
|
enableTinyCloudDebug,
|
|
@@ -13283,6 +13519,279 @@ var AutoApproveSpaceCreationHandler = class {
|
|
|
13283
13519
|
};
|
|
13284
13520
|
var defaultSpaceCreationHandler = new AutoApproveSpaceCreationHandler();
|
|
13285
13521
|
|
|
13522
|
+
// src/authorization/openkey-protocol.ts
|
|
13523
|
+
function validateAuthorizationResultV1(value) {
|
|
13524
|
+
if (!value || typeof value !== "object") {
|
|
13525
|
+
return { ok: false, error: "authorization result must be an object" };
|
|
13526
|
+
}
|
|
13527
|
+
const v = value;
|
|
13528
|
+
if (v.protocolVersion !== 1) {
|
|
13529
|
+
return { ok: false, error: `unsupported protocolVersion ${String(v.protocolVersion)}` };
|
|
13530
|
+
}
|
|
13531
|
+
if (typeof v.address !== "string" || !v.address) {
|
|
13532
|
+
return { ok: false, error: "address must be a non-empty string" };
|
|
13533
|
+
}
|
|
13534
|
+
if (typeof v.signature !== "string" || !v.signature) {
|
|
13535
|
+
return { ok: false, error: "signature must be a non-empty string" };
|
|
13536
|
+
}
|
|
13537
|
+
if (typeof v.signedMessage !== "string" || !v.signedMessage) {
|
|
13538
|
+
return { ok: false, error: "signedMessage must be a non-empty string" };
|
|
13539
|
+
}
|
|
13540
|
+
if (!Array.isArray(v.selectedActionKeys) || v.selectedActionKeys.some((k) => typeof k !== "string")) {
|
|
13541
|
+
return { ok: false, error: "selectedActionKeys must be a string[]" };
|
|
13542
|
+
}
|
|
13543
|
+
if (!Array.isArray(v.permissions)) {
|
|
13544
|
+
return { ok: false, error: "permissions must be an array" };
|
|
13545
|
+
}
|
|
13546
|
+
const permissions = [];
|
|
13547
|
+
for (const [index, entry] of v.permissions.entries()) {
|
|
13548
|
+
if (!entry || typeof entry !== "object") {
|
|
13549
|
+
return { ok: false, error: `permissions[${index}] must be an object` };
|
|
13550
|
+
}
|
|
13551
|
+
const e = entry;
|
|
13552
|
+
if (typeof e.service !== "string" || typeof e.space !== "string" || typeof e.path !== "string") {
|
|
13553
|
+
return { ok: false, error: `permissions[${index}] must have string service/space/path` };
|
|
13554
|
+
}
|
|
13555
|
+
if (!Array.isArray(e.actions) || e.actions.some((a) => typeof a !== "string")) {
|
|
13556
|
+
return { ok: false, error: `permissions[${index}].actions must be a string[]` };
|
|
13557
|
+
}
|
|
13558
|
+
permissions.push({
|
|
13559
|
+
service: e.service,
|
|
13560
|
+
space: e.space,
|
|
13561
|
+
path: e.path,
|
|
13562
|
+
actions: e.actions
|
|
13563
|
+
});
|
|
13564
|
+
}
|
|
13565
|
+
return {
|
|
13566
|
+
ok: true,
|
|
13567
|
+
value: {
|
|
13568
|
+
protocolVersion: 1,
|
|
13569
|
+
address: v.address,
|
|
13570
|
+
signature: v.signature,
|
|
13571
|
+
signedMessage: v.signedMessage,
|
|
13572
|
+
selectedActionKeys: v.selectedActionKeys,
|
|
13573
|
+
permissions
|
|
13574
|
+
}
|
|
13575
|
+
};
|
|
13576
|
+
}
|
|
13577
|
+
var OPENKEY_ACTION_ID_SEPARATOR = "\0";
|
|
13578
|
+
function isPlausibleOpenKeyActionId(id) {
|
|
13579
|
+
return typeof id === "string" && id.split(OPENKEY_ACTION_ID_SEPARATOR).length === 4 && id.length > 0;
|
|
13580
|
+
}
|
|
13581
|
+
function parseCanonicalRecapResource(resource) {
|
|
13582
|
+
if (!resource.startsWith("tinycloud:")) {
|
|
13583
|
+
return { space: resource, path: "" };
|
|
13584
|
+
}
|
|
13585
|
+
const firstSlash = resource.indexOf("/");
|
|
13586
|
+
if (firstSlash < 0) {
|
|
13587
|
+
return { space: resource, path: "" };
|
|
13588
|
+
}
|
|
13589
|
+
const space = resource.slice(0, firstSlash);
|
|
13590
|
+
const rest = resource.slice(firstSlash + 1);
|
|
13591
|
+
const secondSlash = rest.indexOf("/");
|
|
13592
|
+
if (secondSlash < 0) {
|
|
13593
|
+
return { space, path: "" };
|
|
13594
|
+
}
|
|
13595
|
+
return { space, path: rest.slice(secondSlash + 1) };
|
|
13596
|
+
}
|
|
13597
|
+
function extractImmutableSiweFields(siwe) {
|
|
13598
|
+
const lines = siwe.split(/\r?\n/);
|
|
13599
|
+
const result = {};
|
|
13600
|
+
const headerLine = lines[0];
|
|
13601
|
+
if (headerLine) {
|
|
13602
|
+
const domainMatch = headerLine.match(/^(.+?)\s+wants you to sign in/);
|
|
13603
|
+
if (domainMatch) {
|
|
13604
|
+
result.domain = domainMatch[1];
|
|
13605
|
+
}
|
|
13606
|
+
}
|
|
13607
|
+
for (let i = 1; i < lines.length && i < 5; i++) {
|
|
13608
|
+
const line = lines[i]?.trim() ?? "";
|
|
13609
|
+
if (/^0x[0-9a-fA-F]{40}$/.test(line)) {
|
|
13610
|
+
result.address = line;
|
|
13611
|
+
break;
|
|
13612
|
+
}
|
|
13613
|
+
}
|
|
13614
|
+
for (const line of lines) {
|
|
13615
|
+
const match = line.match(/^([A-Z][A-Za-z ]*):\s*(.*)$/);
|
|
13616
|
+
if (!match) continue;
|
|
13617
|
+
const [, key, value] = match;
|
|
13618
|
+
switch (key) {
|
|
13619
|
+
case "URI":
|
|
13620
|
+
result.uri = value;
|
|
13621
|
+
break;
|
|
13622
|
+
case "Version":
|
|
13623
|
+
result.version = value;
|
|
13624
|
+
break;
|
|
13625
|
+
case "Chain ID":
|
|
13626
|
+
result.chainId = value;
|
|
13627
|
+
break;
|
|
13628
|
+
case "Nonce":
|
|
13629
|
+
result.nonce = value;
|
|
13630
|
+
break;
|
|
13631
|
+
case "Issued At":
|
|
13632
|
+
result.issuedAt = value;
|
|
13633
|
+
break;
|
|
13634
|
+
// Sol MAJOR-4: complete immutable-field coverage.
|
|
13635
|
+
case "Expiration Time":
|
|
13636
|
+
result.expirationTime = value;
|
|
13637
|
+
break;
|
|
13638
|
+
case "Not Before":
|
|
13639
|
+
result.notBefore = value;
|
|
13640
|
+
break;
|
|
13641
|
+
case "Request ID":
|
|
13642
|
+
result.requestId = value;
|
|
13643
|
+
break;
|
|
13644
|
+
default:
|
|
13645
|
+
break;
|
|
13646
|
+
}
|
|
13647
|
+
}
|
|
13648
|
+
const uriLineIdx = lines.findIndex((l) => /^URI:/.test(l));
|
|
13649
|
+
if (uriLineIdx > 3) {
|
|
13650
|
+
let end = uriLineIdx - 1;
|
|
13651
|
+
while (end > 3 && lines[end] === "") end -= 1;
|
|
13652
|
+
if (end >= 3) {
|
|
13653
|
+
result.statement = lines.slice(3, end + 1).join("\n");
|
|
13654
|
+
} else {
|
|
13655
|
+
result.statement = "";
|
|
13656
|
+
}
|
|
13657
|
+
} else {
|
|
13658
|
+
result.statement = "";
|
|
13659
|
+
}
|
|
13660
|
+
result.nonRecapResources = lines.filter((l) => /^- /.test(l) && !/^- urn:recap:/.test(l)).join("\n");
|
|
13661
|
+
return result;
|
|
13662
|
+
}
|
|
13663
|
+
function diffImmutableSiweFields(original, signed, options2) {
|
|
13664
|
+
const baseKeys = [
|
|
13665
|
+
"domain",
|
|
13666
|
+
"address",
|
|
13667
|
+
"uri",
|
|
13668
|
+
"version",
|
|
13669
|
+
"chainId",
|
|
13670
|
+
"nonce",
|
|
13671
|
+
"issuedAt",
|
|
13672
|
+
"expirationTime",
|
|
13673
|
+
"notBefore",
|
|
13674
|
+
"requestId",
|
|
13675
|
+
"nonRecapResources"
|
|
13676
|
+
];
|
|
13677
|
+
const keys = options2?.originalHasRecap ? baseKeys : [...baseKeys, "statement"];
|
|
13678
|
+
const diffs = [];
|
|
13679
|
+
for (const key of keys) {
|
|
13680
|
+
const a = original[key] ?? "";
|
|
13681
|
+
const b = signed[key] ?? "";
|
|
13682
|
+
if (a !== b) {
|
|
13683
|
+
diffs.push(key);
|
|
13684
|
+
}
|
|
13685
|
+
}
|
|
13686
|
+
return diffs;
|
|
13687
|
+
}
|
|
13688
|
+
function extractRecapAttenuations(siwe) {
|
|
13689
|
+
const merged = {};
|
|
13690
|
+
const lines = siwe.split(/\r?\n/);
|
|
13691
|
+
for (const line of lines) {
|
|
13692
|
+
const match = line.match(/urn:recap:([A-Za-z0-9_-]+=*)/);
|
|
13693
|
+
if (!match) continue;
|
|
13694
|
+
const encoded = match[1];
|
|
13695
|
+
let decodedJson;
|
|
13696
|
+
try {
|
|
13697
|
+
const normalized = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
13698
|
+
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
|
|
13699
|
+
decodedJson = Buffer.from(padded, "base64").toString("utf8");
|
|
13700
|
+
} catch (err6) {
|
|
13701
|
+
throw new Error(
|
|
13702
|
+
`Failed to decode urn:recap: payload: ${err6.message}`
|
|
13703
|
+
);
|
|
13704
|
+
}
|
|
13705
|
+
let parsed;
|
|
13706
|
+
try {
|
|
13707
|
+
parsed = JSON.parse(decodedJson);
|
|
13708
|
+
} catch (err6) {
|
|
13709
|
+
throw new Error(
|
|
13710
|
+
`urn:recap: payload is not valid JSON: ${err6.message}`
|
|
13711
|
+
);
|
|
13712
|
+
}
|
|
13713
|
+
if (!parsed || typeof parsed !== "object") {
|
|
13714
|
+
throw new Error("urn:recap: payload must be an object");
|
|
13715
|
+
}
|
|
13716
|
+
const att = parsed.att;
|
|
13717
|
+
if (att === void 0) {
|
|
13718
|
+
continue;
|
|
13719
|
+
}
|
|
13720
|
+
if (typeof att !== "object" || att === null || Array.isArray(att)) {
|
|
13721
|
+
throw new Error("urn:recap: att must be an object");
|
|
13722
|
+
}
|
|
13723
|
+
for (const [resource, actionMap] of Object.entries(att)) {
|
|
13724
|
+
if (!actionMap || typeof actionMap !== "object" || Array.isArray(actionMap)) {
|
|
13725
|
+
throw new Error(`urn:recap: att[${resource}] must be an object`);
|
|
13726
|
+
}
|
|
13727
|
+
const existing = merged[resource] ?? {};
|
|
13728
|
+
for (const [action, caveats] of Object.entries(actionMap)) {
|
|
13729
|
+
if (!Array.isArray(caveats)) {
|
|
13730
|
+
throw new Error(
|
|
13731
|
+
`urn:recap: att[${resource}][${action}] must be an array`
|
|
13732
|
+
);
|
|
13733
|
+
}
|
|
13734
|
+
const previous = existing[action] ?? [];
|
|
13735
|
+
existing[action] = previous.concat(caveats);
|
|
13736
|
+
}
|
|
13737
|
+
merged[resource] = existing;
|
|
13738
|
+
}
|
|
13739
|
+
}
|
|
13740
|
+
return merged;
|
|
13741
|
+
}
|
|
13742
|
+
function stableStringify(value) {
|
|
13743
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
13744
|
+
if (Array.isArray(value)) {
|
|
13745
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
13746
|
+
}
|
|
13747
|
+
const entries = Object.entries(value).sort(
|
|
13748
|
+
([a], [b]) => a.localeCompare(b)
|
|
13749
|
+
);
|
|
13750
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
13751
|
+
}
|
|
13752
|
+
function caveatsDeepEqual(a, b) {
|
|
13753
|
+
return stableStringify(a) === stableStringify(b);
|
|
13754
|
+
}
|
|
13755
|
+
function unauthorizedRecapCapabilities(child, parent) {
|
|
13756
|
+
const unauthorized = [];
|
|
13757
|
+
for (const [resource, actions] of Object.entries(child)) {
|
|
13758
|
+
const parentActions = parent[resource];
|
|
13759
|
+
for (const [action, childCaveatsRaw] of Object.entries(actions)) {
|
|
13760
|
+
if (!parentActions || parentActions[action] === void 0) {
|
|
13761
|
+
unauthorized.push({ resource, action });
|
|
13762
|
+
continue;
|
|
13763
|
+
}
|
|
13764
|
+
const parentCaveatsRaw = parentActions[action];
|
|
13765
|
+
const parentCaveats = Array.isArray(parentCaveatsRaw) ? parentCaveatsRaw : [];
|
|
13766
|
+
const childCaveats = Array.isArray(childCaveatsRaw) ? childCaveatsRaw : [];
|
|
13767
|
+
const parentCanonCounts = /* @__PURE__ */ new Map();
|
|
13768
|
+
for (const c of parentCaveats) {
|
|
13769
|
+
const k = stableStringify(c);
|
|
13770
|
+
parentCanonCounts.set(k, (parentCanonCounts.get(k) ?? 0) + 1);
|
|
13771
|
+
}
|
|
13772
|
+
const childCanonCounts = /* @__PURE__ */ new Map();
|
|
13773
|
+
for (const c of childCaveats) {
|
|
13774
|
+
const k = stableStringify(c);
|
|
13775
|
+
childCanonCounts.set(k, (childCanonCounts.get(k) ?? 0) + 1);
|
|
13776
|
+
}
|
|
13777
|
+
let equal = parentCanonCounts.size === childCanonCounts.size;
|
|
13778
|
+
if (equal) {
|
|
13779
|
+
for (const [k, n] of parentCanonCounts) {
|
|
13780
|
+
if (childCanonCounts.get(k) !== n) {
|
|
13781
|
+
equal = false;
|
|
13782
|
+
break;
|
|
13783
|
+
}
|
|
13784
|
+
}
|
|
13785
|
+
}
|
|
13786
|
+
if (!equal) {
|
|
13787
|
+
unauthorized.push({ resource, action });
|
|
13788
|
+
}
|
|
13789
|
+
void caveatsDeepEqual;
|
|
13790
|
+
}
|
|
13791
|
+
}
|
|
13792
|
+
return unauthorized;
|
|
13793
|
+
}
|
|
13794
|
+
|
|
13286
13795
|
// src/version.ts
|
|
13287
13796
|
var ProtocolMismatchError = class extends Error {
|
|
13288
13797
|
constructor(sdkProtocol, nodeProtocol, nodeVersion, host) {
|
|
@@ -13394,17 +13903,9 @@ function equals3(a, b) {
|
|
|
13394
13903
|
return true;
|
|
13395
13904
|
}
|
|
13396
13905
|
|
|
13397
|
-
// ../../node_modules/uint8arrays/dist/src/alloc.
|
|
13398
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
13399
|
-
|
|
13400
|
-
// ../../node_modules/uint8arrays/dist/src/util/as-uint8array.node.js
|
|
13401
|
-
function asUint8Array(buf) {
|
|
13402
|
-
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
13403
|
-
}
|
|
13404
|
-
|
|
13405
|
-
// ../../node_modules/uint8arrays/dist/src/alloc.node.js
|
|
13906
|
+
// ../../node_modules/uint8arrays/dist/src/alloc.js
|
|
13406
13907
|
function allocUnsafe(size = 0) {
|
|
13407
|
-
return
|
|
13908
|
+
return new Uint8Array(size);
|
|
13408
13909
|
}
|
|
13409
13910
|
|
|
13410
13911
|
// ../../node_modules/uint8-varint/dist/src/index.js
|
|
@@ -13580,14 +14081,24 @@ function decode6(buf, offset = 0) {
|
|
|
13580
14081
|
}
|
|
13581
14082
|
}
|
|
13582
14083
|
|
|
13583
|
-
// ../../node_modules/uint8arrays/dist/src/
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
return asUint8Array(Buffer3.concat(arrays, length2));
|
|
14084
|
+
// ../../node_modules/uint8arrays/dist/src/util/as-uint8array.js
|
|
14085
|
+
function asUint8Array(buf) {
|
|
14086
|
+
return buf;
|
|
13587
14087
|
}
|
|
13588
14088
|
|
|
13589
|
-
// ../../node_modules/uint8arrays/dist/src/
|
|
13590
|
-
|
|
14089
|
+
// ../../node_modules/uint8arrays/dist/src/concat.js
|
|
14090
|
+
function concat(arrays, length2) {
|
|
14091
|
+
if (length2 == null) {
|
|
14092
|
+
length2 = arrays.reduce((acc, curr) => acc + curr.length, 0);
|
|
14093
|
+
}
|
|
14094
|
+
const output = allocUnsafe(length2);
|
|
14095
|
+
let offset = 0;
|
|
14096
|
+
for (const arr of arrays) {
|
|
14097
|
+
output.set(arr, offset);
|
|
14098
|
+
offset += arr.length;
|
|
14099
|
+
}
|
|
14100
|
+
return asUint8Array(output);
|
|
14101
|
+
}
|
|
13591
14102
|
|
|
13592
14103
|
// ../../node_modules/uint8arrays/dist/src/util/bases.js
|
|
13593
14104
|
function createCodec(name2, prefix, encode5, decode7) {
|
|
@@ -13636,28 +14147,21 @@ var BASES = {
|
|
|
13636
14147
|
};
|
|
13637
14148
|
var bases_default = BASES;
|
|
13638
14149
|
|
|
13639
|
-
// ../../node_modules/uint8arrays/dist/src/from-string.
|
|
14150
|
+
// ../../node_modules/uint8arrays/dist/src/from-string.js
|
|
13640
14151
|
function fromString2(string2, encoding = "utf8") {
|
|
13641
14152
|
const base3 = bases_default[encoding];
|
|
13642
14153
|
if (base3 == null) {
|
|
13643
14154
|
throw new Error(`Unsupported encoding "${encoding}"`);
|
|
13644
14155
|
}
|
|
13645
|
-
if (encoding === "utf8" || encoding === "utf-8") {
|
|
13646
|
-
return asUint8Array(Buffer4.from(string2, "utf-8"));
|
|
13647
|
-
}
|
|
13648
14156
|
return base3.decoder.decode(`${base3.prefix}${string2}`);
|
|
13649
14157
|
}
|
|
13650
14158
|
|
|
13651
|
-
// ../../node_modules/uint8arrays/dist/src/to-string.
|
|
13652
|
-
import { Buffer as Buffer5 } from "buffer";
|
|
14159
|
+
// ../../node_modules/uint8arrays/dist/src/to-string.js
|
|
13653
14160
|
function toString2(array, encoding = "utf8") {
|
|
13654
14161
|
const base3 = bases_default[encoding];
|
|
13655
14162
|
if (base3 == null) {
|
|
13656
14163
|
throw new Error(`Unsupported encoding "${encoding}"`);
|
|
13657
14164
|
}
|
|
13658
|
-
if (encoding === "utf8" || encoding === "utf-8") {
|
|
13659
|
-
return Buffer5.from(array.buffer, array.byteOffset, array.byteLength).toString("utf8");
|
|
13660
|
-
}
|
|
13661
14165
|
return base3.encoder.encode(array).substring(1);
|
|
13662
14166
|
}
|
|
13663
14167
|
|
|
@@ -13691,8 +14195,218 @@ var UnknownProtocolError = class extends Error {
|
|
|
13691
14195
|
};
|
|
13692
14196
|
__publicField(UnknownProtocolError, "name", "UnknownProtocolError");
|
|
13693
14197
|
|
|
13694
|
-
// ../../node_modules/@chainsafe/is-ip/lib/
|
|
13695
|
-
|
|
14198
|
+
// ../../node_modules/@chainsafe/is-ip/lib/parser.js
|
|
14199
|
+
var Parser = class {
|
|
14200
|
+
constructor() {
|
|
14201
|
+
__publicField(this, "index", 0);
|
|
14202
|
+
__publicField(this, "input", "");
|
|
14203
|
+
}
|
|
14204
|
+
new(input) {
|
|
14205
|
+
this.index = 0;
|
|
14206
|
+
this.input = input;
|
|
14207
|
+
return this;
|
|
14208
|
+
}
|
|
14209
|
+
/** Run a parser, and restore the pre-parse state if it fails. */
|
|
14210
|
+
readAtomically(fn) {
|
|
14211
|
+
const index = this.index;
|
|
14212
|
+
const result = fn();
|
|
14213
|
+
if (result === void 0) {
|
|
14214
|
+
this.index = index;
|
|
14215
|
+
}
|
|
14216
|
+
return result;
|
|
14217
|
+
}
|
|
14218
|
+
/** Run a parser, but fail if the entire input wasn't consumed. Doesn't run atomically. */
|
|
14219
|
+
parseWith(fn) {
|
|
14220
|
+
const result = fn();
|
|
14221
|
+
if (this.index !== this.input.length) {
|
|
14222
|
+
return void 0;
|
|
14223
|
+
}
|
|
14224
|
+
return result;
|
|
14225
|
+
}
|
|
14226
|
+
/** Peek the next character from the input */
|
|
14227
|
+
peekChar() {
|
|
14228
|
+
if (this.index >= this.input.length) {
|
|
14229
|
+
return void 0;
|
|
14230
|
+
}
|
|
14231
|
+
return this.input[this.index];
|
|
14232
|
+
}
|
|
14233
|
+
/** Read the next character from the input */
|
|
14234
|
+
readChar() {
|
|
14235
|
+
if (this.index >= this.input.length) {
|
|
14236
|
+
return void 0;
|
|
14237
|
+
}
|
|
14238
|
+
return this.input[this.index++];
|
|
14239
|
+
}
|
|
14240
|
+
/** Read the next character from the input if it matches the target. */
|
|
14241
|
+
readGivenChar(target) {
|
|
14242
|
+
return this.readAtomically(() => {
|
|
14243
|
+
const char = this.readChar();
|
|
14244
|
+
if (char !== target) {
|
|
14245
|
+
return void 0;
|
|
14246
|
+
}
|
|
14247
|
+
return char;
|
|
14248
|
+
});
|
|
14249
|
+
}
|
|
14250
|
+
/**
|
|
14251
|
+
* Helper for reading separators in an indexed loop. Reads the separator
|
|
14252
|
+
* character iff index > 0, then runs the parser. When used in a loop,
|
|
14253
|
+
* the separator character will only be read on index > 0 (see
|
|
14254
|
+
* readIPv4Addr for an example)
|
|
14255
|
+
*/
|
|
14256
|
+
readSeparator(sep, index, inner) {
|
|
14257
|
+
return this.readAtomically(() => {
|
|
14258
|
+
if (index > 0) {
|
|
14259
|
+
if (this.readGivenChar(sep) === void 0) {
|
|
14260
|
+
return void 0;
|
|
14261
|
+
}
|
|
14262
|
+
}
|
|
14263
|
+
return inner();
|
|
14264
|
+
});
|
|
14265
|
+
}
|
|
14266
|
+
/**
|
|
14267
|
+
* Read a number off the front of the input in the given radix, stopping
|
|
14268
|
+
* at the first non-digit character or eof. Fails if the number has more
|
|
14269
|
+
* digits than max_digits or if there is no number.
|
|
14270
|
+
*/
|
|
14271
|
+
readNumber(radix, maxDigits, allowZeroPrefix, maxBytes) {
|
|
14272
|
+
return this.readAtomically(() => {
|
|
14273
|
+
let result = 0;
|
|
14274
|
+
let digitCount = 0;
|
|
14275
|
+
const leadingChar = this.peekChar();
|
|
14276
|
+
if (leadingChar === void 0) {
|
|
14277
|
+
return void 0;
|
|
14278
|
+
}
|
|
14279
|
+
const hasLeadingZero = leadingChar === "0";
|
|
14280
|
+
const maxValue2 = 2 ** (8 * maxBytes) - 1;
|
|
14281
|
+
while (true) {
|
|
14282
|
+
const digit = this.readAtomically(() => {
|
|
14283
|
+
const char = this.readChar();
|
|
14284
|
+
if (char === void 0) {
|
|
14285
|
+
return void 0;
|
|
14286
|
+
}
|
|
14287
|
+
const num = Number.parseInt(char, radix);
|
|
14288
|
+
if (Number.isNaN(num)) {
|
|
14289
|
+
return void 0;
|
|
14290
|
+
}
|
|
14291
|
+
return num;
|
|
14292
|
+
});
|
|
14293
|
+
if (digit === void 0) {
|
|
14294
|
+
break;
|
|
14295
|
+
}
|
|
14296
|
+
result *= radix;
|
|
14297
|
+
result += digit;
|
|
14298
|
+
if (result > maxValue2) {
|
|
14299
|
+
return void 0;
|
|
14300
|
+
}
|
|
14301
|
+
digitCount += 1;
|
|
14302
|
+
if (maxDigits !== void 0) {
|
|
14303
|
+
if (digitCount > maxDigits) {
|
|
14304
|
+
return void 0;
|
|
14305
|
+
}
|
|
14306
|
+
}
|
|
14307
|
+
}
|
|
14308
|
+
if (digitCount === 0) {
|
|
14309
|
+
return void 0;
|
|
14310
|
+
} else if (!allowZeroPrefix && hasLeadingZero && digitCount > 1) {
|
|
14311
|
+
return void 0;
|
|
14312
|
+
} else {
|
|
14313
|
+
return result;
|
|
14314
|
+
}
|
|
14315
|
+
});
|
|
14316
|
+
}
|
|
14317
|
+
/** Read an IPv4 address. */
|
|
14318
|
+
readIPv4Addr() {
|
|
14319
|
+
return this.readAtomically(() => {
|
|
14320
|
+
const out = new Uint8Array(4);
|
|
14321
|
+
for (let i = 0; i < out.length; i++) {
|
|
14322
|
+
const ix = this.readSeparator(".", i, () => this.readNumber(10, 3, false, 1));
|
|
14323
|
+
if (ix === void 0) {
|
|
14324
|
+
return void 0;
|
|
14325
|
+
}
|
|
14326
|
+
out[i] = ix;
|
|
14327
|
+
}
|
|
14328
|
+
return out;
|
|
14329
|
+
});
|
|
14330
|
+
}
|
|
14331
|
+
/** Read an IPv6 Address. */
|
|
14332
|
+
readIPv6Addr() {
|
|
14333
|
+
const readGroups = (groups) => {
|
|
14334
|
+
for (let i = 0; i < groups.length / 2; i++) {
|
|
14335
|
+
const ix = i * 2;
|
|
14336
|
+
if (i < groups.length - 3) {
|
|
14337
|
+
const ipv4 = this.readSeparator(":", i, () => this.readIPv4Addr());
|
|
14338
|
+
if (ipv4 !== void 0) {
|
|
14339
|
+
groups[ix] = ipv4[0];
|
|
14340
|
+
groups[ix + 1] = ipv4[1];
|
|
14341
|
+
groups[ix + 2] = ipv4[2];
|
|
14342
|
+
groups[ix + 3] = ipv4[3];
|
|
14343
|
+
return [ix + 4, true];
|
|
14344
|
+
}
|
|
14345
|
+
}
|
|
14346
|
+
const group = this.readSeparator(":", i, () => this.readNumber(16, 4, true, 2));
|
|
14347
|
+
if (group === void 0) {
|
|
14348
|
+
return [ix, false];
|
|
14349
|
+
}
|
|
14350
|
+
groups[ix] = group >> 8;
|
|
14351
|
+
groups[ix + 1] = group & 255;
|
|
14352
|
+
}
|
|
14353
|
+
return [groups.length, false];
|
|
14354
|
+
};
|
|
14355
|
+
return this.readAtomically(() => {
|
|
14356
|
+
const head = new Uint8Array(16);
|
|
14357
|
+
const [headSize, headIp4] = readGroups(head);
|
|
14358
|
+
if (headSize === 16) {
|
|
14359
|
+
return head;
|
|
14360
|
+
}
|
|
14361
|
+
if (headIp4) {
|
|
14362
|
+
return void 0;
|
|
14363
|
+
}
|
|
14364
|
+
if (this.readGivenChar(":") === void 0) {
|
|
14365
|
+
return void 0;
|
|
14366
|
+
}
|
|
14367
|
+
if (this.readGivenChar(":") === void 0) {
|
|
14368
|
+
return void 0;
|
|
14369
|
+
}
|
|
14370
|
+
const tail = new Uint8Array(14);
|
|
14371
|
+
const limit = 16 - (headSize + 2);
|
|
14372
|
+
const [tailSize] = readGroups(tail.subarray(0, limit));
|
|
14373
|
+
head.set(tail.subarray(0, tailSize), 16 - tailSize);
|
|
14374
|
+
return head;
|
|
14375
|
+
});
|
|
14376
|
+
}
|
|
14377
|
+
/** Read an IP Address, either IPv4 or IPv6. */
|
|
14378
|
+
readIPAddr() {
|
|
14379
|
+
return this.readIPv4Addr() ?? this.readIPv6Addr();
|
|
14380
|
+
}
|
|
14381
|
+
};
|
|
14382
|
+
|
|
14383
|
+
// ../../node_modules/@chainsafe/is-ip/lib/parse.js
|
|
14384
|
+
var MAX_IPV6_LENGTH = 45;
|
|
14385
|
+
var MAX_IPV4_LENGTH = 15;
|
|
14386
|
+
var parser = new Parser();
|
|
14387
|
+
function parseIPv4(input) {
|
|
14388
|
+
if (input.length > MAX_IPV4_LENGTH) {
|
|
14389
|
+
return void 0;
|
|
14390
|
+
}
|
|
14391
|
+
return parser.new(input).parseWith(() => parser.readIPv4Addr());
|
|
14392
|
+
}
|
|
14393
|
+
function parseIPv6(input) {
|
|
14394
|
+
if (input.includes("%")) {
|
|
14395
|
+
input = input.split("%")[0];
|
|
14396
|
+
}
|
|
14397
|
+
if (input.length > MAX_IPV6_LENGTH) {
|
|
14398
|
+
return void 0;
|
|
14399
|
+
}
|
|
14400
|
+
return parser.new(input).parseWith(() => parser.readIPv6Addr());
|
|
14401
|
+
}
|
|
14402
|
+
|
|
14403
|
+
// ../../node_modules/@chainsafe/is-ip/lib/is-ip.js
|
|
14404
|
+
function isIPv4(input) {
|
|
14405
|
+
return Boolean(parseIPv4(input));
|
|
14406
|
+
}
|
|
14407
|
+
function isIPv6(input) {
|
|
14408
|
+
return Boolean(parseIPv6(input));
|
|
14409
|
+
}
|
|
13696
14410
|
|
|
13697
14411
|
// ../../node_modules/@multiformats/multiaddr/dist/src/constants.js
|
|
13698
14412
|
var CODE_IP4 = 4;
|
|
@@ -14649,25 +15363,17 @@ ipRegex.v4 = (options2) => options2 && options2.exact ? v4exact : new RegExp(`${
|
|
|
14649
15363
|
ipRegex.v6 = (options2) => options2 && options2.exact ? v6exact : new RegExp(`${boundry(options2)}${v6}${boundry(options2)}`, "g");
|
|
14650
15364
|
var ip_regex_default = ipRegex;
|
|
14651
15365
|
|
|
14652
|
-
// ../../node_modules/function-timeout/
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
const script = new vm.Script("returnValue = function_()");
|
|
14656
|
-
const wrappedFunction = (...arguments_) => {
|
|
14657
|
-
const context = {
|
|
14658
|
-
function_: () => function_(...arguments_)
|
|
14659
|
-
};
|
|
14660
|
-
script.runInNewContext(context, { timeout });
|
|
14661
|
-
return context.returnValue;
|
|
14662
|
-
};
|
|
15366
|
+
// ../../node_modules/function-timeout/browser.js
|
|
15367
|
+
function functionTimeout(function_) {
|
|
15368
|
+
const wrappedFunction = (...arguments_) => function_(...arguments_);
|
|
14663
15369
|
Object.defineProperty(wrappedFunction, "name", {
|
|
14664
15370
|
value: `functionTimeout(${function_.name || "<anonymous>"})`,
|
|
14665
15371
|
configurable: true
|
|
14666
15372
|
});
|
|
14667
15373
|
return wrappedFunction;
|
|
14668
15374
|
}
|
|
14669
|
-
function isTimeoutError(
|
|
14670
|
-
return
|
|
15375
|
+
function isTimeoutError() {
|
|
15376
|
+
return false;
|
|
14671
15377
|
}
|
|
14672
15378
|
|
|
14673
15379
|
// ../../node_modules/clone-regexp/node_modules/is-regexp/index.js
|
|
@@ -15069,13 +15775,14 @@ async function discoverLocalTinyCloudNode(options2 = {}) {
|
|
|
15069
15775
|
}
|
|
15070
15776
|
const fetchFn = options2.fetch ?? globalThis.fetch;
|
|
15071
15777
|
const identityStore = options2.identityStore ?? defaultLocalNodeIdentityStore;
|
|
15072
|
-
const staticCandidates = [
|
|
15073
|
-
|
|
15778
|
+
const staticCandidates = [];
|
|
15779
|
+
if (options2.localNodeUrl) {
|
|
15780
|
+
staticCandidates.push({
|
|
15074
15781
|
source: "local-loopback",
|
|
15075
|
-
url: options2.localNodeUrl
|
|
15782
|
+
url: options2.localNodeUrl,
|
|
15076
15783
|
timeoutMs: LOCAL_LOOPBACK_PROBE_TIMEOUT_MS
|
|
15077
|
-
}
|
|
15078
|
-
|
|
15784
|
+
});
|
|
15785
|
+
}
|
|
15079
15786
|
if (options2.localLinkName) {
|
|
15080
15787
|
if (isValidDnsLabel(options2.localLinkName)) {
|
|
15081
15788
|
staticCandidates.push({
|
|
@@ -15528,7 +16235,7 @@ export {
|
|
|
15528
16235
|
EXPIRY,
|
|
15529
16236
|
EncryptionService,
|
|
15530
16237
|
EnsDataSchema,
|
|
15531
|
-
|
|
16238
|
+
ErrorCodes4 as ErrorCodes,
|
|
15532
16239
|
HOLDER_KEY_BINDING_PRESENTATION_SCHEMA,
|
|
15533
16240
|
HOOKS,
|
|
15534
16241
|
HooksService2 as HooksService,
|
|
@@ -15550,6 +16257,7 @@ export {
|
|
|
15550
16257
|
MemoryShareCache,
|
|
15551
16258
|
NETWORK_NAME_PATTERN,
|
|
15552
16259
|
NetworkIdError,
|
|
16260
|
+
OPENKEY_ACTION_ID_SEPARATOR,
|
|
15553
16261
|
POLICY_ENGINE_CHALLENGE_REQUEST_SCHEMA,
|
|
15554
16262
|
POLICY_ENGINE_CHALLENGE_RESPONSE_SCHEMA,
|
|
15555
16263
|
POLICY_ENGINE_DENIAL_SCHEMA,
|
|
@@ -15676,6 +16384,7 @@ export {
|
|
|
15676
16384
|
deriveSignedReceiverKey,
|
|
15677
16385
|
didCacheKey,
|
|
15678
16386
|
didEquals,
|
|
16387
|
+
diffImmutableSiweFields,
|
|
15679
16388
|
disableTinyCloudDebug,
|
|
15680
16389
|
discoverLocalTinyCloudNode,
|
|
15681
16390
|
discoverNetwork,
|
|
@@ -15696,6 +16405,8 @@ export {
|
|
|
15696
16405
|
expandActionShortNames,
|
|
15697
16406
|
expandPermissionEntries,
|
|
15698
16407
|
expandPermissionEntry,
|
|
16408
|
+
extractImmutableSiweFields,
|
|
16409
|
+
extractRecapAttenuations,
|
|
15699
16410
|
fetchLocationRecord,
|
|
15700
16411
|
fetchPeerId,
|
|
15701
16412
|
generateRandomReceiverKey,
|
|
@@ -15708,6 +16419,7 @@ export {
|
|
|
15708
16419
|
isCapabilitySubset,
|
|
15709
16420
|
isEvmAddress,
|
|
15710
16421
|
isNetworkId,
|
|
16422
|
+
isPlausibleOpenKeyActionId,
|
|
15711
16423
|
isV2ShareLink,
|
|
15712
16424
|
jcsCanonicalize,
|
|
15713
16425
|
loadManifest,
|
|
@@ -15725,6 +16437,7 @@ export {
|
|
|
15725
16437
|
ok5 as ok,
|
|
15726
16438
|
openWrappedKey,
|
|
15727
16439
|
parseCanonicalNetworkId,
|
|
16440
|
+
parseCanonicalRecapResource,
|
|
15728
16441
|
parseExpiry,
|
|
15729
16442
|
parseNetworkId2 as parseNetworkId,
|
|
15730
16443
|
parseNodeNativePortableDelegation,
|
|
@@ -15756,6 +16469,8 @@ export {
|
|
|
15756
16469
|
submitHostDelegation,
|
|
15757
16470
|
tinyCloudDebugLogger,
|
|
15758
16471
|
toSignedObjectError,
|
|
16472
|
+
unauthorizedRecapCapabilities,
|
|
16473
|
+
validateAuthorizationResultV1,
|
|
15759
16474
|
validateClientSession,
|
|
15760
16475
|
validateEnvelope,
|
|
15761
16476
|
validateLocationRecord,
|