@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
|
@@ -15660,7 +15660,8 @@ var LCNAuthedProfileValidator = LCNPublicProfileValidator.extend({
|
|
|
15660
15660
|
did: LCNProfileValidator.shape.did
|
|
15661
15661
|
});
|
|
15662
15662
|
var LCNConnectionProfileValidator = LCNAuthedProfileValidator.extend({
|
|
15663
|
-
email: LCNProfileValidator.shape.email
|
|
15663
|
+
email: LCNProfileValidator.shape.email,
|
|
15664
|
+
connectedAt: external_exports.iso.datetime().optional().describe("When the viewer and this profile became connected.")
|
|
15664
15665
|
});
|
|
15665
15666
|
var LCNVisibleProfileValidator = external_exports.union([
|
|
15666
15667
|
LCNConnectionProfileValidator.strict(),
|
|
@@ -17544,6 +17545,56 @@ mustache.Writer = Writer;
|
|
|
17544
17545
|
var mustache_default = mustache;
|
|
17545
17546
|
|
|
17546
17547
|
// src/plugin.ts
|
|
17548
|
+
var LEARNCARD_DOMAIN_SUFFIXES = [".learncard.com", ".learncard.app", ".learncard.ai"];
|
|
17549
|
+
var isLearnCardDomain = /* @__PURE__ */ __name((host) => {
|
|
17550
|
+
return LEARNCARD_DOMAIN_SUFFIXES.some(
|
|
17551
|
+
(suffix) => host === suffix.replace(/^\./, "") || host.endsWith(suffix)
|
|
17552
|
+
);
|
|
17553
|
+
}, "isLearnCardDomain");
|
|
17554
|
+
var isLocalhostHost = /* @__PURE__ */ __name((host) => {
|
|
17555
|
+
const lower = host.toLowerCase();
|
|
17556
|
+
return lower === "localhost" || lower === "127.0.0.1";
|
|
17557
|
+
}, "isLocalhostHost");
|
|
17558
|
+
var validateFederationUrl = /* @__PURE__ */ __name((userProvidedUrl, config2) => {
|
|
17559
|
+
let parsed;
|
|
17560
|
+
try {
|
|
17561
|
+
parsed = new URL(userProvidedUrl);
|
|
17562
|
+
} catch {
|
|
17563
|
+
throw new Error(`Invalid federation endpoint URL: ${userProvidedUrl}`);
|
|
17564
|
+
}
|
|
17565
|
+
if (config2.serviceOrigin) {
|
|
17566
|
+
const endpointOrigin = parsed.origin;
|
|
17567
|
+
if (endpointOrigin === config2.serviceOrigin) {
|
|
17568
|
+
return parsed.href;
|
|
17569
|
+
}
|
|
17570
|
+
}
|
|
17571
|
+
const host = parsed.hostname.toLowerCase();
|
|
17572
|
+
const isLocalhost = isLocalhostHost(host);
|
|
17573
|
+
if (isLocalhost) {
|
|
17574
|
+
if (!config2.allowLocalhostFederation) {
|
|
17575
|
+
throw new Error(
|
|
17576
|
+
`Localhost federation is disabled. Set allowLocalhostFederation: true for development.`
|
|
17577
|
+
);
|
|
17578
|
+
}
|
|
17579
|
+
if (parsed.protocol === "https:") {
|
|
17580
|
+
parsed.protocol = "http:";
|
|
17581
|
+
}
|
|
17582
|
+
return parsed.href;
|
|
17583
|
+
}
|
|
17584
|
+
if (parsed.protocol !== "https:") {
|
|
17585
|
+
throw new Error(`Federation requires HTTPS for non-localhost hosts: ${userProvidedUrl}`);
|
|
17586
|
+
}
|
|
17587
|
+
if (config2.trustedFederationHosts !== void 0) {
|
|
17588
|
+
const trustedHosts = new Set(config2.trustedFederationHosts);
|
|
17589
|
+
const allowAnyHost = trustedHosts.has("*");
|
|
17590
|
+
if (!allowAnyHost && !isLearnCardDomain(host) && !trustedHosts.has(host)) {
|
|
17591
|
+
throw new Error(
|
|
17592
|
+
`Federation host '${host}' is not trusted. Add it to trustedFederationHosts or use '*' to allow any host.`
|
|
17593
|
+
);
|
|
17594
|
+
}
|
|
17595
|
+
}
|
|
17596
|
+
return parsed.href;
|
|
17597
|
+
}, "validateFederationUrl");
|
|
17547
17598
|
var uint8ArrayToBase64Url = /* @__PURE__ */ __name((bytes) => {
|
|
17548
17599
|
let binary = "";
|
|
17549
17600
|
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
@@ -17637,8 +17688,20 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
|
|
|
17637
17688
|
}, "issueCredentialWithNetworkStatus");
|
|
17638
17689
|
async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
|
|
17639
17690
|
const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
|
|
17640
|
-
const
|
|
17641
|
-
const
|
|
17691
|
+
const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
|
|
17692
|
+
const {
|
|
17693
|
+
guardianApprovalGetter,
|
|
17694
|
+
extraHeaders,
|
|
17695
|
+
trustedFederationHosts,
|
|
17696
|
+
allowLocalhostFederation
|
|
17697
|
+
} = resolvedOptions;
|
|
17698
|
+
const serviceUrl = new URL(url2);
|
|
17699
|
+
const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
|
|
17700
|
+
const federationConfig = {
|
|
17701
|
+
trustedFederationHosts,
|
|
17702
|
+
allowLocalhostFederation: allowLocalhostFederation ?? serviceIsLocalhost,
|
|
17703
|
+
serviceOrigin: serviceUrl.origin
|
|
17704
|
+
};
|
|
17642
17705
|
let did = "";
|
|
17643
17706
|
try {
|
|
17644
17707
|
const idPlane = learnCard?.id;
|
|
@@ -17707,8 +17770,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17707
17770
|
}
|
|
17708
17771
|
}, "getBoostTemplateForIssuance");
|
|
17709
17772
|
const getInboxEndpointForDid = /* @__PURE__ */ __name(async (_learnCard, recipientDid) => {
|
|
17710
|
-
const
|
|
17711
|
-
const serviceDomain = `${
|
|
17773
|
+
const serviceUrl2 = new URL(url2);
|
|
17774
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
17712
17775
|
const localServiceDid = `did:web:${serviceDomain}`;
|
|
17713
17776
|
const getInferredServiceDid = /* @__PURE__ */ __name((did2) => {
|
|
17714
17777
|
if (!did2.startsWith("did:web:")) return null;
|
|
@@ -17729,12 +17792,12 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17729
17792
|
}), "getInboxService");
|
|
17730
17793
|
const inferredServiceDid = getInferredServiceDid(recipientDid);
|
|
17731
17794
|
if (inferredServiceDid === localServiceDid) {
|
|
17732
|
-
return `${
|
|
17795
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17733
17796
|
}
|
|
17734
17797
|
const didDoc = await _learnCard.invoke.resolveDid(recipientDid);
|
|
17735
17798
|
const inboxService = getInboxService(didDoc);
|
|
17736
17799
|
if ((inboxService?.serviceDid || inferredServiceDid) === localServiceDid) {
|
|
17737
|
-
return `${
|
|
17800
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17738
17801
|
}
|
|
17739
17802
|
if (!inboxService?.serviceEndpoint) {
|
|
17740
17803
|
throw new Error(
|
|
@@ -17896,7 +17959,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17896
17959
|
return client.profileManager.updateProfileManager.mutate(manager);
|
|
17897
17960
|
}, "updateProfileManagerProfile"),
|
|
17898
17961
|
deleteProfile: /* @__PURE__ */ __name(async () => {
|
|
17899
|
-
|
|
17962
|
+
await initialQuery;
|
|
17963
|
+
if (!apiToken) await ensureUser();
|
|
17900
17964
|
const result = await client.profile.deleteProfile.mutate();
|
|
17901
17965
|
if (result) {
|
|
17902
17966
|
userData = void 0;
|
|
@@ -18047,11 +18111,10 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18047
18111
|
proofFormat: "jwt",
|
|
18048
18112
|
challenge: `inbox-federation-${crypto.randomUUID()}`
|
|
18049
18113
|
});
|
|
18050
|
-
|
|
18051
|
-
if (receiveUrl.includes("localhost")) {
|
|
18052
|
-
receiveUrl = receiveUrl.replace("https://", "http://");
|
|
18053
|
-
}
|
|
18114
|
+
const receiveUrl = validateFederationUrl(inboxEndpoint, federationConfig);
|
|
18054
18115
|
const response = await fetch(receiveUrl, {
|
|
18116
|
+
// A redirect must not bypass endpoint validation or forward credentials.
|
|
18117
|
+
redirect: "error",
|
|
18055
18118
|
method: "POST",
|
|
18056
18119
|
headers: {
|
|
18057
18120
|
"Content-Type": "application/json",
|
|
@@ -18526,8 +18589,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18526
18589
|
const isDid = recipient.startsWith("did:");
|
|
18527
18590
|
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(recipient);
|
|
18528
18591
|
const isPhone = /^\+?[\d\s-]{10,}$/.test(recipient.replace(/[\s-]/g, ""));
|
|
18529
|
-
const
|
|
18530
|
-
const serviceDomain = `${
|
|
18592
|
+
const serviceUrl2 = new URL(url2);
|
|
18593
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
18531
18594
|
const recipientDomain = recipient.startsWith("did:web:") ? recipient.split(":")[2] : void 0;
|
|
18532
18595
|
const isRemoteDidWebRecipient = recipient.startsWith("did:web:") && recipientDomain !== serviceDomain;
|
|
18533
18596
|
if (isRemoteDidWebRecipient && input.templateUri) {
|
|
@@ -19327,7 +19390,9 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
19327
19390
|
}, "getActivityChain"),
|
|
19328
19391
|
isServiceTrusted: /* @__PURE__ */ __name(async (_learnCard, serviceDid) => {
|
|
19329
19392
|
const trustedServices = await client.federation.getTrustedServices.query({});
|
|
19330
|
-
return trustedServices.some(
|
|
19393
|
+
return trustedServices.some(
|
|
19394
|
+
(service) => service.did === serviceDid
|
|
19395
|
+
);
|
|
19331
19396
|
}, "isServiceTrusted"),
|
|
19332
19397
|
getTrustedServices: /* @__PURE__ */ __name(async () => {
|
|
19333
19398
|
return client.federation.getTrustedServices.query({});
|
|
@@ -19383,9 +19448,7 @@ var getVerifyBoostPlugin = /* @__PURE__ */ __name(async (learnCard, trustedBoost
|
|
|
19383
19448
|
const boostCredential = credential?.boostCredential;
|
|
19384
19449
|
try {
|
|
19385
19450
|
if (boostCredential) {
|
|
19386
|
-
const verifyBoostCredential = await learnCard.invoke.verifyCredential(
|
|
19387
|
-
boostCredential
|
|
19388
|
-
);
|
|
19451
|
+
const verifyBoostCredential = await learnCard.invoke.verifyCredential(boostCredential);
|
|
19389
19452
|
const boostCredentialErrors = verifyBoostCredential.errors ?? [];
|
|
19390
19453
|
if (verifyBoostCredential.status?.length) {
|
|
19391
19454
|
verificationCheck.status = [
|