@learncard/network-plugin 2.13.17 → 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.
@@ -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(365).optional().describe("The number of days the credential will be valid for."),
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 {
@@ -17669,6 +17867,27 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
17669
17867
  await appendNetworkCredentialStatus(client, credential, statusPurposes)
17670
17868
  );
17671
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");
17672
17891
  async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
17673
17892
  const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
17674
17893
  const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
@@ -18430,6 +18649,27 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18430
18649
  await ensureUser();
18431
18650
  return client.boost.allocateCredentialStatus.mutate(options2);
18432
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"),
18433
18673
  revokeBoostRecipient: /* @__PURE__ */ __name(async (_learnCard, boostUri, recipientProfileId, credentialUri) => {
18434
18674
  await ensureUser();
18435
18675
  const input = { boostUri, recipientProfileId };
@@ -18496,6 +18736,17 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18496
18736
  if (typeof options2 === "object" && options2.overideFn) {
18497
18737
  boost = options2.overideFn(boost);
18498
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
+ }
18499
18750
  const statusPurposes = typeof options2 === "object" ? options2.statusPurposes : void 0;
18500
18751
  const vc = await issueCredentialWithNetworkStatus(
18501
18752
  _learnCard,
@@ -18503,6 +18754,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18503
18754
  boost,
18504
18755
  statusPurposes
18505
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
+ }
18506
18765
  if (typeof options2 === "object" && !options2.encrypt || !options2) {
18507
18766
  return client.boost.sendBoost.mutate({
18508
18767
  profileId,
@@ -18985,6 +19244,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18985
19244
  await ensureUser();
18986
19245
  return client.inbox.finalize.mutate();
18987
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"),
18988
19264
  sendGuardianApprovalEmail: /* @__PURE__ */ __name(async (_learnCard, options2) => {
18989
19265
  await ensureUser();
18990
19266
  return client.inbox.sendGuardianApprovalEmail.mutate(options2);