@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/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 +600 -218
- 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 +602 -218
- 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 +93 -19
- 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 +332 -52
- 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 +118 -22
|
@@ -21,11 +21,59 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/index.ts
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
|
+
ACT_AS_HEADER: () => ACT_AS_HEADER,
|
|
24
25
|
getLearnCardNetworkPlugin: () => getLearnCardNetworkPlugin,
|
|
25
26
|
getVerifyBoostPlugin: () => getVerifyBoostPlugin
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(index_exports);
|
|
28
29
|
|
|
30
|
+
// src/inbox-batch.ts
|
|
31
|
+
var waitForInboxCredentialBatch = /* @__PURE__ */ __name(async (read, options = {}) => {
|
|
32
|
+
const { timeoutMs = 6e5, intervalMs = 2e3, signal, onProgress } = options;
|
|
33
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647 || !Number.isFinite(intervalMs) || intervalMs <= 0 || intervalMs > 2147483647) {
|
|
34
|
+
throw new RangeError("timeoutMs and intervalMs must be positive finite timer durations.");
|
|
35
|
+
}
|
|
36
|
+
const controller = new AbortController();
|
|
37
|
+
const abort = /* @__PURE__ */ __name(() => controller.abort(signal?.reason), "abort");
|
|
38
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
39
|
+
if (signal?.aborted) abort();
|
|
40
|
+
const timeout = setTimeout(() => {
|
|
41
|
+
const error51 = new Error(
|
|
42
|
+
"Timed out waiting for inbox batch. Keep the batch ID to check again."
|
|
43
|
+
);
|
|
44
|
+
error51.name = "TimeoutError";
|
|
45
|
+
controller.abort(error51);
|
|
46
|
+
}, timeoutMs);
|
|
47
|
+
const cancellable = /* @__PURE__ */ __name((operation) => new Promise((resolve, reject) => {
|
|
48
|
+
const interrupted = /* @__PURE__ */ __name(() => reject(controller.signal.reason), "interrupted");
|
|
49
|
+
if (controller.signal.aborted) return interrupted();
|
|
50
|
+
controller.signal.addEventListener("abort", interrupted, { once: true });
|
|
51
|
+
Promise.resolve().then(() => {
|
|
52
|
+
if (controller.signal.aborted) throw controller.signal.reason;
|
|
53
|
+
return operation();
|
|
54
|
+
}).then(resolve, reject).finally(() => controller.signal.removeEventListener("abort", interrupted));
|
|
55
|
+
}), "cancellable");
|
|
56
|
+
let delay = intervalMs;
|
|
57
|
+
let sleepTimer;
|
|
58
|
+
try {
|
|
59
|
+
while (true) {
|
|
60
|
+
const batch = await cancellable(() => read(controller.signal));
|
|
61
|
+
onProgress?.(batch);
|
|
62
|
+
if (batch.done) return batch;
|
|
63
|
+
await cancellable(
|
|
64
|
+
() => new Promise((resolve) => {
|
|
65
|
+
sleepTimer = setTimeout(resolve, delay);
|
|
66
|
+
})
|
|
67
|
+
);
|
|
68
|
+
delay = Math.min(delay * 1.5, Math.max(intervalMs, 1e4));
|
|
69
|
+
}
|
|
70
|
+
} finally {
|
|
71
|
+
clearTimeout(timeout);
|
|
72
|
+
clearTimeout(sleepTimer);
|
|
73
|
+
signal?.removeEventListener("abort", abort);
|
|
74
|
+
}
|
|
75
|
+
}, "waitForInboxCredentialBatch");
|
|
76
|
+
|
|
29
77
|
// src/plugin.ts
|
|
30
78
|
var import_network_brain_client = require("@learncard/network-brain-client");
|
|
31
79
|
|
|
@@ -15583,6 +15631,204 @@ var StringQuery = external_exports.union([
|
|
|
15583
15631
|
$or: BaseStringQuery.array()
|
|
15584
15632
|
})
|
|
15585
15633
|
]);
|
|
15634
|
+
var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
|
|
15635
|
+
var ManagedCredentialRefreshServiceValidator = external_exports.object({
|
|
15636
|
+
id: external_exports.string().min(1),
|
|
15637
|
+
type: external_exports.literal("LearnCardCredentialRefresh2026"),
|
|
15638
|
+
authorization: LearnCardRefreshAuthorizationValidator.optional()
|
|
15639
|
+
}).catchall(external_exports.any());
|
|
15640
|
+
var StandardCredentialRefreshServiceValidator = external_exports.object({
|
|
15641
|
+
id: external_exports.string().min(1),
|
|
15642
|
+
type: external_exports.literal("1EdTechCredentialRefresh")
|
|
15643
|
+
}).catchall(external_exports.any());
|
|
15644
|
+
var SupportedCredentialRefreshServiceValidator = external_exports.union([
|
|
15645
|
+
ManagedCredentialRefreshServiceValidator,
|
|
15646
|
+
StandardCredentialRefreshServiceValidator
|
|
15647
|
+
]);
|
|
15648
|
+
var AllocateCredentialRefreshInputValidator = external_exports.object({
|
|
15649
|
+
holder: external_exports.object({
|
|
15650
|
+
profileId: external_exports.string().optional(),
|
|
15651
|
+
did: external_exports.string().min(1)
|
|
15652
|
+
}),
|
|
15653
|
+
credentialId: external_exports.string().min(1)
|
|
15654
|
+
});
|
|
15655
|
+
var AllocateCredentialRefreshResultValidator = external_exports.object({
|
|
15656
|
+
refreshId: external_exports.string().min(1),
|
|
15657
|
+
refreshService: ManagedCredentialRefreshServiceValidator.extend({
|
|
15658
|
+
authorization: LearnCardRefreshAuthorizationValidator
|
|
15659
|
+
})
|
|
15660
|
+
});
|
|
15661
|
+
var ManagedCredentialRefreshReceiptValidator = external_exports.object({
|
|
15662
|
+
refreshId: external_exports.string().min(1),
|
|
15663
|
+
refreshService: ManagedCredentialRefreshServiceValidator,
|
|
15664
|
+
credentialId: external_exports.string().min(1),
|
|
15665
|
+
issuerDid: external_exports.string().min(1),
|
|
15666
|
+
holderDid: external_exports.string().min(1),
|
|
15667
|
+
credentialStatus: CredentialStatusValidator.or(
|
|
15668
|
+
CredentialStatusValidator.array()
|
|
15669
|
+
).optional()
|
|
15670
|
+
}).strip();
|
|
15671
|
+
var InboxCredentialRefreshReceiptValidator = ManagedCredentialRefreshReceiptValidator.omit(
|
|
15672
|
+
{ holderDid: true }
|
|
15673
|
+
).extend({ holderDid: external_exports.string().min(1).optional() });
|
|
15674
|
+
var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
|
|
15675
|
+
var PublishCredentialRefreshBaseFields = {
|
|
15676
|
+
refreshId: external_exports.string().min(1),
|
|
15677
|
+
notifyHolder: external_exports.boolean().optional(),
|
|
15678
|
+
updateSummary: external_exports.string().optional(),
|
|
15679
|
+
idempotencyKey: external_exports.string().optional()
|
|
15680
|
+
};
|
|
15681
|
+
var PublishIssuerSignedRefreshValidator = external_exports.object({
|
|
15682
|
+
...PublishCredentialRefreshBaseFields,
|
|
15683
|
+
mode: external_exports.literal("issuer-signed"),
|
|
15684
|
+
signedCredential: VCValidator
|
|
15685
|
+
});
|
|
15686
|
+
var PublishSigningAuthorityRefreshValidator = external_exports.object({
|
|
15687
|
+
...PublishCredentialRefreshBaseFields,
|
|
15688
|
+
mode: external_exports.literal("signing-authority"),
|
|
15689
|
+
credential: UnsignedVCValidator,
|
|
15690
|
+
signingAuthority: external_exports.object({
|
|
15691
|
+
type: external_exports.string().min(1)
|
|
15692
|
+
}).catchall(external_exports.any())
|
|
15693
|
+
});
|
|
15694
|
+
var PublishCredentialRefreshInputValidator = external_exports.object({
|
|
15695
|
+
...PublishCredentialRefreshBaseFields,
|
|
15696
|
+
mode: CredentialRefreshSigningModeValidator,
|
|
15697
|
+
signedCredential: VCValidator.optional(),
|
|
15698
|
+
credential: UnsignedVCValidator.optional(),
|
|
15699
|
+
signingAuthority: external_exports.object({
|
|
15700
|
+
type: external_exports.string().min(1)
|
|
15701
|
+
}).catchall(external_exports.any()).optional()
|
|
15702
|
+
}).superRefine((input, ctx) => {
|
|
15703
|
+
if (input.mode === "issuer-signed" && !input.signedCredential) {
|
|
15704
|
+
ctx.addIssue({
|
|
15705
|
+
code: "custom",
|
|
15706
|
+
path: ["signedCredential"],
|
|
15707
|
+
message: "signedCredential is required for issuer-signed publication"
|
|
15708
|
+
});
|
|
15709
|
+
}
|
|
15710
|
+
if (input.mode === "issuer-signed" && (input.credential !== void 0 || input.signingAuthority !== void 0)) {
|
|
15711
|
+
ctx.addIssue({
|
|
15712
|
+
code: "custom",
|
|
15713
|
+
path: ["mode"],
|
|
15714
|
+
message: "issuer-signed publication cannot include signing-authority fields"
|
|
15715
|
+
});
|
|
15716
|
+
}
|
|
15717
|
+
if (input.mode === "signing-authority") {
|
|
15718
|
+
if (input.signedCredential !== void 0) {
|
|
15719
|
+
ctx.addIssue({
|
|
15720
|
+
code: "custom",
|
|
15721
|
+
path: ["signedCredential"],
|
|
15722
|
+
message: "signing-authority publication cannot include signedCredential"
|
|
15723
|
+
});
|
|
15724
|
+
}
|
|
15725
|
+
if (!input.credential) {
|
|
15726
|
+
ctx.addIssue({
|
|
15727
|
+
code: "custom",
|
|
15728
|
+
path: ["credential"],
|
|
15729
|
+
message: "credential is required for signing-authority publication"
|
|
15730
|
+
});
|
|
15731
|
+
}
|
|
15732
|
+
if (!input.signingAuthority) {
|
|
15733
|
+
ctx.addIssue({
|
|
15734
|
+
code: "custom",
|
|
15735
|
+
path: ["signingAuthority"],
|
|
15736
|
+
message: "signingAuthority is required for signing-authority publication"
|
|
15737
|
+
});
|
|
15738
|
+
}
|
|
15739
|
+
}
|
|
15740
|
+
});
|
|
15741
|
+
var PublishCredentialRefreshNotificationValidator = external_exports.enum([
|
|
15742
|
+
"queued",
|
|
15743
|
+
"suppressed",
|
|
15744
|
+
"not-applicable",
|
|
15745
|
+
/** Publication succeeded, but the post-commit notification enqueue must be retried. */
|
|
15746
|
+
"delivery-failed"
|
|
15747
|
+
]);
|
|
15748
|
+
var PublishCredentialRefreshResultValidator = external_exports.object({
|
|
15749
|
+
refreshId: external_exports.string().min(1),
|
|
15750
|
+
version: external_exports.number().int().positive(),
|
|
15751
|
+
publishedAt: external_exports.string().min(1),
|
|
15752
|
+
notification: PublishCredentialRefreshNotificationValidator
|
|
15753
|
+
});
|
|
15754
|
+
var CredentialRefreshVersionMetadataValidator = external_exports.object({
|
|
15755
|
+
version: external_exports.number().int().positive(),
|
|
15756
|
+
publishedAt: external_exports.string().min(1),
|
|
15757
|
+
effectiveAt: external_exports.string().optional(),
|
|
15758
|
+
etag: external_exports.string().optional(),
|
|
15759
|
+
signingMode: CredentialRefreshSigningModeValidator.optional(),
|
|
15760
|
+
updateSummary: external_exports.string().optional()
|
|
15761
|
+
});
|
|
15762
|
+
var GetCredentialRefreshHistoryInputValidator = external_exports.object({
|
|
15763
|
+
refreshId: external_exports.string().min(1),
|
|
15764
|
+
cursor: external_exports.string().optional(),
|
|
15765
|
+
limit: external_exports.number().int().positive().optional()
|
|
15766
|
+
});
|
|
15767
|
+
var GetCredentialRefreshHistoryResultValidator = external_exports.object({
|
|
15768
|
+
records: CredentialRefreshVersionMetadataValidator.array(),
|
|
15769
|
+
hasMore: external_exports.boolean(),
|
|
15770
|
+
cursor: external_exports.string().optional()
|
|
15771
|
+
});
|
|
15772
|
+
var CredentialRefreshChallengeValidator = external_exports.object({
|
|
15773
|
+
challenge: external_exports.string().min(1),
|
|
15774
|
+
expiresAt: external_exports.string().min(1),
|
|
15775
|
+
domain: external_exports.string().optional(),
|
|
15776
|
+
scheme: external_exports.literal("LearnCardDIDAuth").optional()
|
|
15777
|
+
});
|
|
15778
|
+
var PublicCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
15779
|
+
format: external_exports.literal("vc"),
|
|
15780
|
+
credential: VCValidator,
|
|
15781
|
+
etag: external_exports.string().optional()
|
|
15782
|
+
});
|
|
15783
|
+
var JweCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
15784
|
+
format: external_exports.literal("jwe"),
|
|
15785
|
+
jwe: JWEValidator,
|
|
15786
|
+
etag: external_exports.string().optional(),
|
|
15787
|
+
/** Present on LearnCard-managed endpoints; optional for interoperable JWE services. */
|
|
15788
|
+
version: external_exports.number().int().positive().optional()
|
|
15789
|
+
});
|
|
15790
|
+
var CredentialRefreshResponseEnvelopeValidator = external_exports.discriminatedUnion("format", [
|
|
15791
|
+
PublicCredentialRefreshEnvelopeValidator,
|
|
15792
|
+
JweCredentialRefreshEnvelopeValidator
|
|
15793
|
+
]);
|
|
15794
|
+
var CredentialRefreshFailureCodeValidator = external_exports.enum([
|
|
15795
|
+
"UNAVAILABLE",
|
|
15796
|
+
"TIMEOUT",
|
|
15797
|
+
"UNSUPPORTED_SERVICE",
|
|
15798
|
+
"UNAUTHORIZED",
|
|
15799
|
+
"MALFORMED_RESPONSE",
|
|
15800
|
+
"INVALID_PROOF",
|
|
15801
|
+
"ISSUER_MISMATCH",
|
|
15802
|
+
"ID_MISMATCH",
|
|
15803
|
+
"ROLLBACK",
|
|
15804
|
+
"REVOKED",
|
|
15805
|
+
"UNSAFE_ENDPOINT"
|
|
15806
|
+
]);
|
|
15807
|
+
var CredentialRefreshUpdatedResultValidator = external_exports.object({
|
|
15808
|
+
status: external_exports.literal("updated"),
|
|
15809
|
+
credential: VCValidator,
|
|
15810
|
+
etag: external_exports.string().optional(),
|
|
15811
|
+
managedVersion: external_exports.number().int().positive().optional()
|
|
15812
|
+
});
|
|
15813
|
+
var CredentialRefreshUnchangedResultValidator = external_exports.object({
|
|
15814
|
+
status: external_exports.literal("unchanged"),
|
|
15815
|
+
checkedAt: external_exports.string().min(1),
|
|
15816
|
+
etag: external_exports.string().optional()
|
|
15817
|
+
});
|
|
15818
|
+
var CredentialRefreshUnsupportedResultValidator = external_exports.object({
|
|
15819
|
+
status: external_exports.literal("unsupported")
|
|
15820
|
+
});
|
|
15821
|
+
var CredentialRefreshFailedResultValidator = external_exports.object({
|
|
15822
|
+
status: external_exports.literal("failed"),
|
|
15823
|
+
code: CredentialRefreshFailureCodeValidator,
|
|
15824
|
+
retryable: external_exports.boolean()
|
|
15825
|
+
});
|
|
15826
|
+
var CredentialRefreshResultValidator = external_exports.discriminatedUnion("status", [
|
|
15827
|
+
CredentialRefreshUpdatedResultValidator,
|
|
15828
|
+
CredentialRefreshUnchangedResultValidator,
|
|
15829
|
+
CredentialRefreshUnsupportedResultValidator,
|
|
15830
|
+
CredentialRefreshFailedResultValidator
|
|
15831
|
+
]);
|
|
15586
15832
|
var LCNProfileDisplayValidator = external_exports.object({
|
|
15587
15833
|
backgroundColor: external_exports.string().optional(),
|
|
15588
15834
|
backgroundImage: external_exports.string().optional(),
|
|
@@ -15918,7 +16164,13 @@ var SendBoostInputValidator = external_exports.object({
|
|
|
15918
16164
|
"Options for email/phone recipients (Universal Inbox)"
|
|
15919
16165
|
),
|
|
15920
16166
|
templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
15921
|
-
integrationId: external_exports.string().optional().describe("Integration ID for activity tracking")
|
|
16167
|
+
integrationId: external_exports.string().optional().describe("Integration ID for activity tracking"),
|
|
16168
|
+
refresh: external_exports.boolean().optional().describe(
|
|
16169
|
+
"Request managed credential refresh for this send. Profile/DID recipients use immediate issuance; email/phone recipients use deferred Universal Inbox signing and bind the holder at claim."
|
|
16170
|
+
),
|
|
16171
|
+
idempotencyKey: external_exports.string().min(1).max(200).optional().describe(
|
|
16172
|
+
"Caller-chosen key that makes a managed refresh send (refresh: true) safe to retry as a whole: retries with the same key reuse the same boost, refresh allocation and result. Reusing a key for a different request is rejected. With signedCredential, requires prior tRPC prepareRefreshableSend; direct REST callers omit the key and retry the exact signed credential and templateUri."
|
|
16173
|
+
)
|
|
15922
16174
|
}).refine((data) => data.templateUri || data.template || data.signedCredential, {
|
|
15923
16175
|
message: "Either templateUri, template, or signedCredential must be provided.",
|
|
15924
16176
|
path: ["templateUri"]
|
|
@@ -15933,8 +16185,12 @@ var SendBoostInputValidator = external_exports.object({
|
|
|
15933
16185
|
message: "guardianEmail must differ from recipient (self-approval not allowed)",
|
|
15934
16186
|
path: ["options", "guardianEmail"]
|
|
15935
16187
|
}
|
|
15936
|
-
)
|
|
16188
|
+
).refine((data) => !data.idempotencyKey || data.refresh === true, {
|
|
16189
|
+
message: "idempotencyKey is only supported with refresh: true.",
|
|
16190
|
+
path: ["idempotencyKey"]
|
|
16191
|
+
});
|
|
15937
16192
|
var SendInboxResponseValidator = external_exports.object({
|
|
16193
|
+
refresh: InboxCredentialRefreshReceiptValidator.optional(),
|
|
15938
16194
|
issuanceId: external_exports.string(),
|
|
15939
16195
|
status: external_exports.enum(["PENDING", "ISSUED", "EXPIRED", "DELIVERED", "CLAIMED"]),
|
|
15940
16196
|
claimUrl: external_exports.string().url().optional().describe("Present when suppressDelivery=true"),
|
|
@@ -15949,8 +16205,34 @@ var SendBoostResponseValidator = external_exports.object({
|
|
|
15949
16205
|
activityId: external_exports.string().describe("Links to the activity lifecycle for this issuance"),
|
|
15950
16206
|
inbox: SendInboxResponseValidator.optional().describe(
|
|
15951
16207
|
"Present when sent via email/phone (Universal Inbox)"
|
|
16208
|
+
),
|
|
16209
|
+
refresh: ManagedCredentialRefreshReceiptValidator.optional().describe(
|
|
16210
|
+
"Present when managed refresh was requested: issuance metadata the issuer keeps to publish future updates"
|
|
15952
16211
|
)
|
|
15953
16212
|
});
|
|
16213
|
+
var PrepareRefreshableSendInputValidator = external_exports.object({
|
|
16214
|
+
recipient: external_exports.string(),
|
|
16215
|
+
templateUri: external_exports.string().optional(),
|
|
16216
|
+
template: SendBoostTemplateValidator.optional(),
|
|
16217
|
+
contractUri: external_exports.string().optional(),
|
|
16218
|
+
templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
16219
|
+
integrationId: external_exports.string().optional(),
|
|
16220
|
+
/** Credential ID to allocate for; generated server-side when omitted. */
|
|
16221
|
+
credentialId: external_exports.string().min(1).optional(),
|
|
16222
|
+
idempotencyKey: external_exports.string().min(1).max(200).optional()
|
|
16223
|
+
}).refine((data) => Boolean(data.templateUri) !== Boolean(data.template), {
|
|
16224
|
+
message: "Provide exactly one of templateUri or template."
|
|
16225
|
+
});
|
|
16226
|
+
var PrepareRefreshableSendResultValidator = external_exports.object({
|
|
16227
|
+
boostUri: external_exports.string(),
|
|
16228
|
+
credentialId: external_exports.string(),
|
|
16229
|
+
refreshId: external_exports.string(),
|
|
16230
|
+
refreshService: ManagedCredentialRefreshServiceValidator,
|
|
16231
|
+
/** The DID to use as credentialSubject.id (recipient DID, or the profile's did:web). */
|
|
16232
|
+
holderDid: external_exports.string(),
|
|
16233
|
+
/** Present when this idempotencyKey already completed: return it without signing. */
|
|
16234
|
+
completed: SendBoostResponseValidator.optional()
|
|
16235
|
+
});
|
|
15954
16236
|
var SendInputValidator = external_exports.discriminatedUnion("type", [SendBoostInputValidator]);
|
|
15955
16237
|
var SendResponseValidator = external_exports.discriminatedUnion("type", [SendBoostResponseValidator]);
|
|
15956
16238
|
var ConsentFlowTermsStatusValidator = external_exports.enum(["live", "stale", "withdrawn"]);
|
|
@@ -16269,6 +16551,7 @@ var LCNNotificationValidator = external_exports.object({
|
|
|
16269
16551
|
webhookUrl: external_exports.string().optional()
|
|
16270
16552
|
});
|
|
16271
16553
|
var AUTH_GRANT_AUDIENCE_DOMAIN_PREFIX = "auth-grant:";
|
|
16554
|
+
var ACT_AS_HEADER = "X-LearnCard-Act-As";
|
|
16272
16555
|
var AuthGrantValidator = external_exports.object({
|
|
16273
16556
|
id: external_exports.string(),
|
|
16274
16557
|
name: external_exports.string(),
|
|
@@ -16281,6 +16564,7 @@ var AuthGrantValidator = external_exports.object({
|
|
|
16281
16564
|
}, "error")
|
|
16282
16565
|
}),
|
|
16283
16566
|
scope: external_exports.string(),
|
|
16567
|
+
actAs: external_exports.string().optional(),
|
|
16284
16568
|
createdAt: external_exports.iso.datetime({ error: "createdAt must be a valid ISO 8601 datetime string" }),
|
|
16285
16569
|
expiresAt: external_exports.iso.datetime({ error: "expiresAt must be a valid ISO 8601 datetime string" }).nullish().optional()
|
|
16286
16570
|
});
|
|
@@ -16352,6 +16636,8 @@ var CreateContactMethodSessionResponseValidator = external_exports.object({
|
|
|
16352
16636
|
sessionJwt: external_exports.string()
|
|
16353
16637
|
});
|
|
16354
16638
|
var InboxCredentialValidator = external_exports.object({
|
|
16639
|
+
refresh: InboxCredentialRefreshReceiptValidator.optional(),
|
|
16640
|
+
refreshId: external_exports.string().optional(),
|
|
16355
16641
|
id: external_exports.string(),
|
|
16356
16642
|
credential: external_exports.string().optional(),
|
|
16357
16643
|
isSigned: external_exports.boolean(),
|
|
@@ -16406,12 +16692,19 @@ var IssueInboxCredentialValidator = external_exports.object({
|
|
|
16406
16692
|
templateUri: external_exports.string().optional().describe(
|
|
16407
16693
|
"URI of a boost template to use for issuance. The boost credential will be resolved and used. Mutually exclusive with credential field."
|
|
16408
16694
|
),
|
|
16695
|
+
refresh: external_exports.boolean().optional().describe(
|
|
16696
|
+
"Allocate managed refresh before signing. Requires unsigned content and a registered signing authority; binds the holder on claim."
|
|
16697
|
+
),
|
|
16698
|
+
idempotencyKey: external_exports.string().min(1).max(200).optional(),
|
|
16409
16699
|
// === OPTIONAL FEATURES ===
|
|
16410
16700
|
// Add major, distinct features at the top level.
|
|
16411
16701
|
//consentRequest: ConsentRequestValidator.optional(),
|
|
16412
16702
|
// === PROCESS CONFIGURATION (Optional) ===
|
|
16413
16703
|
// HOW should this issuance be handled?
|
|
16414
16704
|
configuration: external_exports.object({
|
|
16705
|
+
guardianEmail: external_exports.string().email().optional().describe(
|
|
16706
|
+
"Require approval from this guardian before the recipient can claim. Must differ from the recipient email."
|
|
16707
|
+
),
|
|
16415
16708
|
signingAuthority: IssueInboxSigningAuthorityValidator.optional().describe(
|
|
16416
16709
|
"The signing authority to use for the credential. If not provided, the users default signing authority will be used if the credential is not signed."
|
|
16417
16710
|
),
|
|
@@ -16465,17 +16758,130 @@ var IssueInboxCredentialValidator = external_exports.object({
|
|
|
16465
16758
|
}).optional().describe(
|
|
16466
16759
|
"Configuration for the credential issuance. If not provided, the default configuration will be used."
|
|
16467
16760
|
)
|
|
16761
|
+
}).refine((data) => !data.idempotencyKey || data.refresh === true, {
|
|
16762
|
+
message: "idempotencyKey requires refresh: true."
|
|
16468
16763
|
}).refine((data) => data.credential || data.templateUri, {
|
|
16469
16764
|
message: "Either credential or templateUri must be provided.",
|
|
16470
16765
|
path: ["credential"]
|
|
16471
|
-
})
|
|
16766
|
+
}).refine(
|
|
16767
|
+
(data) => !data.configuration?.guardianEmail || data.recipient.type !== "email" || data.configuration.guardianEmail.toLowerCase() !== data.recipient.value.toLowerCase(),
|
|
16768
|
+
{
|
|
16769
|
+
message: "guardianEmail must differ from recipient (self-approval not allowed)",
|
|
16770
|
+
path: ["configuration", "guardianEmail"]
|
|
16771
|
+
}
|
|
16772
|
+
);
|
|
16472
16773
|
var IssueInboxCredentialResponseValidator = external_exports.object({
|
|
16774
|
+
refresh: InboxCredentialRefreshReceiptValidator.optional(),
|
|
16473
16775
|
issuanceId: external_exports.string(),
|
|
16474
16776
|
status: LCNInboxStatusEnumValidator,
|
|
16475
16777
|
recipient: ContactMethodQueryValidator,
|
|
16476
16778
|
claimUrl: external_exports.string().url().optional(),
|
|
16477
16779
|
recipientDid: external_exports.string().optional()
|
|
16478
16780
|
});
|
|
16781
|
+
var InboxBatchConfigurationValidator = IssueInboxCredentialValidator.shape.configuration.unwrap().extend({
|
|
16782
|
+
refresh: IssueInboxCredentialValidator.shape.refresh.describe(
|
|
16783
|
+
"Enable managed refresh by default. An item configuration.refresh overrides this value, including false."
|
|
16784
|
+
),
|
|
16785
|
+
delivery: IssueInboxCredentialValidator.shape.configuration.unwrap().shape.delivery.unwrap().extend({ suppress: external_exports.boolean().optional() }).optional()
|
|
16786
|
+
});
|
|
16787
|
+
var InboxBatchItemConfigurationValidator = InboxBatchConfigurationValidator.extend({
|
|
16788
|
+
guardianEmail: InboxBatchConfigurationValidator.shape.guardianEmail.nullable().describe(
|
|
16789
|
+
"Require guardian approval, or set null to clear a batch-level guardianEmail for this item."
|
|
16790
|
+
)
|
|
16791
|
+
});
|
|
16792
|
+
var IssueInboxCredentialBatchItemValidator = external_exports.object({
|
|
16793
|
+
...IssueInboxCredentialValidator.shape,
|
|
16794
|
+
configuration: InboxBatchItemConfigurationValidator.optional(),
|
|
16795
|
+
idempotencyKey: external_exports.string().max(256).optional()
|
|
16796
|
+
}).refine((data) => data.credential || data.templateUri, {
|
|
16797
|
+
message: "Either credential or templateUri must be provided.",
|
|
16798
|
+
path: ["credential"]
|
|
16799
|
+
}).describe(
|
|
16800
|
+
"One issuance: provide credential or templateUri. Invalid input is rejected at submission with its item index."
|
|
16801
|
+
);
|
|
16802
|
+
var IssueInboxCredentialBatchValidator = external_exports.object({
|
|
16803
|
+
requestId: external_exports.string().min(1).max(256).optional(),
|
|
16804
|
+
items: external_exports.array(IssueInboxCredentialBatchItemValidator).min(1).max(100),
|
|
16805
|
+
configuration: InboxBatchConfigurationValidator.optional()
|
|
16806
|
+
}).superRefine((batch, ctx) => {
|
|
16807
|
+
batch.items.forEach((item, index) => {
|
|
16808
|
+
const itemGuardian = item.configuration?.guardianEmail;
|
|
16809
|
+
const guardian = itemGuardian === null ? void 0 : itemGuardian ?? batch.configuration?.guardianEmail;
|
|
16810
|
+
if (guardian && item.recipient.type === "email" && guardian.toLowerCase() === item.recipient.value.toLowerCase()) {
|
|
16811
|
+
ctx.addIssue({
|
|
16812
|
+
code: "custom",
|
|
16813
|
+
path: ["items", index, "configuration", "guardianEmail"],
|
|
16814
|
+
message: "guardianEmail must differ from recipient (self-approval not allowed)"
|
|
16815
|
+
});
|
|
16816
|
+
}
|
|
16817
|
+
});
|
|
16818
|
+
});
|
|
16819
|
+
var InboxBatchErrorReasonValidator = external_exports.enum([
|
|
16820
|
+
"DUPLICATE_KEY",
|
|
16821
|
+
"IDEMPOTENCY_MISMATCH",
|
|
16822
|
+
"IN_PROGRESS",
|
|
16823
|
+
"UNCONFIRMED"
|
|
16824
|
+
]);
|
|
16825
|
+
var IssueInboxCredentialBatchItemResultValidator = external_exports.discriminatedUnion("success", [
|
|
16826
|
+
IssueInboxCredentialResponseValidator.extend({
|
|
16827
|
+
success: external_exports.literal(true),
|
|
16828
|
+
index: external_exports.number().int().nonnegative(),
|
|
16829
|
+
deduplicated: external_exports.boolean().optional(),
|
|
16830
|
+
guardianStatus: GuardianStatusValidator.optional(),
|
|
16831
|
+
idempotencyKey: external_exports.string().optional()
|
|
16832
|
+
}),
|
|
16833
|
+
external_exports.object({
|
|
16834
|
+
success: external_exports.literal(false),
|
|
16835
|
+
index: external_exports.number().int().nonnegative(),
|
|
16836
|
+
idempotencyKey: external_exports.string().optional(),
|
|
16837
|
+
recipient: ContactMethodQueryValidator.optional(),
|
|
16838
|
+
error: external_exports.object({
|
|
16839
|
+
code: external_exports.string(),
|
|
16840
|
+
message: external_exports.string(),
|
|
16841
|
+
reason: InboxBatchErrorReasonValidator.optional()
|
|
16842
|
+
}),
|
|
16843
|
+
issuanceId: external_exports.string().optional().describe(
|
|
16844
|
+
"Present when issuance completed but replay storage could not be confirmed. Reconcile this issuance; do not issue again with a new key."
|
|
16845
|
+
),
|
|
16846
|
+
claimUrl: external_exports.string().url().optional().describe(
|
|
16847
|
+
"Claim URL of the completed issuance, if available, when replay storage could not be confirmed."
|
|
16848
|
+
)
|
|
16849
|
+
})
|
|
16850
|
+
]);
|
|
16851
|
+
var IssueInboxCredentialBatchResponseValidator = external_exports.object({
|
|
16852
|
+
results: external_exports.array(IssueInboxCredentialBatchItemResultValidator),
|
|
16853
|
+
summary: external_exports.object({
|
|
16854
|
+
total: external_exports.number(),
|
|
16855
|
+
succeeded: external_exports.number(),
|
|
16856
|
+
failed: external_exports.number(),
|
|
16857
|
+
deduplicated: external_exports.number()
|
|
16858
|
+
})
|
|
16859
|
+
});
|
|
16860
|
+
var InboxBatchReceiptValidator = external_exports.object({
|
|
16861
|
+
batchId: external_exports.string(),
|
|
16862
|
+
status: external_exports.enum(["QUEUED", "PROCESSING", "COMPLETED", "NEEDS_RECONCILIATION"]),
|
|
16863
|
+
createdAt: external_exports.string()
|
|
16864
|
+
});
|
|
16865
|
+
var InboxBatchStatusValidator = external_exports.object({
|
|
16866
|
+
batchId: external_exports.string(),
|
|
16867
|
+
createdAt: external_exports.string(),
|
|
16868
|
+
done: external_exports.boolean().describe(
|
|
16869
|
+
"True when no queued or processing items remain, including unconfirmed outcomes."
|
|
16870
|
+
),
|
|
16871
|
+
status: external_exports.enum(["QUEUED", "PROCESSING", "COMPLETED", "NEEDS_RECONCILIATION"]),
|
|
16872
|
+
items: external_exports.array(
|
|
16873
|
+
external_exports.object({
|
|
16874
|
+
index: external_exports.number().int().nonnegative(),
|
|
16875
|
+
state: external_exports.enum(["QUEUED", "PROCESSING", "COMPLETED", "NEEDS_RECONCILIATION"]),
|
|
16876
|
+
result: IssueInboxCredentialBatchItemResultValidator.optional()
|
|
16877
|
+
})
|
|
16878
|
+
),
|
|
16879
|
+
summary: IssueInboxCredentialBatchResponseValidator.shape.summary.extend({
|
|
16880
|
+
completed: external_exports.number(),
|
|
16881
|
+
pending: external_exports.number(),
|
|
16882
|
+
unconfirmed: external_exports.number()
|
|
16883
|
+
})
|
|
16884
|
+
});
|
|
16479
16885
|
var CredentialNameRefValidator = external_exports.object({ name: external_exports.string() }).passthrough();
|
|
16480
16886
|
var ClaimInboxCredentialValidator = external_exports.object({
|
|
16481
16887
|
credential: VCValidator.or(VPValidator).or(UnsignedVCValidator).or(CredentialNameRefValidator).describe("The credential to issue, or a { name } reference to resolve a boost template."),
|
|
@@ -16961,6 +17367,7 @@ var CredentialActivityValidator = external_exports.object({
|
|
|
16961
17367
|
eventType: CredentialActivityEventTypeValidator,
|
|
16962
17368
|
timestamp: external_exports.string(),
|
|
16963
17369
|
actorProfileId: external_exports.string().optional(),
|
|
17370
|
+
onBehalfOf: external_exports.string().optional(),
|
|
16964
17371
|
recipientType: CredentialActivityRecipientTypeValidator,
|
|
16965
17372
|
recipientIdentifier: external_exports.string(),
|
|
16966
17373
|
boostUri: external_exports.string().optional(),
|
|
@@ -17110,191 +17517,6 @@ var inAppMessagesFlagValidator = external_exports.object({
|
|
|
17110
17517
|
version: external_exports.number().default(1),
|
|
17111
17518
|
messages: external_exports.array(inAppMessageValidator).default([])
|
|
17112
17519
|
}).passthrough();
|
|
17113
|
-
var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
|
|
17114
|
-
var ManagedCredentialRefreshServiceValidator = external_exports.object({
|
|
17115
|
-
id: external_exports.string().min(1),
|
|
17116
|
-
type: external_exports.literal("LearnCardCredentialRefresh2026"),
|
|
17117
|
-
authorization: LearnCardRefreshAuthorizationValidator.optional()
|
|
17118
|
-
}).catchall(external_exports.any());
|
|
17119
|
-
var StandardCredentialRefreshServiceValidator = external_exports.object({
|
|
17120
|
-
id: external_exports.string().min(1),
|
|
17121
|
-
type: external_exports.literal("1EdTechCredentialRefresh")
|
|
17122
|
-
}).catchall(external_exports.any());
|
|
17123
|
-
var SupportedCredentialRefreshServiceValidator = external_exports.union([
|
|
17124
|
-
ManagedCredentialRefreshServiceValidator,
|
|
17125
|
-
StandardCredentialRefreshServiceValidator
|
|
17126
|
-
]);
|
|
17127
|
-
var AllocateCredentialRefreshInputValidator = external_exports.object({
|
|
17128
|
-
holder: external_exports.object({
|
|
17129
|
-
profileId: external_exports.string().optional(),
|
|
17130
|
-
did: external_exports.string().min(1)
|
|
17131
|
-
}),
|
|
17132
|
-
credentialId: external_exports.string().min(1)
|
|
17133
|
-
});
|
|
17134
|
-
var AllocateCredentialRefreshResultValidator = external_exports.object({
|
|
17135
|
-
refreshId: external_exports.string().min(1),
|
|
17136
|
-
refreshService: ManagedCredentialRefreshServiceValidator.extend({
|
|
17137
|
-
authorization: LearnCardRefreshAuthorizationValidator
|
|
17138
|
-
})
|
|
17139
|
-
});
|
|
17140
|
-
var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
|
|
17141
|
-
var PublishCredentialRefreshBaseFields = {
|
|
17142
|
-
refreshId: external_exports.string().min(1),
|
|
17143
|
-
notifyHolder: external_exports.boolean().optional(),
|
|
17144
|
-
updateSummary: external_exports.string().optional(),
|
|
17145
|
-
idempotencyKey: external_exports.string().optional()
|
|
17146
|
-
};
|
|
17147
|
-
var PublishIssuerSignedRefreshValidator = external_exports.object({
|
|
17148
|
-
...PublishCredentialRefreshBaseFields,
|
|
17149
|
-
mode: external_exports.literal("issuer-signed"),
|
|
17150
|
-
signedCredential: VCValidator
|
|
17151
|
-
});
|
|
17152
|
-
var PublishSigningAuthorityRefreshValidator = external_exports.object({
|
|
17153
|
-
...PublishCredentialRefreshBaseFields,
|
|
17154
|
-
mode: external_exports.literal("signing-authority"),
|
|
17155
|
-
credential: UnsignedVCValidator,
|
|
17156
|
-
signingAuthority: external_exports.object({
|
|
17157
|
-
type: external_exports.string().min(1)
|
|
17158
|
-
}).catchall(external_exports.any())
|
|
17159
|
-
});
|
|
17160
|
-
var PublishCredentialRefreshInputValidator = external_exports.object({
|
|
17161
|
-
...PublishCredentialRefreshBaseFields,
|
|
17162
|
-
mode: CredentialRefreshSigningModeValidator,
|
|
17163
|
-
signedCredential: VCValidator.optional(),
|
|
17164
|
-
credential: UnsignedVCValidator.optional(),
|
|
17165
|
-
signingAuthority: external_exports.object({
|
|
17166
|
-
type: external_exports.string().min(1)
|
|
17167
|
-
}).catchall(external_exports.any()).optional()
|
|
17168
|
-
}).superRefine((input, ctx) => {
|
|
17169
|
-
if (input.mode === "issuer-signed" && !input.signedCredential) {
|
|
17170
|
-
ctx.addIssue({
|
|
17171
|
-
code: "custom",
|
|
17172
|
-
path: ["signedCredential"],
|
|
17173
|
-
message: "signedCredential is required for issuer-signed publication"
|
|
17174
|
-
});
|
|
17175
|
-
}
|
|
17176
|
-
if (input.mode === "issuer-signed" && (input.credential !== void 0 || input.signingAuthority !== void 0)) {
|
|
17177
|
-
ctx.addIssue({
|
|
17178
|
-
code: "custom",
|
|
17179
|
-
path: ["mode"],
|
|
17180
|
-
message: "issuer-signed publication cannot include signing-authority fields"
|
|
17181
|
-
});
|
|
17182
|
-
}
|
|
17183
|
-
if (input.mode === "signing-authority") {
|
|
17184
|
-
if (input.signedCredential !== void 0) {
|
|
17185
|
-
ctx.addIssue({
|
|
17186
|
-
code: "custom",
|
|
17187
|
-
path: ["signedCredential"],
|
|
17188
|
-
message: "signing-authority publication cannot include signedCredential"
|
|
17189
|
-
});
|
|
17190
|
-
}
|
|
17191
|
-
if (!input.credential) {
|
|
17192
|
-
ctx.addIssue({
|
|
17193
|
-
code: "custom",
|
|
17194
|
-
path: ["credential"],
|
|
17195
|
-
message: "credential is required for signing-authority publication"
|
|
17196
|
-
});
|
|
17197
|
-
}
|
|
17198
|
-
if (!input.signingAuthority) {
|
|
17199
|
-
ctx.addIssue({
|
|
17200
|
-
code: "custom",
|
|
17201
|
-
path: ["signingAuthority"],
|
|
17202
|
-
message: "signingAuthority is required for signing-authority publication"
|
|
17203
|
-
});
|
|
17204
|
-
}
|
|
17205
|
-
}
|
|
17206
|
-
});
|
|
17207
|
-
var PublishCredentialRefreshNotificationValidator = external_exports.enum([
|
|
17208
|
-
"queued",
|
|
17209
|
-
"suppressed",
|
|
17210
|
-
"not-applicable",
|
|
17211
|
-
/** Publication succeeded, but the post-commit notification enqueue must be retried. */
|
|
17212
|
-
"delivery-failed"
|
|
17213
|
-
]);
|
|
17214
|
-
var PublishCredentialRefreshResultValidator = external_exports.object({
|
|
17215
|
-
refreshId: external_exports.string().min(1),
|
|
17216
|
-
version: external_exports.number().int().positive(),
|
|
17217
|
-
publishedAt: external_exports.string().min(1),
|
|
17218
|
-
notification: PublishCredentialRefreshNotificationValidator
|
|
17219
|
-
});
|
|
17220
|
-
var CredentialRefreshVersionMetadataValidator = external_exports.object({
|
|
17221
|
-
version: external_exports.number().int().positive(),
|
|
17222
|
-
publishedAt: external_exports.string().min(1),
|
|
17223
|
-
effectiveAt: external_exports.string().optional(),
|
|
17224
|
-
etag: external_exports.string().optional(),
|
|
17225
|
-
signingMode: CredentialRefreshSigningModeValidator.optional(),
|
|
17226
|
-
updateSummary: external_exports.string().optional()
|
|
17227
|
-
});
|
|
17228
|
-
var GetCredentialRefreshHistoryInputValidator = external_exports.object({
|
|
17229
|
-
refreshId: external_exports.string().min(1),
|
|
17230
|
-
cursor: external_exports.string().optional(),
|
|
17231
|
-
limit: external_exports.number().int().positive().optional()
|
|
17232
|
-
});
|
|
17233
|
-
var GetCredentialRefreshHistoryResultValidator = external_exports.object({
|
|
17234
|
-
records: CredentialRefreshVersionMetadataValidator.array(),
|
|
17235
|
-
hasMore: external_exports.boolean(),
|
|
17236
|
-
cursor: external_exports.string().optional()
|
|
17237
|
-
});
|
|
17238
|
-
var CredentialRefreshChallengeValidator = external_exports.object({
|
|
17239
|
-
challenge: external_exports.string().min(1),
|
|
17240
|
-
expiresAt: external_exports.string().min(1),
|
|
17241
|
-
domain: external_exports.string().optional(),
|
|
17242
|
-
scheme: external_exports.literal("LearnCardDIDAuth").optional()
|
|
17243
|
-
});
|
|
17244
|
-
var PublicCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17245
|
-
format: external_exports.literal("vc"),
|
|
17246
|
-
credential: VCValidator,
|
|
17247
|
-
etag: external_exports.string().optional()
|
|
17248
|
-
});
|
|
17249
|
-
var JweCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17250
|
-
format: external_exports.literal("jwe"),
|
|
17251
|
-
jwe: JWEValidator,
|
|
17252
|
-
etag: external_exports.string().optional(),
|
|
17253
|
-
/** Present on LearnCard-managed endpoints; optional for interoperable JWE services. */
|
|
17254
|
-
version: external_exports.number().int().positive().optional()
|
|
17255
|
-
});
|
|
17256
|
-
var CredentialRefreshResponseEnvelopeValidator = external_exports.discriminatedUnion("format", [
|
|
17257
|
-
PublicCredentialRefreshEnvelopeValidator,
|
|
17258
|
-
JweCredentialRefreshEnvelopeValidator
|
|
17259
|
-
]);
|
|
17260
|
-
var CredentialRefreshFailureCodeValidator = external_exports.enum([
|
|
17261
|
-
"UNAVAILABLE",
|
|
17262
|
-
"TIMEOUT",
|
|
17263
|
-
"UNSUPPORTED_SERVICE",
|
|
17264
|
-
"UNAUTHORIZED",
|
|
17265
|
-
"MALFORMED_RESPONSE",
|
|
17266
|
-
"INVALID_PROOF",
|
|
17267
|
-
"ISSUER_MISMATCH",
|
|
17268
|
-
"ID_MISMATCH",
|
|
17269
|
-
"ROLLBACK",
|
|
17270
|
-
"REVOKED",
|
|
17271
|
-
"UNSAFE_ENDPOINT"
|
|
17272
|
-
]);
|
|
17273
|
-
var CredentialRefreshUpdatedResultValidator = external_exports.object({
|
|
17274
|
-
status: external_exports.literal("updated"),
|
|
17275
|
-
credential: VCValidator,
|
|
17276
|
-
etag: external_exports.string().optional(),
|
|
17277
|
-
managedVersion: external_exports.number().int().positive().optional()
|
|
17278
|
-
});
|
|
17279
|
-
var CredentialRefreshUnchangedResultValidator = external_exports.object({
|
|
17280
|
-
status: external_exports.literal("unchanged"),
|
|
17281
|
-
checkedAt: external_exports.string().min(1),
|
|
17282
|
-
etag: external_exports.string().optional()
|
|
17283
|
-
});
|
|
17284
|
-
var CredentialRefreshUnsupportedResultValidator = external_exports.object({
|
|
17285
|
-
status: external_exports.literal("unsupported")
|
|
17286
|
-
});
|
|
17287
|
-
var CredentialRefreshFailedResultValidator = external_exports.object({
|
|
17288
|
-
status: external_exports.literal("failed"),
|
|
17289
|
-
code: CredentialRefreshFailureCodeValidator,
|
|
17290
|
-
retryable: external_exports.boolean()
|
|
17291
|
-
});
|
|
17292
|
-
var CredentialRefreshResultValidator = external_exports.discriminatedUnion("status", [
|
|
17293
|
-
CredentialRefreshUpdatedResultValidator,
|
|
17294
|
-
CredentialRefreshUnchangedResultValidator,
|
|
17295
|
-
CredentialRefreshUnsupportedResultValidator,
|
|
17296
|
-
CredentialRefreshFailedResultValidator
|
|
17297
|
-
]);
|
|
17298
17520
|
|
|
17299
17521
|
// src/plugin.ts
|
|
17300
17522
|
var import_helpers = require("@learncard/helpers");
|
|
@@ -17912,27 +18134,40 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
|
|
|
17912
18134
|
await appendNetworkCredentialStatus(client, credential, statusPurposes)
|
|
17913
18135
|
);
|
|
17914
18136
|
}, "issueCredentialWithNetworkStatus");
|
|
17915
|
-
var
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
|
|
17922
|
-
}
|
|
17923
|
-
};
|
|
17924
|
-
var
|
|
17925
|
-
const
|
|
17926
|
-
const
|
|
17927
|
-
const
|
|
17928
|
-
|
|
17929
|
-
);
|
|
18137
|
+
var injectManagedRefreshService = /* @__PURE__ */ __name((credential, refreshService) => (0, import_helpers.injectManagedRefreshService)(credential, refreshService), "injectManagedRefreshService");
|
|
18138
|
+
var getCredentialSubjectIds = /* @__PURE__ */ __name((vc) => {
|
|
18139
|
+
const subject = vc.credentialSubject;
|
|
18140
|
+
const subjects = Array.isArray(subject) ? subject : subject ? [subject] : [];
|
|
18141
|
+
return subjects.flatMap((entry) => {
|
|
18142
|
+
const id = entry?.id;
|
|
18143
|
+
return typeof id === "string" && id.length > 0 ? [id] : [];
|
|
18144
|
+
});
|
|
18145
|
+
}, "getCredentialSubjectIds");
|
|
18146
|
+
var buildManagedRefreshReceipt = /* @__PURE__ */ __name((vc, allocation, credentialId, fallbackHolderDid, fallbackIssuerDid) => {
|
|
18147
|
+
const issuerDid = (0, import_helpers.getCredentialIssuerId)(vc) ?? fallbackIssuerDid;
|
|
18148
|
+
const holderDid = getCredentialSubjectIds(vc)[0] ?? fallbackHolderDid;
|
|
18149
|
+
const rawStatus = vc.credentialStatus;
|
|
18150
|
+
const hasStatus = rawStatus !== void 0 && rawStatus !== null && !(Array.isArray(rawStatus) && rawStatus.length === 0);
|
|
17930
18151
|
return {
|
|
17931
|
-
|
|
17932
|
-
|
|
17933
|
-
|
|
17934
|
-
|
|
17935
|
-
|
|
18152
|
+
refreshId: allocation.refreshId,
|
|
18153
|
+
refreshService: allocation.refreshService,
|
|
18154
|
+
credentialId: typeof vc.id === "string" && vc.id.length > 0 ? vc.id : credentialId,
|
|
18155
|
+
issuerDid,
|
|
18156
|
+
holderDid,
|
|
18157
|
+
...hasStatus ? {
|
|
18158
|
+
credentialStatus: rawStatus
|
|
18159
|
+
} : {}
|
|
18160
|
+
};
|
|
18161
|
+
}, "buildManagedRefreshReceipt");
|
|
18162
|
+
var ACT_AS_TARGET_NOT_FOUND_MESSAGE = "Act-as target profile not found";
|
|
18163
|
+
var isActAsDenial = /* @__PURE__ */ __name((error51) => {
|
|
18164
|
+
const code = error51?.data?.code;
|
|
18165
|
+
if (code === "FORBIDDEN" || code === "BAD_REQUEST") return true;
|
|
18166
|
+
if (code === "NOT_FOUND") {
|
|
18167
|
+
return error51?.message === ACT_AS_TARGET_NOT_FOUND_MESSAGE;
|
|
18168
|
+
}
|
|
18169
|
+
return false;
|
|
18170
|
+
}, "isActAsDenial");
|
|
17936
18171
|
async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
|
|
17937
18172
|
const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
|
|
17938
18173
|
const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
|
|
@@ -17940,8 +18175,10 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17940
18175
|
guardianApprovalGetter,
|
|
17941
18176
|
extraHeaders,
|
|
17942
18177
|
trustedFederationHosts,
|
|
17943
|
-
allowLocalhostFederation
|
|
18178
|
+
allowLocalhostFederation,
|
|
18179
|
+
actAs
|
|
17944
18180
|
} = resolvedOptions;
|
|
18181
|
+
const mergedExtraHeaders = actAs ? { ...extraHeaders, [ACT_AS_HEADER]: actAs } : extraHeaders;
|
|
17945
18182
|
const serviceUrl = new URL(url2);
|
|
17946
18183
|
const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
|
|
17947
18184
|
const federationConfig = {
|
|
@@ -17959,7 +18196,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17959
18196
|
learnCard?.debug?.("LCN: no local DID available at init; will fetch from profile");
|
|
17960
18197
|
}
|
|
17961
18198
|
learnCard?.debug?.("Adding LearnCardNetwork Plugin");
|
|
17962
|
-
const client = apiToken ? await (0, import_network_brain_client.getApiTokenClient)(url2, apiToken, guardianApprovalGetter,
|
|
18199
|
+
const client = apiToken ? await (0, import_network_brain_client.getApiTokenClient)(url2, apiToken, guardianApprovalGetter, mergedExtraHeaders) : await (0, import_network_brain_client.getClient)(
|
|
17963
18200
|
url2,
|
|
17964
18201
|
async (challenge) => {
|
|
17965
18202
|
const jwt2 = await learnCard.invoke.getDidAuthVp({
|
|
@@ -17970,7 +18207,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17970
18207
|
return jwt2;
|
|
17971
18208
|
},
|
|
17972
18209
|
guardianApprovalGetter,
|
|
17973
|
-
|
|
18210
|
+
mergedExtraHeaders
|
|
17974
18211
|
);
|
|
17975
18212
|
let userData;
|
|
17976
18213
|
learnCard?.debug?.("LCN: initial getProfile query starting", { apiToken: !!apiToken });
|
|
@@ -18173,6 +18410,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18173
18410
|
getManagedProfiles: /* @__PURE__ */ __name(async (_learnCard, options2 = {}) => {
|
|
18174
18411
|
return client.profileManager.getManagedProfiles.query(options2);
|
|
18175
18412
|
}, "getManagedProfiles"),
|
|
18413
|
+
actAs: /* @__PURE__ */ __name(async (_learnCard, profileId) => {
|
|
18414
|
+
const actingOptions = {
|
|
18415
|
+
...resolvedOptions,
|
|
18416
|
+
actAs: profileId
|
|
18417
|
+
};
|
|
18418
|
+
const actingPlugin = apiToken ? await getLearnCardNetworkPlugin(_learnCard, url2, apiToken, actingOptions) : await getLearnCardNetworkPlugin(_learnCard, url2, actingOptions);
|
|
18419
|
+
try {
|
|
18420
|
+
await actingPlugin.methods.getLCNClient(_learnCard).profile.getProfile.query();
|
|
18421
|
+
} catch (error51) {
|
|
18422
|
+
if (isActAsDenial(error51)) {
|
|
18423
|
+
const message = error51 instanceof Error ? error51.message : "Act-as request was denied.";
|
|
18424
|
+
throw new Error(message, { cause: error51 });
|
|
18425
|
+
}
|
|
18426
|
+
_learnCard.debug?.("LCN actAs: getProfile failed (non-fatal)", error51);
|
|
18427
|
+
}
|
|
18428
|
+
return _learnCard.addPlugin(actingPlugin);
|
|
18429
|
+
}, "actAs"),
|
|
18176
18430
|
claimPendingGuardianLinks: /* @__PURE__ */ __name(async () => {
|
|
18177
18431
|
await ensureUser();
|
|
18178
18432
|
return client.inbox.claimPendingGuardianLinks.mutate({});
|
|
@@ -18782,15 +19036,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18782
19036
|
boost = options2.overideFn(boost);
|
|
18783
19037
|
}
|
|
18784
19038
|
const enableRefresh = typeof options2 === "object" && options2.enableRefresh === true;
|
|
18785
|
-
let
|
|
19039
|
+
let refreshAllocation;
|
|
18786
19040
|
if (enableRefresh) {
|
|
18787
19041
|
if (!boost.id) boost.id = `urn:uuid:${crypto.randomUUID()}`;
|
|
18788
|
-
|
|
19042
|
+
refreshAllocation = await client.credentialRefresh.allocateCredentialRefresh.mutate({
|
|
18789
19043
|
holder: { profileId, did: targetProfile.did },
|
|
18790
19044
|
credentialId: boost.id
|
|
18791
19045
|
});
|
|
18792
|
-
|
|
18793
|
-
boost = injectManagedRefreshService(boost, allocation.refreshService);
|
|
19046
|
+
boost = injectManagedRefreshService(boost, refreshAllocation.refreshService);
|
|
18794
19047
|
}
|
|
18795
19048
|
const statusPurposes = typeof options2 === "object" ? options2.statusPurposes : void 0;
|
|
18796
19049
|
const vc = await issueCredentialWithNetworkStatus(
|
|
@@ -18799,13 +19052,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18799
19052
|
boost,
|
|
18800
19053
|
statusPurposes
|
|
18801
19054
|
);
|
|
18802
|
-
if (
|
|
18803
|
-
|
|
18804
|
-
refreshId:
|
|
19055
|
+
if (refreshAllocation) {
|
|
19056
|
+
const credentialUri = await client.credentialRefresh.sendRefreshableCredential.mutate({
|
|
19057
|
+
refreshId: refreshAllocation.refreshId,
|
|
18805
19058
|
credential: vc,
|
|
18806
19059
|
boostUri,
|
|
18807
19060
|
...typeof options2 === "object" && options2.skipNotification ? { skipNotification: true } : {}
|
|
18808
19061
|
});
|
|
19062
|
+
return {
|
|
19063
|
+
credentialUri,
|
|
19064
|
+
refresh: buildManagedRefreshReceipt(
|
|
19065
|
+
vc,
|
|
19066
|
+
refreshAllocation,
|
|
19067
|
+
boost.id ?? "",
|
|
19068
|
+
targetProfile.did,
|
|
19069
|
+
_learnCard.id.did()
|
|
19070
|
+
)
|
|
19071
|
+
};
|
|
18809
19072
|
}
|
|
18810
19073
|
if (typeof options2 === "object" && !options2.encrypt || !options2) {
|
|
18811
19074
|
return client.boost.sendBoost.mutate({
|
|
@@ -18871,6 +19134,94 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18871
19134
|
}, "claimBoostWithLink"),
|
|
18872
19135
|
send: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18873
19136
|
await ensureUser();
|
|
19137
|
+
if (input.type === "boost" && input.refresh === true) {
|
|
19138
|
+
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input.recipient);
|
|
19139
|
+
const isPhone = /^\+?[\d\s-]{10,}$/.test(input.recipient.replace(/[\s-]/g, ""));
|
|
19140
|
+
if (isEmail || isPhone) return client.boost.send.mutate(input);
|
|
19141
|
+
const canIssueLocally = "issueCredential" in _learnCard.invoke;
|
|
19142
|
+
if (canIssueLocally && !input.signedCredential && (input.templateUri || input.template)) {
|
|
19143
|
+
let boost;
|
|
19144
|
+
if (input.templateUri) {
|
|
19145
|
+
const result = await getBoostTemplateForIssuance(
|
|
19146
|
+
_learnCard,
|
|
19147
|
+
input.templateUri
|
|
19148
|
+
);
|
|
19149
|
+
const data = await UnsignedVCValidator.spa(result);
|
|
19150
|
+
if (!data.success)
|
|
19151
|
+
throw new Error("Did not get a valid boost from URI");
|
|
19152
|
+
boost = data.data;
|
|
19153
|
+
} else {
|
|
19154
|
+
boost = JSON.parse(
|
|
19155
|
+
JSON.stringify(input.template.credential)
|
|
19156
|
+
);
|
|
19157
|
+
}
|
|
19158
|
+
const prepared = await client.boost.prepareRefreshableSend.mutate({
|
|
19159
|
+
recipient: input.recipient,
|
|
19160
|
+
...input.templateUri ? { templateUri: input.templateUri } : { template: input.template },
|
|
19161
|
+
...input.contractUri ? { contractUri: input.contractUri } : {},
|
|
19162
|
+
...input.templateData ? { templateData: input.templateData } : {},
|
|
19163
|
+
...input.integrationId ? { integrationId: input.integrationId } : {},
|
|
19164
|
+
...boost.id ? { credentialId: boost.id } : {},
|
|
19165
|
+
...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}
|
|
19166
|
+
});
|
|
19167
|
+
if (prepared.completed) return prepared.completed;
|
|
19168
|
+
const boostString = JSON.stringify(boost);
|
|
19169
|
+
const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
|
|
19170
|
+
if (input.templateData && Object.keys(input.templateData).length > 0) {
|
|
19171
|
+
try {
|
|
19172
|
+
const rendered = renderTemplateJson(
|
|
19173
|
+
boostString,
|
|
19174
|
+
input.templateData
|
|
19175
|
+
);
|
|
19176
|
+
boost = JSON.parse(rendered);
|
|
19177
|
+
boost = appendTemplateEvidence(
|
|
19178
|
+
boost,
|
|
19179
|
+
input.templateData,
|
|
19180
|
+
allowAutoAppendEvidence
|
|
19181
|
+
);
|
|
19182
|
+
} catch (error51) {
|
|
19183
|
+
throw new Error(
|
|
19184
|
+
`Failed to apply template data: ${error51 instanceof Error ? error51.message : "Unknown error"}`,
|
|
19185
|
+
{ cause: error51 }
|
|
19186
|
+
);
|
|
19187
|
+
}
|
|
19188
|
+
}
|
|
19189
|
+
if ((0, import_helpers.isVC2Format)(boost)) {
|
|
19190
|
+
boost.validFrom = (/* @__PURE__ */ new Date()).toISOString();
|
|
19191
|
+
} else {
|
|
19192
|
+
boost.issuanceDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
19193
|
+
}
|
|
19194
|
+
boost.issuer = _learnCard.id.did();
|
|
19195
|
+
if (Array.isArray(boost.credentialSubject)) {
|
|
19196
|
+
boost.credentialSubject = boost.credentialSubject.map((subject) => ({
|
|
19197
|
+
...subject,
|
|
19198
|
+
id: prepared.holderDid
|
|
19199
|
+
}));
|
|
19200
|
+
} else {
|
|
19201
|
+
boost.credentialSubject = {
|
|
19202
|
+
...boost.credentialSubject,
|
|
19203
|
+
id: prepared.holderDid
|
|
19204
|
+
};
|
|
19205
|
+
}
|
|
19206
|
+
boost.id = prepared.credentialId;
|
|
19207
|
+
if (boost.type?.includes("BoostCredential"))
|
|
19208
|
+
boost.boostId = prepared.boostUri;
|
|
19209
|
+
boost = injectManagedRefreshService(boost, prepared.refreshService);
|
|
19210
|
+
const signedCredential = await issueCredentialWithNetworkStatus(
|
|
19211
|
+
_learnCard,
|
|
19212
|
+
client,
|
|
19213
|
+
boost
|
|
19214
|
+
);
|
|
19215
|
+
return client.boost.send.mutate({
|
|
19216
|
+
...input,
|
|
19217
|
+
template: void 0,
|
|
19218
|
+
templateUri: prepared.boostUri,
|
|
19219
|
+
signedCredential,
|
|
19220
|
+
refresh: true
|
|
19221
|
+
});
|
|
19222
|
+
}
|
|
19223
|
+
return client.boost.send.mutate(input);
|
|
19224
|
+
}
|
|
18874
19225
|
if (input.type === "boost") {
|
|
18875
19226
|
const recipient = input.recipient;
|
|
18876
19227
|
const isDid = recipient.startsWith("did:");
|
|
@@ -19277,6 +19628,37 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
19277
19628
|
await ensureUser();
|
|
19278
19629
|
return client.inbox.issue.mutate(issueInboxCredential);
|
|
19279
19630
|
}, "sendCredentialViaInbox"),
|
|
19631
|
+
sendCredentialsViaInbox: /* @__PURE__ */ __name(async (_learnCard, batch) => {
|
|
19632
|
+
await ensureUser();
|
|
19633
|
+
return client.inbox.issueBatch.mutate(batch);
|
|
19634
|
+
}, "sendCredentialsViaInbox"),
|
|
19635
|
+
sendCredentialBatchViaInbox: /* @__PURE__ */ __name(async (_learnCard, batch) => {
|
|
19636
|
+
await ensureUser();
|
|
19637
|
+
return client.inbox.issueBatch.mutate(batch);
|
|
19638
|
+
}, "sendCredentialBatchViaInbox"),
|
|
19639
|
+
waitForInboxCredentialBatch: /* @__PURE__ */ __name(async (_learnCard, batchId, options2) => {
|
|
19640
|
+
await ensureUser();
|
|
19641
|
+
return waitForInboxCredentialBatch(
|
|
19642
|
+
(signal) => client.inbox.getBatch.query({ batchId }, { signal }),
|
|
19643
|
+
options2
|
|
19644
|
+
);
|
|
19645
|
+
}, "waitForInboxCredentialBatch"),
|
|
19646
|
+
sendCredentialsViaInboxAndWait: /* @__PURE__ */ __name(async (_learnCard, batch, options2) => {
|
|
19647
|
+
await ensureUser();
|
|
19648
|
+
if (options2?.signal?.aborted) throw options2.signal.reason;
|
|
19649
|
+
const receipt = await client.inbox.issueBatch.mutate(batch, {
|
|
19650
|
+
signal: options2?.signal
|
|
19651
|
+
});
|
|
19652
|
+
await options2?.onSubmitted?.(receipt);
|
|
19653
|
+
return waitForInboxCredentialBatch(
|
|
19654
|
+
(signal) => client.inbox.getBatch.query({ batchId: receipt.batchId }, { signal }),
|
|
19655
|
+
options2
|
|
19656
|
+
);
|
|
19657
|
+
}, "sendCredentialsViaInboxAndWait"),
|
|
19658
|
+
getInboxCredentialBatch: /* @__PURE__ */ __name(async (_learnCard, batchId) => {
|
|
19659
|
+
await ensureUser();
|
|
19660
|
+
return client.inbox.getBatch.query({ batchId });
|
|
19661
|
+
}, "getInboxCredentialBatch"),
|
|
19280
19662
|
getMySentInboxCredentials: /* @__PURE__ */ __name(async (_learnCard, options2) => {
|
|
19281
19663
|
await ensureUser();
|
|
19282
19664
|
return client.inbox.getMyIssuedCredentials.query(options2);
|