@learncard/network-plugin 3.2.3 → 4.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.
@@ -53,7 +53,7 @@ var waitForInboxCredentialBatch = /* @__PURE__ */ __name(async (read, options =
53
53
  }, "waitForInboxCredentialBatch");
54
54
 
55
55
  // src/plugin.ts
56
- import { getClient, getApiTokenClient } from "@learncard/network-brain-client";
56
+ import { getClient, getApiTokenClient, getAnonymousClient } from "@learncard/network-brain-client";
57
57
 
58
58
  // ../../../node_modules/zod/v4/classic/external.js
59
59
  var external_exports = {};
@@ -21030,12 +21030,46 @@ var StringQuery = external_exports.union([
21030
21030
  $or: BaseStringQuery.array()
21031
21031
  })
21032
21032
  ]);
21033
+ var BITSTRING_STATUS_PURPOSES = ["revocation", "suspension"];
21034
+ var BitstringStatusPurposeValidator = external_exports.enum(BITSTRING_STATUS_PURPOSES);
21035
+ var BitstringStatusListEntryValidator = external_exports.object({
21036
+ id: external_exports.string().optional(),
21037
+ type: external_exports.literal("BitstringStatusListEntry"),
21038
+ statusPurpose: BitstringStatusPurposeValidator,
21039
+ statusListIndex: external_exports.string().or(external_exports.number().int().nonnegative()),
21040
+ statusListCredential: external_exports.string()
21041
+ });
21042
+ var AllocatedBitstringStatusListEntryValidator = BitstringStatusListEntryValidator.extend({
21043
+ id: external_exports.string()
21044
+ });
21045
+ var BitstringStatusListCredentialSubjectValidator = external_exports.object({
21046
+ id: external_exports.string().optional(),
21047
+ type: external_exports.literal("BitstringStatusList"),
21048
+ statusPurpose: BitstringStatusPurposeValidator,
21049
+ encodedList: external_exports.string()
21050
+ });
21051
+ var AllocateCredentialStatusInputValidator = external_exports.object({
21052
+ statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
21053
+ listSize: external_exports.number().int().positive().optional()
21054
+ }).default({});
21055
+ var AttachCredentialRefreshStatusEntriesInputValidator = external_exports.object({
21056
+ refreshId: external_exports.string().min(1),
21057
+ credentialStatus: CredentialStatusValidator.or(CredentialStatusValidator.array()).nullable()
21058
+ });
21033
21059
  var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
21034
21060
  var ManagedCredentialRefreshServiceValidator = external_exports.object({
21035
21061
  id: external_exports.string().min(1),
21036
21062
  type: external_exports.literal("LearnCardCredentialRefresh2026"),
21037
21063
  authorization: LearnCardRefreshAuthorizationValidator.optional()
21038
21064
  }).catchall(external_exports.any());
