@learncard/network-plugin 3.2.2 → 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.
@@ -21052,12 +21052,46 @@ var StringQuery = external_exports.union([
21052
21052
  $or: BaseStringQuery.array()
21053
21053
  })
21054
21054
  ]);
21055
+ var BITSTRING_STATUS_PURPOSES = ["revocation", "suspension"];
21056
+ var BitstringStatusPurposeValidator = external_exports.enum(BITSTRING_STATUS_PURPOSES);
21057
+ var BitstringStatusListEntryValidator = external_exports.object({
21058
+ id: external_exports.string().optional(),
21059
+ type: external_exports.literal("BitstringStatusListEntry"),
21060
+ statusPurpose: BitstringStatusPurposeValidator,
21061
+ statusListIndex: external_exports.string().or(external_exports.number().int().nonnegative()),
21062
+ statusListCredential: external_exports.string()
21063
+ });
21064
+ var AllocatedBitstringStatusListEntryValidator = BitstringStatusListEntryValidator.extend({
21065
+ id: external_exports.string()
21066
+ });
21067
+ var BitstringStatusListCredentialSubjectValidator = external_exports.object({
21068
+ id: external_exports.string().optional(),
21069
+ type: external_exports.literal("BitstringStatusList"),
21070
+ statusPurpose: BitstringStatusPurposeValidator,
21071
+ encodedList: external_exports.string()
21072
+ });
21073
+ var AllocateCredentialStatusInputValidator = external_exports.object({
21074
+ statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
21075
+ listSize: external_exports.number().int().positive().optional()
21076
+ }).default({});
21077
+ var AttachCredentialRefreshStatusEntriesInputValidator = external_exports.object({
21078
+ refreshId: external_exports.string().min(1),
21079
+ credentialStatus: CredentialStatusValidator.or(CredentialStatusValidator.array()).nullable()
21080
+ });
21055
21081
  var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
21056
21082
  var ManagedCredentialRefreshServiceValidator = external_exports.object({
21057
21083
  id: external_exports.string().min(1),
21058
21084
  type: external_exports.literal("LearnCardCredentialRefresh2026"),
21059
21085
  authorization: LearnCardRefreshAuthorizationValidator.optional()
21060
21086
  }).catchall(external_exports.any());
