@learncard/network-plugin 2.13.15 → 2.13.17
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/lcn-plugin.cjs.development.cjs +81 -18
- package/dist/lcn-plugin.cjs.development.cjs.map +3 -3
- package/dist/lcn-plugin.cjs.production.min.cjs +34 -34
- package/dist/lcn-plugin.cjs.production.min.cjs.map +3 -3
- package/dist/lcn-plugin.esm.js +81 -18
- package/dist/lcn-plugin.esm.js.map +3 -3
- package/dist/plugin.d.ts +26 -6
- package/dist/plugin.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/plugin.ts +177 -36
package/dist/lcn-plugin.esm.js
CHANGED
|
@@ -15639,7 +15639,8 @@ var LCNAuthedProfileValidator = LCNPublicProfileValidator.extend({
|
|
|
15639
15639
|
did: LCNProfileValidator.shape.did
|
|
15640
15640
|
});
|
|
15641
15641
|
var LCNConnectionProfileValidator = LCNAuthedProfileValidator.extend({
|
|
15642
|
-
email: LCNProfileValidator.shape.email
|
|
15642
|
+
email: LCNProfileValidator.shape.email,
|
|
15643
|
+
connectedAt: external_exports.iso.datetime().optional().describe("When the viewer and this profile became connected.")
|
|
15643
15644
|
});
|
|
15644
15645
|
var LCNVisibleProfileValidator = external_exports.union([
|
|
15645
15646
|
LCNConnectionProfileValidator.strict(),
|
|
@@ -17527,6 +17528,56 @@ mustache.Writer = Writer;
|
|
|
17527
17528
|
var mustache_default = mustache;
|
|
17528
17529
|
|
|
17529
17530
|
// src/plugin.ts
|
|
17531
|
+
var LEARNCARD_DOMAIN_SUFFIXES = [".learncard.com", ".learncard.app", ".learncard.ai"];
|
|
17532
|
+
var isLearnCardDomain = /* @__PURE__ */ __name((host) => {
|
|
17533
|
+
return LEARNCARD_DOMAIN_SUFFIXES.some(
|
|
17534
|
+
(suffix) => host === suffix.replace(/^\./, "") || host.endsWith(suffix)
|
|
17535
|
+
);
|
|
17536
|
+
}, "isLearnCardDomain");
|
|
17537
|
+
var isLocalhostHost = /* @__PURE__ */ __name((host) => {
|
|
17538
|
+
const lower = host.toLowerCase();
|
|
17539
|
+
return lower === "localhost" || lower === "127.0.0.1";
|
|
17540
|
+
}, "isLocalhostHost");
|
|
17541
|
+
var validateFederationUrl = /* @__PURE__ */ __name((userProvidedUrl, config2) => {
|
|
17542
|
+
let parsed;
|
|
17543
|
+
try {
|
|
17544
|
+
parsed = new URL(userProvidedUrl);
|
|
17545
|
+
} catch {
|
|
17546
|
+
throw new Error(`Invalid federation endpoint URL: ${userProvidedUrl}`);
|
|
17547
|
+
}
|
|
17548
|
+
if (config2.serviceOrigin) {
|
|
17549
|
+
const endpointOrigin = parsed.origin;
|
|
17550
|
+
if (endpointOrigin === config2.serviceOrigin) {
|
|
17551
|
+
return parsed.href;
|
|
17552
|
+
}
|
|
17553
|
+
}
|
|
17554
|
+
const host = parsed.hostname.toLowerCase();
|
|
17555
|
+
const isLocalhost = isLocalhostHost(host);
|
|
17556
|
+
if (isLocalhost) {
|
|
17557
|
+
if (!config2.allowLocalhostFederation) {
|
|
17558
|
+
throw new Error(
|
|
17559
|
+
`Localhost federation is disabled. Set allowLocalhostFederation: true for development.`
|
|
17560
|
+
);
|
|
17561
|
+
}
|
|
17562
|
+
if (parsed.protocol === "https:") {
|
|
17563
|
+
parsed.protocol = "http:";
|
|
17564
|
+
}
|
|
17565
|
+
return parsed.href;
|
|
17566
|
+
}
|
|
17567
|
+
if (parsed.protocol !== "https:") {
|
|
17568
|
+
throw new Error(`Federation requires HTTPS for non-localhost hosts: ${userProvidedUrl}`);
|
|
17569
|
+
}
|
|
17570
|
+
if (config2.trustedFederationHosts !== void 0) {
|
|
17571
|
+
const trustedHosts = new Set(config2.trustedFederationHosts);
|
|
17572
|
+
const allowAnyHost = trustedHosts.has("*");
|
|
17573
|
+
if (!allowAnyHost && !isLearnCardDomain(host) && !trustedHosts.has(host)) {
|
|
17574
|
+
throw new Error(
|
|
17575
|
+
`Federation host '${host}' is not trusted. Add it to trustedFederationHosts or use '*' to allow any host.`
|
|
17576
|
+
);
|
|
17577
|
+
}
|
|
17578
|
+
}
|
|
17579
|
+
return parsed.href;
|
|
17580
|
+
}, "validateFederationUrl");
|
|
17530
17581
|
var uint8ArrayToBase64Url = /* @__PURE__ */ __name((bytes) => {
|
|
17531
17582
|
let binary = "";
|
|
17532
17583
|
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
@@ -17620,8 +17671,20 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
|
|
|
17620
17671
|
}, "issueCredentialWithNetworkStatus");
|
|
17621
17672
|
async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
|
|
17622
17673
|
const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
|
|
17623
|
-
const
|
|
17624
|
-
const
|
|
17674
|
+
const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
|
|
17675
|
+
const {
|
|
17676
|
+
guardianApprovalGetter,
|
|
17677
|
+
extraHeaders,
|
|
17678
|
+
trustedFederationHosts,
|
|
17679
|
+
allowLocalhostFederation
|
|
17680
|
+
} = resolvedOptions;
|
|
17681
|
+
const serviceUrl = new URL(url2);
|
|
17682
|
+
const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
|
|
17683
|
+
const federationConfig = {
|
|
17684
|
+
trustedFederationHosts,
|
|
17685
|
+
allowLocalhostFederation: allowLocalhostFederation ?? serviceIsLocalhost,
|
|
17686
|
+
serviceOrigin: serviceUrl.origin
|
|
17687
|
+
};
|
|
17625
17688
|
let did = "";
|
|
17626
17689
|
try {
|
|
17627
17690
|
const idPlane = learnCard?.id;
|
|
@@ -17690,8 +17753,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17690
17753
|
}
|
|
17691
17754
|
}, "getBoostTemplateForIssuance");
|
|
17692
17755
|
const getInboxEndpointForDid = /* @__PURE__ */ __name(async (_learnCard, recipientDid) => {
|
|
17693
|
-
const
|
|
17694
|
-
const serviceDomain = `${
|
|
17756
|
+
const serviceUrl2 = new URL(url2);
|
|
17757
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
17695
17758
|
const localServiceDid = `did:web:${serviceDomain}`;
|
|
17696
17759
|
const getInferredServiceDid = /* @__PURE__ */ __name((did2) => {
|
|
17697
17760
|
if (!did2.startsWith("did:web:")) return null;
|
|
@@ -17712,12 +17775,12 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17712
17775
|
}), "getInboxService");
|
|
17713
17776
|
const inferredServiceDid = getInferredServiceDid(recipientDid);
|
|
17714
17777
|
if (inferredServiceDid === localServiceDid) {
|
|
17715
|
-
return `${
|
|
17778
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17716
17779
|
}
|
|
17717
17780
|
const didDoc = await _learnCard.invoke.resolveDid(recipientDid);
|
|
17718
17781
|
const inboxService = getInboxService(didDoc);
|
|
17719
17782
|
if ((inboxService?.serviceDid || inferredServiceDid) === localServiceDid) {
|
|
17720
|
-
return `${
|
|
17783
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17721
17784
|
}
|
|
17722
17785
|
if (!inboxService?.serviceEndpoint) {
|
|
17723
17786
|
throw new Error(
|
|
@@ -17879,7 +17942,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17879
17942
|
return client.profileManager.updateProfileManager.mutate(manager);
|
|
17880
17943
|
}, "updateProfileManagerProfile"),
|
|
17881
17944
|
deleteProfile: /* @__PURE__ */ __name(async () => {
|
|
17882
|
-
|
|
17945
|
+
await initialQuery;
|
|
17946
|
+
if (!apiToken) await ensureUser();
|
|
17883
17947
|
const result = await client.profile.deleteProfile.mutate();
|
|
17884
17948
|
if (result) {
|
|
17885
17949
|
userData = void 0;
|
|
@@ -18030,11 +18094,10 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18030
18094
|
proofFormat: "jwt",
|
|
18031
18095
|
challenge: `inbox-federation-${crypto.randomUUID()}`
|
|
18032
18096
|
});
|
|
18033
|
-
|
|
18034
|
-
if (receiveUrl.includes("localhost")) {
|
|
18035
|
-
receiveUrl = receiveUrl.replace("https://", "http://");
|
|
18036
|
-
}
|
|
18097
|
+
const receiveUrl = validateFederationUrl(inboxEndpoint, federationConfig);
|
|
18037
18098
|
const response = await fetch(receiveUrl, {
|
|
18099
|
+
// A redirect must not bypass endpoint validation or forward credentials.
|
|
18100
|
+
redirect: "error",
|
|
18038
18101
|
method: "POST",
|
|
18039
18102
|
headers: {
|
|
18040
18103
|
"Content-Type": "application/json",
|
|
@@ -18509,8 +18572,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18509
18572
|
const isDid = recipient.startsWith("did:");
|
|
18510
18573
|
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(recipient);
|
|
18511
18574
|
const isPhone = /^\+?[\d\s-]{10,}$/.test(recipient.replace(/[\s-]/g, ""));
|
|
18512
|
-
const
|
|
18513
|
-
const serviceDomain = `${
|
|
18575
|
+
const serviceUrl2 = new URL(url2);
|
|
18576
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
18514
18577
|
const recipientDomain = recipient.startsWith("did:web:") ? recipient.split(":")[2] : void 0;
|
|
18515
18578
|
const isRemoteDidWebRecipient = recipient.startsWith("did:web:") && recipientDomain !== serviceDomain;
|
|
18516
18579
|
if (isRemoteDidWebRecipient && input.templateUri) {
|
|
@@ -19310,7 +19373,9 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
19310
19373
|
}, "getActivityChain"),
|
|
19311
19374
|
isServiceTrusted: /* @__PURE__ */ __name(async (_learnCard, serviceDid) => {
|
|
19312
19375
|
const trustedServices = await client.federation.getTrustedServices.query({});
|
|
19313
|
-
return trustedServices.some(
|
|
19376
|
+
return trustedServices.some(
|
|
19377
|
+
(service) => service.did === serviceDid
|
|
19378
|
+
);
|
|
19314
19379
|
}, "isServiceTrusted"),
|
|
19315
19380
|
getTrustedServices: /* @__PURE__ */ __name(async () => {
|
|
19316
19381
|
return client.federation.getTrustedServices.query({});
|
|
@@ -19366,9 +19431,7 @@ var getVerifyBoostPlugin = /* @__PURE__ */ __name(async (learnCard, trustedBoost
|
|
|
19366
19431
|
const boostCredential = credential?.boostCredential;
|
|
19367
19432
|
try {
|
|
19368
19433
|
if (boostCredential) {
|
|
19369
|
-
const verifyBoostCredential = await learnCard.invoke.verifyCredential(
|
|
19370
|
-
boostCredential
|
|
19371
|
-
);
|
|
19434
|
+
const verifyBoostCredential = await learnCard.invoke.verifyCredential(boostCredential);
|
|
19372
19435
|
const boostCredentialErrors = verifyBoostCredential.errors ?? [];
|
|
19373
19436
|
if (verifyBoostCredential.status?.length) {
|
|
19374
19437
|
verificationCheck.status = [
|