@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/README.md +12 -0
- package/dist/inbox-batch.d.ts +5 -0
- package/dist/inbox-batch.d.ts.map +1 -0
- package/dist/inbox-batch.test.d.ts +2 -0
- package/dist/inbox-batch.test.d.ts.map +1 -0
- package/dist/lcn-plugin.cjs.development.cjs +1091 -203
- package/dist/lcn-plugin.cjs.development.cjs.map +4 -4
- package/dist/lcn-plugin.cjs.production.min.cjs +36 -36
- package/dist/lcn-plugin.cjs.production.min.cjs.map +4 -4
- package/dist/lcn-plugin.esm.js +1093 -203
- package/dist/lcn-plugin.esm.js.map +4 -4
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/test/act-as.test.d.ts +2 -0
- package/dist/test/act-as.test.d.ts.map +1 -0
- package/dist/test/refresh-send.test-d.d.ts +2 -0
- package/dist/test/refresh-send.test-d.d.ts.map +1 -0
- package/dist/test/refresh-send.test.d.ts +2 -0
- package/dist/test/refresh-send.test.d.ts.map +1 -0
- package/dist/types.d.ts +129 -20
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/inbox-batch.test.ts +105 -0
- package/src/inbox-batch.ts +66 -0
- package/src/plugin.ts +402 -55
- package/src/test/act-as.test.ts +323 -0
- package/src/test/index.test.ts +161 -10
- package/src/test/refresh-send.test-d.ts +152 -0
- package/src/test/refresh-send.test.ts +646 -0
- package/src/types.ts +178 -23
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: (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|