@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
package/dist/lcn-plugin.esm.js
CHANGED
|
@@ -15873,7 +15873,10 @@ var SendOptionsValidator = external_exports.object({
|
|
|
15873
15873
|
webhookUrl: external_exports.string().url().optional().describe("Webhook URL to receive claim notifications"),
|
|
15874
15874
|
suppressDelivery: external_exports.boolean().optional().describe("If true, returns claimUrl without sending email/SMS"),
|
|
15875
15875
|
branding: SendBrandingOptionsValidator.optional().describe("Branding for email/SMS delivery"),
|
|
15876
|
-
guardianEmail: external_exports.string().email().optional().describe("Guardian email that must approve before student can claim")
|
|
15876
|
+
guardianEmail: external_exports.string().email().optional().describe("Guardian email that must approve before student can claim"),
|
|
15877
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
15878
|
+
"How many days the credential stays claimable in the Universal Inbox (default 30). Does not change the credential validity period."
|
|
15879
|
+
)
|
|
15877
15880
|
});
|
|
15878
15881
|
var SendBoostInputValidator = external_exports.object({
|
|
15879
15882
|
type: external_exports.literal("boost"),
|
|
@@ -16168,7 +16171,8 @@ var LCNNotificationTypeEnumValidator = external_exports.enum([
|
|
|
16168
16171
|
"APP_NOTIFICATION",
|
|
16169
16172
|
"CREDENTIAL_REVOKED",
|
|
16170
16173
|
"CREDENTIAL_SUSPENDED",
|
|
16171
|
-
"CREDENTIAL_UNSUSPENDED"
|
|
16174
|
+
"CREDENTIAL_UNSUSPENDED",
|
|
16175
|
+
"CREDENTIAL_REFRESHED"
|
|
16172
16176
|
]);
|
|
16173
16177
|
var LCNNotificationMessageValidator = external_exports.object({
|
|
16174
16178
|
title: external_exports.string().optional(),
|
|
@@ -16300,12 +16304,16 @@ var CreateContactMethodSessionResponseValidator = external_exports.object({
|
|
|
16300
16304
|
});
|
|
16301
16305
|
var InboxCredentialValidator = external_exports.object({
|
|
16302
16306
|
id: external_exports.string(),
|
|
16303
|
-
credential: external_exports.string(),
|
|
16307
|
+
credential: external_exports.string().optional(),
|
|
16304
16308
|
isSigned: external_exports.boolean(),
|
|
16305
16309
|
currentStatus: LCNInboxStatusEnumValidator,
|
|
16306
16310
|
isAccepted: external_exports.boolean().optional(),
|
|
16307
16311
|
expiresAt: external_exports.string(),
|
|
16308
16312
|
createdAt: external_exports.string(),
|
|
16313
|
+
finalizedAt: external_exports.string().optional(),
|
|
16314
|
+
expiredAt: external_exports.string().optional(),
|
|
16315
|
+
credentialName: external_exports.string().optional(),
|
|
16316
|
+
achievementType: external_exports.string().optional(),
|
|
16309
16317
|
issuerDid: external_exports.string(),
|
|
16310
16318
|
webhookUrl: external_exports.string().optional(),
|
|
16311
16319
|
boostUri: external_exports.string().optional(),
|
|
@@ -16359,7 +16367,9 @@ var IssueInboxCredentialValidator = external_exports.object({
|
|
|
16359
16367
|
"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."
|
|
16360
16368
|
),
|
|
16361
16369
|
webhookUrl: external_exports.string().url().optional().describe("The webhook URL to receive credential issuance events."),
|
|
16362
|
-
expiresInDays: external_exports.number().min(1).max(
|
|
16370
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
16371
|
+
"How many days the encrypted inbox payload remains claimable. This does not change the credential validity period."
|
|
16372
|
+
),
|
|
16363
16373
|
templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe(
|
|
16364
16374
|
"Template data to render into the boost credential template using Mustache syntax. Only used when boostUri is provided."
|
|
16365
16375
|
),
|
|
@@ -16422,6 +16432,9 @@ var ClaimInboxCredentialValidator = external_exports.object({
|
|
|
16422
16432
|
credential: VCValidator.or(VPValidator).or(UnsignedVCValidator).or(CredentialNameRefValidator).describe("The credential to issue, or a { name } reference to resolve a boost template."),
|
|
16423
16433
|
configuration: external_exports.object({
|
|
16424
16434
|
publishableKey: external_exports.string(),
|
|
16435
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
16436
|
+
"Inbox claim window in days. Defaults to 720; use a shorter window for sensitive records."
|
|
16437
|
+
),
|
|
16425
16438
|
signingAuthorityName: external_exports.string().optional(),
|
|
16426
16439
|
listingId: external_exports.string().optional(),
|
|
16427
16440
|
listingSlug: external_exports.string().optional()
|
|
@@ -17048,6 +17061,191 @@ var inAppMessagesFlagValidator = external_exports.object({
|
|
|
17048
17061
|
version: external_exports.number().default(1),
|
|
17049
17062
|
messages: external_exports.array(inAppMessageValidator).default([])
|
|
17050
17063
|
}).passthrough();
|
|
17064
|
+
var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
|
|
17065
|
+
var ManagedCredentialRefreshServiceValidator = external_exports.object({
|
|
17066
|
+
id: external_exports.string().min(1),
|
|
17067
|
+
type: external_exports.literal("LearnCardCredentialRefresh2026"),
|
|
17068
|
+
authorization: LearnCardRefreshAuthorizationValidator.optional()
|
|
17069
|
+
}).catchall(external_exports.any());
|
|
17070
|
+
var StandardCredentialRefreshServiceValidator = external_exports.object({
|
|
17071
|
+
id: external_exports.string().min(1),
|
|
17072
|
+
type: external_exports.literal("1EdTechCredentialRefresh")
|
|
17073
|
+
}).catchall(external_exports.any());
|
|
17074
|
+
var SupportedCredentialRefreshServiceValidator = external_exports.union([
|
|
17075
|
+
ManagedCredentialRefreshServiceValidator,
|
|
17076
|
+
StandardCredentialRefreshServiceValidator
|
|
17077
|
+
]);
|
|
17078
|
+
var AllocateCredentialRefreshInputValidator = external_exports.object({
|
|
17079
|
+
holder: external_exports.object({
|
|
17080
|
+
profileId: external_exports.string().optional(),
|
|
17081
|
+
did: external_exports.string().min(1)
|
|
17082
|
+
}),
|
|
17083
|
+
credentialId: external_exports.string().min(1)
|
|
17084
|
+
});
|
|
17085
|
+
var AllocateCredentialRefreshResultValidator = external_exports.object({
|
|
17086
|
+
refreshId: external_exports.string().min(1),
|
|
17087
|
+
refreshService: ManagedCredentialRefreshServiceValidator.extend({
|
|
17088
|
+
authorization: LearnCardRefreshAuthorizationValidator
|
|
17089
|
+
})
|
|
17090
|
+
});
|
|
17091
|
+
var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
|
|
17092
|
+
var PublishCredentialRefreshBaseFields = {
|
|
17093
|
+
refreshId: external_exports.string().min(1),
|
|
17094
|
+
notifyHolder: external_exports.boolean().optional(),
|
|
17095
|
+
updateSummary: external_exports.string().optional(),
|
|
17096
|
+
idempotencyKey: external_exports.string().optional()
|
|
17097
|
+
};
|
|
17098
|
+
var PublishIssuerSignedRefreshValidator = external_exports.object({
|
|
17099
|
+
...PublishCredentialRefreshBaseFields,
|
|
17100
|
+
mode: external_exports.literal("issuer-signed"),
|
|
17101
|
+
signedCredential: VCValidator
|
|
17102
|
+
});
|
|
17103
|
+
var PublishSigningAuthorityRefreshValidator = external_exports.object({
|
|
17104
|
+
...PublishCredentialRefreshBaseFields,
|
|
17105
|
+
mode: external_exports.literal("signing-authority"),
|
|
17106
|
+
credential: UnsignedVCValidator,
|
|
17107
|
+
signingAuthority: external_exports.object({
|
|
17108
|
+
type: external_exports.string().min(1)
|
|
17109
|
+
}).catchall(external_exports.any())
|
|
17110
|
+
});
|
|
17111
|
+
var PublishCredentialRefreshInputValidator = external_exports.object({
|
|
17112
|
+
...PublishCredentialRefreshBaseFields,
|
|
17113
|
+
mode: CredentialRefreshSigningModeValidator,
|
|
17114
|
+
signedCredential: VCValidator.optional(),
|
|
17115
|
+
credential: UnsignedVCValidator.optional(),
|
|
17116
|
+
signingAuthority: external_exports.object({
|
|
17117
|
+
type: external_exports.string().min(1)
|
|
17118
|
+
}).catchall(external_exports.any()).optional()
|
|
17119
|
+
}).superRefine((input, ctx) => {
|
|
17120
|
+
if (input.mode === "issuer-signed" && !input.signedCredential) {
|
|
17121
|
+
ctx.addIssue({
|
|
17122
|
+
code: "custom",
|
|
17123
|
+
path: ["signedCredential"],
|
|
17124
|
+
message: "signedCredential is required for issuer-signed publication"
|
|
17125
|
+
});
|
|
17126
|
+
}
|
|
17127
|
+
if (input.mode === "issuer-signed" && (input.credential !== void 0 || input.signingAuthority !== void 0)) {
|
|
17128
|
+
ctx.addIssue({
|
|
17129
|
+
code: "custom",
|
|
17130
|
+
path: ["mode"],
|
|
17131
|
+
message: "issuer-signed publication cannot include signing-authority fields"
|
|
17132
|
+
});
|
|
17133
|
+
}
|
|
17134
|
+
if (input.mode === "signing-authority") {
|
|
17135
|
+
if (input.signedCredential !== void 0) {
|
|
17136
|
+
ctx.addIssue({
|
|
17137
|
+
code: "custom",
|
|
17138
|
+
path: ["signedCredential"],
|
|
17139
|
+
message: "signing-authority publication cannot include signedCredential"
|
|
17140
|
+
});
|
|
17141
|
+
}
|
|
17142
|
+
if (!input.credential) {
|
|
17143
|
+
ctx.addIssue({
|
|
17144
|
+
code: "custom",
|
|
17145
|
+
path: ["credential"],
|
|
17146
|
+
message: "credential is required for signing-authority publication"
|
|
17147
|
+
});
|
|
17148
|
+
}
|
|
17149
|
+
if (!input.signingAuthority) {
|
|
17150
|
+
ctx.addIssue({
|
|
17151
|
+
code: "custom",
|
|
17152
|
+
path: ["signingAuthority"],
|
|
17153
|
+
message: "signingAuthority is required for signing-authority publication"
|
|
17154
|
+
});
|
|
17155
|
+
}
|
|
17156
|
+
}
|
|
17157
|
+
});
|
|
17158
|
+
var PublishCredentialRefreshNotificationValidator = external_exports.enum([
|
|
17159
|
+
"queued",
|
|
17160
|
+
"suppressed",
|
|
17161
|
+
"not-applicable",
|
|
17162
|
+
/** Publication succeeded, but the post-commit notification enqueue must be retried. */
|
|
17163
|
+
"delivery-failed"
|
|
17164
|
+
]);
|
|
17165
|
+
var PublishCredentialRefreshResultValidator = external_exports.object({
|
|
17166
|
+
refreshId: external_exports.string().min(1),
|
|
17167
|
+
version: external_exports.number().int().positive(),
|
|
17168
|
+
publishedAt: external_exports.string().min(1),
|
|
17169
|
+
notification: PublishCredentialRefreshNotificationValidator
|
|
17170
|
+
});
|
|
17171
|
+
var CredentialRefreshVersionMetadataValidator = external_exports.object({
|
|
17172
|
+
version: external_exports.number().int().positive(),
|
|
17173
|
+
publishedAt: external_exports.string().min(1),
|
|
17174
|
+
effectiveAt: external_exports.string().optional(),
|
|
17175
|
+
etag: external_exports.string().optional(),
|
|
17176
|
+
signingMode: CredentialRefreshSigningModeValidator.optional(),
|
|
17177
|
+
updateSummary: external_exports.string().optional()
|
|
17178
|
+
});
|
|
17179
|
+
var GetCredentialRefreshHistoryInputValidator = external_exports.object({
|
|
17180
|
+
refreshId: external_exports.string().min(1),
|
|
17181
|
+
cursor: external_exports.string().optional(),
|
|
17182
|
+
limit: external_exports.number().int().positive().optional()
|
|
17183
|
+
});
|
|
17184
|
+
var GetCredentialRefreshHistoryResultValidator = external_exports.object({
|
|
17185
|
+
records: CredentialRefreshVersionMetadataValidator.array(),
|
|
17186
|
+
hasMore: external_exports.boolean(),
|
|
17187
|
+
cursor: external_exports.string().optional()
|
|
17188
|
+
});
|
|
17189
|
+
var CredentialRefreshChallengeValidator = external_exports.object({
|
|
17190
|
+
challenge: external_exports.string().min(1),
|
|
17191
|
+
expiresAt: external_exports.string().min(1),
|
|
17192
|
+
domain: external_exports.string().optional(),
|
|
17193
|
+
scheme: external_exports.literal("LearnCardDIDAuth").optional()
|
|
17194
|
+
});
|
|
17195
|
+
var PublicCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17196
|
+
format: external_exports.literal("vc"),
|
|
17197
|
+
credential: VCValidator,
|
|
17198
|
+
etag: external_exports.string().optional()
|
|
17199
|
+
});
|
|
17200
|
+
var JweCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17201
|
+
format: external_exports.literal("jwe"),
|
|
17202
|
+
jwe: JWEValidator,
|
|
17203
|
+
etag: external_exports.string().optional(),
|
|
17204
|
+
/** Present on LearnCard-managed endpoints; optional for interoperable JWE services. */
|
|
17205
|
+
version: external_exports.number().int().positive().optional()
|
|
17206
|
+
});
|
|
17207
|
+
var CredentialRefreshResponseEnvelopeValidator = external_exports.discriminatedUnion("format", [
|
|
17208
|
+
PublicCredentialRefreshEnvelopeValidator,
|
|
17209
|
+
JweCredentialRefreshEnvelopeValidator
|
|
17210
|
+
]);
|
|
17211
|
+
var CredentialRefreshFailureCodeValidator = external_exports.enum([
|
|
17212
|
+
"UNAVAILABLE",
|
|
17213
|
+
"TIMEOUT",
|
|
17214
|
+
"UNSUPPORTED_SERVICE",
|
|
17215
|
+
"UNAUTHORIZED",
|
|
17216
|
+
"MALFORMED_RESPONSE",
|
|
17217
|
+
"INVALID_PROOF",
|
|
17218
|
+
"ISSUER_MISMATCH",
|
|
17219
|
+
"ID_MISMATCH",
|
|
17220
|
+
"ROLLBACK",
|
|
17221
|
+
"REVOKED",
|
|
17222
|
+
"UNSAFE_ENDPOINT"
|
|
17223
|
+
]);
|
|
17224
|
+
var CredentialRefreshUpdatedResultValidator = external_exports.object({
|
|
17225
|
+
status: external_exports.literal("updated"),
|
|
17226
|
+
credential: VCValidator,
|
|
17227
|
+
etag: external_exports.string().optional(),
|
|
17228
|
+
managedVersion: external_exports.number().int().positive().optional()
|
|
17229
|
+
});
|
|
17230
|
+
var CredentialRefreshUnchangedResultValidator = external_exports.object({
|
|
17231
|
+
status: external_exports.literal("unchanged"),
|
|
17232
|
+
checkedAt: external_exports.string().min(1),
|
|
17233
|
+
etag: external_exports.string().optional()
|
|
17234
|
+
});
|
|
17235
|
+
var CredentialRefreshUnsupportedResultValidator = external_exports.object({
|
|
17236
|
+
status: external_exports.literal("unsupported")
|
|
17237
|
+
});
|
|
17238
|
+
var CredentialRefreshFailedResultValidator = external_exports.object({
|
|
17239
|
+
status: external_exports.literal("failed"),
|
|
17240
|
+
code: CredentialRefreshFailureCodeValidator,
|
|
17241
|
+
retryable: external_exports.boolean()
|
|
17242
|
+
});
|
|
17243
|
+
var CredentialRefreshResultValidator = external_exports.discriminatedUnion("status", [
|
|
17244
|
+
CredentialRefreshUpdatedResultValidator,
|
|
17245
|
+
CredentialRefreshUnchangedResultValidator,
|
|
17246
|
+
CredentialRefreshUnsupportedResultValidator,
|
|
17247
|
+
CredentialRefreshFailedResultValidator
|
|
17248
|
+
]);
|
|
17051
17249
|
|
|
17052
17250
|
// src/plugin.ts
|
|
17053
17251
|
import {
|
|
@@ -17528,6 +17726,56 @@ mustache.Writer = Writer;
|
|
|
17528
17726
|
var mustache_default = mustache;
|
|
17529
17727
|
|
|
17530
17728
|
// src/plugin.ts
|
|
17729
|
+
var LEARNCARD_DOMAIN_SUFFIXES = [".learncard.com", ".learncard.app", ".learncard.ai"];
|
|
17730
|
+
var isLearnCardDomain = /* @__PURE__ */ __name((host) => {
|
|
17731
|
+
return LEARNCARD_DOMAIN_SUFFIXES.some(
|
|
17732
|
+
(suffix) => host === suffix.replace(/^\./, "") || host.endsWith(suffix)
|
|
17733
|
+
);
|
|
17734
|
+
}, "isLearnCardDomain");
|
|
17735
|
+
var isLocalhostHost = /* @__PURE__ */ __name((host) => {
|
|
17736
|
+
const lower = host.toLowerCase();
|
|
17737
|
+
return lower === "localhost" || lower === "127.0.0.1";
|
|
17738
|
+
}, "isLocalhostHost");
|
|
17739
|
+
var validateFederationUrl = /* @__PURE__ */ __name((userProvidedUrl, config2) => {
|
|
17740
|
+
let parsed;
|
|
17741
|
+
try {
|
|
17742
|
+
parsed = new URL(userProvidedUrl);
|
|
17743
|
+
} catch {
|
|
17744
|
+
throw new Error(`Invalid federation endpoint URL: ${userProvidedUrl}`);
|
|
17745
|
+
}
|
|
17746
|
+
if (config2.serviceOrigin) {
|
|
17747
|
+
const endpointOrigin = parsed.origin;
|
|
17748
|
+
if (endpointOrigin === config2.serviceOrigin) {
|
|
17749
|
+
return parsed.href;
|
|
17750
|
+
}
|
|
17751
|
+
}
|
|
17752
|
+
const host = parsed.hostname.toLowerCase();
|
|
17753
|
+
const isLocalhost = isLocalhostHost(host);
|
|
17754
|
+
if (isLocalhost) {
|
|
17755
|
+
if (!config2.allowLocalhostFederation) {
|
|
17756
|
+
throw new Error(
|
|
17757
|
+
`Localhost federation is disabled. Set allowLocalhostFederation: true for development.`
|
|
17758
|
+
);
|
|
17759
|
+
}
|
|
17760
|
+
if (parsed.protocol === "https:") {
|
|
17761
|
+
parsed.protocol = "http:";
|
|
17762
|
+
}
|
|
17763
|
+
return parsed.href;
|
|
17764
|
+
}
|
|
17765
|
+
if (parsed.protocol !== "https:") {
|
|
17766
|
+
throw new Error(`Federation requires HTTPS for non-localhost hosts: ${userProvidedUrl}`);
|
|
17767
|
+
}
|
|
17768
|
+
if (config2.trustedFederationHosts !== void 0) {
|
|
17769
|
+
const trustedHosts = new Set(config2.trustedFederationHosts);
|
|
17770
|
+
const allowAnyHost = trustedHosts.has("*");
|
|
17771
|
+
if (!allowAnyHost && !isLearnCardDomain(host) && !trustedHosts.has(host)) {
|
|
17772
|
+
throw new Error(
|
|
17773
|
+
`Federation host '${host}' is not trusted. Add it to trustedFederationHosts or use '*' to allow any host.`
|
|
17774
|
+
);
|
|
17775
|
+
}
|
|
17776
|
+
}
|
|
17777
|
+
return parsed.href;
|
|
17778
|
+
}, "validateFederationUrl");
|
|
17531
17779
|
var uint8ArrayToBase64Url = /* @__PURE__ */ __name((bytes) => {
|
|
17532
17780
|
let binary = "";
|
|
17533
17781
|
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
@@ -17619,10 +17867,43 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
|
|
|
17619
17867
|
await appendNetworkCredentialStatus(client, credential, statusPurposes)
|
|
17620
17868
|
);
|
|
17621
17869
|
}, "issueCredentialWithNetworkStatus");
|
|
17870
|
+
var MANAGED_REFRESH_SERVICE_CONTEXT = {
|
|
17871
|
+
"LearnCardCredentialRefresh2026": "https://learncard.com/refresh#LearnCardCredentialRefresh2026",
|
|
17872
|
+
authorization: {
|
|
17873
|
+
"@id": "https://purl.imsglobal.org/spec/ob/v3p0#authorization",
|
|
17874
|
+
"@context": {
|
|
17875
|
+
LearnCardDIDAuth: "https://docs.learncard.com/definitions#LearnCardDIDAuth"
|
|
17876
|
+
}
|
|
17877
|
+
}
|
|
17878
|
+
};
|
|
17879
|
+
var injectManagedRefreshService = /* @__PURE__ */ __name((credential, refreshService) => {
|
|
17880
|
+
const existingContext = credential["@context"];
|
|
17881
|
+
const contextList = Array.isArray(existingContext) ? existingContext : [existingContext];
|
|
17882
|
+
const hasMapping = contextList.some(
|
|
17883
|
+
(entry) => !!entry && typeof entry === "object" && "LearnCardCredentialRefresh2026" in entry
|
|
17884
|
+
);
|
|
17885
|
+
return {
|
|
17886
|
+
...credential,
|
|
17887
|
+
"@context": hasMapping ? contextList : [...contextList, MANAGED_REFRESH_SERVICE_CONTEXT],
|
|
17888
|
+
refreshService
|
|
17889
|
+
};
|
|
17890
|
+
}, "injectManagedRefreshService");
|
|
17622
17891
|
async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
|
|
17623
17892
|
const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
|
|
17624
|
-
const
|
|
17625
|
-
const
|
|
17893
|
+
const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
|
|
17894
|
+
const {
|
|
17895
|
+
guardianApprovalGetter,
|
|
17896
|
+
extraHeaders,
|
|
17897
|
+
trustedFederationHosts,
|
|
17898
|
+
allowLocalhostFederation
|
|
17899
|
+
} = resolvedOptions;
|
|
17900
|
+
const serviceUrl = new URL(url2);
|
|
17901
|
+
const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
|
|
17902
|
+
const federationConfig = {
|
|
17903
|
+
trustedFederationHosts,
|
|
17904
|
+
allowLocalhostFederation: allowLocalhostFederation ?? serviceIsLocalhost,
|
|
17905
|
+
serviceOrigin: serviceUrl.origin
|
|
17906
|
+
};
|
|
17626
17907
|
let did = "";
|
|
17627
17908
|
try {
|
|
17628
17909
|
const idPlane = learnCard?.id;
|
|
@@ -17691,8 +17972,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17691
17972
|
}
|
|
17692
17973
|
}, "getBoostTemplateForIssuance");
|
|
17693
17974
|
const getInboxEndpointForDid = /* @__PURE__ */ __name(async (_learnCard, recipientDid) => {
|
|
17694
|
-
const
|
|
17695
|
-
const serviceDomain = `${
|
|
17975
|
+
const serviceUrl2 = new URL(url2);
|
|
17976
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
17696
17977
|
const localServiceDid = `did:web:${serviceDomain}`;
|
|
17697
17978
|
const getInferredServiceDid = /* @__PURE__ */ __name((did2) => {
|
|
17698
17979
|
if (!did2.startsWith("did:web:")) return null;
|
|
@@ -17713,12 +17994,12 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17713
17994
|
}), "getInboxService");
|
|
17714
17995
|
const inferredServiceDid = getInferredServiceDid(recipientDid);
|
|
17715
17996
|
if (inferredServiceDid === localServiceDid) {
|
|
17716
|
-
return `${
|
|
17997
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17717
17998
|
}
|
|
17718
17999
|
const didDoc = await _learnCard.invoke.resolveDid(recipientDid);
|
|
17719
18000
|
const inboxService = getInboxService(didDoc);
|
|
17720
18001
|
if ((inboxService?.serviceDid || inferredServiceDid) === localServiceDid) {
|
|
17721
|
-
return `${
|
|
18002
|
+
return `${serviceUrl2.origin}/api/inbox/receive`;
|
|
17722
18003
|
}
|
|
17723
18004
|
if (!inboxService?.serviceEndpoint) {
|
|
17724
18005
|
throw new Error(
|
|
@@ -17880,7 +18161,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17880
18161
|
return client.profileManager.updateProfileManager.mutate(manager);
|
|
17881
18162
|
}, "updateProfileManagerProfile"),
|
|
17882
18163
|
deleteProfile: /* @__PURE__ */ __name(async () => {
|
|
17883
|
-
|
|
18164
|
+
await initialQuery;
|
|
18165
|
+
if (!apiToken) await ensureUser();
|
|
17884
18166
|
const result = await client.profile.deleteProfile.mutate();
|
|
17885
18167
|
if (result) {
|
|
17886
18168
|
userData = void 0;
|
|
@@ -18031,11 +18313,10 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18031
18313
|
proofFormat: "jwt",
|
|
18032
18314
|
challenge: `inbox-federation-${crypto.randomUUID()}`
|
|
18033
18315
|
});
|
|
18034
|
-
|
|
18035
|
-
if (receiveUrl.includes("localhost")) {
|
|
18036
|
-
receiveUrl = receiveUrl.replace("https://", "http://");
|
|
18037
|
-
}
|
|
18316
|
+
const receiveUrl = validateFederationUrl(inboxEndpoint, federationConfig);
|
|
18038
18317
|
const response = await fetch(receiveUrl, {
|
|
18318
|
+
// A redirect must not bypass endpoint validation or forward credentials.
|
|
18319
|
+
redirect: "error",
|
|
18039
18320
|
method: "POST",
|
|
18040
18321
|
headers: {
|
|
18041
18322
|
"Content-Type": "application/json",
|
|
@@ -18368,6 +18649,27 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18368
18649
|
await ensureUser();
|
|
18369
18650
|
return client.boost.allocateCredentialStatus.mutate(options2);
|
|
18370
18651
|
}, "allocateCredentialStatus"),
|
|
18652
|
+
allocateCredentialRefresh: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18653
|
+
await ensureUser();
|
|
18654
|
+
return client.credentialRefresh.allocateCredentialRefresh.mutate(input);
|
|
18655
|
+
}, "allocateCredentialRefresh"),
|
|
18656
|
+
sendRefreshableCredential: /* @__PURE__ */ __name(async (_learnCard, refreshId, credential, boostUri, skipNotification) => {
|
|
18657
|
+
await ensureUser();
|
|
18658
|
+
return client.credentialRefresh.sendRefreshableCredential.mutate({
|
|
18659
|
+
refreshId,
|
|
18660
|
+
credential,
|
|
18661
|
+
boostUri,
|
|
18662
|
+
...skipNotification ? { skipNotification: true } : {}
|
|
18663
|
+
});
|
|
18664
|
+
}, "sendRefreshableCredential"),
|
|
18665
|
+
publishCredentialRefresh: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18666
|
+
await ensureUser();
|
|
18667
|
+
return client.credentialRefresh.publishCredentialRefresh.mutate(input);
|
|
18668
|
+
}, "publishCredentialRefresh"),
|
|
18669
|
+
getCredentialRefreshHistory: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18670
|
+
await ensureUser();
|
|
18671
|
+
return client.credentialRefresh.getCredentialRefreshHistory.query(input);
|
|
18672
|
+
}, "getCredentialRefreshHistory"),
|
|
18371
18673
|
revokeBoostRecipient: /* @__PURE__ */ __name(async (_learnCard, boostUri, recipientProfileId, credentialUri) => {
|
|
18372
18674
|
await ensureUser();
|
|
18373
18675
|
const input = { boostUri, recipientProfileId };
|
|
@@ -18434,6 +18736,17 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18434
18736
|
if (typeof options2 === "object" && options2.overideFn) {
|
|
18435
18737
|
boost = options2.overideFn(boost);
|
|
18436
18738
|
}
|
|
18739
|
+
const enableRefresh = typeof options2 === "object" && options2.enableRefresh === true;
|
|
18740
|
+
let managedRefreshId;
|
|
18741
|
+
if (enableRefresh) {
|
|
18742
|
+
if (!boost.id) boost.id = `urn:uuid:${crypto.randomUUID()}`;
|
|
18743
|
+
const allocation = await client.credentialRefresh.allocateCredentialRefresh.mutate({
|
|
18744
|
+
holder: { profileId, did: targetProfile.did },
|
|
18745
|
+
credentialId: boost.id
|
|
18746
|
+
});
|
|
18747
|
+
managedRefreshId = allocation.refreshId;
|
|
18748
|
+
boost = injectManagedRefreshService(boost, allocation.refreshService);
|
|
18749
|
+
}
|
|
18437
18750
|
const statusPurposes = typeof options2 === "object" ? options2.statusPurposes : void 0;
|
|
18438
18751
|
const vc = await issueCredentialWithNetworkStatus(
|
|
18439
18752
|
_learnCard,
|
|
@@ -18441,6 +18754,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18441
18754
|
boost,
|
|
18442
18755
|
statusPurposes
|
|
18443
18756
|
);
|
|
18757
|
+
if (managedRefreshId) {
|
|
18758
|
+
return client.credentialRefresh.sendRefreshableCredential.mutate({
|
|
18759
|
+
refreshId: managedRefreshId,
|
|
18760
|
+
credential: vc,
|
|
18761
|
+
boostUri,
|
|
18762
|
+
...typeof options2 === "object" && options2.skipNotification ? { skipNotification: true } : {}
|
|
18763
|
+
});
|
|
18764
|
+
}
|
|
18444
18765
|
if (typeof options2 === "object" && !options2.encrypt || !options2) {
|
|
18445
18766
|
return client.boost.sendBoost.mutate({
|
|
18446
18767
|
profileId,
|
|
@@ -18510,8 +18831,8 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18510
18831
|
const isDid = recipient.startsWith("did:");
|
|
18511
18832
|
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(recipient);
|
|
18512
18833
|
const isPhone = /^\+?[\d\s-]{10,}$/.test(recipient.replace(/[\s-]/g, ""));
|
|
18513
|
-
const
|
|
18514
|
-
const serviceDomain = `${
|
|
18834
|
+
const serviceUrl2 = new URL(url2);
|
|
18835
|
+
const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
|
|
18515
18836
|
const recipientDomain = recipient.startsWith("did:web:") ? recipient.split(":")[2] : void 0;
|
|
18516
18837
|
const isRemoteDidWebRecipient = recipient.startsWith("did:web:") && recipientDomain !== serviceDomain;
|
|
18517
18838
|
if (isRemoteDidWebRecipient && input.templateUri) {
|
|
@@ -18923,6 +19244,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18923
19244
|
await ensureUser();
|
|
18924
19245
|
return client.inbox.finalize.mutate();
|
|
18925
19246
|
}, "finalizeInboxCredentials"),
|
|
19247
|
+
recoverInboxCredentials: /* @__PURE__ */ __name(async (learnCard2, options2 = {}) => {
|
|
19248
|
+
const result = await client.inbox.getMyInboxDeliveries.query(options2);
|
|
19249
|
+
const results = await Promise.allSettled(
|
|
19250
|
+
result.records.map(async (record2) => ({
|
|
19251
|
+
...record2,
|
|
19252
|
+
credential: VCValidator.parse(
|
|
19253
|
+
await learnCard2.invoke.decryptDagJwe(record2.credential, [
|
|
19254
|
+
learnCard2.id.keypair()
|
|
19255
|
+
])
|
|
19256
|
+
)
|
|
19257
|
+
}))
|
|
19258
|
+
);
|
|
19259
|
+
const records = results.flatMap(
|
|
19260
|
+
(record2) => record2.status === "fulfilled" ? [record2.value] : []
|
|
19261
|
+
);
|
|
19262
|
+
return { ...result, records, failed: results.length - records.length };
|
|
19263
|
+
}, "recoverInboxCredentials"),
|
|
18926
19264
|
sendGuardianApprovalEmail: /* @__PURE__ */ __name(async (_learnCard, options2) => {
|
|
18927
19265
|
await ensureUser();
|
|
18928
19266
|
return client.inbox.sendGuardianApprovalEmail.mutate(options2);
|