21065
+ var ManagedCredentialRefreshBindingValidator = ManagedCredentialRefreshServiceValidator.or(
21066
+ RefreshServiceValidator.array().refine(
21067
+ (services) => services.some(
21068
+ (service) => ManagedCredentialRefreshServiceValidator.safeParse(service).success
21069
+ ),
21070
+ "A managed refresh service is required"
21071
+ )
21072
+ );
21039
21073
  var StandardCredentialRefreshServiceValidator = external_exports.object({
21040
21074
  id: external_exports.string().min(1),
21041
21075
  type: external_exports.literal("1EdTechCredentialRefresh")
@@ -21059,7 +21093,9 @@ var AllocateCredentialRefreshResultValidator = external_exports.object({
21059
21093
  });
21060
21094
  var ManagedCredentialRefreshReceiptValidator = external_exports.object({
21061
21095
  refreshId: external_exports.string().min(1),
21062
- refreshService: ManagedCredentialRefreshServiceValidator,
21096
+ refreshService: ManagedCredentialRefreshBindingValidator,
21097
+ /** Legacy receipts authenticate only the allocated managed entry, not other services. */
21098
+ refreshServiceBinding: external_exports.literal("managed-entry").optional(),
21063
21099
  credentialId: external_exports.string().min(1),
21064
21100
  issuerDid: external_exports.string().min(1),
21065
21101
  holderDid: external_exports.string().min(1),
@@ -21067,14 +21103,43 @@ var ManagedCredentialRefreshReceiptValidator = external_exports.object({
21067
21103
  CredentialStatusValidator.array()
21068
21104
  ).optional()
21069
21105
  }).strip();
21106
+ var GetCredentialRefreshReceiptInputValidator = external_exports.object({ uri: external_exports.string().min(1) });
21107
+ var CredentialRefreshReceiptValidator = ManagedCredentialRefreshReceiptValidator.extend({
21108
+ encryptionMode: external_exports.enum(["network", "holder"])
21109
+ });
21110
+ var HolderEncryptedHandoffValidator = external_exports.object({
21111
+ refreshId: external_exports.string().min(1),
21112
+ credentialId: external_exports.string().min(1),
21113
+ holderDid: external_exports.string().min(1),
21114
+ issuerDid: external_exports.string().min(1),
21115
+ credentialStatus: CredentialStatusValidator.or(CredentialStatusValidator.array()),
21116
+ refreshService: ManagedCredentialRefreshBindingValidator.optional(),
21117
+ jwe: JWEValidator
21118
+ }).strict();
21119
+ var SendHolderEncryptedRefreshableInputValidator = external_exports.object({
21120
+ handoff: HolderEncryptedHandoffValidator,
21121
+ idempotencyKey: external_exports.string().min(1).optional(),
21122
+ boostUri: external_exports.string().optional(),
21123
+ skipNotification: external_exports.boolean().optional()
21124
+ });
21125
+ var GetEncryptionRecipientsInputValidator = external_exports.object({ refreshId: external_exports.string().min(1) });
21126
+ var EncryptionRecipientsResultValidator = external_exports.object({
21127
+ recipientKeyIds: external_exports.array(external_exports.string())
21128
+ });
21070
21129
  var InboxCredentialRefreshReceiptValidator = ManagedCredentialRefreshReceiptValidator.omit(
21071
21130
  { holderDid: true }
21072
21131
  ).extend({ holderDid: external_exports.string().min(1).optional() });
21073
21132
  var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
21133
+ var CredentialRefreshUpdateReasonValidator = external_exports.enum(["corrected", "updated", "reissued"]);
21074
21134
  var PublishCredentialRefreshBaseFields = {
21075
21135
  refreshId: external_exports.string().min(1),
21076
21136
  notifyHolder: external_exports.boolean().optional(),
21077
- updateSummary: external_exports.string().optional(),
21137
+ updateSummary: external_exports.string().max(280).optional().describe(
21138
+ "Public legacy update summary. Do not include private claims; prefer updateReason."
21139
+ ),
21140
+ updateReason: CredentialRefreshUpdateReasonValidator.optional().describe(
21141
+ "Public reason for this update"
21142
+ ),
21078
21143
  idempotencyKey: external_exports.string().optional()
21079
21144
  };
21080
21145
  var PublishIssuerSignedRefreshValidator = external_exports.object({
@@ -21150,13 +21215,25 @@ var PublishCredentialRefreshResultValidator = external_exports.object({
21150
21215
  publishedAt: external_exports.string().min(1),
21151
21216
  notification: PublishCredentialRefreshNotificationValidator
21152
21217
  });
21218
+ var PublishHolderEncryptedRefreshInputValidator = external_exports.object({
21219
+ handoff: HolderEncryptedHandoffValidator,
21220
+ notify: external_exports.boolean(),
21221
+ updateSummary: external_exports.string().max(280).optional().describe(
21222
+ "Public legacy update summary. Do not include private claims; prefer updateReason."
21223
+ ),
21224
+ updateReason: CredentialRefreshUpdateReasonValidator.optional().describe(
21225
+ "Public reason for this update"
21226
+ ),
21227
+ idempotencyKey: external_exports.string().optional()
21228
+ });
21153
21229
  var CredentialRefreshVersionMetadataValidator = external_exports.object({
21154
21230
  version: external_exports.number().int().positive(),
21155
21231
  publishedAt: external_exports.string().min(1),
21156
21232
  effectiveAt: external_exports.string().optional(),
21157
21233
  etag: external_exports.string().optional(),
21158
21234
  signingMode: CredentialRefreshSigningModeValidator.optional(),
21159
- updateSummary: external_exports.string().optional()
21235
+ updateSummary: external_exports.string().optional(),
21236
+ updateReason: CredentialRefreshUpdateReasonValidator.optional()
21160
21237
  });
21161
21238
  var GetCredentialRefreshHistoryInputValidator = external_exports.object({
21162
21239
  refreshId: external_exports.string().min(1),
@@ -21199,6 +21276,7 @@ var CredentialRefreshFailureCodeValidator = external_exports.enum([
21199
21276
  "INVALID_PROOF",
21200
21277
  "ISSUER_MISMATCH",
21201
21278
  "ID_MISMATCH",
21279
+ "BINDING_MISMATCH",
21202
21280
  "ROLLBACK",
21203
21281
  "REVOKED",
21204
21282
  "UNSAFE_ENDPOINT"
@@ -21523,6 +21601,11 @@ var AutoBoostConfigValidator = external_exports.object({
21523
21601
  name: external_exports.string()
21524
21602
  })
21525
21603
  });
21604
+ var CredentialDisplayValidator = external_exports.object({
21605
+ name: external_exports.string().trim().min(1).max(280).optional(),
21606
+ category: external_exports.string().max(280).optional(),
21607
+ image: external_exports.string().max(2048).url().refine((url2) => url2.startsWith("https://"), { message: "Image URL must use https" }).optional()
21608
+ });
21526
21609
  var SendBoostTemplateValidator = BoostValidator.partial().omit({ uri: true, claimPermissions: true }).extend({
21527
21610
  credential: VCValidator.or(UnsignedVCValidator),
21528
21611
  claimPermissions: BoostPermissionsValidator.partial().optional(),
@@ -21561,6 +21644,10 @@ var SendBoostInputValidator = external_exports.object({
21561
21644
  templateUri: external_exports.string().optional(),
21562
21645
  template: SendBoostTemplateValidator.optional(),
21563
21646
  signedCredential: VCValidator.optional(),
21647
+ display: CredentialDisplayValidator.optional().describe(
21648
+ "Public display metadata for managed and signed-only sends. Nothing is inferred from credential content; omitted names use generic copy. The exception is category: when display.category is omitted for an inline template, the template's category is copied, since consent-flow write authorization is keyed on it."
21649
+ ),
21650
+ statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
21564
21651
  options: SendOptionsValidator.optional().describe(
21565
21652
  "Options for email/phone recipients (Universal Inbox)"
21566
21653
  ),
@@ -21599,7 +21686,10 @@ var SendInboxResponseValidator = external_exports.object({
21599
21686
  "Present when guardianEmail was specified"
21600
21687
  )
21601
21688
  });
21689
+ var StatusManagementValidator = external_exports.enum(["network", "external", "mixed", "none"]);
21602
21690
  var SendBoostResponseValidator = external_exports.object({
21691
+ /** Public status providers for a managed send; external entries require provider-side updates. */
21692
+ statusManagement: StatusManagementValidator.optional(),
21603
21693
  type: external_exports.literal("boost"),
21604
21694
  credentialUri: external_exports.string(),
21605
21695
  uri: external_exports.string(),
@@ -21612,19 +21702,33 @@ var SendBoostResponseValidator = external_exports.object({
21612
21702
  )
21613
21703
  });
21614
21704
  var PrepareRefreshableSendInputValidator = external_exports.object({
21705
+ /** Opt in to signing the server-bound statusEntries; omission preserves client allocation. */
21706
+ statusBinding: external_exports.literal("server").optional(),
21707
+ statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
21615
21708
  recipient: external_exports.string(),
21616
21709
  templateUri: external_exports.string().optional(),
21617
21710
  template: SendBoostTemplateValidator.optional(),
21711
+ display: CredentialDisplayValidator.optional().describe("Public display metadata only"),
21618
21712
  contractUri: external_exports.string().optional(),
21619
21713
  templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
21620
21714
  integrationId: external_exports.string().optional(),
21621
21715
  /** Credential ID to allocate for; generated server-side when omitted. */
21622
21716
  credentialId: external_exports.string().min(1).optional(),
21623
- idempotencyKey: external_exports.string().min(1).max(200).optional()
21624
- }).refine((data) => Boolean(data.templateUri) !== Boolean(data.template), {
21625
- message: "Provide exactly one of templateUri or template."
21717
+ idempotencyKey: external_exports.string().min(1).max(200).optional(),
21718
+ /**
21719
+ * `'holder'` requests student-only encryption (LC-2345): the SDK signs and
21720
+ * encrypts locally and the server never receives plaintext. Requires a
21721
+ * profile or DID recipient; rejected for signedCredential-only sends and for
21722
+ * inbox (email/phone) recipients. Defaults to `'network'`.
21723
+ */
21724
+ encryption: external_exports.enum(["network", "holder"]).optional()
21725
+ }).refine((data) => !(data.templateUri && data.template), {
21726
+ message: "Provide at most one of templateUri or template."
21626
21727
  });
21627
21728
  var PrepareRefreshableSendResultValidator = external_exports.object({
21729
+ /** Public status providers known at preparation; final send reports the signed entries. */
21730
+ statusManagement: StatusManagementValidator.optional(),
21731
+ statusEntries: external_exports.array(BitstringStatusListEntryValidator).optional(),
21628
21732
  boostUri: external_exports.string(),
21629
21733
  credentialId: external_exports.string(),
21630
21734
  refreshId: external_exports.string(),
@@ -21632,11 +21736,110 @@ var PrepareRefreshableSendResultValidator = external_exports.object({
21632
21736
  /** The DID to use as credentialSubject.id (recipient DID, or the profile's did:web). */
21633
21737
  holderDid: external_exports.string(),
21634
21738
  /** Present when this idempotencyKey already completed: return it without signing. */
21635
- completed: SendBoostResponseValidator.optional()
21739
+ completed: SendBoostResponseValidator.optional(),
21740
+ /**
21741
+ * Present only when `encryption: 'holder'` was requested: the exact
21742
+ * key-agreement verification-method ids (holder + current managers) the SDK
21743
+ * must encrypt to. Recomputed on every call, so a later manager change can
21744
+ * make a previously-prepared set stale (see `credentialRefresh.sendHolderEncryptedRefreshable`
21745
+ * and `credentialRefresh.getEncryptionRecipients`).
21746
+ */
21747
+ recipientKeyIds: external_exports.array(external_exports.string()).optional()
21636
21748
  });
21637
21749
  var SendInputValidator = external_exports.discriminatedUnion("type", [SendBoostInputValidator]);
21638
21750
  var SendResponseValidator = external_exports.discriminatedUnion("type", [SendBoostResponseValidator]);
21639
- var ConsentFlowTermsStatusValidator = external_exports.enum(["live", "stale", "withdrawn"]);
21751
+ var ConsentFlowTermsStatusValidator = external_exports.enum([
21752
+ "live",
21753
+ "consumed",
21754
+ "withdrawn",
21755
+ "needs_reconsent",
21756
+ "suspended"
21757
+ ]);
21758
+ var ConsentFlowContractChangeKindValidator = external_exports.enum([
21759
+ "relaxed",
21760
+ "expanded_optional",
21761
+ "requires_consent"
21762
+ ]);
21763
+ var ConsentFlowContractScopeValidator = external_exports.object({
21764
+ area: external_exports.enum(["read", "write"]),
21765
+ type: external_exports.enum(["credential", "personal"]),
21766
+ key: external_exports.string(),
21767
+ required: external_exports.boolean(),
21768
+ reason: external_exports.string().optional()
21769
+ });
21770
+ var ConsentFlowContractDetailValueValidator = external_exports.union([
21771
+ external_exports.string(),
21772
+ external_exports.boolean(),
21773
+ external_exports.string().array()
21774
+ ]);
21775
+ var ConsentFlowContractDetailChangeValidator = external_exports.object({
21776
+ field: external_exports.enum([
21777
+ "name",
21778
+ "subtitle",
21779
+ "description",
21780
+ "reasonForAccessing",
21781
+ "image",
21782
+ "needsGuardianConsent",
21783
+ "redirectUrl",
21784
+ "frontDoorBoostUri",
21785
+ "expiresAt",
21786
+ "writers",
21787
+ "autoboosts"
21788
+ ]),
21789
+ before: ConsentFlowContractDetailValueValidator.optional(),
21790
+ after: ConsentFlowContractDetailValueValidator.optional()
21791
+ });
21792
+ var ConsentFlowContractDiffValidator = external_exports.object({
21793
+ added: ConsentFlowContractScopeValidator.array(),
21794
+ removed: ConsentFlowContractScopeValidator.array(),
21795
+ changed: ConsentFlowContractScopeValidator.array(),
21796
+ details: ConsentFlowContractDetailChangeValidator.array().optional()
21797
+ });
21798
+ var ConsentFlowContractUpdatePreviewValidator = external_exports.object({
21799
+ headline: external_exports.string(),
21800
+ subhead: external_exports.string(),
21801
+ rows: external_exports.array(
21802
+ external_exports.object({
21803
+ scope: ConsentFlowContractScopeValidator,
21804
+ change: external_exports.enum(["added", "removed", "changed"]),
21805
+ label: external_exports.string(),
21806
+ subtitle: external_exports.string()
21807
+ })
21808
+ ),
21809
+ primaryLabel: external_exports.string()
21810
+ });
21811
+ var ConsentFlowContractStatusValidator = external_exports.enum(["active", "retired"]);
21812
+ var ConsentFlowContractVersionValidator = external_exports.object({
21813
+ version: external_exports.number().int().positive(),
21814
+ createdAt: external_exports.string(),
21815
+ reason: external_exports.string().optional(),
21816
+ kind: ConsentFlowContractChangeKindValidator.optional()
21817
+ });
21818
+ var ConsentFlowContractUpdateResultValidator = external_exports.object({
21819
+ version: external_exports.number().int().positive(),
21820
+ kind: ConsentFlowContractChangeKindValidator,
21821
+ affectedUsers: external_exports.number().int().nonnegative(),
21822
+ preview: ConsentFlowContractUpdatePreviewValidator
21823
+ });
21824
+ var ConsentFlowConsentStatusValidator = external_exports.object({
21825
+ status: ConsentFlowTermsStatusValidator.or(external_exports.literal("not_consented")),
21826
+ consentedVersion: external_exports.number().int().positive().optional(),
21827
+ currentVersion: external_exports.number().int().positive(),
21828
+ needsReconsent: external_exports.boolean(),
21829
+ reviewUrl: external_exports.string().optional()
21830
+ });
21831
+ var ConsentFlowContractNotificationDataValidator = external_exports.object({
21832
+ contractUri: external_exports.string(),
21833
+ contractName: external_exports.string().optional(),
21834
+ fromVersion: external_exports.number().int().positive(),
21835
+ toVersion: external_exports.number().int().positive(),
21836
+ kind: ConsentFlowContractChangeKindValidator,
21837
+ reason: external_exports.string().optional(),
21838
+ diff: ConsentFlowContractDiffValidator,
21839
+ reconsentDeadline: external_exports.string().optional(),
21840
+ reviewUrl: external_exports.string(),
21841
+ preview: ConsentFlowContractUpdatePreviewValidator.optional()
21842
+ });
21640
21843
  var ConsentFlowContractValidator = external_exports.object({
21641
21844
  read: external_exports.object({
21642
21845
  anonymize: external_exports.boolean().optional(),
@@ -21645,13 +21848,18 @@ var ConsentFlowContractValidator = external_exports.object({
21645
21848
  external_exports.string(),
21646
21849
  external_exports.object({
21647
21850
  required: external_exports.boolean(),
21648
- defaultEnabled: external_exports.boolean().optional()
21851
+ defaultEnabled: external_exports.boolean().optional(),
21852
+ reason: external_exports.string().optional()
21649
21853
  })
21650
21854
  ).default({})
21651
21855
  }).prefault({ categories: {} }),
21652
21856
  personal: external_exports.record(
21653
21857
  external_exports.string(),
21654
- external_exports.object({ required: external_exports.boolean(), defaultEnabled: external_exports.boolean().optional() })
21858
+ external_exports.object({
21859
+ required: external_exports.boolean(),
21860
+ defaultEnabled: external_exports.boolean().optional(),
21861
+ reason: external_exports.string().optional()
21862
+ })
21655
21863
  ).default({})
21656
21864
  }).prefault({ credentials: { categories: {} }, personal: {} }),
21657
21865
  write: external_exports.object({
@@ -21660,16 +21868,55 @@ var ConsentFlowContractValidator = external_exports.object({
21660
21868
  external_exports.string(),
21661
21869
  external_exports.object({
21662
21870
  required: external_exports.boolean(),
21663
- defaultEnabled: external_exports.boolean().optional()
21871
+ defaultEnabled: external_exports.boolean().optional(),
21872
+ reason: external_exports.string().optional()
21664
21873
  })
21665
21874
  ).default({})
21666
21875
  }).prefault({ categories: {} }),
21667
21876
  personal: external_exports.record(
21668
21877
  external_exports.string(),
21669
- external_exports.object({ required: external_exports.boolean(), defaultEnabled: external_exports.boolean().optional() })
21878
+ external_exports.object({
21879
+ required: external_exports.boolean(),
21880
+ defaultEnabled: external_exports.boolean().optional(),
21881
+ reason: external_exports.string().optional()
21882
+ })
21670
21883
  ).default({})
21671
21884
  }).prefault({ credentials: { categories: {} }, personal: {} })
21672
21885
  });
21886
+ var ConsentFlowContractScopePatchValidator = external_exports.object({
21887
+ required: external_exports.boolean(),
21888
+ defaultEnabled: external_exports.boolean().optional(),
21889
+ reason: external_exports.string().optional()
21890
+ }).nullable();
21891
+ var ConsentFlowContractChangesValidator = external_exports.object({
21892
+ contract: external_exports.object({
21893
+ read: external_exports.object({
21894
+ anonymize: external_exports.boolean().optional(),
21895
+ credentials: external_exports.object({
21896
+ categories: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21897
+ }).optional(),
21898
+ personal: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21899
+ }).optional(),
21900
+ write: external_exports.object({
21901
+ credentials: external_exports.object({
21902
+ categories: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21903
+ }).optional(),
21904
+ personal: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21905
+ }).optional()
21906
+ }).optional(),
21907
+ name: external_exports.string().optional(),
21908
+ subtitle: external_exports.string().optional(),
21909
+ description: external_exports.string().optional(),
21910
+ reasonForAccessing: external_exports.string().optional(),
21911
+ image: external_exports.string().optional(),
21912
+ needsGuardianConsent: external_exports.boolean().optional(),
21913
+ redirectUrl: external_exports.string().optional(),
21914
+ frontDoorBoostUri: external_exports.string().optional(),
21915
+ expiresAt: external_exports.string().nullable().optional(),
21916
+ autoboosts: AutoBoostConfigValidator.array().optional(),
21917
+ writers: external_exports.string().array().optional(),
21918
+ recipients: external_exports.string().array().optional()
21919
+ });
21673
21920
  var ConsentFlowContractDetailsValidator = external_exports.object({
21674
21921
  contract: ConsentFlowContractValidator,
21675
21922
  owner: LCNProfileValidator,
@@ -21688,7 +21935,19 @@ var ConsentFlowContractDetailsValidator = external_exports.object({
21688
21935
  autoBoosts: external_exports.string().array().optional(),
21689
21936
  writers: external_exports.array(LCNProfileValidator).optional(),
21690
21937
  recipients: external_exports.array(LCNPublicProfileValidator.extend({ did: external_exports.string() })).optional(),
21691
- audienceVersion: external_exports.number().int().nonnegative().optional()
21938
+ audienceVersion: external_exports.number().int().nonnegative().optional(),
21939
+ version: external_exports.number().int().positive(),
21940
+ status: ConsentFlowContractStatusValidator.optional(),
21941
+ latestUpdate: external_exports.object({
21942
+ fromVersion: external_exports.number().int().positive(),
21943
+ toVersion: external_exports.number().int().positive(),
21944
+ kind: ConsentFlowContractChangeKindValidator,
21945
+ reason: external_exports.string().optional(),
21946
+ diff: ConsentFlowContractDiffValidator,
21947
+ reconsentDeadline: external_exports.string().optional(),
21948
+ createdAt: external_exports.string(),
21949
+ preview: ConsentFlowContractUpdatePreviewValidator
21950
+ }).optional()
21692
21951
  });
21693
21952
  var ConsentFlowContractRequestStatusValidator = external_exports.enum(["pending", "accepted", "denied", "cancelled"]).nullable();
21694
21953
  var ConsentFlowContractRequestReadStatusValidator = external_exports.enum(["unseen", "seen"]).nullable();
@@ -21777,7 +22036,12 @@ var PaginatedConsentFlowTermsValidator = PaginationResponseValidator.extend({
21777
22036
  contract: ConsentFlowContractDetailsValidator,
21778
22037
  uri: external_exports.string(),
21779
22038
  consenter: LCNProfileValidator,
21780
- status: ConsentFlowTermsStatusValidator
22039
+ status: ConsentFlowTermsStatusValidator,
22040
+ consentedVersion: external_exports.number().int().positive(),
22041
+ lastReviewedVersion: external_exports.number().int().positive().optional(),
22042
+ reconsentDeadline: external_exports.string().optional(),
22043
+ newOptionsUntil: external_exports.string().optional(),
22044
+ cumulativeUpdate: ConsentFlowContractDetailsValidator.shape.latestUpdate
21781
22045
  }).array()
21782
22046
  });
21783
22047
  var ConsentFlowGuardianApprovalValidator = external_exports.object({
@@ -21853,7 +22117,8 @@ var ConsentFlowTransactionActionValidator = external_exports.enum([
21853
22117
  "update",
21854
22118
  "sync",
21855
22119
  "withdraw",
21856
- "write"
22120
+ "write",
22121
+ "reconsent"
21857
22122
  ]);
21858
22123
  var ConsentFlowTransactionsQueryValidator = external_exports.object({
21859
22124
  terms: ConsentFlowTermsQueryValidator.optional(),
@@ -21872,8 +22137,12 @@ var ConsentFlowTransactionValidator = external_exports.object({
21872
22137
  referral: ConsentFlowReferralValidator.optional(),
21873
22138
  id: external_exports.string(),
21874
22139
  action: ConsentFlowTransactionActionValidator,
22140
+ kind: ConsentFlowContractChangeKindValidator.optional(),
21875
22141
  date: external_exports.string(),
21876
- uris: external_exports.string().array().optional()
22142
+ uris: external_exports.string().array().optional(),
22143
+ consentedVersion: external_exports.number().int().positive().optional(),
22144
+ reconsentDeadline: external_exports.string().optional(),
22145
+ newOptionsUntil: external_exports.string().optional()
21877
22146
  });
21878
22147
  var HolderExportConsentRecordValidator = external_exports.object({
21879
22148
  termsUri: external_exports.string(),
@@ -21881,6 +22150,10 @@ var HolderExportConsentRecordValidator = external_exports.object({
21881
22150
  contract: ConsentFlowContractDetailsValidator,
21882
22151
  terms: ConsentFlowTermsValidator,
21883
22152
  referral: ConsentFlowReferralValidator.optional(),
22153
+ consentedVersion: external_exports.number().int().positive(),
22154
+ reconsentDeadline: external_exports.string().optional(),
22155
+ newOptionsUntil: external_exports.string().optional(),
22156
+ cumulativeUpdate: ConsentFlowContractDetailsValidator.shape.latestUpdate,
21884
22157
  transactions: ConsentFlowTransactionValidator.array()
21885
22158
  });
21886
22159
  var HolderExportMetadataValidator = external_exports.object({
@@ -21941,10 +22214,12 @@ var LCNNotificationTypeEnumValidator = external_exports.enum([
21941
22214
  "GUARDIAN_APPROVED",
21942
22215
  "GUARDIAN_REJECTED",
21943
22216
  "APP_NOTIFICATION",
22217
+ "ANNOUNCEMENT",
21944
22218
  "CREDENTIAL_REVOKED",
21945
22219
  "CREDENTIAL_SUSPENDED",
21946
22220
  "CREDENTIAL_UNSUSPENDED",
21947
- "CREDENTIAL_REFRESHED"
22221
+ "CREDENTIAL_REFRESHED",
22222
+ "CONSENT_FLOW_CONTRACT_UPDATED"
21948
22223
  ]);
21949
22224
  var LCNNotificationMessageValidator = external_exports.object({
21950
22225
  title: external_exports.string().optional(),
@@ -21973,12 +22248,26 @@ var LCNNotificationInboxValidator = external_exports.object({
21973
22248
  timestamp: external_exports.iso.datetime().optional()
21974
22249
  });
21975
22250
  var LCNNotificationMetadataValidator = external_exports.object({
21976
- connectionPrompt: LCNConnectionPromptMetadataValidator.optional()
22251
+ connectionPrompt: LCNConnectionPromptMetadataValidator.optional(),
22252
+ campaignId: external_exports.string().regex(/^[a-z0-9-]{3,64}$/).optional(),
22253
+ campaignCreatedAt: external_exports.iso.datetime().optional(),
22254
+ campaignHasInApp: external_exports.boolean().optional(),
22255
+ campaignTestId: external_exports.uuid().optional()
21977
22256
  }).catchall(external_exports.unknown());
21978
22257
  var LCNNotificationDataValidator = external_exports.object({
21979
22258
  vcUris: external_exports.array(external_exports.string()).optional(),
21980
22259
  vpUris: external_exports.array(external_exports.string()).optional(),
21981
22260
  transaction: ConsentFlowTransactionValidator.optional(),
22261
+ contractUri: external_exports.string().optional(),
22262
+ contractName: external_exports.string().optional(),
22263
+ fromVersion: external_exports.number().int().positive().optional(),
22264
+ toVersion: external_exports.number().int().positive().optional(),
22265
+ kind: ConsentFlowContractChangeKindValidator.optional(),
22266
+ reason: external_exports.string().optional(),
22267
+ diff: ConsentFlowContractDiffValidator.optional(),
22268
+ reconsentDeadline: external_exports.string().optional(),
22269
+ reviewUrl: external_exports.string().optional(),
22270
+ preview: ConsentFlowContractUpdatePreviewValidator.optional(),
21982
22271
  inbox: LCNNotificationInboxValidator.optional(),
21983
22272
  metadata: LCNNotificationMetadataValidator.optional()
21984
22273
  }).loose();
@@ -23077,28 +23366,6 @@ var EscrowPinStatusValidator = external_exports.object({
23077
23366
  */
23078
23367
  wrongAttempts: external_exports.number().int().nonnegative().optional()
23079
23368
  });
23080
- var BITSTRING_STATUS_PURPOSES = ["revocation", "suspension"];
23081
- var BitstringStatusPurposeValidator = external_exports.enum(BITSTRING_STATUS_PURPOSES);
23082
- var BitstringStatusListEntryValidator = external_exports.object({
23083
- id: external_exports.string().optional(),
23084
- type: external_exports.literal("BitstringStatusListEntry"),
23085
- statusPurpose: BitstringStatusPurposeValidator,
23086
- statusListIndex: external_exports.string().or(external_exports.number().int().nonnegative()),
23087
- statusListCredential: external_exports.string()
23088
- });
23089
- var AllocatedBitstringStatusListEntryValidator = BitstringStatusListEntryValidator.extend({
23090
- id: external_exports.string()
23091
- });
23092
- var BitstringStatusListCredentialSubjectValidator = external_exports.object({
23093
- id: external_exports.string().optional(),
23094
- type: external_exports.literal("BitstringStatusList"),
23095
- statusPurpose: BitstringStatusPurposeValidator,
23096
- encodedList: external_exports.string()
23097
- });
23098
- var AllocateCredentialStatusInputValidator = external_exports.object({
23099
- statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
23100
- listSize: external_exports.number().int().positive().optional()
23101
- }).default({});
23102
23369
  var isSafeInAppMessagePath = /* @__PURE__ */ __name2((path) => {
23103
23370
  let decoded = path;
23104
23371
  for (let depth = 0; depth < 5; depth += 1) {
@@ -23379,24 +23646,46 @@ var inAppMessagesFlagEnvelopeValidator = external_exports.object({
23379
23646
  }).passthrough();
23380
23647
  var CampaignIdValidator = external_exports.string().regex(/^[a-z0-9-]{3,64}$/);
23381
23648
  var CampaignStatusValidator = external_exports.enum(["draft", "live", "paused", "archived"]);
23382
- var CampaignChannelValidator = external_exports.enum(["inApp", "notify"]);
23649
+ var CampaignChannelValidator = external_exports.enum(["inApp", "notify", "email"]);
23383
23650
  var CampaignEventValidator = external_exports.enum(["shown", "clicked", "dismissed", "converted"]);
23384
- var timestamp = external_exports.iso.datetime({ offset: true }).overwrite((value) => new Date(value).toISOString());
23651
+ var timestamp = external_exports.iso.datetime({ offset: true }).overwrite((value) => {
23652
+ const date5 = new Date(value);
23653
+ return Number.isFinite(date5.getTime()) ? date5.toISOString() : value;
23654
+ });
23385
23655
  var notification = external_exports.object({ title: external_exports.string().min(1), body: external_exports.string().min(1) }).strict();
23386
- var channels = external_exports.array(CampaignChannelValidator).min(1).max(2).refine((values) => new Set(values).size === values.length, "Channels must be unique");
23656
+ var CampaignEmailValidator = external_exports.object({
23657
+ subject: external_exports.string().trim().min(1).max(200).regex(/^[^\r\n]+$/),
23658
+ title: external_exports.string().trim().min(1).max(200),
23659
+ body: external_exports.string().trim().min(1).max(2e4),
23660
+ heroImageUrl: external_exports.url().startsWith("https://").max(2048).optional(),
23661
+ ctaLabel: external_exports.string().trim().min(1).max(100)
23662
+ }).strict();
23663
+ var AnnouncementPreferencesValidator = external_exports.object({
23664
+ announcementEmailOptOut: external_exports.boolean(),
23665
+ announcementPushOptOut: external_exports.boolean()
23666
+ }).strict();
23667
+ var channels = external_exports.array(CampaignChannelValidator).min(1).max(3).refine((values) => new Set(values).size === values.length, "Channels must be unique");
23387
23668
  var campaignDefinition = external_exports.object({
23388
23669
  id: CampaignIdValidator,
23389
23670
  name: external_exports.string().trim().min(1).max(200),
23390
23671
  status: CampaignStatusValidator.default("draft"),
23391
23672
  channels,
23392
- message: inAppMessageValidator,
23673
+ message: inAppMessageValidator.optional(),
23393
23674
  notification: notification.optional(),
23675
+ email: CampaignEmailValidator.optional(),
23394
23676
  startsAt: timestamp.optional(),
23395
23677
  endsAt: timestamp.optional(),
23396
23678
  excludeMinors: external_exports.boolean().default(true),
23397
23679
  selfEnroll: external_exports.boolean().default(false)
23398
23680
  }).strict();
23399
23681
  var validDefinition = /* @__PURE__ */ __name2((value, ctx) => {
23682
+ if (value.channels.includes("inApp") && !value.message) {
23683
+ ctx.addIssue({
23684
+ code: "custom",
23685
+ path: ["message"],
23686
+ message: "In-app requires a message"
23687
+ });
23688
+ }
23400
23689
  if (value.channels.includes("notify") && !value.notification) {
23401
23690
  ctx.addIssue({
23402
23691
  code: "custom",
@@ -23404,15 +23693,23 @@ var validDefinition = /* @__PURE__ */ __name2((value, ctx) => {
23404
23693
  message: "Notify requires a title and body"
23405
23694
  });
23406
23695
  }
23696
+ if (value.channels.includes("email") && !value.email) {
23697
+ ctx.addIssue({
23698
+ code: "custom",
23699
+ path: ["email"],
23700
+ message: "Email requires announcement content"
23701
+ });
23702
+ }
23407
23703
  if (value.startsAt && value.endsAt && value.startsAt >= value.endsAt) {
23408
23704
  ctx.addIssue({ code: "custom", path: ["endsAt"], message: "End must be after start" });
23409
23705
  }
23410
23706
  }, "validDefinition");
23411
23707
  var CampaignValidator = campaignDefinition.extend({
23708
+ tenantId: external_exports.string().optional(),
23412
23709
  createdAt: timestamp,
23413
23710
  updatedAt: timestamp
23414
23711
  }).superRefine(validDefinition).superRefine((value, ctx) => {
23415
- if (value.message.id !== value.id) {
23712
+ if (value.message && value.message.id !== value.id) {
23416
23713
  ctx.addIssue({
23417
23714
  code: "custom",
23418
23715
  path: ["message", "id"],
@@ -23421,21 +23718,23 @@ var CampaignValidator = campaignDefinition.extend({
23421
23718
  }
23422
23719
  });
23423
23720
  var CreateCampaignInputValidator = campaignDefinition.extend({
23424
- message: inAppMessageAuthoringValidator
23721
+ message: inAppMessageAuthoringValidator.optional()
23425
23722
  }).superRefine(validDefinition);
23426
23723
  var CampaignUpdatesValidator = campaignDefinition.omit({ id: true }).partial().extend({
23427
23724
  // A PATCH must not apply creation defaults to fields the caller omitted.
23428
23725
  status: CampaignStatusValidator.optional(),
23429
23726
  excludeMinors: external_exports.boolean().optional(),
23430
23727
  selfEnroll: external_exports.boolean().optional(),
23431
- message: inAppMessageAuthoringValidator.optional(),
23728
+ message: inAppMessageAuthoringValidator.nullable().optional(),
23432
23729
  notification: notification.nullable().optional(),
23730
+ email: CampaignEmailValidator.nullable().optional(),
23433
23731
  startsAt: timestamp.nullable().optional(),
23434
23732
  endsAt: timestamp.nullable().optional()
23435
23733
  }).strict();
23436
23734
  var UpdateCampaignInputValidator = external_exports.object({
23437
23735
  campaignId: CampaignIdValidator,
23438
- updates: CampaignUpdatesValidator
23736
+ updates: CampaignUpdatesValidator,
23737
+ expectedUpdatedAt: timestamp.optional()
23439
23738
  }).strict();
23440
23739
  var identifier = external_exports.string().trim().min(1).max(2048);
23441
23740
  var metadataKey = external_exports.string().regex(/^[a-zA-Z_][a-zA-Z0-9_.-]{0,63}$/).refine(
@@ -23487,7 +23786,8 @@ var CampaignUserStateValidator = external_exports.object({
23487
23786
  clickedAt: timestamp.optional(),
23488
23787
  dismissedAt: timestamp.optional(),
23489
23788
  convertedAt: timestamp.optional(),
23490
- notifiedAt: timestamp.optional()
23789
+ notifiedAt: timestamp.optional(),
23790
+ emailedAt: timestamp.optional()
23491
23791
  });
23492
23792
  var MyCampaignValidator = external_exports.object({
23493
23793
  campaign: campaignDefinition.pick({
@@ -23496,12 +23796,19 @@ var MyCampaignValidator = external_exports.object({
23496
23796
  startsAt: true,
23497
23797
  endsAt: true,
23498
23798
  selfEnroll: true
23499
- }),
23500
- state: CampaignUserStateValidator
23799
+ }).extend({ message: inAppMessageValidator }),
23800
+ state: CampaignUserStateValidator,
23801
+ testId: external_exports.uuid().optional()
23802
+ });
23803
+ var CampaignTestValidator = external_exports.object({
23804
+ id: external_exports.uuid(),
23805
+ campaignId: CampaignIdValidator,
23806
+ message: inAppMessageValidator
23501
23807
  });
23502
23808
  var CampaignStatsValidator = external_exports.object({
23503
23809
  audience: external_exports.number().int().nonnegative(),
23504
23810
  notified: external_exports.number().int().nonnegative(),
23811
+ emailed: external_exports.number().int().nonnegative(),
23505
23812
  shown: external_exports.number().int().nonnegative(),
23506
23813
  clicked: external_exports.number().int().nonnegative(),
23507
23814
  dismissed: external_exports.number().int().nonnegative(),
@@ -23528,6 +23835,31 @@ var PaginatedCampaignAudienceValidator = external_exports.object({
23528
23835
  hasMore: external_exports.boolean(),
23529
23836
  cursor: external_exports.string().optional()
23530
23837
  });
23838
+ var CampaignDispatchPreviewValidator = external_exports.object({
23839
+ campaignId: CampaignIdValidator,
23840
+ audienceCount: external_exports.number().int().nonnegative(),
23841
+ alreadyNotifiedCount: external_exports.number().int().nonnegative(),
23842
+ recipientCount: external_exports.number().int().nonnegative(),
23843
+ notificationRecipientCount: external_exports.number().int().nonnegative().optional(),
23844
+ emailRecipientCount: external_exports.number().int().nonnegative().optional(),
23845
+ previewToken: external_exports.string().regex(/^[a-f0-9]{64}$/),
23846
+ blockedReason: external_exports.enum([
23847
+ "not_live",
23848
+ "notify_disabled",
23849
+ "email_confirmation_required",
23850
+ "not_started",
23851
+ "ended",
23852
+ "no_recipients"
23853
+ ]).optional()
23854
+ });
23855
+ var CampaignDispatchOptionsValidator = external_exports.object({
23856
+ expectedPreviewToken: CampaignDispatchPreviewValidator.shape.previewToken.optional()
23857
+ }).strict();
23858
+ var CampaignAudienceResultValidator = external_exports.object({
23859
+ count: external_exports.number().int().nonnegative(),
23860
+ added: external_exports.number().int().nonnegative(),
23861
+ notFound: external_exports.array(external_exports.string())
23862
+ });
23531
23863
  var SHARE_LINK_ID_BYTES = 16;
23532
23864
  var SHARE_CONTENT_KEY_BYTES = 32;
23533
23865
  var SHARE_IV_BYTES = 12;
@@ -24051,16 +24383,231 @@ var SkillIconNamesValidator = external_exports.array(external_exports.string().n
24051
24383
  }
24052
24384
  );
24053
24385
  var GenerateSkillIconsInputValidator = external_exports.object({ names: SkillIconNamesValidator });
24386
+ var RoleValidator = external_exports.enum(["user", "assistant", "tool", "system"]);
24387
+ var AiSessionMode = {
24388
+ tutor: "ai-tutor",
24389
+ insights: "ai-insights"
24390
+ };
24391
+ var AiSessionModeValidator = external_exports.enum([AiSessionMode.tutor, AiSessionMode.insights]);
24392
+ var StructuredResponseValidator = external_exports.object({
24393
+ notes: external_exports.string().optional(),
24394
+ questions: external_exports.array(external_exports.string())
24395
+ });
24396
+ var IntroStreamModeValidator = external_exports.enum(["formatted", "structured"]);
24397
+ var ChatMessageValidator = external_exports.object({
24398
+ role: RoleValidator,
24399
+ content: external_exports.string().nullable(),
24400
+ tool_call_id: external_exports.string().optional(),
24401
+ tool_calls: external_exports.array(
24402
+ external_exports.object({
24403
+ id: external_exports.string(),
24404
+ type: external_exports.literal("function"),
24405
+ function: external_exports.object({
24406
+ name: external_exports.string(),
24407
+ arguments: external_exports.string()
24408
+ })
24409
+ })
24410
+ ).optional()
24411
+ });
24412
+ var InsightArtifactValidator = external_exports.object({
24413
+ title: external_exports.string(),
24414
+ summary: external_exports.string(),
24415
+ category: external_exports.string(),
24416
+ question: external_exports.string(),
24417
+ narrative: external_exports.string()
24418
+ });
24419
+ var ArtifactSuggestionValidator = external_exports.object({
24420
+ artifact: InsightArtifactValidator,
24421
+ source_text: external_exports.string().optional(),
24422
+ created_at: external_exports.string()
24423
+ });
24424
+ var ThreadCredentialContextValidator = external_exports.object({
24425
+ uri: external_exports.string(),
24426
+ type: external_exports.string(),
24427
+ context: external_exports.string(),
24428
+ score: external_exports.number(),
24429
+ strongestScore: external_exports.number().optional(),
24430
+ averageScore: external_exports.number().optional(),
24431
+ matchCount: external_exports.number().optional(),
24432
+ title: external_exports.string().optional()
24433
+ });
24434
+ var ThreadValidator = external_exports.object({
24435
+ id: external_exports.string(),
24436
+ did: external_exports.string(),
24437
+ topicCredentialUri: external_exports.string().nullable().optional(),
24438
+ title: external_exports.string(),
24439
+ created_at: external_exports.string(),
24440
+ last_message_at: external_exports.string(),
24441
+ active: external_exports.boolean().optional(),
24442
+ ended_at: external_exports.string().optional(),
24443
+ plan_started_at: external_exports.string().optional(),
24444
+ summaries: external_exports.array(
24445
+ external_exports.object({
24446
+ summary_data: external_exports.string(),
24447
+ credential_uri: external_exports.string(),
24448
+ created_at: external_exports.string()
24449
+ })
24450
+ ).optional(),
24451
+ plans: external_exports.array(
24452
+ external_exports.object({
24453
+ plan_data: external_exports.string(),
24454
+ created_at: external_exports.string(),
24455
+ consentRevision: external_exports.string().optional()
24456
+ })
24457
+ ).optional(),
24458
+ credentials: external_exports.array(ThreadCredentialContextValidator).optional(),
24459
+ credentialSearchTopic: external_exports.string().optional(),
24460
+ credentialContextStatus: external_exports.enum(["pending", "ready", "empty", "error"]).optional(),
24461
+ mode: AiSessionModeValidator.optional(),
24462
+ artifactSuggestions: external_exports.array(ArtifactSuggestionValidator).optional()
24463
+ });
24464
+ var CredentialVerificationMetadataValidator = external_exports.object({
24465
+ credentialUri: external_exports.string(),
24466
+ contentHash: external_exports.string().regex(/^[a-f0-9]{64}$/),
24467
+ status: external_exports.enum(["valid", "invalid"]),
24468
+ checkedAt: external_exports.string().datetime(),
24469
+ verifier: external_exports.object({
24470
+ name: external_exports.string(),
24471
+ version: external_exports.string()
24472
+ }),
24473
+ verifiedPayload: external_exports.enum(["credential", "boostCredential"]),
24474
+ checks: external_exports.array(external_exports.string()),
24475
+ errors: external_exports.array(external_exports.string()),
24476
+ warnings: external_exports.array(external_exports.string()),
24477
+ provenance: external_exports.object({
24478
+ source: external_exports.enum(["wallet", "generated"]),
24479
+ retrievedAt: external_exports.string().datetime()
24480
+ }),
24481
+ consent: external_exports.object({
24482
+ contractUri: external_exports.string(),
24483
+ receiptId: external_exports.string().min(1),
24484
+ grantedAt: external_exports.string().datetime().optional(),
24485
+ updatedAt: external_exports.string().datetime(),
24486
+ contractUpdatedAt: external_exports.string().min(1),
24487
+ status: external_exports.literal("live"),
24488
+ expiresAt: external_exports.string().datetime().optional(),
24489
+ contractExpiresAt: external_exports.string().datetime().optional(),
24490
+ categories: external_exports.array(external_exports.string()),
24491
+ credentialUris: external_exports.array(external_exports.string()),
24492
+ personalFields: external_exports.array(external_exports.string()),
24493
+ purpose: external_exports.enum(["credential-ingestion", "model-inference", "embedding"]),
24494
+ revision: external_exports.string().min(1),
24495
+ guardian: external_exports.object({ required: external_exports.boolean(), approved: external_exports.boolean() })
24496
+ })
24497
+ });
24498
+ var ModelSafeCredentialFactValidator = external_exports.object({
24499
+ kind: external_exports.enum([
24500
+ "skill",
24501
+ "goal",
24502
+ "achievement",
24503
+ "course",
24504
+ "experience",
24505
+ "competency",
24506
+ "title",
24507
+ "summary",
24508
+ "assessment",
24509
+ "grade",
24510
+ "date",
24511
+ "alignment",
24512
+ "criteria",
24513
+ "pathway",
24514
+ "topic"
24515
+ ]),
24516
+ value: external_exports.string().min(1).max(240),
24517
+ label: external_exports.string().min(1).max(120).optional()
24518
+ });
24519
+ var ModelSafeCredentialProjectionValidator = external_exports.object({
24520
+ schemaVersion: external_exports.literal("1"),
24521
+ category: external_exports.string().min(1).max(120),
24522
+ credentialTypes: external_exports.array(external_exports.string().min(1).max(120)).max(20),
24523
+ facts: external_exports.array(ModelSafeCredentialFactValidator).max(100),
24524
+ // Present only on credentials that are past their expiry, so the model can
24525
+ // tell a lapsed credential from a current one.
24526
+ expired: external_exports.literal(true).optional(),
24527
+ expirationDate: external_exports.string().datetime().optional()
24528
+ });
24529
+ var AIPassportCredentialRecordValidator = external_exports.object({
24530
+ id: external_exports.string(),
24531
+ uri: external_exports.string(),
24532
+ category: external_exports.string(),
24533
+ credential: VCValidator,
24534
+ aiContext: external_exports.string(),
24535
+ generalSummary: external_exports.string().optional(),
24536
+ createdAt: external_exports.string(),
24537
+ verification: CredentialVerificationMetadataValidator.optional(),
24538
+ projection: ModelSafeCredentialProjectionValidator.optional()
24539
+ });
24540
+ var AuthenticatedMessageValidator = external_exports.object({
24541
+ message: ChatMessageValidator.optional(),
24542
+ threadId: external_exports.string().optional(),
24543
+ selectedQuestion: external_exports.string().optional(),
24544
+ action: external_exports.enum([
24545
+ "start_topic",
24546
+ "continue_plan",
24547
+ "start_topic_uri",
24548
+ "start_learning_pathway",
24549
+ "start_insights_session",
24550
+ "close_insights_session",
24551
+ "artifact_suggestion"
24552
+ ]).optional(),
24553
+ topic: external_exports.string().optional(),
24554
+ topicUri: external_exports.string().optional(),
24555
+ pathwayUri: external_exports.string().optional(),
24556
+ mode: AiSessionModeValidator.optional(),
24557
+ introStreamMode: IntroStreamModeValidator.optional(),
24558
+ // BCP-47 language for AI responses (LC-1901). This has to live on the
24559
+ // validator, not just the inferred type — z.object strips unknown keys, so an
24560
+ // undeclared `locale` would be dropped before the WS handler ever saw it.
24561
+ locale: external_exports.string().nullish()
24562
+ });
24563
+ var DebugInfoValidator = external_exports.object({
24564
+ operation: external_exports.string(),
24565
+ collection: external_exports.string(),
24566
+ input: external_exports.unknown().optional(),
24567
+ output: external_exports.unknown().optional(),
24568
+ timestamp: external_exports.string(),
24569
+ duration: external_exports.number().optional()
24570
+ });
24571
+ var TimingEventValidator = external_exports.object({
24572
+ event: external_exports.literal("timing"),
24573
+ operation: external_exports.string(),
24574
+ phase: external_exports.enum(["start", "end", "complete"]),
24575
+ duration: external_exports.number().optional(),
24576
+ metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
24577
+ timestamp: external_exports.string()
24578
+ });
24579
+ var LearningPathwayValidator = external_exports.object({
24580
+ id: external_exports.string(),
24581
+ learningPathway: external_exports.object({
24582
+ stepIndex: external_exports.number(),
24583
+ step: external_exports.object({
24584
+ title: external_exports.string(),
24585
+ description: external_exports.string(),
24586
+ summary: external_exports.string(),
24587
+ learned: external_exports.array(external_exports.string()),
24588
+ skills: external_exports.array(
24589
+ external_exports.object({
24590
+ title: external_exports.string(),
24591
+ description: external_exports.string()
24592
+ })
24593
+ )
24594
+ })
24595
+ })
24596
+ });
24054
24597
 
24055
24598
  // src/plugin.ts
24056
24599
  import {
24057
24600
  getCredentialIssuerId,
24058
24601
  getCredentialStatusArray,
24059
24602
  injectManagedRefreshService as injectSharedManagedRefreshService,
24603
+ prepareManagedRefreshContext,
24604
+ isDisplayOnlyAnchorTemplate,
24060
24605
  isVC2Format,
24061
24606
  materializeCredentialFields,
24062
24607
  isEncrypted,
24063
- resolveStorageReadResult
24608
+ resolveStorageReadResult,
24609
+ assertExactJweRecipients,
24610
+ assertManagedCredentialBinding
24064
24611
  } from "@learncard/helpers";
24065
24612
 
24066
24613
  // ../../../node_modules/mustache/mustache.mjs
@@ -24671,7 +25218,14 @@ var appendNetworkCredentialStatus = /* @__PURE__ */ __name(async (client, creden
24671
25218
  credential.credentialStatus = credentialStatuses.length === 1 ? credentialStatuses[0] : credentialStatuses;
24672
25219
  return credential;
24673
25220
  }, "appendNetworkCredentialStatus");
24674
- var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard, client, credential, statusPurposes) => {
25221
+ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard, client, credential, statusPurposes, statusEntries) => {
25222
+ if (statusEntries) {
25223
+ const prepared = UnsignedVCValidator.parse({
25224
+ ...materializeCredentialFields(credential),
25225
+ credentialStatus: statusEntries.length === 1 && !Array.isArray(credential.credentialStatus) ? statusEntries[0] : statusEntries
25226
+ });
25227
+ return learnCard.invoke.issueCredential(prepareManagedRefreshContext(prepared));
25228
+ }
24675
25229
  return learnCard.invoke.issueCredential(
24676
25230
  await appendNetworkCredentialStatus(
24677
25231
  client,
@@ -24696,7 +25250,7 @@ var buildManagedRefreshReceipt = /* @__PURE__ */ __name((vc, allocation, credent
24696
25250
  const hasStatus = rawStatus !== void 0 && rawStatus !== null && !(Array.isArray(rawStatus) && rawStatus.length === 0);
24697
25251
  return {
24698
25252
  refreshId: allocation.refreshId,
24699
- refreshService: allocation.refreshService,
25253
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(vc.refreshService),
24700
25254
  credentialId: typeof vc.id === "string" && vc.id.length > 0 ? vc.id : credentialId,
24701
25255
  issuerDid,
24702
25256
  holderDid,
@@ -24705,6 +25259,40 @@ var buildManagedRefreshReceipt = /* @__PURE__ */ __name((vc, allocation, credent
24705
25259
  } : {}
24706
25260
  };
24707
25261
  }, "buildManagedRefreshReceipt");
25262
+ var HOLDER_MODE_PREPARE_UNSUPPORTED = "Server does not support holder-mode encryption (missing recipientKeyIds from prepareRefreshableSend); refusing to fall back to network-mode plaintext delivery.";
25263
+ var getPreparedRecipientKeyIds = /* @__PURE__ */ __name((prepared) => prepared.recipientKeyIds, "getPreparedRecipientKeyIds");
25264
+ var isRecipientsChangedError = /* @__PURE__ */ __name((error62) => {
25265
+ const code = error62?.data?.code;
25266
+ const message = error62?.message;
25267
+ return code === "CONFLICT" && message === "RECIPIENTS_CHANGED";
25268
+ }, "isRecipientsChangedError");
25269
+ var didFromRecipientKeyId = /* @__PURE__ */ __name((keyId) => {
25270
+ const [did] = keyId.split("#");
25271
+ if (!did) throw new Error(`Invalid recipient key id: ${keyId}`);
25272
+ return did;
25273
+ }, "didFromRecipientKeyId");
25274
+ var buildHolderEncryptedHandoff = /* @__PURE__ */ __name(async (learnCard, signedCredential, bindings, recipientKeyIds) => {
25275
+ const recipientDids = recipientKeyIds.map(didFromRecipientKeyId);
25276
+ const jwe = await learnCard.invoke.createDagJweExact?.(signedCredential, recipientDids);
25277
+ if (!jwe) {
25278
+ throw new Error(
25279
+ 'encryption: "holder" requires the Encryption plugin (createDagJweExact), which this wallet does not have.'
25280
+ );
25281
+ }
25282
+ assertExactJweRecipients(jwe, recipientKeyIds);
25283
+ return HolderEncryptedHandoffValidator.parse({ ...bindings, jwe });
25284
+ }, "buildHolderEncryptedHandoff");
25285
+ var deliverHolderEncryptedHandoff = /* @__PURE__ */ __name(async (holderClient, refreshId, recipientKeyIds, buildHandoff, deliver) => {
25286
+ const handoff2 = await buildHandoff(recipientKeyIds);
25287
+ try {
25288
+ return await deliver(handoff2);
25289
+ } catch (error62) {
25290
+ if (!isRecipientsChangedError(error62)) throw error62;
25291
+ const fresh = await holderClient.getEncryptionRecipients.query({ refreshId });
25292
+ const retryHandoff = await buildHandoff(fresh.recipientKeyIds);
25293
+ return deliver(retryHandoff);
25294
+ }
25295
+ }, "deliverHolderEncryptedHandoff");
24708
25296
  var ACT_AS_TARGET_NOT_FOUND_MESSAGE = "Act-as target profile not found";
24709
25297
  var isActAsDenial = /* @__PURE__ */ __name((error62) => {
24710
25298
  const code = error62?.data?.code;
@@ -24715,6 +25303,11 @@ var isActAsDenial = /* @__PURE__ */ __name((error62) => {
24715
25303
  return false;
24716
25304
  }, "isActAsDenial");
24717
25305
  var getInboxFailureReason = /* @__PURE__ */ __name((reason) => reason instanceof Error ? `${reason.name}: ${reason.message}` : String(reason), "getInboxFailureReason");
25306
+ var normalizePublicDisplay = /* @__PURE__ */ __name((input2) => {
25307
+ const category = input2.display?.category ?? input2.template?.category?.slice(0, 280);
25308
+ if (!input2.display && !category) return void 0;
25309
+ return { ...input2.display, ...category ? { category } : {} };
25310
+ }, "normalizePublicDisplay");
24718
25311
  async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
24719
25312
  const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
24720
25313
  const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
@@ -24801,6 +25394,13 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
24801
25394
  return _learnCard.invoke.resolveFromLCN(boostUri);
24802
25395
  }
24803
25396
  }, "getBoostTemplateForIssuance");
25397
+ const assertIssuableBoostTemplate = /* @__PURE__ */ __name((boost) => {
25398
+ if (isDisplayOnlyAnchorTemplate(boost)) {
25399
+ throw new Error(
25400
+ "This Boost is a display-only anchor and has no issuance credential. Pass `template` or `signedCredential` instead of reusing its uri as a templateUri."
25401
+ );
25402
+ }
25403
+ }, "assertIssuableBoostTemplate");
24804
25404
  const getInboxEndpointForDid = /* @__PURE__ */ __name(async (_learnCard, recipientDid) => {
24805
25405
  const serviceUrl2 = new URL(url2);
24806
25406
  const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
@@ -25593,6 +26193,124 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25593
26193
  await ensureUser();
25594
26194
  return client.credentialRefresh.getCredentialRefreshHistory.query(input2);
25595
26195
  }, "getCredentialRefreshHistory"),
26196
+ getCredentialRefreshReceipt: /* @__PURE__ */ __name(async (_learnCard, input2) => {
26197
+ await ensureUser();
26198
+ return client.credentialRefresh.getReceipt.query(input2);
26199
+ }, "getCredentialRefreshReceipt"),
26200
+ publishHolderEncryptedRefreshable: /* @__PURE__ */ __name(async (_learnCard, receipt, credential, options2) => {
26201
+ await ensureUser();
26202
+ if (!("issueCredential" in _learnCard.invoke)) {
26203
+ throw new Error(
26204
+ "Holder-mode publishing requires local signing capability, which this wallet does not have."
26205
+ );
26206
+ }
26207
+ if (!("createDagJweExact" in _learnCard.invoke)) {
26208
+ throw new Error(
26209
+ "Holder-mode publishing requires the Encryption plugin (createDagJweExact), which this wallet does not have."
26210
+ );
26211
+ }
26212
+ if (receipt.credentialStatus === void 0) {
26213
+ throw new Error(
26214
+ "Holder-mode publishing requires the original send receipt's credentialStatus binding."
26215
+ );
26216
+ }
26217
+ const boundCredentialStatus = BitstringStatusListEntryValidator.array().parse(
26218
+ Array.isArray(receipt.credentialStatus) ? receipt.credentialStatus : [receipt.credentialStatus]
26219
+ );
26220
+ let boost = JSON.parse(JSON.stringify(credential));
26221
+ const boostString = JSON.stringify(boost);
26222
+ const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
26223
+ if (options2.templateData && Object.keys(options2.templateData).length > 0) {
26224
+ try {
26225
+ const rendered = renderTemplateJson(boostString, options2.templateData);
26226
+ boost = JSON.parse(rendered);
26227
+ boost = appendTemplateEvidence(
26228
+ boost,
26229
+ options2.templateData,
26230
+ allowAutoAppendEvidence
26231
+ );
26232
+ } catch (error62) {
26233
+ throw new Error(
26234
+ `Failed to apply template data: ${error62 instanceof Error ? error62.message : "Unknown error"}`,
26235
+ { cause: error62 }
26236
+ );
26237
+ }
26238
+ }
26239
+ if (isVC2Format(boost)) {
26240
+ boost.validFrom = (/* @__PURE__ */ new Date()).toISOString();
26241
+ } else {
26242
+ boost.issuanceDate = (/* @__PURE__ */ new Date()).toISOString();
26243
+ }
26244
+ boost.issuer = receipt.issuerDid;
26245
+ boost.id = receipt.credentialId;
26246
+ if (Array.isArray(boost.credentialSubject)) {
26247
+ boost.credentialSubject = boost.credentialSubject.map((subject) => ({
26248
+ ...subject,
26249
+ id: receipt.holderDid
26250
+ }));
26251
+ } else {
26252
+ boost.credentialSubject = { ...boost.credentialSubject, id: receipt.holderDid };
26253
+ }
26254
+ if (receipt.refreshServiceBinding === "managed-entry" && !credential.refreshService) {
26255
+ throw new Error(
26256
+ "This legacy receipt does not include the original refresh service descriptor. Repair the receipt or reissue the credential before publishing."
26257
+ );
26258
+ }
26259
+ boost = prepareManagedRefreshContext({
26260
+ ...boost,
26261
+ refreshService: receipt.refreshServiceBinding === "managed-entry" ? credential.refreshService : receipt.refreshService
26262
+ });
26263
+ boost.credentialStatus = receipt.credentialStatus;
26264
+ assertManagedCredentialBinding(boost, { ...receipt, encryptionMode: "holder" });
26265
+ const signedCredential = await issueCredentialWithNetworkStatus(
26266
+ _learnCard,
26267
+ client,
26268
+ boost,
26269
+ void 0,
26270
+ boundCredentialStatus
26271
+ );
26272
+ const holderBindings = {
26273
+ refreshId: receipt.refreshId,
26274
+ credentialId: receipt.credentialId,
26275
+ holderDid: receipt.holderDid,
26276
+ issuerDid: receipt.issuerDid,
26277
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(
26278
+ boost.refreshService
26279
+ ),
26280
+ credentialStatus: BitstringStatusListEntryValidator.or(
26281
+ BitstringStatusListEntryValidator.array()
26282
+ ).parse(receipt.credentialStatus)
26283
+ };
26284
+ assertManagedCredentialBinding(signedCredential, {
26285
+ ...holderBindings,
26286
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(
26287
+ boost.refreshService
26288
+ ),
26289
+ encryptionMode: "holder"
26290
+ });
26291
+ const holderClient = client.credentialRefresh;
26292
+ const { recipientKeyIds } = await holderClient.getEncryptionRecipients.query({
26293
+ refreshId: receipt.refreshId
26294
+ });
26295
+ return deliverHolderEncryptedHandoff(
26296
+ holderClient,
26297
+ receipt.refreshId,
26298
+ recipientKeyIds,
26299
+ (keyIds) => buildHolderEncryptedHandoff(
26300
+ _learnCard,
26301
+ signedCredential,
26302
+ holderBindings,
26303
+ keyIds
26304
+ ),
26305
+ (handoff2) => holderClient.publishHolderEncryptedRefreshable.mutate({
26306
+ handoff: handoff2,
26307
+ notify: options2.notify,
26308
+ ...options2.updateSummary !== void 0 ? { updateSummary: options2.updateSummary } : {},
26309
+ ...options2.updateReason !== void 0 ? { updateReason: options2.updateReason } : {},
26310
+ ...options2.idempotencyKey !== void 0 ? { idempotencyKey: options2.idempotencyKey } : {}
26311
+ })
26312
+ );
26313
+ }, "publishHolderEncryptedRefreshable"),
25596
26314
  revokeBoostRecipient: /* @__PURE__ */ __name(async (_learnCard, boostUri, recipientProfileId, credentialUri) => {
25597
26315
  await ensureUser();
25598
26316
  const input2 = { boostUri, recipientProfileId };
@@ -25618,6 +26336,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25618
26336
  sendBoost: /* @__PURE__ */ __name(async (_learnCard, profileId, boostUri, options2 = { encrypt: true, skipNotification: false, templateData: {} }) => {
25619
26337
  await ensureUser();
25620
26338
  const result = await getBoostTemplateForIssuance(_learnCard, boostUri);
26339
+ assertIssuableBoostTemplate(result);
25621
26340
  const data = await UnsignedVCValidator.spa(result);
25622
26341
  if (!data.success) throw new Error("Did not get a valid boost from URI");
25623
26342
  const targetProfile = await _learnCard.invoke.getProfile(profileId);
@@ -25758,18 +26477,65 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25758
26477
  }, "claimBoostWithLink"),
25759
26478
  send: /* @__PURE__ */ __name(async (_learnCard, input2) => {
25760
26479
  await ensureUser();
26480
+ if (input2.type === "boost" && input2.encryption === "holder" && input2.refresh !== true) {
26481
+ throw new Error(
26482
+ 'encryption: "holder" requires refresh: true; holder-mode encryption is only defined for managed refresh sends.'
26483
+ );
26484
+ }
25761
26485
  if (input2.type === "boost" && input2.refresh === true) {
25762
26486
  const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input2.recipient);
25763
26487
  const isPhone = /^\+?[\d\s-]{10,}$/.test(input2.recipient.replace(/[\s-]/g, ""));
25764
- if (isEmail || isPhone) return client.boost.send.mutate(input2);
26488
+ const isHolderEncryption = input2.encryption === "holder";
26489
+ if (isHolderEncryption && (isEmail || isPhone)) {
26490
+ throw new Error(
26491
+ 'encryption: "holder" does not support inbox (email or phone) recipients; use a profile ID or DID recipient instead.'
26492
+ );
26493
+ }
26494
+ if (isHolderEncryption && input2.signedCredential) {
26495
+ throw new Error(
26496
+ 'encryption: "holder" does not support signedCredential; the SDK must sign locally so the server never receives plaintext.'
26497
+ );
26498
+ }
26499
+ const request = {
26500
+ type: "boost",
26501
+ recipient: input2.recipient,
26502
+ templateUri: input2.templateUri,
26503
+ template: input2.template,
26504
+ signedCredential: input2.signedCredential,
26505
+ display: normalizePublicDisplay(input2),
26506
+ statusPurposes: input2.statusPurposes,
26507
+ contractUri: input2.contractUri,
26508
+ templateData: input2.templateData,
26509
+ integrationId: input2.integrationId,
26510
+ options: input2.options,
26511
+ idempotencyKey: input2.idempotencyKey,
26512
+ refresh: true
26513
+ };
26514
+ if (isEmail || isPhone) return client.boost.send.mutate(request);
25765
26515
  const canIssueLocally = "issueCredential" in _learnCard.invoke;
26516
+ if (isHolderEncryption && !canIssueLocally) {
26517
+ throw new Error(
26518
+ 'encryption: "holder" requires local signing capability, which this wallet does not have.'
26519
+ );
26520
+ }
26521
+ if (isHolderEncryption && !("createDagJweExact" in _learnCard.invoke)) {
26522
+ throw new Error(
26523
+ 'encryption: "holder" requires the Encryption plugin (createDagJweExact), which this wallet does not have.'
26524
+ );
26525
+ }
25766
26526
  if (canIssueLocally && !input2.signedCredential && (input2.templateUri || input2.template)) {
25767
26527
  let boost;
26528
+ if (input2.template?.status === "DRAFT") {
26529
+ throw new Error(
26530
+ "Draft Boosts cannot be sent. Publish the template first."
26531
+ );
26532
+ }
25768
26533
  if (input2.templateUri) {
25769
26534
  const result = await getBoostTemplateForIssuance(
25770
26535
  _learnCard,
25771
26536
  input2.templateUri
25772
26537
  );
26538
+ assertIssuableBoostTemplate(result);
25773
26539
  const data = await UnsignedVCValidator.spa(result);
25774
26540
  if (!data.success)
25775
26541
  throw new Error("Did not get a valid boost from URI");
@@ -25780,15 +26546,21 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25780
26546
  );
25781
26547
  }
25782
26548
  const prepared = await client.boost.prepareRefreshableSend.mutate({
26549
+ ...boost.credentialStatus ? {} : { statusBinding: "server" },
26550
+ ...input2.statusPurposes ? { statusPurposes: input2.statusPurposes } : {},
25783
26551
  recipient: input2.recipient,
25784
- ...input2.templateUri ? { templateUri: input2.templateUri } : { template: input2.template },
26552
+ templateUri: input2.templateUri,
26553
+ display: normalizePublicDisplay(input2),
25785
26554
  ...input2.contractUri ? { contractUri: input2.contractUri } : {},
25786
- ...input2.templateData ? { templateData: input2.templateData } : {},
25787
26555
  ...input2.integrationId ? { integrationId: input2.integrationId } : {},
25788
26556
  ...boost.id ? { credentialId: boost.id } : {},
25789
- ...input2.idempotencyKey ? { idempotencyKey: input2.idempotencyKey } : {}
26557
+ ...input2.idempotencyKey ? { idempotencyKey: input2.idempotencyKey } : {},
26558
+ ...isHolderEncryption ? { encryption: "holder" } : {}
25790
26559
  });
25791
26560
  if (prepared.completed) return prepared.completed;
26561
+ if (isHolderEncryption && !getPreparedRecipientKeyIds(prepared)) {
26562
+ throw new Error(HOLDER_MODE_PREPARE_UNSUPPORTED);
26563
+ }
25792
26564
  const boostString = JSON.stringify(boost);
25793
26565
  const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
25794
26566
  if (input2.templateData && Object.keys(input2.templateData).length > 0) {
@@ -25831,20 +26603,89 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25831
26603
  if (boost.type?.includes("BoostCredential"))
25832
26604
  boost.boostId = prepared.boostUri;
25833
26605
  boost = injectManagedRefreshService(boost, prepared.refreshService);
25834
- const signedCredential = await issueCredentialWithNetworkStatus(
26606
+ if (isHolderEncryption && !prepared.statusEntries?.length && !boost.credentialStatus) {
26607
+ throw new Error(
26608
+ "Server did not bind status entries for this holder-mode send; refusing to send a managed credential without a public status binding."
26609
+ );
26610
+ }
26611
+ const signedCredential = boost.credentialStatus ? await _learnCard.invoke.issueCredential(
26612
+ prepareManagedRefreshContext(
26613
+ UnsignedVCValidator.parse(materializeCredentialFields(boost))
26614
+ )
26615
+ ) : await issueCredentialWithNetworkStatus(
25835
26616
  _learnCard,
25836
26617
  client,
25837
- boost
26618
+ boost,
26619
+ input2.statusPurposes ? [
26620
+ .../* @__PURE__ */ new Set([
26621
+ "revocation",
26622
+ ...input2.statusPurposes
26623
+ ])
26624
+ ] : void 0,
26625
+ prepared.statusEntries
25838
26626
  );
25839
- return client.boost.send.mutate({
25840
- ...input2,
25841
- template: void 0,
25842
- templateUri: prepared.boostUri,
25843
- signedCredential,
25844
- refresh: true
26627
+ if (!isHolderEncryption) {
26628
+ return client.boost.send.mutate({
26629
+ type: "boost",
26630
+ recipient: input2.recipient,
26631
+ display: normalizePublicDisplay(input2),
26632
+ statusPurposes: input2.statusPurposes,
26633
+ contractUri: input2.contractUri,
26634
+ integrationId: input2.integrationId,
26635
+ idempotencyKey: input2.idempotencyKey,
26636
+ templateUri: prepared.boostUri,
26637
+ signedCredential,
26638
+ refresh: true
26639
+ });
26640
+ }
26641
+ const initialRecipientKeyIds = getPreparedRecipientKeyIds(prepared);
26642
+ if (!initialRecipientKeyIds) {
26643
+ throw new Error(HOLDER_MODE_PREPARE_UNSUPPORTED);
26644
+ }
26645
+ const boundCredentialStatus = BitstringStatusListEntryValidator.or(
26646
+ BitstringStatusListEntryValidator.array()
26647
+ ).parse(signedCredential.credentialStatus);
26648
+ const holderBindings = {
26649
+ refreshId: prepared.refreshId,
26650
+ credentialId: prepared.credentialId,
26651
+ holderDid: prepared.holderDid,
26652
+ issuerDid: _learnCard.id.did(),
26653
+ credentialStatus: boundCredentialStatus,
26654
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(
26655
+ signedCredential.refreshService
26656
+ )
26657
+ };
26658
+ assertManagedCredentialBinding(signedCredential, {
26659
+ ...holderBindings,
26660
+ encryptionMode: "holder"
25845
26661
  });
26662
+ const holderClient = client.credentialRefresh;
26663
+ const delivered = await deliverHolderEncryptedHandoff(
26664
+ holderClient,
26665
+ prepared.refreshId,
26666
+ initialRecipientKeyIds,
26667
+ (recipientKeyIds) => buildHolderEncryptedHandoff(
26668
+ _learnCard,
26669
+ signedCredential,
26670
+ holderBindings,
26671
+ recipientKeyIds
26672
+ ),
26673
+ (handoff2) => holderClient.sendHolderEncryptedRefreshable.mutate({
26674
+ handoff: handoff2,
26675
+ boostUri: prepared.boostUri,
26676
+ idempotencyKey: input2.idempotencyKey
26677
+ })
26678
+ );
26679
+ return {
26680
+ type: "boost",
26681
+ uri: prepared.boostUri,
26682
+ credentialUri: delivered.uri,
26683
+ activityId: delivered.activityId,
26684
+ statusManagement: delivered.statusManagement,
26685
+ refresh: holderBindings
26686
+ };
25846
26687
  }
25847
- return client.boost.send.mutate(input2);
26688
+ return client.boost.send.mutate(request);
25848
26689
  }
25849
26690
  if (input2.type === "boost") {
25850
26691
  const recipient = input2.recipient;
@@ -25857,6 +26698,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25857
26698
  const isRemoteDidWebRecipient = recipient.startsWith("did:web:") && recipientDomain !== serviceDomain;
25858
26699
  if (isRemoteDidWebRecipient && input2.templateUri) {
25859
26700
  const boostRecord = await _learnCard.invoke.getBoost(input2.templateUri);
26701
+ assertIssuableBoostTemplate(boostRecord.boost);
25860
26702
  let boost = boostRecord.boost;
25861
26703
  const boostString = JSON.stringify(boost);
25862
26704
  const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
@@ -25917,6 +26759,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25917
26759
  _learnCard,
25918
26760
  input2.templateUri
25919
26761
  );
26762
+ assertIssuableBoostTemplate(result);
25920
26763
  const data = await UnsignedVCValidator.spa(result);
25921
26764
  if (data.success) {
25922
26765
  let targetDid;
@@ -26002,17 +26845,29 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26002
26845
  await ensureUser();
26003
26846
  return client.contracts.createConsentFlowContract.mutate(contract);
26004
26847
  }, "createContract"),
26005
- addAutoBoostsToContract: /* @__PURE__ */ __name(async (_learnCard, contractUri, autoboosts) => {
26006
- await ensureUser();
26007
- return client.contracts.addAutoBoostsToContract.mutate({ contractUri, autoboosts });
26008
- }, "addAutoBoostsToContract"),
26009
- removeAutoBoostsFromContract: /* @__PURE__ */ __name(async (_learnCard, contractUri, boostUris) => {
26848
+ updateContract: /* @__PURE__ */ __name(async (_learnCard, uri, changes, options2 = {}) => {
26849
+ const { read, write, contract, ...details } = changes;
26850
+ if (read && contract?.read || write && contract?.write) {
26851
+ throw new Error(
26852
+ "Contract read/write updates must use either the top-level or nested contract shape, not both."
26853
+ );
26854
+ }
26010
26855
  await ensureUser();
26011
- return client.contracts.removeAutoBoostsFromContract.mutate({
26012
- contractUri,
26013
- boostUris
26856
+ return client.contracts.updateConsentFlowContract.mutate({
26857
+ uri,
26858
+ changes: {
26859
+ ...details,
26860
+ ...(contract || read || write) && {
26861
+ contract: {
26862
+ ...contract,
26863
+ ...read && { read },
26864
+ ...write && { write }
26865
+ }
26866
+ }
26867
+ },
26868
+ ...options2
26014
26869
  });
26015
- }, "removeAutoBoostsFromContract"),
26870
+ }, "updateContract"),
26016
26871
  addContractRecipient: /* @__PURE__ */ __name(async (_learnCard, contractUri, recipient) => {
26017
26872
  await ensureUser();
26018
26873
  return client.contracts.addContractRecipient.mutate({ contractUri, recipient });
@@ -26024,6 +26879,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26024
26879
  getContract: /* @__PURE__ */ __name(async (_learnCard, uri) => {
26025
26880
  return client.contracts.getConsentFlowContract.query({ uri });
26026
26881
  }, "getContract"),
26882
+ getContractVersions: /* @__PURE__ */ __name(async (_learnCard, uri) => {
26883
+ await ensureUser();
26884
+ return client.contracts.getContractVersions.query({ uri });
26885
+ }, "getContractVersions"),
26886
+ getConsentStatus: /* @__PURE__ */ __name(async (_learnCard, uri, profileId) => {
26887
+ await ensureUser();
26888
+ return client.contracts.getConsentStatus.query({ uri, profileId });
26889
+ }, "getConsentStatus"),
26027
26890
  getContracts: /* @__PURE__ */ __name(async (_learnCard, options2) => {
26028
26891
  await ensureUser();
26029
26892
  return client.contracts.getConsentFlowContracts.query(options2);
@@ -26080,6 +26943,15 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26080
26943
  audienceVersion
26081
26944
  });
26082
26945
  }, "updateContractTerms"),
26946
+ acceptContractUpdate: /* @__PURE__ */ __name(async (_learnCard, uri, { version: version2, terms, audienceVersion }) => {
26947
+ await ensureUser();
26948
+ return client.contracts.updateConsentedContractTerms.mutate({
26949
+ uri,
26950
+ terms,
26951
+ acceptVersion: version2,
26952
+ audienceVersion
26953
+ });
26954
+ }, "acceptContractUpdate"),
26083
26955
  withdrawConsent: /* @__PURE__ */ __name(async (_learnCard, uri) => {
26084
26956
  await ensureUser();
26085
26957
  return client.contracts.withdrawConsent.mutate({ uri });
@@ -26357,7 +27229,13 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26357
27229
  );
26358
27230
  return [];
26359
27231
  });
26360
- return { ...result, records, failed: results.length - records.length };
27232
+ const { cursor, ...page } = result;
27233
+ return {
27234
+ ...page,
27235
+ ...cursor === void 0 ? {} : { cursor },
27236
+ records,
27237
+ failed: results.length - records.length
27238
+ };
26361
27239
  }, "recoverInboxCredentials"),
26362
27240
  sendGuardianApprovalEmail: /* @__PURE__ */ __name(async (_learnCard, options2) => {
26363
27241
  await ensureUser();
@@ -26714,10 +27592,33 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26714
27592
  await ensureUser();
26715
27593
  return client.appStore.isAdmin.query();
26716
27594
  }, "isAppStoreAdmin"),
27595
+ getAnnouncementPreferences: /* @__PURE__ */ __name(async (_learnCard) => {
27596
+ await ensureUser();
27597
+ return client.campaigns.getAnnouncementPreferences.query();
27598
+ }, "getAnnouncementPreferences"),
27599
+ updateAnnouncementPreferences: /* @__PURE__ */ __name(async (_learnCard, updates) => {
27600
+ await ensureUser();
27601
+ return client.campaigns.updateAnnouncementPreferences.mutate(updates);
27602
+ }, "updateAnnouncementPreferences"),
27603
+ unsubscribeFromAnnouncements: /* @__PURE__ */ __name(async (_learnCard, token) => {
27604
+ return getAnonymousClient(url2).campaigns.unsubscribe.mutate({ token });
27605
+ }, "unsubscribeFromAnnouncements"),
26717
27606
  campaignsIsAdmin: /* @__PURE__ */ __name(async (_learnCard) => {
26718
27607
  await ensureUser();
26719
27608
  return client.campaigns.isAdmin.query();
26720
27609
  }, "campaignsIsAdmin"),
27610
+ campaignsSendTestToMe: /* @__PURE__ */ __name(async (_learnCard, campaignId) => {
27611
+ await ensureUser();
27612
+ return client.campaigns.sendTestToMe.mutate({ campaignId });
27613
+ }, "campaignsSendTestToMe"),
27614
+ campaignsPreviewDispatch: /* @__PURE__ */ __name(async (_learnCard, campaignId) => {
27615
+ await ensureUser();
27616
+ return client.campaigns.previewDispatch.query({ campaignId });
27617
+ }, "campaignsPreviewDispatch"),
27618
+ campaignsDispatch: /* @__PURE__ */ __name(async (_learnCard, campaignId, options2 = {}) => {
27619
+ await ensureUser();
27620
+ return client.campaigns.dispatch.mutate({ campaignId, ...options2 });
27621
+ }, "campaignsDispatch"),
26721
27622
  campaignsCreate: /* @__PURE__ */ __name(async (_learnCard, input2) => {
26722
27623
  await ensureUser();
26723
27624
  return client.campaigns.create.mutate(input2);
@@ -26760,11 +27661,21 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26760
27661
  }, "campaignsGetStats"),
26761
27662
  getMyCampaigns: /* @__PURE__ */ __name(async (_learnCard) => {
26762
27663
  await ensureUser();
26763
- return client.campaigns.getMyCampaigns.query();
27664
+ const response = await client.campaigns.getMyCampaigns.query();
27665
+ if (!Array.isArray(response))
27666
+ throw new Error("Invalid campaigns response: expected an array");
27667
+ return response.flatMap((item) => {
27668
+ const result = MyCampaignValidator.safeParse(item);
27669
+ return result.success ? [result.data] : [];
27670
+ });
26764
27671
  }, "getMyCampaigns"),
26765
- recordCampaignEvent: /* @__PURE__ */ __name(async (_learnCard, campaignId, event) => {
27672
+ recordCampaignEvent: /* @__PURE__ */ __name(async (_learnCard, campaignId, event, testId) => {
26766
27673
  await ensureUser();
26767
- return client.campaigns.recordEvent.mutate({ campaignId, event });
27674
+ return client.campaigns.recordEvent.mutate({
27675
+ campaignId,
27676
+ event,
27677
+ ...testId ? { testId } : {}
27678
+ });
26768
27679
  }, "recordCampaignEvent"),
26769
27680
  enrollInCampaign: /* @__PURE__ */ __name(async (_learnCard, campaignId) => {
26770
27681
  await ensureUser();