@learncard/network-plugin 2.13.16 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lcn-plugin.cjs.development.cjs +355 -17
- 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 +355 -17
- 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/dist/types.d.ts +57 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/plugin.ts +304 -32
- package/src/test/index.test.ts +438 -4
- package/src/types.ts +66 -0
|
@@ -15894,7 +15894,10 @@ var SendOptionsValidator = external_exports.object({
|
|
|
15894
15894
|
webhookUrl: external_exports.string().url().optional().describe("Webhook URL to receive claim notifications"),
|
|
15895
15895
|
suppressDelivery: external_exports.boolean().optional().describe("If true, returns claimUrl without sending email/SMS"),
|
|
15896
15896
|
branding: SendBrandingOptionsValidator.optional().describe("Branding for email/SMS delivery"),
|
|
15897
|
-
guardianEmail: external_exports.string().email().optional().describe("Guardian email that must approve before student can claim")
|
|
15897
|
+
guardianEmail: external_exports.string().email().optional().describe("Guardian email that must approve before student can claim"),
|
|
15898
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
15899
|
+
"How many days the credential stays claimable in the Universal Inbox (default 30). Does not change the credential validity period."
|
|
15900
|
+
)
|
|
15898
15901
|
});
|
|
15899
15902
|
var SendBoostInputValidator = external_exports.object({
|
|
15900
15903
|
type: external_exports.literal("boost"),
|
|
@@ -16189,7 +16192,8 @@ var LCNNotificationTypeEnumValidator = external_exports.enum([
|
|
|
16189
16192
|
"APP_NOTIFICATION",
|
|
16190
16193
|
"CREDENTIAL_REVOKED",
|
|
16191
16194
|
"CREDENTIAL_SUSPENDED",
|
|
16192
|
-
"CREDENTIAL_UNSUSPENDED"
|
|
16195
|
+
"CREDENTIAL_UNSUSPENDED",
|
|
16196
|
+
"CREDENTIAL_REFRESHED"
|
|
16193
16197
|
]);
|
|
16194
16198
|
var LCNNotificationMessageValidator = external_exports.object({
|
|
16195
16199
|
title: external_exports.string().optional(),
|
|
@@ -16321,12 +16325,16 @@ var CreateContactMethodSessionResponseValidator = external_exports.object({
|
|
|
16321
16325
|
});
|
|
16322
16326
|
var InboxCredentialValidator = external_exports.object({
|
|
16323
16327
|
id: external_exports.string(),
|
|
16324
|
-
credential: external_exports.string(),
|
|
16328
|
+
credential: external_exports.string().optional(),
|
|
16325
16329
|
isSigned: external_exports.boolean(),
|
|
16326
16330
|
currentStatus: LCNInboxStatusEnumValidator,
|
|
16327
16331
|
isAccepted: external_exports.boolean().optional(),
|
|
16328
16332
|
expiresAt: external_exports.string(),
|
|
16329
16333
|
createdAt: external_exports.string(),
|
|
16334
|
+
finalizedAt: external_exports.string().optional(),
|
|
16335
|
+
expiredAt: external_exports.string().optional(),
|
|
16336
|
+
credentialName: external_exports.string().optional(),
|
|
16337
|
+
achievementType: external_exports.string().optional(),
|
|
16330
16338
|
issuerDid: external_exports.string(),
|
|
16331
16339
|
webhookUrl: external_exports.string().optional(),
|
|
16332
16340
|
boostUri: external_exports.string().optional(),
|
|
@@ -16380,7 +16388,9 @@ var IssueInboxCredentialValidator = external_exports.object({
|
|
|
16380
16388
|
"The signing authority to use for the credential. If not provided, the users default signing authority will be used if the credential is not signed."
|
|
16381
16389
|
),
|
|
16382
16390
|
webhookUrl: external_exports.string().url().optional().describe("The webhook URL to receive credential issuance events."),
|
|
16383
|
-
expiresInDays: external_exports.number().min(1).max(
|
|
16391
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
16392
|
+
"How many days the encrypted inbox payload remains claimable. This does not change the credential validity period."
|
|
16393
|
+
),
|
|
16384
16394
|
templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe(
|
|
16385
16395
|
"Template data to render into the boost credential template using Mustache syntax. Only used when boostUri is provided."
|
|
16386
16396
|
),
|
|
@@ -16443,6 +16453,9 @@ var ClaimInboxCredentialValidator = external_exports.object({
|
|
|
16443
16453
|
credential: VCValidator.or(VPValidator).or(UnsignedVCValidator).or(CredentialNameRefValidator).describe("The credential to issue, or a { name } reference to resolve a boost template."),
|
|
16444
16454
|
configuration: external_exports.object({
|
|
16445
16455
|
publishableKey: external_exports.string(),
|
|
16456
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
16457
|
+
"Inbox claim window in days. Defaults to 720; use a shorter window for sensitive records."
|
|
16458
|
+
),
|
|
16446
16459
|
signingAuthorityName: external_exports.string().optional(),
|
|
16447
16460
|
listingId: external_exports.string().optional(),
|
|
16448
16461
|
listingSlug: external_exports.string().optional()
|
|
@@ -17069,6 +17082,191 @@ var inAppMessagesFlagValidator = external_exports.object({
|
|
|
17069
17082
|
version: external_exports.number().default(1),
|
|
17070
17083
|
messages: external_exports.array(inAppMessageValidator).default([])
|
|
17071
17084
|
}).passthrough();
|
|
17085
|
+
var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
|
|
17086
|
+
var ManagedCredentialRefreshServiceValidator = external_exports.object({
|
|
17087
|
+
id: external_exports.string().min(1),
|
|
17088
|
+
type: external_exports.literal("LearnCardCredentialRefresh2026"),
|
|
17089
|
+
authorization: LearnCardRefreshAuthorizationValidator.optional()
|
|
17090
|
+
}).catchall(external_exports.any());
|
|
17091
|
+
var StandardCredentialRefreshServiceValidator = external_exports.object({
|
|
17092
|
+
id: external_exports.string().min(1),
|
|
17093
|
+
type: external_exports.literal("1EdTechCredentialRefresh")
|
|
17094
|
+
}).catchall(external_exports.any());
|
|
17095
|
+
var SupportedCredentialRefreshServiceValidator = external_exports.union([
|
|
17096
|
+
ManagedCredentialRefreshServiceValidator,
|
|
17097
|
+
StandardCredentialRefreshServiceValidator
|
|
17098
|
+
]);
|
|
17099
|
+
var AllocateCredentialRefreshInputValidator = external_exports.object({
|
|
17100
|
+
holder: external_exports.object({
|
|
17101
|
+
profileId: external_exports.string().optional(),
|
|
17102
|
+
did: external_exports.string().min(1)
|
|
17103
|
+
}),
|
|
17104
|
+
credentialId: external_exports.string().min(1)
|
|
17105
|
+
});
|
|
17106
|
+
var AllocateCredentialRefreshResultValidator = external_exports.object({
|
|
17107
|
+
refreshId: external_exports.string().min(1),
|
|
17108
|
+
refreshService: ManagedCredentialRefreshServiceValidator.extend({
|
|
17109
|
+
authorization: LearnCardRefreshAuthorizationValidator
|
|
17110
|
+
})
|
|
17111
|
+
});
|
|
17112
|
+
var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
|
|
17113
|
+
var PublishCredentialRefreshBaseFields = {
|
|
17114
|
+
refreshId: external_exports.string().min(1),
|
|
17115
|
+
notifyHolder: external_exports.boolean().optional(),
|
|
17116
|
+
updateSummary: external_exports.string().optional(),
|
|
17117
|
+
idempotencyKey: external_exports.string().optional()
|
|
17118
|
+
};
|
|
17119
|
+
var PublishIssuerSignedRefreshValidator = external_exports.object({
|
|
17120
|
+
...PublishCredentialRefreshBaseFields,
|
|
17121
|
+
mode: external_exports.literal("issuer-signed"),
|
|
17122
|
+
signedCredential: VCValidator
|
|
17123
|
+
});
|
|
17124
|
+
var PublishSigningAuthorityRefreshValidator = external_exports.object({
|
|
17125
|
+
...PublishCredentialRefreshBaseFields,
|
|
17126
|
+
mode: external_exports.literal("signing-authority"),
|
|
17127
|
+
credential: UnsignedVCValidator,
|
|
17128
|
+
signingAuthority: external_exports.object({
|
|
17129
|
+
type: external_exports.string().min(1)
|
|
17130
|
+
}).catchall(external_exports.any())
|
|
17131
|
+
});
|
|
17132
|
+
var PublishCredentialRefreshInputValidator = external_exports.object({
|
|
17133
|
+
...PublishCredentialRefreshBaseFields,
|
|
17134
|
+
mode: CredentialRefreshSigningModeValidator,
|
|
17135
|
+
signedCredential: VCValidator.optional(),
|
|
17136
|
+
credential: UnsignedVCValidator.optional(),
|
|
17137
|
+
signingAuthority: external_exports.object({
|
|
17138
|
+
type: external_exports.string().min(1)
|
|
17139
|
+
}).catchall(external_exports.any()).optional()
|
|
17140
|
+
}).superRefine((input, ctx) => {
|
|
17141
|
+
if (input.mode === "issuer-signed" && !input.signedCredential) {
|
|
17142
|
+
ctx.addIssue({
|
|
17143
|
+
code: "custom",
|
|
17144
|
+
path: ["signedCredential"],
|
|
17145
|
+
message: "signedCredential is required for issuer-signed publication"
|
|
17146
|
+
});
|
|
17147
|
+
}
|
|
17148
|
+
if (input.mode === "issuer-signed" && (input.credential !== void 0 || input.signingAuthority !== void 0)) {
|
|
17149
|
+
ctx.addIssue({
|
|
17150
|
+
code: "custom",
|
|
17151
|
+
path: ["mode"],
|
|
17152
|
+
message: "issuer-signed publication cannot include signing-authority fields"
|
|
17153
|
+
});
|
|
17154
|
+
}
|
|
17155
|
+
if (input.mode === "signing-authority") {
|
|
17156
|
+
if (input.signedCredential !== void 0) {
|
|
17157
|
+
ctx.addIssue({
|
|
17158
|
+
code: "custom",
|
|
17159
|
+
path: ["signedCredential"],
|
|
17160
|
+
message: "signing-authority publication cannot include signedCredential"
|
|
17161
|
+
});
|
|
17162
|
+
}
|
|
17163
|
+
if (!input.credential) {
|
|
17164
|
+
ctx.addIssue({
|
|
17165
|
+
code: "custom",
|
|
17166
|
+
path: ["credential"],
|
|
17167
|
+
message: "credential is required for signing-authority publication"
|
|
17168
|
+
});
|
|
17169
|
+
}
|
|
17170
|
+
if (!input.signingAuthority) {
|
|
17171
|
+
ctx.addIssue({
|
|
17172
|
+
code: "custom",
|
|
17173
|
+
path: ["signingAuthority"],
|
|
17174
|
+
message: "signingAuthority is required for signing-authority publication"
|
|
17175
|
+
});
|
|
17176
|
+
}
|
|
17177
|
+
}
|
|
17178
|
+
});
|
|
17179
|
+
var PublishCredentialRefreshNotificationValidator = external_exports.enum([
|
|
17180
|
+
"queued",
|
|
17181
|
+
"suppressed",
|
|
17182
|
+
"not-applicable",
|
|
17183
|
+
/** Publication succeeded, but the post-commit notification enqueue must be retried. */
|
|
17184
|
+
"delivery-failed"
|
|
17185
|
+
]);
|
|
17186
|
+
var PublishCredentialRefreshResultValidator = external_exports.object({
|
|
17187
|
+
refreshId: external_exports.string().min(1),
|
|
17188
|
+
version: external_exports.number().int().positive(),
|
|
17189
|
+
publishedAt: external_exports.string().min(1),
|
|
17190
|
+
notification: PublishCredentialRefreshNotificationValidator
|
|
17191
|
+
});
|
|
17192
|
+
var CredentialRefreshVersionMetadataValidator = external_exports.object({
|
|
17193
|
+
version: external_exports.number().int().positive(),
|
|
17194
|
+
publishedAt: external_exports.string().min(1),
|
|
17195
|
+
effectiveAt: external_exports.string().optional(),
|
|
17196
|
+
etag: external_exports.string().optional(),
|
|
17197
|
+
signingMode: CredentialRefreshSigningModeValidator.optional(),
|
|
17198
|
+
updateSummary: external_exports.string().optional()
|
|
17199
|
+
});
|
|
17200
|
+
var GetCredentialRefreshHistoryInputValidator = external_exports.object({
|
|
17201
|
+
refreshId: external_exports.string().min(1),
|
|
17202
|
+
cursor: external_exports.string().optional(),
|
|
17203
|
+
limit: external_exports.number().int().positive().optional()
|
|
17204
|
+
});
|
|
17205
|
+
var GetCredentialRefreshHistoryResultValidator = external_exports.object({
|
|
17206
|
+
records: CredentialRefreshVersionMetadataValidator.array(),
|
|
17207
|
+
hasMore: external_exports.boolean(),
|
|
17208
|
+
cursor: external_exports.string().optional()
|
|
17209
|
+
});
|
|
17210
|
+
var CredentialRefreshChallengeValidator = external_exports.object({
|
|
17211
|
+
challenge: external_exports.string().min(1),
|
|
17212
|
+
expiresAt: external_exports.string().min(1),
|
|
17213
|
+
domain: external_exports.string().optional(),
|
|
17214
|
+
scheme: external_exports.literal("LearnCardDIDAuth").optional()
|
|
17215
|
+
});
|
|
17216
|
+
var PublicCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17217
|
+
format: external_exports.literal("vc"),
|
|
17218
|
+
credential: VCValidator,
|
|
17219
|
+
etag: external_exports.string().optional()
|
|
17220
|
+
});
|
|
17221
|
+
var JweCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17222
|
+
format: external_exports.literal("jwe"),
|
|
17223
|
+
jwe: JWEValidator,
|
|
17224
|
+
etag: external_exports.string().optional(),
|
|
17225
|
+
/** Present on LearnCard-managed endpoints; optional for interoperable JWE services. */
|
|
17226
|
+
version: external_exports.number().int().positive().optional()
|
|
17227
|
+
});
|
|
17228
|
+
var CredentialRefreshResponseEnvelopeValidator = external_exports.discriminatedUnion("format", [
|
|
17229
|
+
PublicCredentialRefreshEnvelopeValidator,
|
|
17230
|
+
JweCredentialRefreshEnvelopeValidator
|
|
17231
|
+
]);
|
|
17232
|
+
var CredentialRefreshFailureCodeValidator = external_exports.enum([
|
|
17233
|
+
"UNAVAILABLE",
|
|
17234
|
+
"TIMEOUT",
|
|
17235
|
+
"UNSUPPORTED_SERVICE",
|
|
17236
|
+
"UNAUTHORIZED",
|
|
17237
|
+
"MALFORMED_RESPONSE",
|
|
17238
|
+
"INVALID_PROOF",
|
|
17239
|
+
"ISSUER_MISMATCH",
|
|
17240
|
+
"ID_MISMATCH",
|
|
17241
|
+
"ROLLBACK",
|
|
17242
|
+
"REVOKED",
|
|
17243
|
+
"UNSAFE_ENDPOINT"
|
|
17244
|
+
]);
|
|
17245
|
+
var CredentialRefreshUpdatedResultValidator = external_exports.object({
|
|
17246
|
+
status: external_exports.literal("updated"),
|
|
17247
|
+
credential: VCValidator,
|
|
17248
|
+
etag: external_exports.string().optional(),
|
|
17249
|
+
managedVersion: external_exports.number().int().positive().optional()
|
|
17250
|
+
});
|
|
17251
|
+
var CredentialRefreshUnchangedResultValidator = external_exports.object({
|
|
17252
|
+
status: external_exports.literal("unchanged"),
|
|
17253
|
+
checkedAt: external_exports.string().min(1),
|
|
17254
|
+
etag: external_exports.string().optional()
|
|
17255
|
+
});
|
|
17256
|
+
var CredentialRefreshUnsupportedResultValidator = external_exports.object({
|
|
17257
|
+
status: external_exports.literal("unsupported")
|
|
17258
|
+
});
|
|
17259
|
+
var CredentialRefreshFailedResultValidator = external_exports.object({
|
|
17260
|
+
status: external_exports.literal("failed"),
|
|
17261
|
+
code: CredentialRefreshFailureCodeValidator,
|
|
17262
|
+
retryable: external_exports.boolean()
|
|
17263
|
+
});
|
|
17264
|
+
var CredentialRefreshResultValidator = external_exports.discriminatedUnion("status", [
|
|
17265
|
+
CredentialRefreshUpdatedResultValidator,
|
|
17266
|
+
CredentialRefreshUnchangedResultValidator,
|
|
17267
|
+
CredentialRefreshUnsupportedResultValidator,
|
|
17268
|
+
CredentialRefreshFailedResultValidator
|
|
17269
|
+
]);
|
|
17072
17270
|
|
|
17073
17271
|
// src/plugin.ts
|
|
17074
17272
|
var import_helpers = require("@learncard/helpers");
|
|
@@ -17545,6 +17743,56 @@ mustache.Writer = Writer;
|
|
|
17545
17743
|
var mustache_default = mustache;
|
|
17546
17744
|
|
|
17547
17745
|
// src/plugin.ts
|
|
17746
|
+
var LEARNCARD_DOMAIN_SUFFIXES = [".learncard.com", ".learncard.app", ".learncard.ai"];
|
|
17747
|
+
var isLearnCardDomain = /* @__PURE__ */ __name((host) => {
|
|
17748
|
+
return LEARNCARD_DOMAIN_SUFFIXES.some(
|
|
17749
|
+
(suffix) => host === suffix.replace(/^\./, "") || host.endsWith(suffix)
|
|
17750
|
+
);
|
|
17751
|
+
}, "isLearnCardDomain");
|
|
17752
|
+
var isLocalhostHost = /* @__PURE__ */ __name((host) => {
|
|
17753
|
+
const lower = host.toLowerCase();
|
|
17754
|
+
return lower === "localhost" || lower === "127.0.0.1";
|
|
17755
|
+
}, "isLocalhostHost");
|
|
17756
|
+
var validateFederationUrl = /* @__PURE__ */ __name((userProvidedUrl, config2) => {
|
|
17757
|
+
let parsed;
|
|
17758
|
+
try {
|
|
17759
|
+
parsed = new URL(userProvidedUrl);
|
|
17760
|
+
} catch {
|
|
17761
|
+
throw new Error(`Invalid federation endpoint URL: ${userProvidedUrl}`);
|
|
17762
|
+
}
|
|
17763
|
+
if (config2.serviceOrigin) {
|
|
17764
|
+
const endpointOrigin = parsed.origin;
|
|
17765
|
+
if (endpointOrigin === config2.serviceOrigin) {
|
|
17766
|
+
return parsed.href;
|
|
17767
|
+
}
|
|
17768
|
+
}
|
|
17769
|
+
const host = parsed.hostname.toLowerCase();
|
|
17770
|
+
const isLocalhost = isLocalhostHost(host);
|
|
17771
|
+
if (isLocalhost) {
|
|
17772
|
+
if (!config2.allowLocalhostFederation) {
|
|
17773
|
+
throw new Error(
|
|
17774
|
+
`Localhost federation is disabled. Set allowLocalhostFederation: true for development.`
|
|
17775
|
+
);
|
|
17776
|
+
}
|
|
17777
|
+
if (parsed.protocol === "https:") {
|
|
17778
|
+
parsed.protocol = "http:";
|
|
17779
|
+
}
|
|
17780
|
+
return parsed.href;
|
|
17781
|
+
}
|
|
17782
|
+
if (parsed.protocol !== "https:") {
|
|
17783
|
+
throw new Error(`Federation requires HTTPS for non-localhost hosts: ${userProvidedUrl}`);
|
|
17784
|
+
}
|
|
17785
|
+
if (config2.trustedFederationHosts !== void 0) {
|
|
17786
|
+
const trustedHosts = new Set(config2.trustedFederationHosts);
|
|
17787
|
+
const allowAnyHost = trustedHosts.has("*");
|
|
17788
|
+
if (!allowAnyHost && !isLearnCardDomain(host) && !trustedHosts.has(host)) {
|
|
17789
|
+
throw new Error(
|
|
17790
|
+
`Federation host '${host}' is not trusted. Add it to trustedFederationHosts or use '*' to allow any host.`
|
|
17791
|
+
);
|
|
17792
|
+
}
|
|
17793
|
+
}
|
|
17794
|
+
return parsed.href;
|
|
17795
|
+
}, "validateFederationUrl");
|
|
17548
17796
|
var uint8ArrayToBase64Url = /* @__PURE__ */ __name((bytes) => {
|
|
17549
17797
|
let binary = "";
|
|
17550
17798
|
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
@@ -17636,10 +17884,43 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
|
|
|
17636
17884
|
await appendNetworkCredentialStatus(client, credential, statusPurposes)
|
|
17637
17885
|
);
|
|
17638
17886
|
}, "issueCredentialWithNetworkStatus");
|
|
17887
|
+
var MANAGED_REFRESH_SERVICE_CONTEXT = {
|
|
17888
|
+
"LearnCardCredentialRefresh2026": "https://learncard.com/refresh#LearnCardCredentialRefresh2026",
|
|
17889
|
+
authorization: {
|
|
17890
|
+
"@id": "https://purl.imsglobal.org/spec/ob/v3p0#authorization",
|
|
17891
|
+
"@context": {
|
|
17892
|
+
LearnCardDIDAuth: "https://docs.learncard.com/definitions#LearnCardDIDAuth"
|
|
17893
|
+
}
|
|
17894
|
+
}
|
|
17895
|
+
};
|
|
17896
|
+
var injectManagedRefreshService = /* @__PURE__ */ __name((credential, refreshService) => {
|
|
17897
|
+
const existingContext = credential["@context"];
|
|
17898
|
+
const contextList = Array.isArray(existingContext) ? existingContext : [existingContext];
|
|
17899
|
+
const hasMapping = contextList.some(
|
|
17900
|
+
(entry) => !!entry && typeof entry === "object" && "LearnCardCredentialRefresh2026" in entry
|
|
17901
|
+
);
|
|
17902
|
+
return {
|
|
17903
|
+
...credential,
|
|
17904
|
+
"@context": hasMapping ? contextList : [...contextList, MANAGED_REFRESH_SERVICE_CONTEXT],
|
|
17905
|
+
refreshService
|
|
17906
|
+
};
|
|
17907
|
+
}, "injectManagedRefreshService");
|
|
17639
17908
|
async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
|
|
17640
17909
|
const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
|
|
17641
|
-
const
|
|
17642
|
-
const
|
|
17910
|
+
const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
|
|
17911
|
+
const {
|
|
17912
|
+
guardianApprovalGetter,
|
|
17913
|
+
extraHeaders,
|
|
17914
|
+
trustedFederationHosts,
|
|
17915
|
+
allowLocalhostFederation
|
|
17916
|
+
} = resolvedOptions;
|
|
17917
|
+
const serviceUrl = new URL(url2);
|
|
17918
|
+
const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
|
|
17919
|
+
const federationConfig = {
|
|
17920
|
+
trustedFederationHosts,
|
|
17921
|
+
allowLocalhostFederation: allowLocalhostFederation ?? serviceIsLocalhost,
|
|
17922
|
+
serviceOrigin: serviceUrl.origin
|
|
17923
|
+
};
|
|
17643
17924
|
let did = "";
|
|
17644
17925
|
try {
|
|
17645
17926
|
const idPlane = learnCard?.id;
|
|
@@ -17708,8 +17989,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17708
17989
|
}
|
|
17709
17990
|
}, "getBoostTemplateForIssuance");
|
|
17710
17991
|
const getInboxEndpointForDid = /* @__PURE__ */ __name(async (_learnCard, recipientDid) => {
|
|
17711
|
-
const
|
|
17712
|
-
const serviceDomain = `${
|
|
17992
|
+
const serviceUrl2 = new URL(url2);
|
|
17993
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
17713
17994
|
const localServiceDid = `did:web:${serviceDomain}`;
|
|
17714
17995
|
const getInferredServiceDid = /* @__PURE__ */ __name((did2) => {
|
|
17715
17996
|
if (!did2.startsWith("did:web:")) return null;
|
|
@@ -17730,12 +18011,12 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17730
18011
|
}), "getInboxService");
|
|
17731
18012
|
const inferredServiceDid = getInferredServiceDid(recipientDid);
|
|
17732
18013
|
if (inferredServiceDid === localServiceDid) {
|
|
17733
|
-
return `${
|
|
18014
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17734
18015
|
}
|
|
17735
18016
|
const didDoc = await _learnCard.invoke.resolveDid(recipientDid);
|
|
17736
18017
|
const inboxService = getInboxService(didDoc);
|
|
17737
18018
|
if ((inboxService?.serviceDid || inferredServiceDid) === localServiceDid) {
|
|
17738
|
-
return `${
|
|
18019
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17739
18020
|
}
|
|
17740
18021
|
if (!inboxService?.serviceEndpoint) {
|
|
17741
18022
|
throw new Error(
|
|
@@ -17897,7 +18178,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17897
18178
|
return client.profileManager.updateProfileManager.mutate(manager);
|
|
17898
18179
|
}, "updateProfileManagerProfile"),
|
|
17899
18180
|
deleteProfile: /* @__PURE__ */ __name(async () => {
|
|
17900
|
-
|
|
18181
|
+
await initialQuery;
|
|
18182
|
+
if (!apiToken) await ensureUser();
|
|
17901
18183
|
const result = await client.profile.deleteProfile.mutate();
|
|
17902
18184
|
if (result) {
|
|
17903
18185
|
userData = void 0;
|
|
@@ -18048,11 +18330,10 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18048
18330
|
proofFormat: "jwt",
|
|
18049
18331
|
challenge: `inbox-federation-${crypto.randomUUID()}`
|
|
18050
18332
|
});
|
|
18051
|
-
|
|
18052
|
-
if (receiveUrl.includes("localhost")) {
|
|
18053
|
-
receiveUrl = receiveUrl.replace("https://", "http://");
|
|
18054
|
-
}
|
|
18333
|
+
const receiveUrl = validateFederationUrl(inboxEndpoint, federationConfig);
|
|
18055
18334
|
const response = await fetch(receiveUrl, {
|
|
18335
|
+
// A redirect must not bypass endpoint validation or forward credentials.
|
|
18336
|
+
redirect: "error",
|
|
18056
18337
|
method: "POST",
|
|
18057
18338
|
headers: {
|
|
18058
18339
|
"Content-Type": "application/json",
|
|
@@ -18385,6 +18666,27 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18385
18666
|
await ensureUser();
|
|
18386
18667
|
return client.boost.allocateCredentialStatus.mutate(options2);
|
|
18387
18668
|
}, "allocateCredentialStatus"),
|
|
18669
|
+
allocateCredentialRefresh: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18670
|
+
await ensureUser();
|
|
18671
|
+
return client.credentialRefresh.allocateCredentialRefresh.mutate(input);
|
|
18672
|
+
}, "allocateCredentialRefresh"),
|
|
18673
|
+
sendRefreshableCredential: /* @__PURE__ */ __name(async (_learnCard, refreshId, credential, boostUri, skipNotification) => {
|
|
18674
|
+
await ensureUser();
|
|
18675
|
+
return client.credentialRefresh.sendRefreshableCredential.mutate({
|
|
18676
|
+
refreshId,
|
|
18677
|
+
credential,
|
|
18678
|
+
boostUri,
|
|
18679
|
+
...skipNotification ? { skipNotification: true } : {}
|
|
18680
|
+
});
|
|
18681
|
+
}, "sendRefreshableCredential"),
|
|
18682
|
+
publishCredentialRefresh: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18683
|
+
await ensureUser();
|
|
18684
|
+
return client.credentialRefresh.publishCredentialRefresh.mutate(input);
|
|
18685
|
+
}, "publishCredentialRefresh"),
|
|
18686
|
+
getCredentialRefreshHistory: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18687
|
+
await ensureUser();
|
|
18688
|
+
return client.credentialRefresh.getCredentialRefreshHistory.query(input);
|
|
18689
|
+
}, "getCredentialRefreshHistory"),
|
|
18388
18690
|
revokeBoostRecipient: /* @__PURE__ */ __name(async (_learnCard, boostUri, recipientProfileId, credentialUri) => {
|
|
18389
18691
|
await ensureUser();
|
|
18390
18692
|
const input = { boostUri, recipientProfileId };
|
|
@@ -18451,6 +18753,17 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18451
18753
|
if (typeof options2 === "object" && options2.overideFn) {
|
|
18452
18754
|
boost = options2.overideFn(boost);
|
|
18453
18755
|
}
|
|
18756
|
+
const enableRefresh = typeof options2 === "object" && options2.enableRefresh === true;
|
|
18757
|
+
let managedRefreshId;
|
|
18758
|
+
if (enableRefresh) {
|
|
18759
|
+
if (!boost.id) boost.id = `urn:uuid:${crypto.randomUUID()}`;
|
|
18760
|
+
const allocation = await client.credentialRefresh.allocateCredentialRefresh.mutate({
|
|
18761
|
+
holder: { profileId, did: targetProfile.did },
|
|
18762
|
+
credentialId: boost.id
|
|
18763
|
+
});
|
|
18764
|
+
managedRefreshId = allocation.refreshId;
|
|
18765
|
+
boost = injectManagedRefreshService(boost, allocation.refreshService);
|
|
18766
|
+
}
|
|
18454
18767
|
const statusPurposes = typeof options2 === "object" ? options2.statusPurposes : void 0;
|
|
18455
18768
|
const vc = await issueCredentialWithNetworkStatus(
|
|
18456
18769
|
_learnCard,
|
|
@@ -18458,6 +18771,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18458
18771
|
boost,
|
|
18459
18772
|
statusPurposes
|
|
18460
18773
|
);
|
|
18774
|
+
if (managedRefreshId) {
|
|
18775
|
+
return client.credentialRefresh.sendRefreshableCredential.mutate({
|
|
18776
|
+
refreshId: managedRefreshId,
|
|
18777
|
+
credential: vc,
|
|
18778
|
+
boostUri,
|
|
18779
|
+
...typeof options2 === "object" && options2.skipNotification ? { skipNotification: true } : {}
|
|
18780
|
+
});
|
|
18781
|
+
}
|
|
18461
18782
|
if (typeof options2 === "object" && !options2.encrypt || !options2) {
|
|
18462
18783
|
return client.boost.sendBoost.mutate({
|
|
18463
18784
|
profileId,
|
|
@@ -18527,8 +18848,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18527
18848
|
const isDid = recipient.startsWith("did:");
|
|
18528
18849
|
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(recipient);
|
|
18529
18850
|
const isPhone = /^\+?[\d\s-]{10,}$/.test(recipient.replace(/[\s-]/g, ""));
|
|
18530
|
-
const
|
|
18531
|
-
const serviceDomain = `${
|
|
18851
|
+
const serviceUrl2 = new URL(url2);
|
|
18852
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
18532
18853
|
const recipientDomain = recipient.startsWith("did:web:") ? recipient.split(":")[2] : void 0;
|
|
18533
18854
|
const isRemoteDidWebRecipient = recipient.startsWith("did:web:") && recipientDomain !== serviceDomain;
|
|
18534
18855
|
if (isRemoteDidWebRecipient && input.templateUri) {
|
|
@@ -18940,6 +19261,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18940
19261
|
await ensureUser();
|
|
18941
19262
|
return client.inbox.finalize.mutate();
|
|
18942
19263
|
}, "finalizeInboxCredentials"),
|
|
19264
|
+
recoverInboxCredentials: /* @__PURE__ */ __name(async (learnCard2, options2 = {}) => {
|
|
19265
|
+
const result = await client.inbox.getMyInboxDeliveries.query(options2);
|
|
19266
|
+
const results = await Promise.allSettled(
|
|
19267
|
+
result.records.map(async (record2) => ({
|
|
19268
|
+
...record2,
|
|
19269
|
+
credential: VCValidator.parse(
|
|
19270
|
+
await learnCard2.invoke.decryptDagJwe(record2.credential, [
|
|
19271
|
+
learnCard2.id.keypair()
|
|
19272
|
+
])
|
|
19273
|
+
)
|
|
19274
|
+
}))
|
|
19275
|
+
);
|
|
19276
|
+
const records = results.flatMap(
|
|
19277
|
+
(record2) => record2.status === "fulfilled" ? [record2.value] : []
|
|
19278
|
+
);
|
|
19279
|
+
return { ...result, records, failed: results.length - records.length };
|
|
19280
|
+
}, "recoverInboxCredentials"),
|
|
18943
19281
|
sendGuardianApprovalEmail: /* @__PURE__ */ __name(async (_learnCard, options2) => {
|
|
18944
19282
|
await ensureUser();
|
|
18945
19283
|
return client.inbox.sendGuardianApprovalEmail.mutate(options2);
|