@learncard/network-plugin 2.14.0 → 3.0.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.
@@ -21,11 +21,59 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/index.ts
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
+ ACT_AS_HEADER: () => ACT_AS_HEADER,
24
25
  getLearnCardNetworkPlugin: () => getLearnCardNetworkPlugin,
25
26
  getVerifyBoostPlugin: () => getVerifyBoostPlugin
26
27
  });
27
28
  module.exports = __toCommonJS(index_exports);
28
29
 
30
+ // src/inbox-batch.ts
31
+ var waitForInboxCredentialBatch = /* @__PURE__ */ __name(async (read, options = {}) => {
32
+ const { timeoutMs = 6e5, intervalMs = 2e3, signal, onProgress } = options;
33
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647 || !Number.isFinite(intervalMs) || intervalMs <= 0 || intervalMs > 2147483647) {
34
+ throw new RangeError("timeoutMs and intervalMs must be positive finite timer durations.");
35
+ }
36
+ const controller = new AbortController();
37
+ const abort = /* @__PURE__ */ __name(() => controller.abort(signal?.reason), "abort");
38
+ signal?.addEventListener("abort", abort, { once: true });
39
+ if (signal?.aborted) abort();
40
+ const timeout = setTimeout(() => {
41
+ const error51 = new Error(
42
+ "Timed out waiting for inbox batch. Keep the batch ID to check again."
43
+ );
44
+ error51.name = "TimeoutError";
45
+ controller.abort(error51);
46
+ }, timeoutMs);
47
+ const cancellable = /* @__PURE__ */ __name((operation) => new Promise((resolve, reject) => {
48
+ const interrupted = /* @__PURE__ */ __name(() => reject(controller.signal.reason), "interrupted");
49
+ if (controller.signal.aborted) return interrupted();
50
+ controller.signal.addEventListener("abort", interrupted, { once: true });
51
+ Promise.resolve().then(() => {
52
+ if (controller.signal.aborted) throw controller.signal.reason;
53
+ return operation();
54
+ }).then(resolve, reject).finally(() => controller.signal.removeEventListener("abort", interrupted));
55
+ }), "cancellable");
56
+ let delay = intervalMs;
57
+ let sleepTimer;
58
+ try {
59
+ while (true) {
60
+ const batch = await cancellable(() => read(controller.signal));
61
+ onProgress?.(batch);
62
+ if (batch.done) return batch;
63
+ await cancellable(
64
+ () => new Promise((resolve) => {
65
+ sleepTimer = setTimeout(resolve, delay);
66
+ })
67
+ );
68
+ delay = Math.min(delay * 1.5, Math.max(intervalMs, 1e4));
69
+ }
70
+ } finally {
71
+ clearTimeout(timeout);
72
+ clearTimeout(sleepTimer);
73
+ signal?.removeEventListener("abort", abort);
74
+ }
75
+ }, "waitForInboxCredentialBatch");
76
+
29
77
  // src/plugin.ts
30
78
  var import_network_brain_client = require("@learncard/network-brain-client");
31
79
 
@@ -15126,14 +15174,22 @@ var UnsignedVCValidator = external_exports.object({
15126
15174
  }).catchall(external_exports.any());
15127
15175
  var ProofValidator = external_exports.object({
15128
15176
  type: external_exports.string(),
15129
- created: external_exports.string(),
15177
+ created: external_exports.string().optional(),
15130
15178
  challenge: external_exports.string().optional(),
15131
15179
  domain: external_exports.string().optional(),
15132
15180
  nonce: external_exports.string().optional(),
15133
15181
  proofPurpose: external_exports.string(),
15134
15182
  verificationMethod: external_exports.string(),
15135
15183
  jws: external_exports.string().optional()
15136
- }).catchall(external_exports.any());
15184
+ }).catchall(external_exports.any()).superRefine((proof, ctx) => {
15185
+ if (proof.created === void 0 && (proof.type !== "DataIntegrityProof" || proof.cryptosuite !== "ecdsa-rdfc-2019")) {
15186
+ ctx.addIssue({
15187
+ code: "custom",
15188
+ path: ["created"],
15189
+ message: "created is required for this proof suite"
15190
+ });
15191
+ }
15192
+ });
15137
15193
  var VCValidator = UnsignedVCValidator.extend({
15138
15194
  proof: ProofValidator.or(ProofValidator.array())
15139
15195
  });
@@ -15575,6 +15631,204 @@ var StringQuery = external_exports.union([
15575
15631
  $or: BaseStringQuery.array()
15576
15632
  })
15577
15633
  ]);