21087
+ var ManagedCredentialRefreshBindingValidator = ManagedCredentialRefreshServiceValidator.or(
21088
+ RefreshServiceValidator.array().refine(
21089
+ (services) => services.some(
21090
+ (service) => ManagedCredentialRefreshServiceValidator.safeParse(service).success
21091
+ ),
21092
+ "A managed refresh service is required"
21093
+ )
21094
+ );
21061
21095
  var StandardCredentialRefreshServiceValidator = external_exports.object({
21062
21096
  id: external_exports.string().min(1),
21063
21097
  type: external_exports.literal("1EdTechCredentialRefresh")
@@ -21081,7 +21115,9 @@ var AllocateCredentialRefreshResultValidator = external_exports.object({
21081
21115
  });
21082
21116
  var ManagedCredentialRefreshReceiptValidator = external_exports.object({
21083
21117
  refreshId: external_exports.string().min(1),
21084
- refreshService: ManagedCredentialRefreshServiceValidator,
21118
+ refreshService: ManagedCredentialRefreshBindingValidator,
21119
+ /** Legacy receipts authenticate only the allocated managed entry, not other services. */
21120
+ refreshServiceBinding: external_exports.literal("managed-entry").optional(),
21085
21121
  credentialId: external_exports.string().min(1),
21086
21122
  issuerDid: external_exports.string().min(1),
21087
21123
  holderDid: external_exports.string().min(1),
@@ -21089,14 +21125,43 @@ var ManagedCredentialRefreshReceiptValidator = external_exports.object({
21089
21125
  CredentialStatusValidator.array()
21090
21126
  ).optional()
21091
21127
  }).strip();
21128
+ var GetCredentialRefreshReceiptInputValidator = external_exports.object({ uri: external_exports.string().min(1) });
21129
+ var CredentialRefreshReceiptValidator = ManagedCredentialRefreshReceiptValidator.extend({
21130
+ encryptionMode: external_exports.enum(["network", "holder"])
21131
+ });
21132
+ var HolderEncryptedHandoffValidator = external_exports.object({
21133
+ refreshId: external_exports.string().min(1),
21134
+ credentialId: external_exports.string().min(1),
21135
+ holderDid: external_exports.string().min(1),
21136
+ issuerDid: external_exports.string().min(1),
21137
+ credentialStatus: CredentialStatusValidator.or(CredentialStatusValidator.array()),
21138
+ refreshService: ManagedCredentialRefreshBindingValidator.optional(),
21139
+ jwe: JWEValidator
21140
+ }).strict();
21141
+ var SendHolderEncryptedRefreshableInputValidator = external_exports.object({
21142
+ handoff: HolderEncryptedHandoffValidator,
21143
+ idempotencyKey: external_exports.string().min(1).optional(),
21144
+ boostUri: external_exports.string().optional(),
21145
+ skipNotification: external_exports.boolean().optional()
21146
+ });
21147
+ var GetEncryptionRecipientsInputValidator = external_exports.object({ refreshId: external_exports.string().min(1) });
21148
+ var EncryptionRecipientsResultValidator = external_exports.object({
21149
+ recipientKeyIds: external_exports.array(external_exports.string())
21150
+ });
21092
21151
  var InboxCredentialRefreshReceiptValidator = ManagedCredentialRefreshReceiptValidator.omit(
21093
21152
  { holderDid: true }
21094
21153
  ).extend({ holderDid: external_exports.string().min(1).optional() });
21095
21154
  var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
21155
+ var CredentialRefreshUpdateReasonValidator = external_exports.enum(["corrected", "updated", "reissued"]);
21096
21156
  var PublishCredentialRefreshBaseFields = {
21097
21157
  refreshId: external_exports.string().min(1),
21098
21158
  notifyHolder: external_exports.boolean().optional(),
21099
- updateSummary: external_exports.string().optional(),
21159
+ updateSummary: external_exports.string().max(280).optional().describe(
21160
+ "Public legacy update summary. Do not include private claims; prefer updateReason."
21161
+ ),
21162
+ updateReason: CredentialRefreshUpdateReasonValidator.optional().describe(
21163
+ "Public reason for this update"
21164
+ ),
21100
21165
  idempotencyKey: external_exports.string().optional()
21101
21166
  };
21102
21167
  var PublishIssuerSignedRefreshValidator = external_exports.object({
@@ -21172,13 +21237,25 @@ var PublishCredentialRefreshResultValidator = external_exports.object({
21172
21237
  publishedAt: external_exports.string().min(1),
21173
21238
  notification: PublishCredentialRefreshNotificationValidator
21174
21239
  });
21240
+ var PublishHolderEncryptedRefreshInputValidator = external_exports.object({
21241
+ handoff: HolderEncryptedHandoffValidator,
21242
+ notify: external_exports.boolean(),
21243
+ updateSummary: external_exports.string().max(280).optional().describe(
21244
+ "Public legacy update summary. Do not include private claims; prefer updateReason."
21245
+ ),
21246
+ updateReason: CredentialRefreshUpdateReasonValidator.optional().describe(
21247
+ "Public reason for this update"
21248
+ ),
21249
+ idempotencyKey: external_exports.string().optional()
21250
+ });
21175
21251
  var CredentialRefreshVersionMetadataValidator = external_exports.object({
21176
21252
  version: external_exports.number().int().positive(),
21177
21253
  publishedAt: external_exports.string().min(1),
21178
21254
  effectiveAt: external_exports.string().optional(),
21179
21255
  etag: external_exports.string().optional(),
21180
21256
  signingMode: CredentialRefreshSigningModeValidator.optional(),
21181
- updateSummary: external_exports.string().optional()
21257
+ updateSummary: external_exports.string().optional(),
21258
+ updateReason: CredentialRefreshUpdateReasonValidator.optional()
21182
21259
  });
21183
21260
  var GetCredentialRefreshHistoryInputValidator = external_exports.object({
21184
21261
  refreshId: external_exports.string().min(1),
@@ -21221,6 +21298,7 @@ var CredentialRefreshFailureCodeValidator = external_exports.enum([
21221
21298
  "INVALID_PROOF",
21222
21299
  "ISSUER_MISMATCH",
21223
21300
  "ID_MISMATCH",
21301
+ "BINDING_MISMATCH",
21224
21302
  "ROLLBACK",
21225
21303
  "REVOKED",
21226
21304
  "UNSAFE_ENDPOINT"
@@ -21545,6 +21623,11 @@ var AutoBoostConfigValidator = external_exports.object({
21545
21623
  name: external_exports.string()
21546
21624
  })
21547
21625
  });
21626
+ var CredentialDisplayValidator = external_exports.object({
21627
+ name: external_exports.string().trim().min(1).max(280).optional(),
21628
+ category: external_exports.string().max(280).optional(),
21629
+ image: external_exports.string().max(2048).url().refine((url2) => url2.startsWith("https://"), { message: "Image URL must use https" }).optional()
21630
+ });
21548
21631
  var SendBoostTemplateValidator = BoostValidator.partial().omit({ uri: true, claimPermissions: true }).extend({
21549
21632
  credential: VCValidator.or(UnsignedVCValidator),
21550
21633
  claimPermissions: BoostPermissionsValidator.partial().optional(),
@@ -21583,6 +21666,10 @@ var SendBoostInputValidator = external_exports.object({
21583
21666
  templateUri: external_exports.string().optional(),
21584
21667
  template: SendBoostTemplateValidator.optional(),
21585
21668
  signedCredential: VCValidator.optional(),
21669
+ display: CredentialDisplayValidator.optional().describe(
21670
+ "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."
21671
+ ),
21672
+ statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
21586
21673
  options: SendOptionsValidator.optional().describe(
21587
21674
  "Options for email/phone recipients (Universal Inbox)"
21588
21675
  ),
@@ -21621,7 +21708,10 @@ var SendInboxResponseValidator = external_exports.object({
21621
21708
  "Present when guardianEmail was specified"
21622
21709
  )
21623
21710
  });
21711
+ var StatusManagementValidator = external_exports.enum(["network", "external", "mixed", "none"]);
21624
21712
  var SendBoostResponseValidator = external_exports.object({
21713
+ /** Public status providers for a managed send; external entries require provider-side updates. */
21714
+ statusManagement: StatusManagementValidator.optional(),
21625
21715
  type: external_exports.literal("boost"),
21626
21716
  credentialUri: external_exports.string(),
21627
21717
  uri: external_exports.string(),
@@ -21634,19 +21724,33 @@ var SendBoostResponseValidator = external_exports.object({
21634
21724
  )
21635
21725
  });
21636
21726
  var PrepareRefreshableSendInputValidator = external_exports.object({
21727
+ /** Opt in to signing the server-bound statusEntries; omission preserves client allocation. */
21728
+ statusBinding: external_exports.literal("server").optional(),
21729
+ statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
21637
21730
  recipient: external_exports.string(),
21638
21731
  templateUri: external_exports.string().optional(),
21639
21732
  template: SendBoostTemplateValidator.optional(),
21733
+ display: CredentialDisplayValidator.optional().describe("Public display metadata only"),
21640
21734
  contractUri: external_exports.string().optional(),
21641
21735
  templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
21642
21736
  integrationId: external_exports.string().optional(),
21643
21737
  /** Credential ID to allocate for; generated server-side when omitted. */
21644
21738
  credentialId: external_exports.string().min(1).optional(),
21645
- idempotencyKey: external_exports.string().min(1).max(200).optional()
21646
- }).refine((data) => Boolean(data.templateUri) !== Boolean(data.template), {
21647
- message: "Provide exactly one of templateUri or template."
21739
+ idempotencyKey: external_exports.string().min(1).max(200).optional(),
21740
+ /**
21741
+ * `'holder'` requests student-only encryption (LC-2345): the SDK signs and
21742
+ * encrypts locally and the server never receives plaintext. Requires a
21743
+ * profile or DID recipient; rejected for signedCredential-only sends and for
21744
+ * inbox (email/phone) recipients. Defaults to `'network'`.
21745
+ */
21746
+ encryption: external_exports.enum(["network", "holder"]).optional()
21747
+ }).refine((data) => !(data.templateUri && data.template), {
21748
+ message: "Provide at most one of templateUri or template."
21648
21749
  });
21649
21750
  var PrepareRefreshableSendResultValidator = external_exports.object({
21751
+ /** Public status providers known at preparation; final send reports the signed entries. */
21752
+ statusManagement: StatusManagementValidator.optional(),
21753
+ statusEntries: external_exports.array(BitstringStatusListEntryValidator).optional(),
21650
21754
  boostUri: external_exports.string(),
21651
21755
  credentialId: external_exports.string(),
21652
21756
  refreshId: external_exports.string(),
@@ -21654,11 +21758,110 @@ var PrepareRefreshableSendResultValidator = external_exports.object({
21654
21758
  /** The DID to use as credentialSubject.id (recipient DID, or the profile's did:web). */
21655
21759
  holderDid: external_exports.string(),
21656
21760
  /** Present when this idempotencyKey already completed: return it without signing. */
21657
- completed: SendBoostResponseValidator.optional()
21761
+ completed: SendBoostResponseValidator.optional(),
21762
+ /**
21763
+ * Present only when `encryption: 'holder'` was requested: the exact
21764
+ * key-agreement verification-method ids (holder + current managers) the SDK
21765
+ * must encrypt to. Recomputed on every call, so a later manager change can
21766
+ * make a previously-prepared set stale (see `credentialRefresh.sendHolderEncryptedRefreshable`
21767
+ * and `credentialRefresh.getEncryptionRecipients`).
21768
+ */
21769
+ recipientKeyIds: external_exports.array(external_exports.string()).optional()
21658
21770
  });
21659
21771
  var SendInputValidator = external_exports.discriminatedUnion("type", [SendBoostInputValidator]);
21660
21772
  var SendResponseValidator = external_exports.discriminatedUnion("type", [SendBoostResponseValidator]);
21661
- var ConsentFlowTermsStatusValidator = external_exports.enum(["live", "stale", "withdrawn"]);
21773
+ var ConsentFlowTermsStatusValidator = external_exports.enum([
21774
+ "live",
21775
+ "consumed",
21776
+ "withdrawn",
21777
+ "needs_reconsent",
21778
+ "suspended"
21779
+ ]);
21780
+ var ConsentFlowContractChangeKindValidator = external_exports.enum([
21781
+ "relaxed",
21782
+ "expanded_optional",
21783
+ "requires_consent"
21784
+ ]);
21785
+ var ConsentFlowContractScopeValidator = external_exports.object({
21786
+ area: external_exports.enum(["read", "write"]),
21787
+ type: external_exports.enum(["credential", "personal"]),
21788
+ key: external_exports.string(),
21789
+ required: external_exports.boolean(),
21790
+ reason: external_exports.string().optional()
21791
+ });
21792
+ var ConsentFlowContractDetailValueValidator = external_exports.union([
21793
+ external_exports.string(),
21794
+ external_exports.boolean(),
21795
+ external_exports.string().array()
21796
+ ]);
21797
+ var ConsentFlowContractDetailChangeValidator = external_exports.object({
21798
+ field: external_exports.enum([
21799
+ "name",
21800
+ "subtitle",
21801
+ "description",
21802
+ "reasonForAccessing",
21803
+ "image",
21804
+ "needsGuardianConsent",
21805
+ "redirectUrl",
21806
+ "frontDoorBoostUri",
21807
+ "expiresAt",
21808
+ "writers",
21809
+ "autoboosts"
21810
+ ]),
21811
+ before: ConsentFlowContractDetailValueValidator.optional(),
21812
+ after: ConsentFlowContractDetailValueValidator.optional()
21813
+ });
21814
+ var ConsentFlowContractDiffValidator = external_exports.object({
21815
+ added: ConsentFlowContractScopeValidator.array(),
21816
+ removed: ConsentFlowContractScopeValidator.array(),
21817
+ changed: ConsentFlowContractScopeValidator.array(),
21818
+ details: ConsentFlowContractDetailChangeValidator.array().optional()
21819
+ });
21820
+ var ConsentFlowContractUpdatePreviewValidator = external_exports.object({
21821
+ headline: external_exports.string(),
21822
+ subhead: external_exports.string(),
21823
+ rows: external_exports.array(
21824
+ external_exports.object({
21825
+ scope: ConsentFlowContractScopeValidator,
21826
+ change: external_exports.enum(["added", "removed", "changed"]),
21827
+ label: external_exports.string(),
21828
+ subtitle: external_exports.string()
21829
+ })
21830
+ ),
21831
+ primaryLabel: external_exports.string()
21832
+ });
21833
+ var ConsentFlowContractStatusValidator = external_exports.enum(["active", "retired"]);
21834
+ var ConsentFlowContractVersionValidator = external_exports.object({
21835
+ version: external_exports.number().int().positive(),
21836
+ createdAt: external_exports.string(),
21837
+ reason: external_exports.string().optional(),
21838
+ kind: ConsentFlowContractChangeKindValidator.optional()
21839
+ });
21840
+ var ConsentFlowContractUpdateResultValidator = external_exports.object({
21841
+ version: external_exports.number().int().positive(),
21842
+ kind: ConsentFlowContractChangeKindValidator,
21843
+ affectedUsers: external_exports.number().int().nonnegative(),
21844
+ preview: ConsentFlowContractUpdatePreviewValidator
21845
+ });
21846
+ var ConsentFlowConsentStatusValidator = external_exports.object({
21847
+ status: ConsentFlowTermsStatusValidator.or(external_exports.literal("not_consented")),
21848
+ consentedVersion: external_exports.number().int().positive().optional(),
21849
+ currentVersion: external_exports.number().int().positive(),
21850
+ needsReconsent: external_exports.boolean(),
21851
+ reviewUrl: external_exports.string().optional()
21852
+ });
21853
+ var ConsentFlowContractNotificationDataValidator = external_exports.object({
21854
+ contractUri: external_exports.string(),
21855
+ contractName: external_exports.string().optional(),
21856
+ fromVersion: external_exports.number().int().positive(),
21857
+ toVersion: external_exports.number().int().positive(),
21858
+ kind: ConsentFlowContractChangeKindValidator,
21859
+ reason: external_exports.string().optional(),
21860
+ diff: ConsentFlowContractDiffValidator,
21861
+ reconsentDeadline: external_exports.string().optional(),
21862
+ reviewUrl: external_exports.string(),
21863
+ preview: ConsentFlowContractUpdatePreviewValidator.optional()
21864
+ });
21662
21865
  var ConsentFlowContractValidator = external_exports.object({
21663
21866
  read: external_exports.object({
21664
21867
  anonymize: external_exports.boolean().optional(),
@@ -21667,13 +21870,18 @@ var ConsentFlowContractValidator = external_exports.object({
21667
21870
  external_exports.string(),
21668
21871
  external_exports.object({
21669
21872
  required: external_exports.boolean(),
21670
- defaultEnabled: external_exports.boolean().optional()
21873
+ defaultEnabled: external_exports.boolean().optional(),
21874
+ reason: external_exports.string().optional()
21671
21875
  })
21672
21876
  ).default({})
21673
21877
  }).prefault({ categories: {} }),
21674
21878
  personal: external_exports.record(
21675
21879
  external_exports.string(),
21676
- external_exports.object({ required: external_exports.boolean(), defaultEnabled: external_exports.boolean().optional() })
21880
+ external_exports.object({
21881
+ required: external_exports.boolean(),
21882
+ defaultEnabled: external_exports.boolean().optional(),
21883
+ reason: external_exports.string().optional()
21884
+ })
21677
21885
  ).default({})
21678
21886
  }).prefault({ credentials: { categories: {} }, personal: {} }),
21679
21887
  write: external_exports.object({
@@ -21682,16 +21890,55 @@ var ConsentFlowContractValidator = external_exports.object({
21682
21890
  external_exports.string(),
21683
21891
  external_exports.object({
21684
21892
  required: external_exports.boolean(),
21685
- defaultEnabled: external_exports.boolean().optional()
21893
+ defaultEnabled: external_exports.boolean().optional(),
21894
+ reason: external_exports.string().optional()
21686
21895
  })
21687
21896
  ).default({})
21688
21897
  }).prefault({ categories: {} }),
21689
21898
  personal: external_exports.record(
21690
21899
  external_exports.string(),
21691
- external_exports.object({ required: external_exports.boolean(), defaultEnabled: external_exports.boolean().optional() })
21900
+ external_exports.object({
21901
+ required: external_exports.boolean(),
21902
+ defaultEnabled: external_exports.boolean().optional(),
21903
+ reason: external_exports.string().optional()
21904
+ })
21692
21905
  ).default({})
21693
21906
  }).prefault({ credentials: { categories: {} }, personal: {} })
21694
21907
  });
21908
+ var ConsentFlowContractScopePatchValidator = external_exports.object({
21909
+ required: external_exports.boolean(),
21910
+ defaultEnabled: external_exports.boolean().optional(),
21911
+ reason: external_exports.string().optional()
21912
+ }).nullable();
21913
+ var ConsentFlowContractChangesValidator = external_exports.object({
21914
+ contract: external_exports.object({
21915
+ read: external_exports.object({
21916
+ anonymize: external_exports.boolean().optional(),
21917
+ credentials: external_exports.object({
21918
+ categories: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21919
+ }).optional(),
21920
+ personal: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21921
+ }).optional(),
21922
+ write: external_exports.object({
21923
+ credentials: external_exports.object({
21924
+ categories: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21925
+ }).optional(),
21926
+ personal: external_exports.record(external_exports.string(), ConsentFlowContractScopePatchValidator).optional()
21927
+ }).optional()
21928
+ }).optional(),
21929
+ name: external_exports.string().optional(),
21930
+ subtitle: external_exports.string().optional(),
21931
+ description: external_exports.string().optional(),
21932
+ reasonForAccessing: external_exports.string().optional(),
21933
+ image: external_exports.string().optional(),
21934
+ needsGuardianConsent: external_exports.boolean().optional(),
21935
+ redirectUrl: external_exports.string().optional(),
21936
+ frontDoorBoostUri: external_exports.string().optional(),
21937
+ expiresAt: external_exports.string().nullable().optional(),
21938
+ autoboosts: AutoBoostConfigValidator.array().optional(),
21939
+ writers: external_exports.string().array().optional(),
21940
+ recipients: external_exports.string().array().optional()
21941
+ });
21695
21942
  var ConsentFlowContractDetailsValidator = external_exports.object({
21696
21943
  contract: ConsentFlowContractValidator,
21697
21944
  owner: LCNProfileValidator,
@@ -21710,7 +21957,19 @@ var ConsentFlowContractDetailsValidator = external_exports.object({
21710
21957
  autoBoosts: external_exports.string().array().optional(),
21711
21958
  writers: external_exports.array(LCNProfileValidator).optional(),
21712
21959
  recipients: external_exports.array(LCNPublicProfileValidator.extend({ did: external_exports.string() })).optional(),
21713
- audienceVersion: external_exports.number().int().nonnegative().optional()
21960
+ audienceVersion: external_exports.number().int().nonnegative().optional(),
21961
+ version: external_exports.number().int().positive(),
21962
+ status: ConsentFlowContractStatusValidator.optional(),
21963
+ latestUpdate: external_exports.object({
21964
+ fromVersion: external_exports.number().int().positive(),
21965
+ toVersion: external_exports.number().int().positive(),
21966
+ kind: ConsentFlowContractChangeKindValidator,
21967
+ reason: external_exports.string().optional(),
21968
+ diff: ConsentFlowContractDiffValidator,
21969
+ reconsentDeadline: external_exports.string().optional(),
21970
+ createdAt: external_exports.string(),
21971
+ preview: ConsentFlowContractUpdatePreviewValidator
21972
+ }).optional()
21714
21973
  });
21715
21974
  var ConsentFlowContractRequestStatusValidator = external_exports.enum(["pending", "accepted", "denied", "cancelled"]).nullable();
21716
21975
  var ConsentFlowContractRequestReadStatusValidator = external_exports.enum(["unseen", "seen"]).nullable();
@@ -21799,7 +22058,12 @@ var PaginatedConsentFlowTermsValidator = PaginationResponseValidator.extend({
21799
22058
  contract: ConsentFlowContractDetailsValidator,
21800
22059
  uri: external_exports.string(),
21801
22060
  consenter: LCNProfileValidator,
21802
- status: ConsentFlowTermsStatusValidator
22061
+ status: ConsentFlowTermsStatusValidator,
22062
+ consentedVersion: external_exports.number().int().positive(),
22063
+ lastReviewedVersion: external_exports.number().int().positive().optional(),
22064
+ reconsentDeadline: external_exports.string().optional(),
22065
+ newOptionsUntil: external_exports.string().optional(),
22066
+ cumulativeUpdate: ConsentFlowContractDetailsValidator.shape.latestUpdate
21803
22067
  }).array()
21804
22068
  });
21805
22069
  var ConsentFlowGuardianApprovalValidator = external_exports.object({
@@ -21875,7 +22139,8 @@ var ConsentFlowTransactionActionValidator = external_exports.enum([
21875
22139
  "update",
21876
22140
  "sync",
21877
22141
  "withdraw",
21878
- "write"
22142
+ "write",
22143
+ "reconsent"
21879
22144
  ]);
21880
22145
  var ConsentFlowTransactionsQueryValidator = external_exports.object({
21881
22146
  terms: ConsentFlowTermsQueryValidator.optional(),
@@ -21894,8 +22159,12 @@ var ConsentFlowTransactionValidator = external_exports.object({
21894
22159
  referral: ConsentFlowReferralValidator.optional(),
21895
22160
  id: external_exports.string(),
21896
22161
  action: ConsentFlowTransactionActionValidator,
22162
+ kind: ConsentFlowContractChangeKindValidator.optional(),
21897
22163
  date: external_exports.string(),
21898
- uris: external_exports.string().array().optional()
22164
+ uris: external_exports.string().array().optional(),
22165
+ consentedVersion: external_exports.number().int().positive().optional(),
22166
+ reconsentDeadline: external_exports.string().optional(),
22167
+ newOptionsUntil: external_exports.string().optional()
21899
22168
  });
21900
22169
  var HolderExportConsentRecordValidator = external_exports.object({
21901
22170
  termsUri: external_exports.string(),
@@ -21903,6 +22172,10 @@ var HolderExportConsentRecordValidator = external_exports.object({
21903
22172
  contract: ConsentFlowContractDetailsValidator,
21904
22173
  terms: ConsentFlowTermsValidator,
21905
22174
  referral: ConsentFlowReferralValidator.optional(),
22175
+ consentedVersion: external_exports.number().int().positive(),
22176
+ reconsentDeadline: external_exports.string().optional(),
22177
+ newOptionsUntil: external_exports.string().optional(),
22178
+ cumulativeUpdate: ConsentFlowContractDetailsValidator.shape.latestUpdate,
21906
22179
  transactions: ConsentFlowTransactionValidator.array()
21907
22180
  });
21908
22181
  var HolderExportMetadataValidator = external_exports.object({
@@ -21963,10 +22236,12 @@ var LCNNotificationTypeEnumValidator = external_exports.enum([
21963
22236
  "GUARDIAN_APPROVED",
21964
22237
  "GUARDIAN_REJECTED",
21965
22238
  "APP_NOTIFICATION",
22239
+ "ANNOUNCEMENT",
21966
22240
  "CREDENTIAL_REVOKED",
21967
22241
  "CREDENTIAL_SUSPENDED",
21968
22242
  "CREDENTIAL_UNSUSPENDED",
21969
- "CREDENTIAL_REFRESHED"
22243
+ "CREDENTIAL_REFRESHED",
22244
+ "CONSENT_FLOW_CONTRACT_UPDATED"
21970
22245
  ]);
21971
22246
  var LCNNotificationMessageValidator = external_exports.object({
21972
22247
  title: external_exports.string().optional(),
@@ -21995,12 +22270,26 @@ var LCNNotificationInboxValidator = external_exports.object({
21995
22270
  timestamp: external_exports.iso.datetime().optional()
21996
22271
  });
21997
22272
  var LCNNotificationMetadataValidator = external_exports.object({
21998
- connectionPrompt: LCNConnectionPromptMetadataValidator.optional()
22273
+ connectionPrompt: LCNConnectionPromptMetadataValidator.optional(),
22274
+ campaignId: external_exports.string().regex(/^[a-z0-9-]{3,64}$/).optional(),
22275
+ campaignCreatedAt: external_exports.iso.datetime().optional(),
22276
+ campaignHasInApp: external_exports.boolean().optional(),
22277
+ campaignTestId: external_exports.uuid().optional()
21999
22278
  }).catchall(external_exports.unknown());
22000
22279
  var LCNNotificationDataValidator = external_exports.object({
22001
22280
  vcUris: external_exports.array(external_exports.string()).optional(),
22002
22281
  vpUris: external_exports.array(external_exports.string()).optional(),
22003
22282
  transaction: ConsentFlowTransactionValidator.optional(),
22283
+ contractUri: external_exports.string().optional(),
22284
+ contractName: external_exports.string().optional(),
22285
+ fromVersion: external_exports.number().int().positive().optional(),
22286
+ toVersion: external_exports.number().int().positive().optional(),
22287
+ kind: ConsentFlowContractChangeKindValidator.optional(),
22288
+ reason: external_exports.string().optional(),
22289
+ diff: ConsentFlowContractDiffValidator.optional(),
22290
+ reconsentDeadline: external_exports.string().optional(),
22291
+ reviewUrl: external_exports.string().optional(),
22292
+ preview: ConsentFlowContractUpdatePreviewValidator.optional(),
22004
22293
  inbox: LCNNotificationInboxValidator.optional(),
22005
22294
  metadata: LCNNotificationMetadataValidator.optional()
22006
22295
  }).loose();
@@ -23099,28 +23388,6 @@ var EscrowPinStatusValidator = external_exports.object({
23099
23388
  */
23100
23389
  wrongAttempts: external_exports.number().int().nonnegative().optional()
23101
23390
  });
23102
- var BITSTRING_STATUS_PURPOSES = ["revocation", "suspension"];
23103
- var BitstringStatusPurposeValidator = external_exports.enum(BITSTRING_STATUS_PURPOSES);
23104
- var BitstringStatusListEntryValidator = external_exports.object({
23105
- id: external_exports.string().optional(),
23106
- type: external_exports.literal("BitstringStatusListEntry"),
23107
- statusPurpose: BitstringStatusPurposeValidator,
23108
- statusListIndex: external_exports.string().or(external_exports.number().int().nonnegative()),
23109
- statusListCredential: external_exports.string()
23110
- });
23111
- var AllocatedBitstringStatusListEntryValidator = BitstringStatusListEntryValidator.extend({
23112
- id: external_exports.string()
23113
- });
23114
- var BitstringStatusListCredentialSubjectValidator = external_exports.object({
23115
- id: external_exports.string().optional(),
23116
- type: external_exports.literal("BitstringStatusList"),
23117
- statusPurpose: BitstringStatusPurposeValidator,
23118
- encodedList: external_exports.string()
23119
- });
23120
- var AllocateCredentialStatusInputValidator = external_exports.object({
23121
- statusPurposes: external_exports.array(BitstringStatusPurposeValidator).optional(),
23122
- listSize: external_exports.number().int().positive().optional()
23123
- }).default({});
23124
23391
  var isSafeInAppMessagePath = /* @__PURE__ */ __name2((path) => {
23125
23392
  let decoded = path;
23126
23393
  for (let depth = 0; depth < 5; depth += 1) {
@@ -23401,24 +23668,46 @@ var inAppMessagesFlagEnvelopeValidator = external_exports.object({
23401
23668
  }).passthrough();
23402
23669
  var CampaignIdValidator = external_exports.string().regex(/^[a-z0-9-]{3,64}$/);
23403
23670
  var CampaignStatusValidator = external_exports.enum(["draft", "live", "paused", "archived"]);
23404
- var CampaignChannelValidator = external_exports.enum(["inApp", "notify"]);
23671
+ var CampaignChannelValidator = external_exports.enum(["inApp", "notify", "email"]);
23405
23672
  var CampaignEventValidator = external_exports.enum(["shown", "clicked", "dismissed", "converted"]);
23406
- var timestamp = external_exports.iso.datetime({ offset: true }).overwrite((value) => new Date(value).toISOString());
23673
+ var timestamp = external_exports.iso.datetime({ offset: true }).overwrite((value) => {
23674
+ const date5 = new Date(value);
23675
+ return Number.isFinite(date5.getTime()) ? date5.toISOString() : value;
23676
+ });
23407
23677
  var notification = external_exports.object({ title: external_exports.string().min(1), body: external_exports.string().min(1) }).strict();
23408
- var channels = external_exports.array(CampaignChannelValidator).min(1).max(2).refine((values) => new Set(values).size === values.length, "Channels must be unique");
23678
+ var CampaignEmailValidator = external_exports.object({
23679
+ subject: external_exports.string().trim().min(1).max(200).regex(/^[^\r\n]+$/),
23680
+ title: external_exports.string().trim().min(1).max(200),
23681
+ body: external_exports.string().trim().min(1).max(2e4),
23682
+ heroImageUrl: external_exports.url().startsWith("https://").max(2048).optional(),
23683
+ ctaLabel: external_exports.string().trim().min(1).max(100)
23684
+ }).strict();
23685
+ var AnnouncementPreferencesValidator = external_exports.object({
23686
+ announcementEmailOptOut: external_exports.boolean(),
23687
+ announcementPushOptOut: external_exports.boolean()
23688
+ }).strict();
23689
+ var channels = external_exports.array(CampaignChannelValidator).min(1).max(3).refine((values) => new Set(values).size === values.length, "Channels must be unique");
23409
23690
  var campaignDefinition = external_exports.object({
23410
23691
  id: CampaignIdValidator,
23411
23692
  name: external_exports.string().trim().min(1).max(200),
23412
23693
  status: CampaignStatusValidator.default("draft"),
23413
23694
  channels,
23414
- message: inAppMessageValidator,
23695
+ message: inAppMessageValidator.optional(),
23415
23696
  notification: notification.optional(),
23697
+ email: CampaignEmailValidator.optional(),
23416
23698
  startsAt: timestamp.optional(),
23417
23699
  endsAt: timestamp.optional(),
23418
23700
  excludeMinors: external_exports.boolean().default(true),
23419
23701
  selfEnroll: external_exports.boolean().default(false)
23420
23702
  }).strict();
23421
23703
  var validDefinition = /* @__PURE__ */ __name2((value, ctx) => {
23704
+ if (value.channels.includes("inApp") && !value.message) {
23705
+ ctx.addIssue({
23706
+ code: "custom",
23707
+ path: ["message"],
23708
+ message: "In-app requires a message"
23709
+ });
23710
+ }
23422
23711
  if (value.channels.includes("notify") && !value.notification) {
23423
23712
  ctx.addIssue({
23424
23713
  code: "custom",
@@ -23426,15 +23715,23 @@ var validDefinition = /* @__PURE__ */ __name2((value, ctx) => {
23426
23715
  message: "Notify requires a title and body"
23427
23716
  });
23428
23717
  }
23718
+ if (value.channels.includes("email") && !value.email) {
23719
+ ctx.addIssue({
23720
+ code: "custom",
23721
+ path: ["email"],
23722
+ message: "Email requires announcement content"
23723
+ });
23724
+ }
23429
23725
  if (value.startsAt && value.endsAt && value.startsAt >= value.endsAt) {
23430
23726
  ctx.addIssue({ code: "custom", path: ["endsAt"], message: "End must be after start" });
23431
23727
  }
23432
23728
  }, "validDefinition");
23433
23729
  var CampaignValidator = campaignDefinition.extend({
23730
+ tenantId: external_exports.string().optional(),
23434
23731
  createdAt: timestamp,
23435
23732
  updatedAt: timestamp
23436
23733
  }).superRefine(validDefinition).superRefine((value, ctx) => {
23437
- if (value.message.id !== value.id) {
23734
+ if (value.message && value.message.id !== value.id) {
23438
23735
  ctx.addIssue({
23439
23736
  code: "custom",
23440
23737
  path: ["message", "id"],
@@ -23443,21 +23740,23 @@ var CampaignValidator = campaignDefinition.extend({
23443
23740
  }
23444
23741
  });
23445
23742
  var CreateCampaignInputValidator = campaignDefinition.extend({
23446
- message: inAppMessageAuthoringValidator
23743
+ message: inAppMessageAuthoringValidator.optional()
23447
23744
  }).superRefine(validDefinition);
23448
23745
  var CampaignUpdatesValidator = campaignDefinition.omit({ id: true }).partial().extend({
23449
23746
  // A PATCH must not apply creation defaults to fields the caller omitted.
23450
23747
  status: CampaignStatusValidator.optional(),
23451
23748
  excludeMinors: external_exports.boolean().optional(),
23452
23749
  selfEnroll: external_exports.boolean().optional(),
23453
- message: inAppMessageAuthoringValidator.optional(),
23750
+ message: inAppMessageAuthoringValidator.nullable().optional(),
23454
23751
  notification: notification.nullable().optional(),
23752
+ email: CampaignEmailValidator.nullable().optional(),
23455
23753
  startsAt: timestamp.nullable().optional(),
23456
23754
  endsAt: timestamp.nullable().optional()
23457
23755
  }).strict();
23458
23756
  var UpdateCampaignInputValidator = external_exports.object({
23459
23757
  campaignId: CampaignIdValidator,
23460
- updates: CampaignUpdatesValidator
23758
+ updates: CampaignUpdatesValidator,
23759
+ expectedUpdatedAt: timestamp.optional()
23461
23760
  }).strict();
23462
23761
  var identifier = external_exports.string().trim().min(1).max(2048);
23463
23762
  var metadataKey = external_exports.string().regex(/^[a-zA-Z_][a-zA-Z0-9_.-]{0,63}$/).refine(
@@ -23509,7 +23808,8 @@ var CampaignUserStateValidator = external_exports.object({
23509
23808
  clickedAt: timestamp.optional(),
23510
23809
  dismissedAt: timestamp.optional(),
23511
23810
  convertedAt: timestamp.optional(),
23512
- notifiedAt: timestamp.optional()
23811
+ notifiedAt: timestamp.optional(),
23812
+ emailedAt: timestamp.optional()
23513
23813
  });
23514
23814
  var MyCampaignValidator = external_exports.object({
23515
23815
  campaign: campaignDefinition.pick({
@@ -23518,12 +23818,19 @@ var MyCampaignValidator = external_exports.object({
23518
23818
  startsAt: true,
23519
23819
  endsAt: true,
23520
23820
  selfEnroll: true
23521
- }),
23522
- state: CampaignUserStateValidator
23821
+ }).extend({ message: inAppMessageValidator }),
23822
+ state: CampaignUserStateValidator,
23823
+ testId: external_exports.uuid().optional()
23824
+ });
23825
+ var CampaignTestValidator = external_exports.object({
23826
+ id: external_exports.uuid(),
23827
+ campaignId: CampaignIdValidator,
23828
+ message: inAppMessageValidator
23523
23829
  });
23524
23830
  var CampaignStatsValidator = external_exports.object({
23525
23831
  audience: external_exports.number().int().nonnegative(),
23526
23832
  notified: external_exports.number().int().nonnegative(),
23833
+ emailed: external_exports.number().int().nonnegative(),
23527
23834
  shown: external_exports.number().int().nonnegative(),
23528
23835
  clicked: external_exports.number().int().nonnegative(),
23529
23836
  dismissed: external_exports.number().int().nonnegative(),
@@ -23550,6 +23857,31 @@ var PaginatedCampaignAudienceValidator = external_exports.object({
23550
23857
  hasMore: external_exports.boolean(),
23551
23858
  cursor: external_exports.string().optional()
23552
23859
  });
23860
+ var CampaignDispatchPreviewValidator = external_exports.object({
23861
+ campaignId: CampaignIdValidator,
23862
+ audienceCount: external_exports.number().int().nonnegative(),
23863
+ alreadyNotifiedCount: external_exports.number().int().nonnegative(),
23864
+ recipientCount: external_exports.number().int().nonnegative(),
23865
+ notificationRecipientCount: external_exports.number().int().nonnegative().optional(),
23866
+ emailRecipientCount: external_exports.number().int().nonnegative().optional(),
23867
+ previewToken: external_exports.string().regex(/^[a-f0-9]{64}$/),
23868
+ blockedReason: external_exports.enum([
23869
+ "not_live",
23870
+ "notify_disabled",
23871
+ "email_confirmation_required",
23872
+ "not_started",
23873
+ "ended",
23874
+ "no_recipients"
23875
+ ]).optional()
23876
+ });
23877
+ var CampaignDispatchOptionsValidator = external_exports.object({
23878
+ expectedPreviewToken: CampaignDispatchPreviewValidator.shape.previewToken.optional()
23879
+ }).strict();
23880
+ var CampaignAudienceResultValidator = external_exports.object({
23881
+ count: external_exports.number().int().nonnegative(),
23882
+ added: external_exports.number().int().nonnegative(),
23883
+ notFound: external_exports.array(external_exports.string())
23884
+ });
23553
23885
  var SHARE_LINK_ID_BYTES = 16;
23554
23886
  var SHARE_CONTENT_KEY_BYTES = 32;
23555
23887
  var SHARE_IV_BYTES = 12;
@@ -24073,6 +24405,217 @@ var SkillIconNamesValidator = external_exports.array(external_exports.string().n
24073
24405
  }
24074
24406
  );
24075
24407
  var GenerateSkillIconsInputValidator = external_exports.object({ names: SkillIconNamesValidator });
24408
+ var RoleValidator = external_exports.enum(["user", "assistant", "tool", "system"]);
24409
+ var AiSessionMode = {
24410
+ tutor: "ai-tutor",
24411
+ insights: "ai-insights"
24412
+ };
24413
+ var AiSessionModeValidator = external_exports.enum([AiSessionMode.tutor, AiSessionMode.insights]);
24414
+ var StructuredResponseValidator = external_exports.object({
24415
+ notes: external_exports.string().optional(),
24416
+ questions: external_exports.array(external_exports.string())
24417
+ });
24418
+ var IntroStreamModeValidator = external_exports.enum(["formatted", "structured"]);
24419
+ var ChatMessageValidator = external_exports.object({
24420
+ role: RoleValidator,
24421
+ content: external_exports.string().nullable(),
24422
+ tool_call_id: external_exports.string().optional(),
24423
+ tool_calls: external_exports.array(
24424
+ external_exports.object({
24425
+ id: external_exports.string(),
24426
+ type: external_exports.literal("function"),
24427
+ function: external_exports.object({
24428
+ name: external_exports.string(),
24429
+ arguments: external_exports.string()
24430
+ })
24431
+ })
24432
+ ).optional()
24433
+ });
24434
+ var InsightArtifactValidator = external_exports.object({
24435
+ title: external_exports.string(),
24436
+ summary: external_exports.string(),
24437
+ category: external_exports.string(),
24438
+ question: external_exports.string(),
24439
+ narrative: external_exports.string()
24440
+ });
24441
+ var ArtifactSuggestionValidator = external_exports.object({
24442
+ artifact: InsightArtifactValidator,
24443
+ source_text: external_exports.string().optional(),
24444
+ created_at: external_exports.string()
24445
+ });
24446
+ var ThreadCredentialContextValidator = external_exports.object({
24447
+ uri: external_exports.string(),
24448
+ type: external_exports.string(),
24449
+ context: external_exports.string(),
24450
+ score: external_exports.number(),
24451
+ strongestScore: external_exports.number().optional(),
24452
+ averageScore: external_exports.number().optional(),
24453
+ matchCount: external_exports.number().optional(),
24454
+ title: external_exports.string().optional()
24455
+ });
24456
+ var ThreadValidator = external_exports.object({
24457
+ id: external_exports.string(),
24458
+ did: external_exports.string(),
24459
+ topicCredentialUri: external_exports.string().nullable().optional(),
24460
+ title: external_exports.string(),
24461
+ created_at: external_exports.string(),
24462
+ last_message_at: external_exports.string(),
24463
+ active: external_exports.boolean().optional(),
24464
+ ended_at: external_exports.string().optional(),
24465
+ plan_started_at: external_exports.string().optional(),
24466
+ summaries: external_exports.array(
24467
+ external_exports.object({
24468
+ summary_data: external_exports.string(),
24469
+ credential_uri: external_exports.string(),
24470
+ created_at: external_exports.string()
24471
+ })
24472
+ ).optional(),
24473
+ plans: external_exports.array(
24474
+ external_exports.object({
24475
+ plan_data: external_exports.string(),
24476
+ created_at: external_exports.string(),
24477
+ consentRevision: external_exports.string().optional()
24478
+ })
24479
+ ).optional(),
24480
+ credentials: external_exports.array(ThreadCredentialContextValidator).optional(),
24481
+ credentialSearchTopic: external_exports.string().optional(),
24482
+ credentialContextStatus: external_exports.enum(["pending", "ready", "empty", "error"]).optional(),
24483
+ mode: AiSessionModeValidator.optional(),
24484
+ artifactSuggestions: external_exports.array(ArtifactSuggestionValidator).optional()
24485
+ });
24486
+ var CredentialVerificationMetadataValidator = external_exports.object({
24487
+ credentialUri: external_exports.string(),
24488
+ contentHash: external_exports.string().regex(/^[a-f0-9]{64}$/),
24489
+ status: external_exports.enum(["valid", "invalid"]),
24490
+ checkedAt: external_exports.string().datetime(),
24491
+ verifier: external_exports.object({
24492
+ name: external_exports.string(),
24493
+ version: external_exports.string()
24494
+ }),
24495
+ verifiedPayload: external_exports.enum(["credential", "boostCredential"]),
24496
+ checks: external_exports.array(external_exports.string()),
24497
+ errors: external_exports.array(external_exports.string()),
24498
+ warnings: external_exports.array(external_exports.string()),
24499
+ provenance: external_exports.object({
24500
+ source: external_exports.enum(["wallet", "generated"]),
24501
+ retrievedAt: external_exports.string().datetime()
24502
+ }),
24503
+ consent: external_exports.object({
24504
+ contractUri: external_exports.string(),
24505
+ receiptId: external_exports.string().min(1),
24506
+ grantedAt: external_exports.string().datetime().optional(),
24507
+ updatedAt: external_exports.string().datetime(),
24508
+ contractUpdatedAt: external_exports.string().min(1),
24509
+ status: external_exports.literal("live"),
24510
+ expiresAt: external_exports.string().datetime().optional(),
24511
+ contractExpiresAt: external_exports.string().datetime().optional(),
24512
+ categories: external_exports.array(external_exports.string()),
24513
+ credentialUris: external_exports.array(external_exports.string()),
24514
+ personalFields: external_exports.array(external_exports.string()),
24515
+ purpose: external_exports.enum(["credential-ingestion", "model-inference", "embedding"]),
24516
+ revision: external_exports.string().min(1),
24517
+ guardian: external_exports.object({ required: external_exports.boolean(), approved: external_exports.boolean() })
24518
+ })
24519
+ });
24520
+ var ModelSafeCredentialFactValidator = external_exports.object({
24521
+ kind: external_exports.enum([
24522
+ "skill",
24523
+ "goal",
24524
+ "achievement",
24525
+ "course",
24526
+ "experience",
24527
+ "competency",
24528
+ "title",
24529
+ "summary",
24530
+ "assessment",
24531
+ "grade",
24532
+ "date",
24533
+ "alignment",
24534
+ "criteria",
24535
+ "pathway",
24536
+ "topic"
24537
+ ]),
24538
+ value: external_exports.string().min(1).max(240),
24539
+ label: external_exports.string().min(1).max(120).optional()
24540
+ });
24541
+ var ModelSafeCredentialProjectionValidator = external_exports.object({
24542
+ schemaVersion: external_exports.literal("1"),
24543
+ category: external_exports.string().min(1).max(120),
24544
+ credentialTypes: external_exports.array(external_exports.string().min(1).max(120)).max(20),
24545
+ facts: external_exports.array(ModelSafeCredentialFactValidator).max(100),
24546
+ // Present only on credentials that are past their expiry, so the model can
24547
+ // tell a lapsed credential from a current one.
24548
+ expired: external_exports.literal(true).optional(),
24549
+ expirationDate: external_exports.string().datetime().optional()
24550
+ });
24551
+ var AIPassportCredentialRecordValidator = external_exports.object({
24552
+ id: external_exports.string(),
24553
+ uri: external_exports.string(),
24554
+ category: external_exports.string(),
24555
+ credential: VCValidator,
24556
+ aiContext: external_exports.string(),
24557
+ generalSummary: external_exports.string().optional(),
24558
+ createdAt: external_exports.string(),
24559
+ verification: CredentialVerificationMetadataValidator.optional(),
24560
+ projection: ModelSafeCredentialProjectionValidator.optional()
24561
+ });
24562
+ var AuthenticatedMessageValidator = external_exports.object({
24563
+ message: ChatMessageValidator.optional(),
24564
+ threadId: external_exports.string().optional(),
24565
+ selectedQuestion: external_exports.string().optional(),
24566
+ action: external_exports.enum([
24567
+ "start_topic",
24568
+ "continue_plan",
24569
+ "start_topic_uri",
24570
+ "start_learning_pathway",
24571
+ "start_insights_session",
24572
+ "close_insights_session",
24573
+ "artifact_suggestion"
24574
+ ]).optional(),
24575
+ topic: external_exports.string().optional(),
24576
+ topicUri: external_exports.string().optional(),
24577
+ pathwayUri: external_exports.string().optional(),
24578
+ mode: AiSessionModeValidator.optional(),
24579
+ introStreamMode: IntroStreamModeValidator.optional(),
24580
+ // BCP-47 language for AI responses (LC-1901). This has to live on the
24581
+ // validator, not just the inferred type — z.object strips unknown keys, so an
24582
+ // undeclared `locale` would be dropped before the WS handler ever saw it.
24583
+ locale: external_exports.string().nullish()
24584
+ });
24585
+ var DebugInfoValidator = external_exports.object({
24586
+ operation: external_exports.string(),
24587
+ collection: external_exports.string(),
24588
+ input: external_exports.unknown().optional(),
24589
+ output: external_exports.unknown().optional(),
24590
+ timestamp: external_exports.string(),
24591
+ duration: external_exports.number().optional()
24592
+ });
24593
+ var TimingEventValidator = external_exports.object({
24594
+ event: external_exports.literal("timing"),
24595
+ operation: external_exports.string(),
24596
+ phase: external_exports.enum(["start", "end", "complete"]),
24597
+ duration: external_exports.number().optional(),
24598
+ metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
24599
+ timestamp: external_exports.string()
24600
+ });
24601
+ var LearningPathwayValidator = external_exports.object({
24602
+ id: external_exports.string(),
24603
+ learningPathway: external_exports.object({
24604
+ stepIndex: external_exports.number(),
24605
+ step: external_exports.object({
24606
+ title: external_exports.string(),
24607
+ description: external_exports.string(),
24608
+ summary: external_exports.string(),
24609
+ learned: external_exports.array(external_exports.string()),
24610
+ skills: external_exports.array(
24611
+ external_exports.object({
24612
+ title: external_exports.string(),
24613
+ description: external_exports.string()
24614
+ })
24615
+ )
24616
+ })
24617
+ })
24618
+ });
24076
24619
 
24077
24620
  // src/plugin.ts
24078
24621
  var import_helpers = require("@learncard/helpers");
@@ -24685,7 +25228,14 @@ var appendNetworkCredentialStatus = /* @__PURE__ */ __name(async (client, creden
24685
25228
  credential.credentialStatus = credentialStatuses.length === 1 ? credentialStatuses[0] : credentialStatuses;
24686
25229
  return credential;
24687
25230
  }, "appendNetworkCredentialStatus");
24688
- var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard, client, credential, statusPurposes) => {
25231
+ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard, client, credential, statusPurposes, statusEntries) => {
25232
+ if (statusEntries) {
25233
+ const prepared = UnsignedVCValidator.parse({
25234
+ ...(0, import_helpers.materializeCredentialFields)(credential),
25235
+ credentialStatus: statusEntries.length === 1 && !Array.isArray(credential.credentialStatus) ? statusEntries[0] : statusEntries
25236
+ });
25237
+ return learnCard.invoke.issueCredential((0, import_helpers.prepareManagedRefreshContext)(prepared));
25238
+ }
24689
25239
  return learnCard.invoke.issueCredential(
24690
25240
  await appendNetworkCredentialStatus(
24691
25241
  client,
@@ -24710,7 +25260,7 @@ var buildManagedRefreshReceipt = /* @__PURE__ */ __name((vc, allocation, credent
24710
25260
  const hasStatus = rawStatus !== void 0 && rawStatus !== null && !(Array.isArray(rawStatus) && rawStatus.length === 0);
24711
25261
  return {
24712
25262
  refreshId: allocation.refreshId,
24713
- refreshService: allocation.refreshService,
25263
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(vc.refreshService),
24714
25264
  credentialId: typeof vc.id === "string" && vc.id.length > 0 ? vc.id : credentialId,
24715
25265
  issuerDid,
24716
25266
  holderDid,
@@ -24719,6 +25269,40 @@ var buildManagedRefreshReceipt = /* @__PURE__ */ __name((vc, allocation, credent
24719
25269
  } : {}
24720
25270
  };
24721
25271
  }, "buildManagedRefreshReceipt");
25272
+ 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.";
25273
+ var getPreparedRecipientKeyIds = /* @__PURE__ */ __name((prepared) => prepared.recipientKeyIds, "getPreparedRecipientKeyIds");
25274
+ var isRecipientsChangedError = /* @__PURE__ */ __name((error62) => {
25275
+ const code = error62?.data?.code;
25276
+ const message = error62?.message;
25277
+ return code === "CONFLICT" && message === "RECIPIENTS_CHANGED";
25278
+ }, "isRecipientsChangedError");
25279
+ var didFromRecipientKeyId = /* @__PURE__ */ __name((keyId) => {
25280
+ const [did] = keyId.split("#");
25281
+ if (!did) throw new Error(`Invalid recipient key id: ${keyId}`);
25282
+ return did;
25283
+ }, "didFromRecipientKeyId");
25284
+ var buildHolderEncryptedHandoff = /* @__PURE__ */ __name(async (learnCard, signedCredential, bindings, recipientKeyIds) => {
25285
+ const recipientDids = recipientKeyIds.map(didFromRecipientKeyId);
25286
+ const jwe = await learnCard.invoke.createDagJweExact?.(signedCredential, recipientDids);
25287
+ if (!jwe) {
25288
+ throw new Error(
25289
+ 'encryption: "holder" requires the Encryption plugin (createDagJweExact), which this wallet does not have.'
25290
+ );
25291
+ }
25292
+ (0, import_helpers.assertExactJweRecipients)(jwe, recipientKeyIds);
25293
+ return HolderEncryptedHandoffValidator.parse({ ...bindings, jwe });
25294
+ }, "buildHolderEncryptedHandoff");
25295
+ var deliverHolderEncryptedHandoff = /* @__PURE__ */ __name(async (holderClient, refreshId, recipientKeyIds, buildHandoff, deliver) => {
25296
+ const handoff2 = await buildHandoff(recipientKeyIds);
25297
+ try {
25298
+ return await deliver(handoff2);
25299
+ } catch (error62) {
25300
+ if (!isRecipientsChangedError(error62)) throw error62;
25301
+ const fresh = await holderClient.getEncryptionRecipients.query({ refreshId });
25302
+ const retryHandoff = await buildHandoff(fresh.recipientKeyIds);
25303
+ return deliver(retryHandoff);
25304
+ }
25305
+ }, "deliverHolderEncryptedHandoff");
24722
25306
  var ACT_AS_TARGET_NOT_FOUND_MESSAGE = "Act-as target profile not found";
24723
25307
  var isActAsDenial = /* @__PURE__ */ __name((error62) => {
24724
25308
  const code = error62?.data?.code;
@@ -24729,6 +25313,11 @@ var isActAsDenial = /* @__PURE__ */ __name((error62) => {
24729
25313
  return false;
24730
25314
  }, "isActAsDenial");
24731
25315
  var getInboxFailureReason = /* @__PURE__ */ __name((reason) => reason instanceof Error ? `${reason.name}: ${reason.message}` : String(reason), "getInboxFailureReason");
25316
+ var normalizePublicDisplay = /* @__PURE__ */ __name((input2) => {
25317
+ const category = input2.display?.category ?? input2.template?.category?.slice(0, 280);
25318
+ if (!input2.display && !category) return void 0;
25319
+ return { ...input2.display, ...category ? { category } : {} };
25320
+ }, "normalizePublicDisplay");
24732
25321
  async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
24733
25322
  const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
24734
25323
  const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
@@ -24815,6 +25404,13 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
24815
25404
  return _learnCard.invoke.resolveFromLCN(boostUri);
24816
25405
  }
24817
25406
  }, "getBoostTemplateForIssuance");
25407
+ const assertIssuableBoostTemplate = /* @__PURE__ */ __name((boost) => {
25408
+ if ((0, import_helpers.isDisplayOnlyAnchorTemplate)(boost)) {
25409
+ throw new Error(
25410
+ "This Boost is a display-only anchor and has no issuance credential. Pass `template` or `signedCredential` instead of reusing its uri as a templateUri."
25411
+ );
25412
+ }
25413
+ }, "assertIssuableBoostTemplate");
24818
25414
  const getInboxEndpointForDid = /* @__PURE__ */ __name(async (_learnCard, recipientDid) => {
24819
25415
  const serviceUrl2 = new URL(url2);
24820
25416
  const serviceDomain = `${serviceUrl2.hostname}${serviceUrl2.port ? `%3A${serviceUrl2.port}` : ""}`;
@@ -25607,6 +26203,124 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25607
26203
  await ensureUser();
25608
26204
  return client.credentialRefresh.getCredentialRefreshHistory.query(input2);
25609
26205
  }, "getCredentialRefreshHistory"),
26206
+ getCredentialRefreshReceipt: /* @__PURE__ */ __name(async (_learnCard, input2) => {
26207
+ await ensureUser();
26208
+ return client.credentialRefresh.getReceipt.query(input2);
26209
+ }, "getCredentialRefreshReceipt"),
26210
+ publishHolderEncryptedRefreshable: /* @__PURE__ */ __name(async (_learnCard, receipt, credential, options2) => {
26211
+ await ensureUser();
26212
+ if (!("issueCredential" in _learnCard.invoke)) {
26213
+ throw new Error(
26214
+ "Holder-mode publishing requires local signing capability, which this wallet does not have."
26215
+ );
26216
+ }
26217
+ if (!("createDagJweExact" in _learnCard.invoke)) {
26218
+ throw new Error(
26219
+ "Holder-mode publishing requires the Encryption plugin (createDagJweExact), which this wallet does not have."
26220
+ );
26221
+ }
26222
+ if (receipt.credentialStatus === void 0) {
26223
+ throw new Error(
26224
+ "Holder-mode publishing requires the original send receipt's credentialStatus binding."
26225
+ );
26226
+ }
26227
+ const boundCredentialStatus = BitstringStatusListEntryValidator.array().parse(
26228
+ Array.isArray(receipt.credentialStatus) ? receipt.credentialStatus : [receipt.credentialStatus]
26229
+ );
26230
+ let boost = JSON.parse(JSON.stringify(credential));
26231
+ const boostString = JSON.stringify(boost);
26232
+ const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
26233
+ if (options2.templateData && Object.keys(options2.templateData).length > 0) {
26234
+ try {
26235
+ const rendered = renderTemplateJson(boostString, options2.templateData);
26236
+ boost = JSON.parse(rendered);
26237
+ boost = appendTemplateEvidence(
26238
+ boost,
26239
+ options2.templateData,
26240
+ allowAutoAppendEvidence
26241
+ );
26242
+ } catch (error62) {
26243
+ throw new Error(
26244
+ `Failed to apply template data: ${error62 instanceof Error ? error62.message : "Unknown error"}`,
26245
+ { cause: error62 }
26246
+ );
26247
+ }
26248
+ }
26249
+ if ((0, import_helpers.isVC2Format)(boost)) {
26250
+ boost.validFrom = (/* @__PURE__ */ new Date()).toISOString();
26251
+ } else {
26252
+ boost.issuanceDate = (/* @__PURE__ */ new Date()).toISOString();
26253
+ }
26254
+ boost.issuer = receipt.issuerDid;
26255
+ boost.id = receipt.credentialId;
26256
+ if (Array.isArray(boost.credentialSubject)) {
26257
+ boost.credentialSubject = boost.credentialSubject.map((subject) => ({
26258
+ ...subject,
26259
+ id: receipt.holderDid
26260
+ }));
26261
+ } else {
26262
+ boost.credentialSubject = { ...boost.credentialSubject, id: receipt.holderDid };
26263
+ }
26264
+ if (receipt.refreshServiceBinding === "managed-entry" && !credential.refreshService) {
26265
+ throw new Error(
26266
+ "This legacy receipt does not include the original refresh service descriptor. Repair the receipt or reissue the credential before publishing."
26267
+ );
26268
+ }
26269
+ boost = (0, import_helpers.prepareManagedRefreshContext)({
26270
+ ...boost,
26271
+ refreshService: receipt.refreshServiceBinding === "managed-entry" ? credential.refreshService : receipt.refreshService
26272
+ });
26273
+ boost.credentialStatus = receipt.credentialStatus;
26274
+ (0, import_helpers.assertManagedCredentialBinding)(boost, { ...receipt, encryptionMode: "holder" });
26275
+ const signedCredential = await issueCredentialWithNetworkStatus(
26276
+ _learnCard,
26277
+ client,
26278
+ boost,
26279
+ void 0,
26280
+ boundCredentialStatus
26281
+ );
26282
+ const holderBindings = {
26283
+ refreshId: receipt.refreshId,
26284
+ credentialId: receipt.credentialId,
26285
+ holderDid: receipt.holderDid,
26286
+ issuerDid: receipt.issuerDid,
26287
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(
26288
+ boost.refreshService
26289
+ ),
26290
+ credentialStatus: BitstringStatusListEntryValidator.or(
26291
+ BitstringStatusListEntryValidator.array()
26292
+ ).parse(receipt.credentialStatus)
26293
+ };
26294
+ (0, import_helpers.assertManagedCredentialBinding)(signedCredential, {
26295
+ ...holderBindings,
26296
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(
26297
+ boost.refreshService
26298
+ ),
26299
+ encryptionMode: "holder"
26300
+ });
26301
+ const holderClient = client.credentialRefresh;
26302
+ const { recipientKeyIds } = await holderClient.getEncryptionRecipients.query({
26303
+ refreshId: receipt.refreshId
26304
+ });
26305
+ return deliverHolderEncryptedHandoff(
26306
+ holderClient,
26307
+ receipt.refreshId,
26308
+ recipientKeyIds,
26309
+ (keyIds) => buildHolderEncryptedHandoff(
26310
+ _learnCard,
26311
+ signedCredential,
26312
+ holderBindings,
26313
+ keyIds
26314
+ ),
26315
+ (handoff2) => holderClient.publishHolderEncryptedRefreshable.mutate({
26316
+ handoff: handoff2,
26317
+ notify: options2.notify,
26318
+ ...options2.updateSummary !== void 0 ? { updateSummary: options2.updateSummary } : {},
26319
+ ...options2.updateReason !== void 0 ? { updateReason: options2.updateReason } : {},
26320
+ ...options2.idempotencyKey !== void 0 ? { idempotencyKey: options2.idempotencyKey } : {}
26321
+ })
26322
+ );
26323
+ }, "publishHolderEncryptedRefreshable"),
25610
26324
  revokeBoostRecipient: /* @__PURE__ */ __name(async (_learnCard, boostUri, recipientProfileId, credentialUri) => {
25611
26325
  await ensureUser();
25612
26326
  const input2 = { boostUri, recipientProfileId };
@@ -25632,6 +26346,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25632
26346
  sendBoost: /* @__PURE__ */ __name(async (_learnCard, profileId, boostUri, options2 = { encrypt: true, skipNotification: false, templateData: {} }) => {
25633
26347
  await ensureUser();
25634
26348
  const result = await getBoostTemplateForIssuance(_learnCard, boostUri);
26349
+ assertIssuableBoostTemplate(result);
25635
26350
  const data = await UnsignedVCValidator.spa(result);
25636
26351
  if (!data.success) throw new Error("Did not get a valid boost from URI");
25637
26352
  const targetProfile = await _learnCard.invoke.getProfile(profileId);
@@ -25772,18 +26487,65 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25772
26487
  }, "claimBoostWithLink"),
25773
26488
  send: /* @__PURE__ */ __name(async (_learnCard, input2) => {
25774
26489
  await ensureUser();
26490
+ if (input2.type === "boost" && input2.encryption === "holder" && input2.refresh !== true) {
26491
+ throw new Error(
26492
+ 'encryption: "holder" requires refresh: true; holder-mode encryption is only defined for managed refresh sends.'
26493
+ );
26494
+ }
25775
26495
  if (input2.type === "boost" && input2.refresh === true) {
25776
26496
  const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input2.recipient);
25777
26497
  const isPhone = /^\+?[\d\s-]{10,}$/.test(input2.recipient.replace(/[\s-]/g, ""));
25778
- if (isEmail || isPhone) return client.boost.send.mutate(input2);
26498
+ const isHolderEncryption = input2.encryption === "holder";
26499
+ if (isHolderEncryption && (isEmail || isPhone)) {
26500
+ throw new Error(
26501
+ 'encryption: "holder" does not support inbox (email or phone) recipients; use a profile ID or DID recipient instead.'
26502
+ );
26503
+ }
26504
+ if (isHolderEncryption && input2.signedCredential) {
26505
+ throw new Error(
26506
+ 'encryption: "holder" does not support signedCredential; the SDK must sign locally so the server never receives plaintext.'
26507
+ );
26508
+ }
26509
+ const request = {
26510
+ type: "boost",
26511
+ recipient: input2.recipient,
26512
+ templateUri: input2.templateUri,
26513
+ template: input2.template,
26514
+ signedCredential: input2.signedCredential,
26515
+ display: normalizePublicDisplay(input2),
26516
+ statusPurposes: input2.statusPurposes,
26517
+ contractUri: input2.contractUri,
26518
+ templateData: input2.templateData,
26519
+ integrationId: input2.integrationId,
26520
+ options: input2.options,
26521
+ idempotencyKey: input2.idempotencyKey,
26522
+ refresh: true
26523
+ };
26524
+ if (isEmail || isPhone) return client.boost.send.mutate(request);
25779
26525
  const canIssueLocally = "issueCredential" in _learnCard.invoke;
26526
+ if (isHolderEncryption && !canIssueLocally) {
26527
+ throw new Error(
26528
+ 'encryption: "holder" requires local signing capability, which this wallet does not have.'
26529
+ );
26530
+ }
26531
+ if (isHolderEncryption && !("createDagJweExact" in _learnCard.invoke)) {
26532
+ throw new Error(
26533
+ 'encryption: "holder" requires the Encryption plugin (createDagJweExact), which this wallet does not have.'
26534
+ );
26535
+ }
25780
26536
  if (canIssueLocally && !input2.signedCredential && (input2.templateUri || input2.template)) {
25781
26537
  let boost;
26538
+ if (input2.template?.status === "DRAFT") {
26539
+ throw new Error(
26540
+ "Draft Boosts cannot be sent. Publish the template first."
26541
+ );
26542
+ }
25782
26543
  if (input2.templateUri) {
25783
26544
  const result = await getBoostTemplateForIssuance(
25784
26545
  _learnCard,
25785
26546
  input2.templateUri
25786
26547
  );
26548
+ assertIssuableBoostTemplate(result);
25787
26549
  const data = await UnsignedVCValidator.spa(result);
25788
26550
  if (!data.success)
25789
26551
  throw new Error("Did not get a valid boost from URI");
@@ -25794,15 +26556,21 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25794
26556
  );
25795
26557
  }
25796
26558
  const prepared = await client.boost.prepareRefreshableSend.mutate({
26559
+ ...boost.credentialStatus ? {} : { statusBinding: "server" },
26560
+ ...input2.statusPurposes ? { statusPurposes: input2.statusPurposes } : {},
25797
26561
  recipient: input2.recipient,
25798
- ...input2.templateUri ? { templateUri: input2.templateUri } : { template: input2.template },
26562
+ templateUri: input2.templateUri,
26563
+ display: normalizePublicDisplay(input2),
25799
26564
  ...input2.contractUri ? { contractUri: input2.contractUri } : {},
25800
- ...input2.templateData ? { templateData: input2.templateData } : {},
25801
26565
  ...input2.integrationId ? { integrationId: input2.integrationId } : {},
25802
26566
  ...boost.id ? { credentialId: boost.id } : {},
25803
- ...input2.idempotencyKey ? { idempotencyKey: input2.idempotencyKey } : {}
26567
+ ...input2.idempotencyKey ? { idempotencyKey: input2.idempotencyKey } : {},
26568
+ ...isHolderEncryption ? { encryption: "holder" } : {}
25804
26569
  });
25805
26570
  if (prepared.completed) return prepared.completed;
26571
+ if (isHolderEncryption && !getPreparedRecipientKeyIds(prepared)) {
26572
+ throw new Error(HOLDER_MODE_PREPARE_UNSUPPORTED);
26573
+ }
25806
26574
  const boostString = JSON.stringify(boost);
25807
26575
  const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
25808
26576
  if (input2.templateData && Object.keys(input2.templateData).length > 0) {
@@ -25845,20 +26613,89 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25845
26613
  if (boost.type?.includes("BoostCredential"))
25846
26614
  boost.boostId = prepared.boostUri;
25847
26615
  boost = injectManagedRefreshService(boost, prepared.refreshService);
25848
- const signedCredential = await issueCredentialWithNetworkStatus(
26616
+ if (isHolderEncryption && !prepared.statusEntries?.length && !boost.credentialStatus) {
26617
+ throw new Error(
26618
+ "Server did not bind status entries for this holder-mode send; refusing to send a managed credential without a public status binding."
26619
+ );
26620
+ }
26621
+ const signedCredential = boost.credentialStatus ? await _learnCard.invoke.issueCredential(
26622
+ (0, import_helpers.prepareManagedRefreshContext)(
26623
+ UnsignedVCValidator.parse((0, import_helpers.materializeCredentialFields)(boost))
26624
+ )
26625
+ ) : await issueCredentialWithNetworkStatus(
25849
26626
  _learnCard,
25850
26627
  client,
25851
- boost
26628
+ boost,
26629
+ input2.statusPurposes ? [
26630
+ .../* @__PURE__ */ new Set([
26631
+ "revocation",
26632
+ ...input2.statusPurposes
26633
+ ])
26634
+ ] : void 0,
26635
+ prepared.statusEntries
25852
26636
  );
25853
- return client.boost.send.mutate({
25854
- ...input2,
25855
- template: void 0,
25856
- templateUri: prepared.boostUri,
25857
- signedCredential,
25858
- refresh: true
26637
+ if (!isHolderEncryption) {
26638
+ return client.boost.send.mutate({
26639
+ type: "boost",
26640
+ recipient: input2.recipient,
26641
+ display: normalizePublicDisplay(input2),
26642
+ statusPurposes: input2.statusPurposes,
26643
+ contractUri: input2.contractUri,
26644
+ integrationId: input2.integrationId,
26645
+ idempotencyKey: input2.idempotencyKey,
26646
+ templateUri: prepared.boostUri,
26647
+ signedCredential,
26648
+ refresh: true
26649
+ });
26650
+ }
26651
+ const initialRecipientKeyIds = getPreparedRecipientKeyIds(prepared);
26652
+ if (!initialRecipientKeyIds) {
26653
+ throw new Error(HOLDER_MODE_PREPARE_UNSUPPORTED);
26654
+ }
26655
+ const boundCredentialStatus = BitstringStatusListEntryValidator.or(
26656
+ BitstringStatusListEntryValidator.array()
26657
+ ).parse(signedCredential.credentialStatus);
26658
+ const holderBindings = {
26659
+ refreshId: prepared.refreshId,
26660
+ credentialId: prepared.credentialId,
26661
+ holderDid: prepared.holderDid,
26662
+ issuerDid: _learnCard.id.did(),
26663
+ credentialStatus: boundCredentialStatus,
26664
+ refreshService: ManagedCredentialRefreshBindingValidator.parse(
26665
+ signedCredential.refreshService
26666
+ )
26667
+ };
26668
+ (0, import_helpers.assertManagedCredentialBinding)(signedCredential, {
26669
+ ...holderBindings,
26670
+ encryptionMode: "holder"
25859
26671
  });
26672
+ const holderClient = client.credentialRefresh;
26673
+ const delivered = await deliverHolderEncryptedHandoff(
26674
+ holderClient,
26675
+ prepared.refreshId,
26676
+ initialRecipientKeyIds,
26677
+ (recipientKeyIds) => buildHolderEncryptedHandoff(
26678
+ _learnCard,
26679
+ signedCredential,
26680
+ holderBindings,
26681
+ recipientKeyIds
26682
+ ),
26683
+ (handoff2) => holderClient.sendHolderEncryptedRefreshable.mutate({
26684
+ handoff: handoff2,
26685
+ boostUri: prepared.boostUri,
26686
+ idempotencyKey: input2.idempotencyKey
26687
+ })
26688
+ );
26689
+ return {
26690
+ type: "boost",
26691
+ uri: prepared.boostUri,
26692
+ credentialUri: delivered.uri,
26693
+ activityId: delivered.activityId,
26694
+ statusManagement: delivered.statusManagement,
26695
+ refresh: holderBindings
26696
+ };
25860
26697
  }
25861
- return client.boost.send.mutate(input2);
26698
+ return client.boost.send.mutate(request);
25862
26699
  }
25863
26700
  if (input2.type === "boost") {
25864
26701
  const recipient = input2.recipient;
@@ -25871,6 +26708,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25871
26708
  const isRemoteDidWebRecipient = recipient.startsWith("did:web:") && recipientDomain !== serviceDomain;
25872
26709
  if (isRemoteDidWebRecipient && input2.templateUri) {
25873
26710
  const boostRecord = await _learnCard.invoke.getBoost(input2.templateUri);
26711
+ assertIssuableBoostTemplate(boostRecord.boost);
25874
26712
  let boost = boostRecord.boost;
25875
26713
  const boostString = JSON.stringify(boost);
25876
26714
  const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
@@ -25931,6 +26769,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
25931
26769
  _learnCard,
25932
26770
  input2.templateUri
25933
26771
  );
26772
+ assertIssuableBoostTemplate(result);
25934
26773
  const data = await UnsignedVCValidator.spa(result);
25935
26774
  if (data.success) {
25936
26775
  let targetDid;
@@ -26016,17 +26855,29 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26016
26855
  await ensureUser();
26017
26856
  return client.contracts.createConsentFlowContract.mutate(contract);
26018
26857
  }, "createContract"),
26019
- addAutoBoostsToContract: /* @__PURE__ */ __name(async (_learnCard, contractUri, autoboosts) => {
26020
- await ensureUser();
26021
- return client.contracts.addAutoBoostsToContract.mutate({ contractUri, autoboosts });
26022
- }, "addAutoBoostsToContract"),
26023
- removeAutoBoostsFromContract: /* @__PURE__ */ __name(async (_learnCard, contractUri, boostUris) => {
26858
+ updateContract: /* @__PURE__ */ __name(async (_learnCard, uri, changes, options2 = {}) => {
26859
+ const { read, write, contract, ...details } = changes;
26860
+ if (read && contract?.read || write && contract?.write) {
26861
+ throw new Error(
26862
+ "Contract read/write updates must use either the top-level or nested contract shape, not both."
26863
+ );
26864
+ }
26024
26865
  await ensureUser();
26025
- return client.contracts.removeAutoBoostsFromContract.mutate({
26026
- contractUri,
26027
- boostUris
26866
+ return client.contracts.updateConsentFlowContract.mutate({
26867
+ uri,
26868
+ changes: {
26869
+ ...details,
26870
+ ...(contract || read || write) && {
26871
+ contract: {
26872
+ ...contract,
26873
+ ...read && { read },
26874
+ ...write && { write }
26875
+ }
26876
+ }
26877
+ },
26878
+ ...options2
26028
26879
  });
26029
- }, "removeAutoBoostsFromContract"),
26880
+ }, "updateContract"),
26030
26881
  addContractRecipient: /* @__PURE__ */ __name(async (_learnCard, contractUri, recipient) => {
26031
26882
  await ensureUser();
26032
26883
  return client.contracts.addContractRecipient.mutate({ contractUri, recipient });
@@ -26038,6 +26889,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26038
26889
  getContract: /* @__PURE__ */ __name(async (_learnCard, uri) => {
26039
26890
  return client.contracts.getConsentFlowContract.query({ uri });
26040
26891
  }, "getContract"),
26892
+ getContractVersions: /* @__PURE__ */ __name(async (_learnCard, uri) => {
26893
+ await ensureUser();
26894
+ return client.contracts.getContractVersions.query({ uri });
26895
+ }, "getContractVersions"),
26896
+ getConsentStatus: /* @__PURE__ */ __name(async (_learnCard, uri, profileId) => {
26897
+ await ensureUser();
26898
+ return client.contracts.getConsentStatus.query({ uri, profileId });
26899
+ }, "getConsentStatus"),
26041
26900
  getContracts: /* @__PURE__ */ __name(async (_learnCard, options2) => {
26042
26901
  await ensureUser();
26043
26902
  return client.contracts.getConsentFlowContracts.query(options2);
@@ -26094,6 +26953,15 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26094
26953
  audienceVersion
26095
26954
  });
26096
26955
  }, "updateContractTerms"),
26956
+ acceptContractUpdate: /* @__PURE__ */ __name(async (_learnCard, uri, { version: version2, terms, audienceVersion }) => {
26957
+ await ensureUser();
26958
+ return client.contracts.updateConsentedContractTerms.mutate({
26959
+ uri,
26960
+ terms,
26961
+ acceptVersion: version2,
26962
+ audienceVersion
26963
+ });
26964
+ }, "acceptContractUpdate"),
26097
26965
  withdrawConsent: /* @__PURE__ */ __name(async (_learnCard, uri) => {
26098
26966
  await ensureUser();
26099
26967
  return client.contracts.withdrawConsent.mutate({ uri });
@@ -26371,7 +27239,13 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26371
27239
  );
26372
27240
  return [];
26373
27241
  });
26374
- return { ...result, records, failed: results.length - records.length };
27242
+ const { cursor, ...page } = result;
27243
+ return {
27244
+ ...page,
27245
+ ...cursor === void 0 ? {} : { cursor },
27246
+ records,
27247
+ failed: results.length - records.length
27248
+ };
26375
27249
  }, "recoverInboxCredentials"),
26376
27250
  sendGuardianApprovalEmail: /* @__PURE__ */ __name(async (_learnCard, options2) => {
26377
27251
  await ensureUser();
@@ -26728,10 +27602,33 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26728
27602
  await ensureUser();
26729
27603
  return client.appStore.isAdmin.query();
26730
27604
  }, "isAppStoreAdmin"),
27605
+ getAnnouncementPreferences: /* @__PURE__ */ __name(async (_learnCard) => {
27606
+ await ensureUser();
27607
+ return client.campaigns.getAnnouncementPreferences.query();
27608
+ }, "getAnnouncementPreferences"),
27609
+ updateAnnouncementPreferences: /* @__PURE__ */ __name(async (_learnCard, updates) => {
27610
+ await ensureUser();
27611
+ return client.campaigns.updateAnnouncementPreferences.mutate(updates);
27612
+ }, "updateAnnouncementPreferences"),
27613
+ unsubscribeFromAnnouncements: /* @__PURE__ */ __name(async (_learnCard, token) => {
27614
+ return (0, import_network_brain_client.getAnonymousClient)(url2).campaigns.unsubscribe.mutate({ token });
27615
+ }, "unsubscribeFromAnnouncements"),
26731
27616
  campaignsIsAdmin: /* @__PURE__ */ __name(async (_learnCard) => {
26732
27617
  await ensureUser();
26733
27618
  return client.campaigns.isAdmin.query();
26734
27619
  }, "campaignsIsAdmin"),
27620
+ campaignsSendTestToMe: /* @__PURE__ */ __name(async (_learnCard, campaignId) => {
27621
+ await ensureUser();
27622
+ return client.campaigns.sendTestToMe.mutate({ campaignId });
27623
+ }, "campaignsSendTestToMe"),
27624
+ campaignsPreviewDispatch: /* @__PURE__ */ __name(async (_learnCard, campaignId) => {
27625
+ await ensureUser();
27626
+ return client.campaigns.previewDispatch.query({ campaignId });
27627
+ }, "campaignsPreviewDispatch"),
27628
+ campaignsDispatch: /* @__PURE__ */ __name(async (_learnCard, campaignId, options2 = {}) => {
27629
+ await ensureUser();
27630
+ return client.campaigns.dispatch.mutate({ campaignId, ...options2 });
27631
+ }, "campaignsDispatch"),
26735
27632
  campaignsCreate: /* @__PURE__ */ __name(async (_learnCard, input2) => {
26736
27633
  await ensureUser();
26737
27634
  return client.campaigns.create.mutate(input2);
@@ -26774,11 +27671,21 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
26774
27671
  }, "campaignsGetStats"),
26775
27672
  getMyCampaigns: /* @__PURE__ */ __name(async (_learnCard) => {
26776
27673
  await ensureUser();
26777
- return client.campaigns.getMyCampaigns.query();
27674
+ const response = await client.campaigns.getMyCampaigns.query();
27675
+ if (!Array.isArray(response))
27676
+ throw new Error("Invalid campaigns response: expected an array");
27677
+ return response.flatMap((item) => {
27678
+ const result = MyCampaignValidator.safeParse(item);
27679
+ return result.success ? [result.data] : [];
27680
+ });
26778
27681
  }, "getMyCampaigns"),
26779
- recordCampaignEvent: /* @__PURE__ */ __name(async (_learnCard, campaignId, event) => {
27682
+ recordCampaignEvent: /* @__PURE__ */ __name(async (_learnCard, campaignId, event, testId) => {
26780
27683
  await ensureUser();
26781
- return client.campaigns.recordEvent.mutate({ campaignId, event });
27684
+ return client.campaigns.recordEvent.mutate({
27685
+ campaignId,
27686
+ event,
27687
+ ...testId ? { testId } : {}
27688
+ });
26782
27689
  }, "recordCampaignEvent"),
26783
27690
  enrollInCampaign: /* @__PURE__ */ __name(async (_learnCard, campaignId) => {
26784
27691
  await ensureUser();