@learncard/network-plugin 2.14.1 → 3.0.1

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
@@ -11,6 +11,18 @@ import {
11
11
  VP,
12
12
  SentCredentialInfo,
13
13
  JWE,
14
+ CreateShareLinkInput,
15
+ UpdateShareLinkInput,
16
+ ListShareLinksInput,
17
+ PaginatedShareLinks,
18
+ ShareLinkOperationKeyInput,
19
+ ShareLinkOwnerCommitOutput,
20
+ ShareLinkOwnerContentOutput,
21
+ ShareLinkOwnerStatusOutput,
22
+ ShareLinkOwnerRecoveryOutput,
23
+ ShareLinkPublicState,
24
+ ShareLinkPublicContentView,
25
+ AcknowledgeViewOutput,
14
26
  Boost,
15
27
  BoostQuery,
16
28
  LCNSigningAuthorityForUserType,
@@ -53,6 +65,9 @@ import {
53
65
  AuthGrantType,
54
66
  AuthGrantQuery,
55
67
  IssueInboxCredentialType,
68
+ IssueInboxCredentialBatch,
69
+ InboxBatchReceipt,
70
+ InboxBatchStatus,
56
71
  InboxCredentialType,
57
72
  PaginatedInboxCredentialsType,
58
73
  PaginatedSkillFrameworksType,
@@ -113,17 +128,68 @@ import {
113
128
  BitstringCredentialStatusEntry,
114
129
  AllocateCredentialRefreshInput,
115
130
  AllocateCredentialRefreshResult,
131
+ ManagedCredentialRefreshReceipt,
116
132
  PublishCredentialRefreshInput,
117
133
  PublishCredentialRefreshResult,
118
134
  GetCredentialRefreshHistoryInput,
119
135
  GetCredentialRefreshHistoryResult,
120
136
  } from '@learncard/types';
121
- import { Plugin } from '@learncard/core';
137
+ import { LearnCard, Plugin } from '@learncard/core';
122
138
  import { ProofOptions } from '@learncard/didkit-plugin';
123
139
  import { VerifyExtension } from '@learncard/vc-plugin';
124
140
 
125
141
  export type { BitstringCredentialStatusPurpose, BitstringCredentialStatusEntry };
126
142
 
143
+ /** Object-form options for the network plugin's `sendBoost` */
144
+ export type SendBoostNetworkOptions = {
145
+ encrypt?: boolean;
146
+ overideFn?: (boost: UnsignedVC) => UnsignedVC;
147
+ skipNotification?: boolean;
148
+ templateData?: Record<string, unknown>;
149
+ statusPurposes?: BitstringCredentialStatusPurpose[];
150
+ /**
151
+ * Opt into a managed refresh service. When true, a stable UUID credential ID is
152
+ * generated if the boost template has none, a refresh service is allocated BEFORE
153
+ * signing and injected into the signed credential, and the credential is sent via
154
+ * the dedicated managed-send procedure (holder-encrypted storage only) instead of
155
+ * legacy credential storage. The `encrypt` option is ignored in this mode —
156
+ * managed storage is always holder-only.
157
+ */
158
+ enableRefresh?: boolean;
159
+ };
160
+
161
+ /** Result of a refresh-enabled `sendBoost` call (opt-in via `enableRefresh: true`) */
162
+ export type SendBoostRefreshResult = {
163
+ /** URI of the issued (managed, holder-encrypted) credential */
164
+ credentialUri: string;
165
+ /** Issuance metadata the issuer keeps in order to publish future updates */
166
+ refresh: ManagedCredentialRefreshReceipt;
167
+ };
168
+
169
+ /** The `enableRefresh` type carried by `sendBoost` options (`undefined` when absent). */
170
+ type EnableRefreshOf<Options> = Options extends object
171
+ ? 'enableRefresh' extends keyof Options
172
+ ? Options extends { enableRefresh?: infer Enabled }
173
+ ? Enabled
174
+ : undefined
175
+ : undefined
176
+ : undefined;
177
+
178
+ /**
179
+ * Resolves the `sendBoost` return type from the (const-inferred) options type.
180
+ *
181
+ * - legacy `boolean` options, omitted options, and object options without
182
+ * `enableRefresh` keep the historical `string` result.
183
+ * - literal `enableRefresh: true` returns the refreshable-issuance result.
184
+ * - anything that may be `true` at runtime (a `boolean`, an optional property, or a
185
+ * union of option shapes) degrades to the union of both shapes.
186
+ */
187
+ export type SendBoostResultFor<Options> = [EnableRefreshOf<Options>] extends [true]
188
+ ? SendBoostRefreshResult
189
+ : true extends EnableRefreshOf<Options>
190
+ ? string | SendBoostRefreshResult
191
+ : string;
192
+
127
193
  /** @group LearnCardNetwork Plugin */
128
194
  export type LearnCardNetworkPluginDependentMethods = {
129
195
  getDidAuthVp: (options?: ProofOptions) => Promise<VP | string>;
@@ -160,6 +226,14 @@ export type LearnCardNetworkPluginMethods = {
160
226
  getManagedProfiles: (
161
227
  options?: Partial<PaginationOptionsType> & { query?: LCNProfileQuery }
162
228
  ) => Promise<PaginatedLCNProfiles>;
229
+ /**
230
+ * Returns a new LearnCard instance whose network plugin sends every request with the
231
+ * `X-LearnCard-Act-As` header set to `profileId`, asking the server to swap the acting
232
+ * profile for the duration of each request. Token scope is unchanged; the server responds
233
+ * `403` if the caller doesn't manage `profileId`, or if an API token's grant doesn't cover
234
+ * it. The original instance (and its headers) is left untouched.
235
+ */
236
+ actAs: (profileId: string) => Promise<ActingLearnCard>;
163
237
  claimPendingGuardianLinks: () => Promise<
164
238
  Array<{ childProfileId: string; childDisplayName: string; managerId: string | null }>
165
239
  >;
@@ -229,6 +303,48 @@ export type LearnCardNetworkPluginMethods = {
229
303
 
230
304
  invalidateInvite: (challenge: string) => Promise<boolean>;
231
305
 
306
+ /**
307
+ * LC-2187 authenticated owner share-link methods. All owner identity and
308
+ * namespace binding is derived server-side from the authenticated session;
309
+ * no caller-supplied owner/namespace/object authority is accepted.
310
+ */
311
+ createShareLink: (input: CreateShareLinkInput) => Promise<ShareLinkOwnerCommitOutput>;
312
+ updateShareLink: (input: UpdateShareLinkInput) => Promise<ShareLinkOwnerCommitOutput>;
313
+ revokeShareLink: (input: {
314
+ id: string;
315
+ expectedVersion?: number;
316
+ clientRequestId?: string;
317
+ }) => Promise<ShareLinkOwnerCommitOutput>;
318
+ getShareLink: (id: string) => Promise<ShareLinkOwnerStatusOutput>;
319
+ getShareLinkOperationStatus: (
320
+ input: ShareLinkOperationKeyInput
321
+ ) => Promise<ShareLinkOwnerStatusOutput>;
322
+ retryShareLinkOperation: (
323
+ input: ShareLinkOperationKeyInput
324
+ ) => Promise<ShareLinkOwnerStatusOutput>;
325
+ getShareLinkRecovery: (id: string) => Promise<ShareLinkOwnerRecoveryOutput>;
326
+ getShareLinkOwnerContent: (id: string) => Promise<ShareLinkOwnerContentOutput>;
327
+
328
+ /**
329
+ * Bounded, newest-first owner share list. Scope (namespace/owner) is derived
330
+ * server-side from the authenticated session; the input carries only a
331
+ * bounded `limit` and an opaque ordering cursor. Ineligible/unknown owners
332
+ * never receive `viewCount`/`lastViewedAt`.
333
+ */
334
+ listShareLinks: (input: ListShareLinksInput) => Promise<PaginatedShareLinks>;
335
+
336
+ /**
337
+ * LC-2187 PUBLIC (anonymous) share-link methods. These require no
338
+ * authentication and no profile: namespace/owner are derived server-side
339
+ * from trusted configuration and the committed share. `resolveShareLink`
340
+ * returns metadata only and never counts; `getShareLinkContent` returns the
341
+ * guarded ciphertext envelope plus a uniformly shaped opaque receipt;
342
+ * `acknowledgeShareLinkView` always resolves to `{ ok: true }`.
343
+ */
344
+ resolveShareLink: (id: string, passcode?: string) => Promise<ShareLinkPublicState>;
345
+ getShareLinkContent: (id: string, passcode?: string) => Promise<ShareLinkPublicContentView>;
346
+ acknowledgeShareLinkView: (receipt: string) => Promise<AcknowledgeViewOutput>;
347
+
232
348
  blockProfile: (profileId: string) => Promise<boolean>;
233
349
  unblockProfile: (profileId: string) => Promise<boolean>;
234
350
  getBlockedProfiles: () => Promise<LCNVisibleProfile[]>;
@@ -252,7 +368,12 @@ export type LearnCardNetworkPluginMethods = {
252
368
  getIncomingCredentials: (from?: string) => Promise<SentCredentialInfo[]>;
253
369
  deleteCredential: (uri: string) => Promise<boolean>;
254
370
 
255
- sendPresentation: (profileId: string, vp: VP, encrypt?: boolean) => Promise<string>;
371
+ sendPresentation: (
372
+ profileId: string,
373
+ vp: VP,
374
+ metadataOrEncrypt?: Record<string, unknown> | boolean,
375
+ encrypt?: boolean
376
+ ) => Promise<string>;
256
377
  acceptPresentation: (uri: string) => Promise<boolean>;
257
378
  getReceivedPresentations: (from?: string) => Promise<SentCredentialInfo[]>;
258
379
  getSentPresentations: (to?: string) => Promise<SentCredentialInfo[]>;
@@ -473,29 +594,23 @@ export type LearnCardNetworkPluginMethods = {
473
594
  recipientProfileId: string,
474
595
  credentialUri?: string
475
596
  ) => Promise<boolean>;
476
- sendBoost: (
597
+ /**
598
+ * Sends a boost credential to a recipient profile.
599
+ *
600
+ * **Return shape (opt-in):** legacy callers (boolean options, omitted options, or
601
+ * object options without `enableRefresh`) receive the issued credential URI as a
602
+ * `string`, exactly as before. Passing literal `{ enableRefresh: true }` opts into
603
+ * managed refresh and returns `{ credentialUri, refresh }` instead, where `refresh`
604
+ * is the issuance receipt needed to publish future versions (see
605
+ * `publishCredentialRefresh`). Options whose `enableRefresh` may be `true` at runtime
606
+ * (a `boolean`, or a variable typed `SendBoostNetworkOptions`) degrade the result to
607
+ * `string | { credentialUri, refresh }`.
608
+ */
609
+ sendBoost: <const Options extends boolean | SendBoostNetworkOptions | undefined = undefined>(
477
610
  profileId: string,
478
611
  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>;
612
+ options?: Options
613
+ ) => Promise<SendBoostResultFor<Options>>;
499
614
 
500
615
  registerSigningAuthority: (endpoint: string, name: string, did: string) => Promise<boolean>;
501
616
  getRegisteredSigningAuthorities: () => Promise<LCNSigningAuthorityForUserType[]>;
@@ -679,6 +794,27 @@ export type LearnCardNetworkPluginMethods = {
679
794
  revokeAuthGrant: (id: string) => Promise<boolean>;
680
795
  getAPITokenForAuthGrant: (id: string) => Promise<string>;
681
796
 
797
+ /** Queue 1–100 credentials; workers may start up to a minute later. Use sendCredentialViaInbox for immediate single issuance. */
798
+ sendCredentialsViaInbox: (batch: IssueInboxCredentialBatch) => Promise<InboxBatchReceipt>;
799
+ /** Explicit batch alias for sendCredentialsViaInbox. Returns a durable receipt. */
800
+ sendCredentialBatchViaInbox: (batch: IssueInboxCredentialBatch) => Promise<InboxBatchReceipt>;
801
+ /** Ordered results and disjoint success/failure/unconfirmed counts. `done` includes unconfirmed outcomes.
802
+ * @see https://docs.learncard.com/sdks/learncard-network/universal-inbox-api
803
+ */
804
+ getInboxCredentialBatch: (batchId: string) => Promise<InboxBatchStatus>;
805
+ /** Poll until done with bounded backoff. Abort/timeout stops waiting, not processing. */
806
+ waitForInboxCredentialBatch: (
807
+ batchId: string,
808
+ options?: WaitForInboxCredentialBatchOptions
809
+ ) => Promise<InboxBatchStatus>;
810
+ /** Submit once and wait; persist the receipt with onSubmitted for recovery after timeout. */
811
+ sendCredentialsViaInboxAndWait: (
812
+ batch: IssueInboxCredentialBatch,
813
+ options?: WaitForInboxCredentialBatchOptions & {
814
+ onSubmitted?: (receipt: InboxBatchReceipt) => void | Promise<void>;
815
+ }
816
+ ) => Promise<InboxBatchStatus>;
817
+ /** Issue one credential synchronously, without waiting for the batch dispatcher. */
682
818
  sendCredentialViaInbox: (
683
819
  issueInboxCredential: IssueInboxCredentialType
684
820
  ) => Promise<IssueInboxCredentialResponseType>;
@@ -971,6 +1107,16 @@ export type LearnCardNetworkPluginMethods = {
971
1107
  };
972
1108
 
973
1109
  /** @group LearnCardNetwork Plugin */
1110
+ /**
1111
+ * The wallet returned by `invoke.actAs`: the caller's existing plugins with a network
1112
+ * plugin bound to the target profile appended. The caller's plugin list cannot be named
1113
+ * from inside the plugin's own method map, hence the open tuple.
1114
+ */
1115
+ export type ActingLearnCard = LearnCard<
1116
+ [...Plugin[], LearnCardNetworkPlugin],
1117
+ 'id' | 'read' | 'store'
1118
+ >;
1119
+
974
1120
  export type LearnCardNetworkPlugin = Plugin<
975
1121
  'LearnCard Network',
976
1122
  'id' | 'read' | 'store',
@@ -988,3 +1134,12 @@ export type TrustedBoostRegistryEntry = {
988
1134
  url: string;
989
1135
  did: string;
990
1136
  };
1137
+
1138
+ export interface WaitForInboxCredentialBatchOptions {
1139
+ /** Overall polling deadline; defaults to ten minutes. */
1140
+ timeoutMs?: number;
1141
+ /** Initial interval; increases by 1.5x up to ten seconds (or this interval if larger). */
1142
+ intervalMs?: number;
1143
+ signal?: AbortSignal;
1144
+ onProgress?: (status: InboxBatchStatus) => void;
1145
+ }