15634
+ var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
15635
+ var ManagedCredentialRefreshServiceValidator = external_exports.object({
15636
+ id: external_exports.string().min(1),
15637
+ type: external_exports.literal("LearnCardCredentialRefresh2026"),
15638
+ authorization: LearnCardRefreshAuthorizationValidator.optional()
15639
+ }).catchall(external_exports.any());
15640
+ var StandardCredentialRefreshServiceValidator = external_exports.object({
15641
+ id: external_exports.string().min(1),
15642
+ type: external_exports.literal("1EdTechCredentialRefresh")
15643
+ }).catchall(external_exports.any());
15644
+ var SupportedCredentialRefreshServiceValidator = external_exports.union([
15645
+ ManagedCredentialRefreshServiceValidator,
15646
+ StandardCredentialRefreshServiceValidator
15647
+ ]);
15648
+ var AllocateCredentialRefreshInputValidator = external_exports.object({
15649
+ holder: external_exports.object({
15650
+ profileId: external_exports.string().optional(),
15651
+ did: external_exports.string().min(1)
15652
+ }),
15653
+ credentialId: external_exports.string().min(1)
15654
+ });
15655
+ var AllocateCredentialRefreshResultValidator = external_exports.object({
15656
+ refreshId: external_exports.string().min(1),
15657
+ refreshService: ManagedCredentialRefreshServiceValidator.extend({
15658
+ authorization: LearnCardRefreshAuthorizationValidator
15659
+ })
15660
+ });
15661
+ var ManagedCredentialRefreshReceiptValidator = external_exports.object({
15662
+ refreshId: external_exports.string().min(1),
15663
+ refreshService: ManagedCredentialRefreshServiceValidator,
15664
+ credentialId: external_exports.string().min(1),
15665
+ issuerDid: external_exports.string().min(1),
15666
+ holderDid: external_exports.string().min(1),
15667
+ credentialStatus: CredentialStatusValidator.or(
15668
+ CredentialStatusValidator.array()
15669
+ ).optional()
15670
+ }).strip();
15671
+ var InboxCredentialRefreshReceiptValidator = ManagedCredentialRefreshReceiptValidator.omit(
15672
+ { holderDid: true }
15673
+ ).extend({ holderDid: external_exports.string().min(1).optional() });
15674
+ var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
15675
+ var PublishCredentialRefreshBaseFields = {
15676
+ refreshId: external_exports.string().min(1),
15677
+ notifyHolder: external_exports.boolean().optional(),
15678
+ updateSummary: external_exports.string().optional(),
15679
+ idempotencyKey: external_exports.string().optional()
15680
+ };
15681
+ var PublishIssuerSignedRefreshValidator = external_exports.object({
15682
+ ...PublishCredentialRefreshBaseFields,
15683
+ mode: external_exports.literal("issuer-signed"),
15684
+ signedCredential: VCValidator
15685
+ });
15686
+ var PublishSigningAuthorityRefreshValidator = external_exports.object({
15687
+ ...PublishCredentialRefreshBaseFields,
15688
+ mode: external_exports.literal("signing-authority"),
15689
+ credential: UnsignedVCValidator,
15690
+ signingAuthority: external_exports.object({
15691
+ type: external_exports.string().min(1)
15692
+ }).catchall(external_exports.any())
15693
+ });
15694
+ var PublishCredentialRefreshInputValidator = external_exports.object({
15695
+ ...PublishCredentialRefreshBaseFields,
15696
+ mode: CredentialRefreshSigningModeValidator,
15697
+ signedCredential: VCValidator.optional(),
15698
+ credential: UnsignedVCValidator.optional(),
15699
+ signingAuthority: external_exports.object({
15700
+ type: external_exports.string().min(1)
15701
+ }).catchall(external_exports.any()).optional()
15702
+ }).superRefine((input, ctx) => {
15703
+ if (input.mode === "issuer-signed" && !input.signedCredential) {
15704
+ ctx.addIssue({
15705
+ code: "custom",
15706
+ path: ["signedCredential"],
15707
+ message: "signedCredential is required for issuer-signed publication"
15708
+ });
15709
+ }
15710
+ if (input.mode === "issuer-signed" && (input.credential !== void 0 || input.signingAuthority !== void 0)) {
15711
+ ctx.addIssue({
15712
+ code: "custom",
15713
+ path: ["mode"],
15714
+ message: "issuer-signed publication cannot include signing-authority fields"
15715
+ });
15716
+ }
15717
+ if (input.mode === "signing-authority") {
15718
+ if (input.signedCredential !== void 0) {
15719
+ ctx.addIssue({
15720
+ code: "custom",
15721
+ path: ["signedCredential"],
15722
+ message: "signing-authority publication cannot include signedCredential"
15723
+ });
15724
+ }
15725
+ if (!input.credential) {
15726
+ ctx.addIssue({
15727
+ code: "custom",
15728
+ path: ["credential"],
15729
+ message: "credential is required for signing-authority publication"
15730
+ });
15731
+ }
15732
+ if (!input.signingAuthority) {
15733
+ ctx.addIssue({
15734
+ code: "custom",
15735
+ path: ["signingAuthority"],
15736
+ message: "signingAuthority is required for signing-authority publication"
15737
+ });
15738
+ }
15739
+ }
15740
+ });
15741
+ var PublishCredentialRefreshNotificationValidator = external_exports.enum([
15742
+ "queued",
15743
+ "suppressed",
15744
+ "not-applicable",
15745
+ /** Publication succeeded, but the post-commit notification enqueue must be retried. */
15746
+ "delivery-failed"
15747
+ ]);
15748
+ var PublishCredentialRefreshResultValidator = external_exports.object({
15749
+ refreshId: external_exports.string().min(1),
15750
+ version: external_exports.number().int().positive(),
15751
+ publishedAt: external_exports.string().min(1),
15752
+ notification: PublishCredentialRefreshNotificationValidator
15753
+ });
15754
+ var CredentialRefreshVersionMetadataValidator = external_exports.object({
15755
+ version: external_exports.number().int().positive(),
15756
+ publishedAt: external_exports.string().min(1),
15757
+ effectiveAt: external_exports.string().optional(),
15758
+ etag: external_exports.string().optional(),
15759
+ signingMode: CredentialRefreshSigningModeValidator.optional(),
15760
+ updateSummary: external_exports.string().optional()
15761
+ });
15762
+ var GetCredentialRefreshHistoryInputValidator = external_exports.object({
15763
+ refreshId: external_exports.string().min(1),
15764
+ cursor: external_exports.string().optional(),
15765
+ limit: external_exports.number().int().positive().optional()
15766
+ });
15767
+ var GetCredentialRefreshHistoryResultValidator = external_exports.object({
15768
+ records: CredentialRefreshVersionMetadataValidator.array(),
15769
+ hasMore: external_exports.boolean(),
15770
+ cursor: external_exports.string().optional()
15771
+ });
15772
+ var CredentialRefreshChallengeValidator = external_exports.object({
15773
+ challenge: external_exports.string().min(1),
15774
+ expiresAt: external_exports.string().min(1),
15775
+ domain: external_exports.string().optional(),
15776
+ scheme: external_exports.literal("LearnCardDIDAuth").optional()
15777
+ });
15778
+ var PublicCredentialRefreshEnvelopeValidator = external_exports.object({
15779
+ format: external_exports.literal("vc"),
15780
+ credential: VCValidator,
15781
+ etag: external_exports.string().optional()
15782
+ });
15783
+ var JweCredentialRefreshEnvelopeValidator = external_exports.object({
15784
+ format: external_exports.literal("jwe"),
15785
+ jwe: JWEValidator,
15786
+ etag: external_exports.string().optional(),
15787
+ /** Present on LearnCard-managed endpoints; optional for interoperable JWE services. */
15788
+ version: external_exports.number().int().positive().optional()
15789
+ });
15790
+ var CredentialRefreshResponseEnvelopeValidator = external_exports.discriminatedUnion("format", [
15791
+ PublicCredentialRefreshEnvelopeValidator,
15792
+ JweCredentialRefreshEnvelopeValidator
15793
+ ]);
15794
+ var CredentialRefreshFailureCodeValidator = external_exports.enum([
15795
+ "UNAVAILABLE",
15796
+ "TIMEOUT",
15797
+ "UNSUPPORTED_SERVICE",
15798
+ "UNAUTHORIZED",
15799
+ "MALFORMED_RESPONSE",
15800
+ "INVALID_PROOF",
15801
+ "ISSUER_MISMATCH",
15802
+ "ID_MISMATCH",
15803
+ "ROLLBACK",
15804
+ "REVOKED",
15805
+ "UNSAFE_ENDPOINT"
15806
+ ]);
15807
+ var CredentialRefreshUpdatedResultValidator = external_exports.object({
15808
+ status: external_exports.literal("updated"),
15809
+ credential: VCValidator,
15810
+ etag: external_exports.string().optional(),
15811
+ managedVersion: external_exports.number().int().positive().optional()
15812
+ });
15813
+ var CredentialRefreshUnchangedResultValidator = external_exports.object({
15814
+ status: external_exports.literal("unchanged"),
15815
+ checkedAt: external_exports.string().min(1),
15816
+ etag: external_exports.string().optional()
15817
+ });
15818
+ var CredentialRefreshUnsupportedResultValidator = external_exports.object({
15819
+ status: external_exports.literal("unsupported")
15820
+ });
15821
+ var CredentialRefreshFailedResultValidator = external_exports.object({
15822
+ status: external_exports.literal("failed"),
15823
+ code: CredentialRefreshFailureCodeValidator,
15824
+ retryable: external_exports.boolean()
15825
+ });
15826
+ var CredentialRefreshResultValidator = external_exports.discriminatedUnion("status", [
15827
+ CredentialRefreshUpdatedResultValidator,
15828
+ CredentialRefreshUnchangedResultValidator,
15829
+ CredentialRefreshUnsupportedResultValidator,
15830
+ CredentialRefreshFailedResultValidator
15831
+ ]);
15578
15832
  var LCNProfileDisplayValidator = external_exports.object({
15579
15833
  backgroundColor: external_exports.string().optional(),
15580
15834
  backgroundImage: external_exports.string().optional(),
@@ -15910,7 +16164,13 @@ var SendBoostInputValidator = external_exports.object({
15910
16164
  "Options for email/phone recipients (Universal Inbox)"
15911
16165
  ),
15912
16166
  templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
15913
- integrationId: external_exports.string().optional().describe("Integration ID for activity tracking")
16167
+ integrationId: external_exports.string().optional().describe("Integration ID for activity tracking"),
16168
+ refresh: external_exports.boolean().optional().describe(
16169
+ "Request managed credential refresh for this send. Profile/DID recipients use immediate issuance; email/phone recipients use deferred Universal Inbox signing and bind the holder at claim."
16170
+ ),
16171
+ idempotencyKey: external_exports.string().min(1).max(200).optional().describe(
16172
+ "Caller-chosen key that makes a managed refresh send (refresh: true) safe to retry as a whole: retries with the same key reuse the same boost, refresh allocation and result. Reusing a key for a different request is rejected. With signedCredential, requires prior tRPC prepareRefreshableSend; direct REST callers omit the key and retry the exact signed credential and templateUri."
16173
+ )
15914
16174
  }).refine((data) => data.templateUri || data.template || data.signedCredential, {
15915
16175
  message: "Either templateUri, template, or signedCredential must be provided.",
15916
16176
  path: ["templateUri"]
@@ -15925,8 +16185,12 @@ var SendBoostInputValidator = external_exports.object({
15925
16185
  message: "guardianEmail must differ from recipient (self-approval not allowed)",
15926
16186
  path: ["options", "guardianEmail"]
15927
16187
  }
15928
- );
16188
+ ).refine((data) => !data.idempotencyKey || data.refresh === true, {
16189
+ message: "idempotencyKey is only supported with refresh: true.",
16190
+ path: ["idempotencyKey"]
16191
+ });
15929
16192
  var SendInboxResponseValidator = external_exports.object({
16193
+ refresh: InboxCredentialRefreshReceiptValidator.optional(),
15930
16194
  issuanceId: external_exports.string(),
15931
16195
  status: external_exports.enum(["PENDING", "ISSUED", "EXPIRED", "DELIVERED", "CLAIMED"]),
15932
16196
  claimUrl: external_exports.string().url().optional().describe("Present when suppressDelivery=true"),
@@ -15941,8 +16205,34 @@ var SendBoostResponseValidator = external_exports.object({
15941
16205
  activityId: external_exports.string().describe("Links to the activity lifecycle for this issuance"),
15942
16206
  inbox: SendInboxResponseValidator.optional().describe(
15943
16207
  "Present when sent via email/phone (Universal Inbox)"
16208
+ ),
16209
+ refresh: ManagedCredentialRefreshReceiptValidator.optional().describe(
16210
+ "Present when managed refresh was requested: issuance metadata the issuer keeps to publish future updates"
15944
16211
  )
15945
16212
  });
16213
+ var PrepareRefreshableSendInputValidator = external_exports.object({
16214
+ recipient: external_exports.string(),
16215
+ templateUri: external_exports.string().optional(),
16216
+ template: SendBoostTemplateValidator.optional(),
16217
+ contractUri: external_exports.string().optional(),
16218
+ templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
16219
+ integrationId: external_exports.string().optional(),
16220
+ /** Credential ID to allocate for; generated server-side when omitted. */
16221
+ credentialId: external_exports.string().min(1).optional(),
16222
+ idempotencyKey: external_exports.string().min(1).max(200).optional()
16223
+ }).refine((data) => Boolean(data.templateUri) !== Boolean(data.template), {
16224
+ message: "Provide exactly one of templateUri or template."
16225
+ });
16226
+ var PrepareRefreshableSendResultValidator = external_exports.object({
16227
+ boostUri: external_exports.string(),
16228
+ credentialId: external_exports.string(),
16229
+ refreshId: external_exports.string(),
16230
+ refreshService: ManagedCredentialRefreshServiceValidator,
16231
+ /** The DID to use as credentialSubject.id (recipient DID, or the profile's did:web). */
16232
+ holderDid: external_exports.string(),
16233
+ /** Present when this idempotencyKey already completed: return it without signing. */
16234
+ completed: SendBoostResponseValidator.optional()
16235
+ });
15946
16236
  var SendInputValidator = external_exports.discriminatedUnion("type", [SendBoostInputValidator]);
15947
16237
  var SendResponseValidator = external_exports.discriminatedUnion("type", [SendBoostResponseValidator]);
15948
16238
  var ConsentFlowTermsStatusValidator = external_exports.enum(["live", "stale", "withdrawn"]);
@@ -16018,15 +16308,6 @@ var ConsentFlowContractDataValidator = external_exports.object({
16018
16308
  var PaginatedConsentFlowDataValidator = PaginationResponseValidator.extend({
16019
16309
  records: ConsentFlowContractDataValidator.array()
16020
16310
  });
16021
- var ConsentFlowContractDataForDidValidator = external_exports.object({
16022
- credentials: external_exports.object({ category: external_exports.string(), uri: external_exports.string() }).array(),
16023
- personal: external_exports.record(external_exports.string(), external_exports.string()).default({}),
16024
- date: external_exports.string(),
16025
- contractUri: external_exports.string()
16026
- });
16027
- var PaginatedConsentFlowDataForDidValidator = PaginationResponseValidator.extend({
16028
- records: ConsentFlowContractDataForDidValidator.array()
16029
- });
16030
16311
  var ConsentFlowTermValidator = external_exports.object({
16031
16312
  sharing: external_exports.boolean().optional(),
16032
16313
  shared: external_exports.string().array().optional(),
@@ -16060,6 +16341,34 @@ var PaginatedConsentFlowTermsValidator = PaginationResponseValidator.extend({
16060
16341
  status: ConsentFlowTermsStatusValidator
16061
16342
  }).array()
16062
16343
  });
16344
+ var ConsentFlowGuardianApprovalValidator = external_exports.object({
16345
+ guardianProfileId: external_exports.string(),
16346
+ guardianDid: external_exports.string(),
16347
+ approvedAt: external_exports.string().datetime(),
16348
+ contractUpdatedAt: external_exports.string()
16349
+ });
16350
+ var ConsentFlowContractDataForDidValidator = external_exports.object({
16351
+ credentials: external_exports.object({ category: external_exports.string(), uri: external_exports.string() }).array(),
16352
+ personal: external_exports.record(external_exports.string(), external_exports.string()).default({}),
16353
+ date: external_exports.string(),
16354
+ createdAt: external_exports.string().optional(),
16355
+ contractUpdatedAt: external_exports.string(),
16356
+ contractExpiresAt: external_exports.string().optional(),
16357
+ reasonForAccessing: external_exports.string().optional(),
16358
+ guardian: external_exports.object({
16359
+ required: external_exports.boolean(),
16360
+ approved: external_exports.boolean(),
16361
+ approval: ConsentFlowGuardianApprovalValidator.optional()
16362
+ }),
16363
+ contractUri: external_exports.string(),
16364
+ termsUri: external_exports.string(),
16365
+ status: ConsentFlowTermsStatusValidator,
16366
+ expiresAt: external_exports.string().optional(),
16367
+ terms: ConsentFlowTermsValidator
16368
+ });
16369
+ var PaginatedConsentFlowDataForDidValidator = PaginationResponseValidator.extend({
16370
+ records: ConsentFlowContractDataForDidValidator.array()
16371
+ });
16063
16372
  var ConsentFlowContractQueryValidator = external_exports.object({
16064
16373
  read: external_exports.object({
16065
16374
  anonymize: external_exports.boolean().optional(),
@@ -16120,6 +16429,7 @@ var ConsentFlowTransactionValidator = external_exports.object({
16120
16429
  expiresAt: external_exports.string().optional(),
16121
16430
  oneTime: external_exports.boolean().optional(),
16122
16431
  terms: ConsentFlowTermsValidator.optional(),
16432
+ guardianApproval: ConsentFlowGuardianApprovalValidator.optional(),
16123
16433
  id: external_exports.string(),
16124
16434
  action: ConsentFlowTransactionActionValidator,
16125
16435
  date: external_exports.string(),
@@ -16241,6 +16551,7 @@ var LCNNotificationValidator = external_exports.object({
16241
16551
  webhookUrl: external_exports.string().optional()
16242
16552
  });
16243
16553
  var AUTH_GRANT_AUDIENCE_DOMAIN_PREFIX = "auth-grant:";
16554
+ var ACT_AS_HEADER = "X-LearnCard-Act-As";
16244
16555
  var AuthGrantValidator = external_exports.object({
16245
16556
  id: external_exports.string(),
16246
16557
  name: external_exports.string(),
@@ -16253,6 +16564,7 @@ var AuthGrantValidator = external_exports.object({
16253
16564
  }, "error")
16254
16565
  }),
16255
16566
  scope: external_exports.string(),
16567
+ actAs: external_exports.string().optional(),
16256
16568
  createdAt: external_exports.iso.datetime({ error: "createdAt must be a valid ISO 8601 datetime string" }),
16257
16569
  expiresAt: external_exports.iso.datetime({ error: "expiresAt must be a valid ISO 8601 datetime string" }).nullish().optional()
16258
16570
  });
@@ -16324,6 +16636,8 @@ var CreateContactMethodSessionResponseValidator = external_exports.object({
16324
16636
  sessionJwt: external_exports.string()
16325
16637
  });
16326
16638
  var InboxCredentialValidator = external_exports.object({
16639
+ refresh: InboxCredentialRefreshReceiptValidator.optional(),
16640
+ refreshId: external_exports.string().optional(),
16327
16641
  id: external_exports.string(),
16328
16642
  credential: external_exports.string().optional(),
16329
16643
  isSigned: external_exports.boolean(),
@@ -16378,12 +16692,19 @@ var IssueInboxCredentialValidator = external_exports.object({
16378
16692
  templateUri: external_exports.string().optional().describe(
16379
16693
  "URI of a boost template to use for issuance. The boost credential will be resolved and used. Mutually exclusive with credential field."
16380
16694
  ),
16695
+ refresh: external_exports.boolean().optional().describe(
16696
+ "Allocate managed refresh before signing. Requires unsigned content and a registered signing authority; binds the holder on claim."
16697
+ ),
16698
+ idempotencyKey: external_exports.string().min(1).max(200).optional(),
16381
16699
  // === OPTIONAL FEATURES ===
16382
16700
  // Add major, distinct features at the top level.
16383
16701
  //consentRequest: ConsentRequestValidator.optional(),
16384
16702
  // === PROCESS CONFIGURATION (Optional) ===
16385
16703
  // HOW should this issuance be handled?
16386
16704
  configuration: external_exports.object({
16705
+ guardianEmail: external_exports.string().email().optional().describe(
16706
+ "Require approval from this guardian before the recipient can claim. Must differ from the recipient email."
16707
+ ),
16387
16708
  signingAuthority: IssueInboxSigningAuthorityValidator.optional().describe(
16388
16709
  "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."
16389
16710
  ),
@@ -16437,25 +16758,138 @@ var IssueInboxCredentialValidator = external_exports.object({
16437
16758
  }).optional().describe(
16438
16759
  "Configuration for the credential issuance. If not provided, the default configuration will be used."
16439
16760
  )
16761
+ }).refine((data) => !data.idempotencyKey || data.refresh === true, {
16762
+ message: "idempotencyKey requires refresh: true."
16440
16763
  }).refine((data) => data.credential || data.templateUri, {
16441
16764
  message: "Either credential or templateUri must be provided.",
16442
16765
  path: ["credential"]
16443
- });
16766
+ }).refine(
16767
+ (data) => !data.configuration?.guardianEmail || data.recipient.type !== "email" || data.configuration.guardianEmail.toLowerCase() !== data.recipient.value.toLowerCase(),
16768
+ {
16769
+ message: "guardianEmail must differ from recipient (self-approval not allowed)",
16770
+ path: ["configuration", "guardianEmail"]
16771
+ }
16772
+ );
16444
16773
  var IssueInboxCredentialResponseValidator = external_exports.object({
16774
+ refresh: InboxCredentialRefreshReceiptValidator.optional(),
16445
16775
  issuanceId: external_exports.string(),
16446
16776
  status: LCNInboxStatusEnumValidator,
16447
16777
  recipient: ContactMethodQueryValidator,
16448
16778
  claimUrl: external_exports.string().url().optional(),
16449
16779
  recipientDid: external_exports.string().optional()
16450
16780
  });
16451
- var CredentialNameRefValidator = external_exports.object({ name: external_exports.string() }).passthrough();
16452
- var ClaimInboxCredentialValidator = external_exports.object({
16453
- credential: VCValidator.or(VPValidator).or(UnsignedVCValidator).or(CredentialNameRefValidator).describe("The credential to issue, or a { name } reference to resolve a boost template."),
16454
- configuration: external_exports.object({
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
- ),
16781
+ var InboxBatchConfigurationValidator = IssueInboxCredentialValidator.shape.configuration.unwrap().extend({
16782
+ refresh: IssueInboxCredentialValidator.shape.refresh.describe(
16783
+ "Enable managed refresh by default. An item configuration.refresh overrides this value, including false."
16784
+ ),
16785
+ delivery: IssueInboxCredentialValidator.shape.configuration.unwrap().shape.delivery.unwrap().extend({ suppress: external_exports.boolean().optional() }).optional()
16786
+ });
16787
+ var InboxBatchItemConfigurationValidator = InboxBatchConfigurationValidator.extend({
16788
+ guardianEmail: InboxBatchConfigurationValidator.shape.guardianEmail.nullable().describe(
16789
+ "Require guardian approval, or set null to clear a batch-level guardianEmail for this item."
16790
+ )
16791
+ });
16792
+ var IssueInboxCredentialBatchItemValidator = external_exports.object({
16793
+ ...IssueInboxCredentialValidator.shape,
16794
+ configuration: InboxBatchItemConfigurationValidator.optional(),
16795
+ idempotencyKey: external_exports.string().max(256).optional()
16796
+ }).refine((data) => data.credential || data.templateUri, {
16797
+ message: "Either credential or templateUri must be provided.",
16798
+ path: ["credential"]
16799
+ }).describe(
16800
+ "One issuance: provide credential or templateUri. Invalid input is rejected at submission with its item index."
16801
+ );
16802
+ var IssueInboxCredentialBatchValidator = external_exports.object({
16803
+ requestId: external_exports.string().min(1).max(256).optional(),
16804
+ items: external_exports.array(IssueInboxCredentialBatchItemValidator).min(1).max(100),
16805
+ configuration: InboxBatchConfigurationValidator.optional()
16806
+ }).superRefine((batch, ctx) => {
16807
+ batch.items.forEach((item, index) => {
16808
+ const itemGuardian = item.configuration?.guardianEmail;
16809
+ const guardian = itemGuardian === null ? void 0 : itemGuardian ?? batch.configuration?.guardianEmail;
16810
+ if (guardian && item.recipient.type === "email" && guardian.toLowerCase() === item.recipient.value.toLowerCase()) {
16811
+ ctx.addIssue({
16812
+ code: "custom",
16813
+ path: ["items", index, "configuration", "guardianEmail"],
16814
+ message: "guardianEmail must differ from recipient (self-approval not allowed)"
16815
+ });
16816
+ }
16817
+ });
16818
+ });
16819
+ var InboxBatchErrorReasonValidator = external_exports.enum([
16820
+ "DUPLICATE_KEY",
16821
+ "IDEMPOTENCY_MISMATCH",
16822
+ "IN_PROGRESS",
16823
+ "UNCONFIRMED"
16824
+ ]);
16825
+ var IssueInboxCredentialBatchItemResultValidator = external_exports.discriminatedUnion("success", [
16826
+ IssueInboxCredentialResponseValidator.extend({
16827
+ success: external_exports.literal(true),
16828
+ index: external_exports.number().int().nonnegative(),
16829
+ deduplicated: external_exports.boolean().optional(),
16830
+ guardianStatus: GuardianStatusValidator.optional(),
16831
+ idempotencyKey: external_exports.string().optional()
16832
+ }),
16833
+ external_exports.object({
16834
+ success: external_exports.literal(false),
16835
+ index: external_exports.number().int().nonnegative(),
16836
+ idempotencyKey: external_exports.string().optional(),
16837
+ recipient: ContactMethodQueryValidator.optional(),
16838
+ error: external_exports.object({
16839
+ code: external_exports.string(),
16840
+ message: external_exports.string(),
16841
+ reason: InboxBatchErrorReasonValidator.optional()
16842
+ }),
16843
+ issuanceId: external_exports.string().optional().describe(
16844
+ "Present when issuance completed but replay storage could not be confirmed. Reconcile this issuance; do not issue again with a new key."
16845
+ ),
16846
+ claimUrl: external_exports.string().url().optional().describe(
16847
+ "Claim URL of the completed issuance, if available, when replay storage could not be confirmed."
16848
+ )
16849
+ })
16850
+ ]);
16851
+ var IssueInboxCredentialBatchResponseValidator = external_exports.object({
16852
+ results: external_exports.array(IssueInboxCredentialBatchItemResultValidator),
16853
+ summary: external_exports.object({
16854
+ total: external_exports.number(),
16855
+ succeeded: external_exports.number(),
16856
+ failed: external_exports.number(),
16857
+ deduplicated: external_exports.number()
16858
+ })
16859
+ });
16860
+ var InboxBatchReceiptValidator = external_exports.object({
16861
+ batchId: external_exports.string(),
16862
+ status: external_exports.enum(["QUEUED", "PROCESSING", "COMPLETED", "NEEDS_RECONCILIATION"]),
16863
+ createdAt: external_exports.string()
16864
+ });
16865
+ var InboxBatchStatusValidator = external_exports.object({
16866
+ batchId: external_exports.string(),
16867
+ createdAt: external_exports.string(),
16868
+ done: external_exports.boolean().describe(
16869
+ "True when no queued or processing items remain, including unconfirmed outcomes."
16870
+ ),
16871
+ status: external_exports.enum(["QUEUED", "PROCESSING", "COMPLETED", "NEEDS_RECONCILIATION"]),
16872
+ items: external_exports.array(
16873
+ external_exports.object({
16874
+ index: external_exports.number().int().nonnegative(),
16875
+ state: external_exports.enum(["QUEUED", "PROCESSING", "COMPLETED", "NEEDS_RECONCILIATION"]),
16876
+ result: IssueInboxCredentialBatchItemResultValidator.optional()
16877
+ })
16878
+ ),
16879
+ summary: IssueInboxCredentialBatchResponseValidator.shape.summary.extend({
16880
+ completed: external_exports.number(),
16881
+ pending: external_exports.number(),
16882
+ unconfirmed: external_exports.number()
16883
+ })
16884
+ });
16885
+ var CredentialNameRefValidator = external_exports.object({ name: external_exports.string() }).passthrough();
16886
+ var ClaimInboxCredentialValidator = external_exports.object({
16887
+ credential: VCValidator.or(VPValidator).or(UnsignedVCValidator).or(CredentialNameRefValidator).describe("The credential to issue, or a { name } reference to resolve a boost template."),
16888
+ configuration: external_exports.object({
16889
+ publishableKey: external_exports.string(),
16890
+ expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
16891
+ "Inbox claim window in days. Defaults to 720; use a shorter window for sensitive records."
16892
+ ),
16459
16893
  signingAuthorityName: external_exports.string().optional(),
16460
16894
  listingId: external_exports.string().optional(),
16461
16895
  listingSlug: external_exports.string().optional()
@@ -16933,6 +17367,7 @@ var CredentialActivityValidator = external_exports.object({
16933
17367
  eventType: CredentialActivityEventTypeValidator,
16934
17368
  timestamp: external_exports.string(),
16935
17369
  actorProfileId: external_exports.string().optional(),
17370
+ onBehalfOf: external_exports.string().optional(),
16936
17371
  recipientType: CredentialActivityRecipientTypeValidator,
16937
17372
  recipientIdentifier: external_exports.string(),
16938
17373
  boostUri: external_exports.string().optional(),
@@ -17082,191 +17517,6 @@ var inAppMessagesFlagValidator = external_exports.object({
17082
17517
  version: external_exports.number().default(1),
17083
17518
  messages: external_exports.array(inAppMessageValidator).default([])
17084
17519
  }).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
- ]);
17270
17520
 
17271
17521
  // src/plugin.ts
17272
17522
  var import_helpers = require("@learncard/helpers");
@@ -17884,27 +18134,40 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
17884
18134
  await appendNetworkCredentialStatus(client, credential, statusPurposes)
17885
18135
  );
17886
18136
  }, "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
- );
18137
+ var injectManagedRefreshService = /* @__PURE__ */ __name((credential, refreshService) => (0, import_helpers.injectManagedRefreshService)(credential, refreshService), "injectManagedRefreshService");
18138
+ var getCredentialSubjectIds = /* @__PURE__ */ __name((vc) => {
18139
+ const subject = vc.credentialSubject;
18140
+ const subjects = Array.isArray(subject) ? subject : subject ? [subject] : [];
18141
+ return subjects.flatMap((entry) => {
18142
+ const id = entry?.id;
18143
+ return typeof id === "string" && id.length > 0 ? [id] : [];
18144
+ });
18145
+ }, "getCredentialSubjectIds");
18146
+ var buildManagedRefreshReceipt = /* @__PURE__ */ __name((vc, allocation, credentialId, fallbackHolderDid, fallbackIssuerDid) => {
18147
+ const issuerDid = (0, import_helpers.getCredentialIssuerId)(vc) ?? fallbackIssuerDid;
18148
+ const holderDid = getCredentialSubjectIds(vc)[0] ?? fallbackHolderDid;
18149
+ const rawStatus = vc.credentialStatus;
18150
+ const hasStatus = rawStatus !== void 0 && rawStatus !== null && !(Array.isArray(rawStatus) && rawStatus.length === 0);
17902
18151
  return {
17903
- ...credential,
17904
- "@context": hasMapping ? contextList : [...contextList, MANAGED_REFRESH_SERVICE_CONTEXT],
17905
- refreshService
17906
- };
17907
- }, "injectManagedRefreshService");
18152
+ refreshId: allocation.refreshId,
18153
+ refreshService: allocation.refreshService,
18154
+ credentialId: typeof vc.id === "string" && vc.id.length > 0 ? vc.id : credentialId,
18155
+ issuerDid,
18156
+ holderDid,
18157
+ ...hasStatus ? {
18158
+ credentialStatus: rawStatus
18159
+ } : {}
18160
+ };
18161
+ }, "buildManagedRefreshReceipt");
18162
+ var ACT_AS_TARGET_NOT_FOUND_MESSAGE = "Act-as target profile not found";
18163
+ var isActAsDenial = /* @__PURE__ */ __name((error51) => {
18164
+ const code = error51?.data?.code;
18165
+ if (code === "FORBIDDEN" || code === "BAD_REQUEST") return true;
18166
+ if (code === "NOT_FOUND") {
18167
+ return error51?.message === ACT_AS_TARGET_NOT_FOUND_MESSAGE;
18168
+ }
18169
+ return false;
18170
+ }, "isActAsDenial");
17908
18171
  async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
17909
18172
  const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
17910
18173
  const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
@@ -17912,8 +18175,10 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
17912
18175
  guardianApprovalGetter,
17913
18176
  extraHeaders,
17914
18177
  trustedFederationHosts,
17915
- allowLocalhostFederation
18178
+ allowLocalhostFederation,
18179
+ actAs
17916
18180
  } = resolvedOptions;
18181
+ const mergedExtraHeaders = actAs ? { ...extraHeaders, [ACT_AS_HEADER]: actAs } : extraHeaders;
17917
18182
  const serviceUrl = new URL(url2);
17918
18183
  const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
17919
18184
  const federationConfig = {
@@ -17931,7 +18196,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
17931
18196
  learnCard?.debug?.("LCN: no local DID available at init; will fetch from profile");
17932
18197
  }
17933
18198
  learnCard?.debug?.("Adding LearnCardNetwork Plugin");
17934
- const client = apiToken ? await (0, import_network_brain_client.getApiTokenClient)(url2, apiToken, guardianApprovalGetter, extraHeaders) : await (0, import_network_brain_client.getClient)(
18199
+ const client = apiToken ? await (0, import_network_brain_client.getApiTokenClient)(url2, apiToken, guardianApprovalGetter, mergedExtraHeaders) : await (0, import_network_brain_client.getClient)(
17935
18200
  url2,
17936
18201
  async (challenge) => {
17937
18202
  const jwt2 = await learnCard.invoke.getDidAuthVp({
@@ -17942,7 +18207,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
17942
18207
  return jwt2;
17943
18208
  },
17944
18209
  guardianApprovalGetter,
17945
- extraHeaders
18210
+ mergedExtraHeaders
17946
18211
  );
17947
18212
  let userData;
17948
18213
  learnCard?.debug?.("LCN: initial getProfile query starting", { apiToken: !!apiToken });
@@ -18145,6 +18410,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18145
18410
  getManagedProfiles: /* @__PURE__ */ __name(async (_learnCard, options2 = {}) => {
18146
18411
  return client.profileManager.getManagedProfiles.query(options2);
18147
18412
  }, "getManagedProfiles"),
18413
+ actAs: /* @__PURE__ */ __name(async (_learnCard, profileId) => {
18414
+ const actingOptions = {
18415
+ ...resolvedOptions,
18416
+ actAs: profileId
18417
+ };
18418
+ const actingPlugin = apiToken ? await getLearnCardNetworkPlugin(_learnCard, url2, apiToken, actingOptions) : await getLearnCardNetworkPlugin(_learnCard, url2, actingOptions);
18419
+ try {
18420
+ await actingPlugin.methods.getLCNClient(_learnCard).profile.getProfile.query();
18421
+ } catch (error51) {
18422
+ if (isActAsDenial(error51)) {
18423
+ const message = error51 instanceof Error ? error51.message : "Act-as request was denied.";
18424
+ throw new Error(message, { cause: error51 });
18425
+ }
18426
+ _learnCard.debug?.("LCN actAs: getProfile failed (non-fatal)", error51);
18427
+ }
18428
+ return _learnCard.addPlugin(actingPlugin);
18429
+ }, "actAs"),
18148
18430
  claimPendingGuardianLinks: /* @__PURE__ */ __name(async () => {
18149
18431
  await ensureUser();
18150
18432
  return client.inbox.claimPendingGuardianLinks.mutate({});
@@ -18754,15 +19036,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18754
19036
  boost = options2.overideFn(boost);
18755
19037
  }
18756
19038
  const enableRefresh = typeof options2 === "object" && options2.enableRefresh === true;
18757
- let managedRefreshId;
19039
+ let refreshAllocation;
18758
19040
  if (enableRefresh) {
18759
19041
  if (!boost.id) boost.id = `urn:uuid:${crypto.randomUUID()}`;
18760
- const allocation = await client.credentialRefresh.allocateCredentialRefresh.mutate({
19042
+ refreshAllocation = await client.credentialRefresh.allocateCredentialRefresh.mutate({
18761
19043
  holder: { profileId, did: targetProfile.did },
18762
19044
  credentialId: boost.id
18763
19045
  });
18764
- managedRefreshId = allocation.refreshId;
18765
- boost = injectManagedRefreshService(boost, allocation.refreshService);
19046
+ boost = injectManagedRefreshService(boost, refreshAllocation.refreshService);
18766
19047
  }
18767
19048
  const statusPurposes = typeof options2 === "object" ? options2.statusPurposes : void 0;
18768
19049
  const vc = await issueCredentialWithNetworkStatus(
@@ -18771,13 +19052,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18771
19052
  boost,
18772
19053
  statusPurposes
18773
19054
  );
18774
- if (managedRefreshId) {
18775
- return client.credentialRefresh.sendRefreshableCredential.mutate({
18776
- refreshId: managedRefreshId,
19055
+ if (refreshAllocation) {
19056
+ const credentialUri = await client.credentialRefresh.sendRefreshableCredential.mutate({
19057
+ refreshId: refreshAllocation.refreshId,
18777
19058
  credential: vc,
18778
19059
  boostUri,
18779
19060
  ...typeof options2 === "object" && options2.skipNotification ? { skipNotification: true } : {}
18780
19061
  });
19062
+ return {
19063
+ credentialUri,
19064
+ refresh: buildManagedRefreshReceipt(
19065
+ vc,
19066
+ refreshAllocation,
19067
+ boost.id ?? "",
19068
+ targetProfile.did,
19069
+ _learnCard.id.did()
19070
+ )
19071
+ };
18781
19072
  }
18782
19073
  if (typeof options2 === "object" && !options2.encrypt || !options2) {
18783
19074
  return client.boost.sendBoost.mutate({
@@ -18843,6 +19134,94 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
18843
19134
  }, "claimBoostWithLink"),
18844
19135
  send: /* @__PURE__ */ __name(async (_learnCard, input) => {
18845
19136
  await ensureUser();
19137
+ if (input.type === "boost" && input.refresh === true) {
19138
+ const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input.recipient);
19139
+ const isPhone = /^\+?[\d\s-]{10,}$/.test(input.recipient.replace(/[\s-]/g, ""));
19140
+ if (isEmail || isPhone) return client.boost.send.mutate(input);
19141
+ const canIssueLocally = "issueCredential" in _learnCard.invoke;
19142
+ if (canIssueLocally && !input.signedCredential && (input.templateUri || input.template)) {
19143
+ let boost;
19144
+ if (input.templateUri) {
19145
+ const result = await getBoostTemplateForIssuance(
19146
+ _learnCard,
19147
+ input.templateUri
19148
+ );
19149
+ const data = await UnsignedVCValidator.spa(result);
19150
+ if (!data.success)
19151
+ throw new Error("Did not get a valid boost from URI");
19152
+ boost = data.data;
19153
+ } else {
19154
+ boost = JSON.parse(
19155
+ JSON.stringify(input.template.credential)
19156
+ );
19157
+ }
19158
+ const prepared = await client.boost.prepareRefreshableSend.mutate({
19159
+ recipient: input.recipient,
19160
+ ...input.templateUri ? { templateUri: input.templateUri } : { template: input.template },
19161
+ ...input.contractUri ? { contractUri: input.contractUri } : {},
19162
+ ...input.templateData ? { templateData: input.templateData } : {},
19163
+ ...input.integrationId ? { integrationId: input.integrationId } : {},
19164
+ ...boost.id ? { credentialId: boost.id } : {},
19165
+ ...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}
19166
+ });
19167
+ if (prepared.completed) return prepared.completed;
19168
+ const boostString = JSON.stringify(boost);
19169
+ const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
19170
+ if (input.templateData && Object.keys(input.templateData).length > 0) {
19171
+ try {
19172
+ const rendered = renderTemplateJson(
19173
+ boostString,
19174
+ input.templateData
19175
+ );
19176
+ boost = JSON.parse(rendered);
19177
+ boost = appendTemplateEvidence(
19178
+ boost,
19179
+ input.templateData,
19180
+ allowAutoAppendEvidence
19181
+ );
19182
+ } catch (error51) {
19183
+ throw new Error(
19184
+ `Failed to apply template data: ${error51 instanceof Error ? error51.message : "Unknown error"}`,
19185
+ { cause: error51 }
19186
+ );
19187
+ }
19188
+ }
19189
+ if ((0, import_helpers.isVC2Format)(boost)) {
19190
+ boost.validFrom = (/* @__PURE__ */ new Date()).toISOString();
19191
+ } else {
19192
+ boost.issuanceDate = (/* @__PURE__ */ new Date()).toISOString();
19193
+ }
19194
+ boost.issuer = _learnCard.id.did();
19195
+ if (Array.isArray(boost.credentialSubject)) {
19196
+ boost.credentialSubject = boost.credentialSubject.map((subject) => ({
19197
+ ...subject,
19198
+ id: prepared.holderDid
19199
+ }));
19200
+ } else {
19201
+ boost.credentialSubject = {
19202
+ ...boost.credentialSubject,
19203
+ id: prepared.holderDid
19204
+ };
19205
+ }
19206
+ boost.id = prepared.credentialId;
19207
+ if (boost.type?.includes("BoostCredential"))
19208
+ boost.boostId = prepared.boostUri;
19209
+ boost = injectManagedRefreshService(boost, prepared.refreshService);
19210
+ const signedCredential = await issueCredentialWithNetworkStatus(
19211
+ _learnCard,
19212
+ client,
19213
+ boost
19214
+ );
19215
+ return client.boost.send.mutate({
19216
+ ...input,
19217
+ template: void 0,
19218
+ templateUri: prepared.boostUri,
19219
+ signedCredential,
19220
+ refresh: true
19221
+ });
19222
+ }
19223
+ return client.boost.send.mutate(input);
19224
+ }
18846
19225
  if (input.type === "boost") {
18847
19226
  const recipient = input.recipient;
18848
19227
  const isDid = recipient.startsWith("did:");
@@ -19249,6 +19628,37 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
19249
19628
  await ensureUser();
19250
19629
  return client.inbox.issue.mutate(issueInboxCredential);
19251
19630
  }, "sendCredentialViaInbox"),
19631
+ sendCredentialsViaInbox: /* @__PURE__ */ __name(async (_learnCard, batch) => {
19632
+ await ensureUser();
19633
+ return client.inbox.issueBatch.mutate(batch);
19634
+ }, "sendCredentialsViaInbox"),
19635
+ sendCredentialBatchViaInbox: /* @__PURE__ */ __name(async (_learnCard, batch) => {
19636
+ await ensureUser();
19637
+ return client.inbox.issueBatch.mutate(batch);
19638
+ }, "sendCredentialBatchViaInbox"),
19639
+ waitForInboxCredentialBatch: /* @__PURE__ */ __name(async (_learnCard, batchId, options2) => {
19640
+ await ensureUser();
19641
+ return waitForInboxCredentialBatch(
19642
+ (signal) => client.inbox.getBatch.query({ batchId }, { signal }),
19643
+ options2
19644
+ );
19645
+ }, "waitForInboxCredentialBatch"),
19646
+ sendCredentialsViaInboxAndWait: /* @__PURE__ */ __name(async (_learnCard, batch, options2) => {
19647
+ await ensureUser();
19648
+ if (options2?.signal?.aborted) throw options2.signal.reason;
19649
+ const receipt = await client.inbox.issueBatch.mutate(batch, {
19650
+ signal: options2?.signal
19651
+ });
19652
+ await options2?.onSubmitted?.(receipt);
19653
+ return waitForInboxCredentialBatch(
19654
+ (signal) => client.inbox.getBatch.query({ batchId: receipt.batchId }, { signal }),
19655
+ options2
19656
+ );
19657
+ }, "sendCredentialsViaInboxAndWait"),
19658
+ getInboxCredentialBatch: /* @__PURE__ */ __name(async (_learnCard, batchId) => {
19659
+ await ensureUser();
19660
+ return client.inbox.getBatch.query({ batchId });
19661
+ }, "getInboxCredentialBatch"),
19252
19662
  getMySentInboxCredentials: /* @__PURE__ */ __name(async (_learnCard, options2) => {
19253
19663
  await ensureUser();
19254
19664
  return client.inbox.getMyIssuedCredentials.query(options2);
@@ -19711,6 +20121,13 @@ var getVerifyBoostPlugin = /* @__PURE__ */ __name(async (learnCard, trustedBoost
19711
20121
  if (!issuerDID) return;
19712
20122
  return boostRegistry.find((o) => o.did === issuerDID);
19713
20123
  }, "getTrustedBoostVerifier");
20124
+ const getTrustedBoostNetwork = /* @__PURE__ */ __name((boostId) => {
20125
+ if (typeof boostId !== "string") return;
20126
+ const match = /^lc:network:([^?#\s]+)\/(?:trpc:)?boost:([^/?#\s]+)$/.exec(boostId);
20127
+ if (!match) return;
20128
+ const networkDid = `did:web:${match[1].replace(/\//g, ":")}`;
20129
+ return boostRegistry.find((entry) => entry.did === networkDid);
20130
+ }, "getTrustedBoostNetwork");
19714
20131
  return {
19715
20132
  name: "VerifyBoost",
19716
20133
  displayName: "Verify Boost Extension",
@@ -19721,18 +20138,20 @@ var getVerifyBoostPlugin = /* @__PURE__ */ __name(async (learnCard, trustedBoost
19721
20138
  credential,
19722
20139
  options
19723
20140
  );
20141
+ const hasOuterVerificationErrors = Boolean(verificationCheck.errors?.length);
19724
20142
  const boostCredential = credential?.boostCredential;
19725
20143
  try {
19726
- if (boostCredential) {
19727
- const verifyBoostCredential = await learnCard.invoke.verifyCredential(boostCredential);
19728
- const boostCredentialErrors = verifyBoostCredential.errors ?? [];
19729
- if (verifyBoostCredential.status?.length) {
20144
+ const boostId = boostCredential?.boostId ?? credential?.boostId;
20145
+ if (boostCredential || credential?.boostId || credential?.type?.includes("BoostCredential")) {
20146
+ const verifyBoostCredential = boostCredential ? await learnCard.invoke.verifyCredential(boostCredential) : verificationCheck;
20147
+ const boostCredentialErrors = boostCredential ? verifyBoostCredential.errors ?? [] : [];
20148
+ if (boostCredential && verifyBoostCredential.status?.length) {
19730
20149
  verificationCheck.status = [
19731
20150
  ...verificationCheck.status ?? [],
19732
20151
  ...verifyBoostCredential.status
19733
20152
  ];
19734
20153
  }
19735
- if (!boostCredential?.boostId && !credential?.boostId) {
20154
+ if (!boostId) {
19736
20155
  verificationCheck.warnings.push(
19737
20156
  "Boost Authenticity could not be verified: Boost ID metadata is missing."
19738
20157
  );
@@ -19750,21 +20169,26 @@ var getVerifyBoostPlugin = /* @__PURE__ */ __name(async (learnCard, trustedBoost
19750
20169
  ...verificationCheck.errors || [],
19751
20170
  "Boost Credential could not be verified."
19752
20171
  ];
19753
- } else if (boostCredential?.boostId !== credential?.boostId) {
20172
+ } else if (hasOuterVerificationErrors) {
20173
+ verificationCheck.warnings.push(
20174
+ "Boost Authenticity could not be verified: Credential verification failed."
20175
+ );
20176
+ } else if (!boostId) {
20177
+ } else if (boostCredential && boostCredential.boostId !== credential.boostId) {
19754
20178
  verificationCheck.errors.push(
19755
20179
  "Boost Authenticity could not be verified: Boost ID metadata is mismatched."
19756
20180
  );
19757
20181
  } else {
19758
- const trustedBoostIssuer = getTrustedBoostVerifier(credential?.issuer);
20182
+ const trustedBoostIssuer = boostCredential ? getTrustedBoostVerifier(credential?.issuer) : getTrustedBoostNetwork(boostId);
19759
20183
  if (trustedBoostIssuer) {
19760
20184
  verificationCheck.checks.push(
19761
20185
  `Boost is Authentic. Verified by ${trustedBoostIssuer.id}.`
19762
20186
  );
19763
20187
  } else {
19764
20188
  verificationCheck.warnings.push(
19765
- `Boost Authenticity could not be verified. Issuer is outside of trust network: ${getIssuerDID(
20189
+ boostCredential ? `Boost Authenticity could not be verified. Issuer is outside of trust network: ${getIssuerDID(
19766
20190
  credential?.issuer
19767
- )}`
20191
+ )}` : `Boost Authenticity could not be verified. Boost ID does not identify a trusted network: ${boostId}`
19768
20192
  );
19769
20193
  }
19770
20194
  }