@learncard/network-plugin 2.14.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/types.ts CHANGED
@@ -53,6 +53,9 @@ import {
53
53
  AuthGrantType,
54
54
  AuthGrantQuery,
55
55
  IssueInboxCredentialType,
56
+ IssueInboxCredentialBatch,
57
+ InboxBatchReceipt,
58
+ InboxBatchStatus,
56
59
  InboxCredentialType,
57
60
  PaginatedInboxCredentialsType,
58
61
  PaginatedSkillFrameworksType,
@@ -113,17 +116,68 @@ import {
113
116
  BitstringCredentialStatusEntry,
114
117
  AllocateCredentialRefreshInput,
115
118
  AllocateCredentialRefreshResult,
119
+ ManagedCredentialRefreshReceipt,
116
120
  PublishCredentialRefreshInput,
117
121
  PublishCredentialRefreshResult,
118
122
  GetCredentialRefreshHistoryInput,
119
123
  GetCredentialRefreshHistoryResult,
120
124
  } from '@learncard/types';
121
- import { Plugin } from '@learncard/core';
125
+ import { LearnCard, Plugin } from '@learncard/core';
122
126
  import { ProofOptions } from '@learncard/didkit-plugin';
123
127
  import { VerifyExtension } from '@learncard/vc-plugin';
124
128
 
125
129
  export type { BitstringCredentialStatusPurpose, BitstringCredentialStatusEntry };
126
130
 
131
+ /** Object-form options for the network plugin's `sendBoost` */
132
+ export type SendBoostNetworkOptions = {
133
+ encrypt?: boolean;
134
+ overideFn?: (boost: UnsignedVC) => UnsignedVC;
135
+ skipNotification?: boolean;
136
+ templateData?: Record<string, unknown>;
137
+ statusPurposes?: BitstringCredentialStatusPurpose[];
138
+ /**
139
+ * Opt into a managed refresh service. When true, a stable UUID credential ID is
140
+ * generated if the boost template has none, a refresh service is allocated BEFORE
141
+ * signing and injected into the signed credential, and the credential is sent via
142
+ * the dedicated managed-send procedure (holder-encrypted storage only) instead of
143
+ * legacy credential storage. The `encrypt` option is ignored in this mode —
144
+ * managed storage is always holder-only.
145
+ */
146
+ enableRefresh?: boolean;
147
+ };
148
+
149
+ /** Result of a refresh-enabled `sendBoost` call (opt-in via `enableRefresh: true`) */
150
+ export type SendBoostRefreshResult = {
151
+ /** URI of the issued (managed, holder-encrypted) credential */
152
+ credentialUri: string;
153
+ /** Issuance metadata the issuer keeps in order to publish future updates */
154
+ refresh: ManagedCredentialRefreshReceipt;
155
+ };
156
+
157
+ /** The `enableRefresh` type carried by `sendBoost` options (`undefined` when absent). */
158
+ type EnableRefreshOf<Options> = Options extends object
159
+ ? 'enableRefresh' extends keyof Options
160
+ ? Options extends { enableRefresh?: infer Enabled }
161
+ ? Enabled
162
+ : undefined
163
+ : undefined
164
+ : undefined;
165
+
166
+ /**
167
+ * Resolves the `sendBoost` return type from the (const-inferred) options type.
168
+ *
169
+ * - legacy `boolean` options, omitted options, and object options without
170
+ * `enableRefresh` keep the historical `string` result.
171
+ * - literal `enableRefresh: true` returns the refreshable-issuance result.
172
+ * - anything that may be `true` at runtime (a `boolean`, an optional property, or a
173
+ * union of option shapes) degrades to the union of both shapes.
174
+ */
175
+ export type SendBoostResultFor<Options> = [EnableRefreshOf<Options>] extends [true]
176
+ ? SendBoostRefreshResult
177
+ : true extends EnableRefreshOf<Options>
178
+ ? string | SendBoostRefreshResult
179
+ : string;
180
+
127
181
  /** @group LearnCardNetwork Plugin */
128
182
  export type LearnCardNetworkPluginDependentMethods = {
129
183
  getDidAuthVp: (options?: ProofOptions) => Promise<VP | string>;
@@ -160,6 +214,14 @@ export type LearnCardNetworkPluginMethods = {
160
214
  getManagedProfiles: (
161
215
  options?: Partial<PaginationOptionsType> & { query?: LCNProfileQuery }
162
216
  ) => Promise<PaginatedLCNProfiles>;
217
+ /**
218
+ * Returns a new LearnCard instance whose network plugin sends every request with the
219
+ * `X-LearnCard-Act-As` header set to `profileId`, asking the server to swap the acting
220
+ * profile for the duration of each request. Token scope is unchanged; the server responds
221
+ * `403` if the caller doesn't manage `profileId`, or if an API token's grant doesn't cover
222
+ * it. The original instance (and its headers) is left untouched.
223
+ */
224
+ actAs: (profileId: string) => Promise<ActingLearnCard>;
163
225
  claimPendingGuardianLinks: () => Promise<
164
226
  Array<{ childProfileId: string; childDisplayName: string; managerId: string | null }>
165
227
  >;
@@ -473,29 +535,23 @@ export type LearnCardNetworkPluginMethods = {
473
535
  recipientProfileId: string,
474
536
  credentialUri?: string
475
537
  ) => Promise<boolean>;
476
- sendBoost: (
538
+ /**
539
+ * Sends a boost credential to a recipient profile.
540
+ *
541
+ * **Return shape (opt-in):** legacy callers (boolean options, omitted options, or
542
+ * object options without `enableRefresh`) receive the issued credential URI as a
543
+ * `string`, exactly as before. Passing literal `{ enableRefresh: true }` opts into
544
+ * managed refresh and returns `{ credentialUri, refresh }` instead, where `refresh`
545
+ * is the issuance receipt needed to publish future versions (see
546
+ * `publishCredentialRefresh`). Options whose `enableRefresh` may be `true` at runtime
547
+ * (a `boolean`, or a variable typed `SendBoostNetworkOptions`) degrade the result to
548
+ * `string | { credentialUri, refresh }`.
549
+ */
550
+ sendBoost: <const Options extends boolean | SendBoostNetworkOptions | undefined = undefined>(
477
551
  profileId: string,
478
552
  boostUri: string,
479
- options?:
480
- | boolean
481
- | {
482
- encrypt?: boolean;
483
- overideFn?: (boost: UnsignedVC) => UnsignedVC;
484
- skipNotification?: boolean;
485
- templateData?: Record<string, unknown>;
486
- statusPurposes?: BitstringCredentialStatusPurpose[];
487
- /**
488
- * Opt into a managed refresh service. When true, a stable UUID
489
- * credential ID is generated if the boost template has none, a
490
- * refresh service is allocated BEFORE signing and injected into the
491
- * signed credential, and the credential is sent via the dedicated
492
- * managed-send procedure (holder-encrypted storage only) instead of
493
- * legacy credential storage. The `encrypt` option is ignored in this
494
- * mode — managed storage is always holder-only.
495
- */
496
- enableRefresh?: boolean;
497
- }
498
- ) => Promise<string>;
553
+ options?: Options
554
+ ) => Promise<SendBoostResultFor<Options>>;
499
555
 
500
556
  registerSigningAuthority: (endpoint: string, name: string, did: string) => Promise<boolean>;
501
557
  getRegisteredSigningAuthorities: () => Promise<LCNSigningAuthorityForUserType[]>;
@@ -679,6 +735,27 @@ export type LearnCardNetworkPluginMethods = {
679
735
  revokeAuthGrant: (id: string) => Promise<boolean>;
680
736
  getAPITokenForAuthGrant: (id: string) => Promise<string>;
681
737
 
738
+ /** Queue 1–100 credentials; workers may start up to a minute later. Use sendCredentialViaInbox for immediate single issuance. */
739
+ sendCredentialsViaInbox: (batch: IssueInboxCredentialBatch) => Promise<InboxBatchReceipt>;
740
+ /** Explicit batch alias for sendCredentialsViaInbox. Returns a durable receipt. */
741
+ sendCredentialBatchViaInbox: (batch: IssueInboxCredentialBatch) => Promise<InboxBatchReceipt>;
742
+ /** Ordered results and disjoint success/failure/unconfirmed counts. `done` includes unconfirmed outcomes.
743
+ * @see https://docs.learncard.com/sdks/learncard-network/universal-inbox-api
744
+ */
745
+ getInboxCredentialBatch: (batchId: string) => Promise<InboxBatchStatus>;
746
+ /** Poll until done with bounded backoff. Abort/timeout stops waiting, not processing. */
747
+ waitForInboxCredentialBatch: (
748
+ batchId: string,
749
+ options?: WaitForInboxCredentialBatchOptions
750
+ ) => Promise<InboxBatchStatus>;
751
+ /** Submit once and wait; persist the receipt with onSubmitted for recovery after timeout. */
752
+ sendCredentialsViaInboxAndWait: (
753
+ batch: IssueInboxCredentialBatch,
754
+ options?: WaitForInboxCredentialBatchOptions & {
755
+ onSubmitted?: (receipt: InboxBatchReceipt) => void | Promise<void>;
756
+ }
757
+ ) => Promise<InboxBatchStatus>;
758
+ /** Issue one credential synchronously, without waiting for the batch dispatcher. */
682
759
  sendCredentialViaInbox: (
683
760
  issueInboxCredential: IssueInboxCredentialType
684
761
  ) => Promise<IssueInboxCredentialResponseType>;
@@ -971,6 +1048,16 @@ export type LearnCardNetworkPluginMethods = {
971
1048
  };
972
1049
 
973
1050
  /** @group LearnCardNetwork Plugin */
1051
+ /**
1052
+ * The wallet returned by `invoke.actAs`: the caller's existing plugins with a network
1053
+ * plugin bound to the target profile appended. The caller's plugin list cannot be named
1054
+ * from inside the plugin's own method map, hence the open tuple.
1055
+ */
1056
+ export type ActingLearnCard = LearnCard<
1057
+ [...Plugin[], LearnCardNetworkPlugin],
1058
+ 'id' | 'read' | 'store'
1059
+ >;
1060
+
974
1061
  export type LearnCardNetworkPlugin = Plugin<
975
1062
  'LearnCard Network',
976
1063
  'id' | 'read' | 'store',
@@ -988,3 +1075,12 @@ export type TrustedBoostRegistryEntry = {
988
1075
  url: string;
989
1076
  did: string;
990
1077
  };
1078
+
1079
+ export interface WaitForInboxCredentialBatchOptions {
1080
+ /** Overall polling deadline; defaults to ten minutes. */
1081
+ timeoutMs?: number;
1082
+ /** Initial interval; increases by 1.5x up to ten seconds (or this interval if larger). */
1083
+ intervalMs?: number;
1084
+ signal?: AbortSignal;
1085
+ onProgress?: (status: InboxBatchStatus) => void;
1086
+ }