@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
|
@@ -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(),
|
|
@@ -17002,6 +17409,12 @@ var AuthSessionError = (_a3 = class extends Error {
|
|
|
17002
17409
|
this.name = "AuthSessionError";
|
|
17003
17410
|
}
|
|
17004
17411
|
}, __name(_a3, "AuthSessionError"), __name2(_a3, "AuthSessionError"), _a3);
|
|
17412
|
+
var EscrowPinStatusValidator = external_exports.object({
|
|
17413
|
+
state: external_exports.enum(["none", "enabled", "locked", "stale"]),
|
|
17414
|
+
enabled: external_exports.boolean(),
|
|
17415
|
+
attemptsRemaining: external_exports.number().int().nonnegative(),
|
|
17416
|
+
salt: external_exports.string().optional()
|
|
17417
|
+
});
|
|
17005
17418
|
var BITSTRING_STATUS_PURPOSES = ["revocation", "suspension"];
|
|
17006
17419
|
var BitstringStatusPurposeValidator = external_exports.enum(BITSTRING_STATUS_PURPOSES);
|
|
17007
17420
|
var BitstringStatusListEntryValidator = external_exports.object({
|
|
@@ -17110,191 +17523,456 @@ var inAppMessagesFlagValidator = external_exports.object({
|
|
|
17110
17523
|
version: external_exports.number().default(1),
|
|
17111
17524
|
messages: external_exports.array(inAppMessageValidator).default([])
|
|
17112
17525
|
}).passthrough();
|
|
17113
|
-
var
|
|
17114
|
-
var
|
|
17115
|
-
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
var
|
|
17120
|
-
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
var
|
|
17124
|
-
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
var
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
}
|
|
17132
|
-
|
|
17133
|
-
});
|
|
17134
|
-
var
|
|
17135
|
-
|
|
17136
|
-
|
|
17137
|
-
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
}
|
|
17147
|
-
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
|
|
17153
|
-
|
|
17154
|
-
|
|
17155
|
-
|
|
17156
|
-
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
}
|
|
17169
|
-
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
|
|
17526
|
+
var SHARE_LINK_ID_BYTES = 16;
|
|
17527
|
+
var SHARE_CONTENT_KEY_BYTES = 32;
|
|
17528
|
+
var SHARE_IV_BYTES = 12;
|
|
17529
|
+
var SHARE_TAG_BYTES = 16;
|
|
17530
|
+
var MAX_SHARE_CIPHERTEXT_BYTES = 512 * 1024;
|
|
17531
|
+
var MAX_SHARE_RECOVERY_JWE_BYTES = 64 * 1024;
|
|
17532
|
+
var MAX_SELECTED_CREDENTIALS = 50;
|
|
17533
|
+
var MAX_ENDORSEMENTS = 200;
|
|
17534
|
+
var MAX_VP_MEMBERS = MAX_SELECTED_CREDENTIALS + MAX_ENDORSEMENTS;
|
|
17535
|
+
var MAX_SHARE_SOURCE_URI_CHARS = 2048;
|
|
17536
|
+
var MAX_SHARE_LINK_REQUEST_BYTES = 1024 * 1024;
|
|
17537
|
+
var SHARE_LINK_PROTOCOL = "lc-share/v1";
|
|
17538
|
+
var SHARE_RECOVERY_PROTOCOL = "lc-share-recovery/v1";
|
|
17539
|
+
var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
17540
|
+
var BASE64URL_LOOKUP = (() => {
|
|
17541
|
+
const table = new Int16Array(128).fill(-1);
|
|
17542
|
+
for (let index = 0; index < BASE64URL_ALPHABET.length; index += 1) {
|
|
17543
|
+
table[BASE64URL_ALPHABET.charCodeAt(index)] = index;
|
|
17544
|
+
}
|
|
17545
|
+
return table;
|
|
17546
|
+
})();
|
|
17547
|
+
var encodeBase64Url = /* @__PURE__ */ __name2((bytes) => {
|
|
17548
|
+
let output = "";
|
|
17549
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
17550
|
+
const first = bytes[index];
|
|
17551
|
+
const second = bytes[index + 1];
|
|
17552
|
+
const third = bytes[index + 2];
|
|
17553
|
+
output += BASE64URL_ALPHABET[first >> 2];
|
|
17554
|
+
output += BASE64URL_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
|
|
17555
|
+
if (second === void 0) break;
|
|
17556
|
+
output += BASE64URL_ALPHABET[(second & 15) << 2 | (third ?? 0) >> 6];
|
|
17557
|
+
if (third === void 0) break;
|
|
17558
|
+
output += BASE64URL_ALPHABET[third & 63];
|
|
17559
|
+
}
|
|
17560
|
+
return output;
|
|
17561
|
+
}, "encodeBase64Url");
|
|
17562
|
+
var decodeBase64Url = /* @__PURE__ */ __name2((value) => {
|
|
17563
|
+
if (typeof value !== "string") return null;
|
|
17564
|
+
const output = new Uint8Array(Math.floor(value.length * 6 / 8));
|
|
17565
|
+
let bits = 0;
|
|
17566
|
+
let bitCount = 0;
|
|
17567
|
+
let outputIndex = 0;
|
|
17568
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
17569
|
+
const code = value.charCodeAt(index);
|
|
17570
|
+
const digit = code < 128 ? BASE64URL_LOOKUP[code] : -1;
|
|
17571
|
+
if (digit < 0) return null;
|
|
17572
|
+
bits = bits << 6 | digit;
|
|
17573
|
+
bitCount += 6;
|
|
17574
|
+
if (bitCount >= 8) {
|
|
17575
|
+
bitCount -= 8;
|
|
17576
|
+
output[outputIndex] = bits >> bitCount & 255;
|
|
17577
|
+
outputIndex += 1;
|
|
17578
|
+
}
|
|
17579
|
+
}
|
|
17580
|
+
return output;
|
|
17581
|
+
}, "decodeBase64Url");
|
|
17582
|
+
var isCanonicalBase64Url = /* @__PURE__ */ __name2((value, expectedBytes) => {
|
|
17583
|
+
if (typeof value !== "string") return false;
|
|
17584
|
+
if (expectedBytes !== void 0 && value.length !== Math.ceil(expectedBytes * 4 / 3))
|
|
17585
|
+
return false;
|
|
17586
|
+
const decoded = decodeBase64Url(value);
|
|
17587
|
+
if (decoded === null) return false;
|
|
17588
|
+
if (expectedBytes !== void 0 && decoded.length !== expectedBytes) return false;
|
|
17589
|
+
return encodeBase64Url(decoded) === value;
|
|
17590
|
+
}, "isCanonicalBase64Url");
|
|
17591
|
+
var utf8ByteLength = /* @__PURE__ */ __name2((value) => new TextEncoder().encode(value).length, "utf8ByteLength");
|
|
17592
|
+
var canonicalBase64Url = /* @__PURE__ */ __name2((bytes) => external_exports.string().refine((value) => isCanonicalBase64Url(value, bytes), {
|
|
17593
|
+
message: `must be canonical base64url for exactly ${bytes} bytes`
|
|
17594
|
+
}), "canonicalBase64Url");
|
|
17595
|
+
var ShareLinkIdValidator = canonicalBase64Url(SHARE_LINK_ID_BYTES);
|
|
17596
|
+
var ShareContentKeyValidator = canonicalBase64Url(SHARE_CONTENT_KEY_BYTES);
|
|
17597
|
+
var ShareIvValidator = canonicalBase64Url(SHARE_IV_BYTES);
|
|
17598
|
+
var ShareCiphertextValidator = external_exports.string().refine(
|
|
17599
|
+
(value) => {
|
|
17600
|
+
if (value.length > Math.ceil(MAX_SHARE_CIPHERTEXT_BYTES * 4 / 3)) return false;
|
|
17601
|
+
const decoded = decodeBase64Url(value);
|
|
17602
|
+
if (decoded === null) return false;
|
|
17603
|
+
if (encodeBase64Url(decoded) !== value) return false;
|
|
17604
|
+
return decoded.length >= SHARE_TAG_BYTES && decoded.length <= MAX_SHARE_CIPHERTEXT_BYTES;
|
|
17605
|
+
},
|
|
17606
|
+
{
|
|
17607
|
+
message: `must be canonical base64url decoding to ${SHARE_TAG_BYTES}..${MAX_SHARE_CIPHERTEXT_BYTES} bytes`
|
|
17175
17608
|
}
|
|
17176
|
-
|
|
17609
|
+
);
|
|
17610
|
+
var ShareEnvelopeValidator = external_exports.object({
|
|
17611
|
+
v: external_exports.literal(1),
|
|
17612
|
+
alg: external_exports.literal("A256GCM"),
|
|
17613
|
+
iv: ShareIvValidator,
|
|
17614
|
+
ct: ShareCiphertextValidator
|
|
17615
|
+
}).strict();
|
|
17616
|
+
var safeVersion = external_exports.number().int().min(1).max(2 ** 31 - 1);
|
|
17617
|
+
var safeCredentialIndex = external_exports.number().int().min(0).max(MAX_VP_MEMBERS - 1);
|
|
17618
|
+
var ShareSelectionEntryValidator = external_exports.object({ credentialIndex: safeCredentialIndex }).strict();
|
|
17619
|
+
var ShareEndorsementEntryValidator = external_exports.object({ credentialIndex: safeCredentialIndex, targetCredentialIndex: safeCredentialIndex }).strict();
|
|
17620
|
+
var ShareSharerValidator = external_exports.object({
|
|
17621
|
+
profileId: external_exports.string().min(1).max(128),
|
|
17622
|
+
displayName: external_exports.string().min(1).max(120),
|
|
17623
|
+
avatar: external_exports.string().max(2048).optional()
|
|
17624
|
+
}).strict();
|
|
17625
|
+
var presentationShape = VPValidator.extend({
|
|
17626
|
+
verifiableCredential: VCValidator.array().min(1).max(MAX_VP_MEMBERS)
|
|
17627
|
+
});
|
|
17628
|
+
var hasBoundedPresentation = /* @__PURE__ */ __name2((value) => {
|
|
17629
|
+
let credentialCount = 0;
|
|
17630
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
17631
|
+
const visit = /* @__PURE__ */ __name2((node, depth) => {
|
|
17632
|
+
if (node === null || typeof node !== "object") return true;
|
|
17633
|
+
if (depth > 32 || ancestors.has(node)) return false;
|
|
17634
|
+
ancestors.add(node);
|
|
17635
|
+
try {
|
|
17636
|
+
for (const [key, child] of Object.entries(node)) {
|
|
17637
|
+
if (key === "verifiableCredential") {
|
|
17638
|
+
credentialCount += Array.isArray(child) ? child.length : 1;
|
|
17639
|
+
if (credentialCount > MAX_VP_MEMBERS) return false;
|
|
17640
|
+
}
|
|
17641
|
+
if (!visit(child, depth + 1)) return false;
|
|
17642
|
+
}
|
|
17643
|
+
return true;
|
|
17644
|
+
} finally {
|
|
17645
|
+
ancestors.delete(node);
|
|
17646
|
+
}
|
|
17647
|
+
}, "visit");
|
|
17648
|
+
return visit(value, 0);
|
|
17649
|
+
}, "hasBoundedPresentation");
|
|
17650
|
+
var ShareManifestPresentationValidator = external_exports.custom(
|
|
17651
|
+
(value) => hasBoundedPresentation(value) && presentationShape.safeParse(value).success,
|
|
17652
|
+
{ message: "invalid share presentation" }
|
|
17653
|
+
);
|
|
17654
|
+
var SharePayloadValidatorShape = external_exports.object({
|
|
17655
|
+
protocol: external_exports.literal(SHARE_LINK_PROTOCOL),
|
|
17656
|
+
shareId: ShareLinkIdValidator,
|
|
17657
|
+
contentVersion: safeVersion,
|
|
17658
|
+
createdAt: external_exports.iso.datetime(),
|
|
17659
|
+
sharer: ShareSharerValidator,
|
|
17660
|
+
presentation: ShareManifestPresentationValidator,
|
|
17661
|
+
selection: ShareSelectionEntryValidator.array().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
17662
|
+
endorsements: ShareEndorsementEntryValidator.array().max(MAX_ENDORSEMENTS).default([])
|
|
17663
|
+
}).strict();
|
|
17664
|
+
var classificationFailure = /* @__PURE__ */ __name2((code, message, path = []) => ({ ok: false, code, message, path }), "classificationFailure");
|
|
17665
|
+
var readSignedClaimId = /* @__PURE__ */ __name2((member) => {
|
|
17666
|
+
if (member === null || typeof member !== "object") return void 0;
|
|
17667
|
+
const record2 = member;
|
|
17668
|
+
const claim = record2.credentialSubject ?? record2.endorsement;
|
|
17669
|
+
if (claim === null || typeof claim !== "object") return void 0;
|
|
17670
|
+
const claimRecord = claim;
|
|
17671
|
+
const nested = claimRecord.endorsement;
|
|
17672
|
+
const nestedId = nested !== null && typeof nested === "object" ? nested.id : void 0;
|
|
17673
|
+
return claimRecord.id ?? nestedId;
|
|
17674
|
+
}, "readSignedClaimId");
|
|
17675
|
+
var classifyShareManifest = /* @__PURE__ */ __name2((payload) => {
|
|
17676
|
+
const members = payload.presentation?.verifiableCredential;
|
|
17677
|
+
if (!Array.isArray(members) || members.length === 0) {
|
|
17678
|
+
return classificationFailure("NO_PRESENTATION_MEMBERS", "presentation has no credentials");
|
|
17679
|
+
}
|
|
17680
|
+
if (members.length > MAX_VP_MEMBERS) {
|
|
17681
|
+
return classificationFailure(
|
|
17682
|
+
"TOO_MANY_VP_MEMBERS",
|
|
17683
|
+
`presentation has ${members.length} members, over the ${MAX_VP_MEMBERS} bound`
|
|
17684
|
+
);
|
|
17685
|
+
}
|
|
17686
|
+
const selection = payload.selection;
|
|
17687
|
+
const endorsements = payload.endorsements ?? [];
|
|
17688
|
+
if (!Array.isArray(selection) || selection.length < 1 || selection.length > MAX_SELECTED_CREDENTIALS) {
|
|
17689
|
+
return classificationFailure("BAD_SELECTION", "selection must contain 1..50 entries");
|
|
17690
|
+
}
|
|
17691
|
+
if (!Array.isArray(endorsements) || endorsements.length > MAX_ENDORSEMENTS) {
|
|
17692
|
+
return classificationFailure(
|
|
17693
|
+
"BAD_ENDORSEMENTS",
|
|
17694
|
+
"endorsements must contain at most 200 entries"
|
|
17695
|
+
);
|
|
17696
|
+
}
|
|
17697
|
+
const selectedIndices = [];
|
|
17698
|
+
const selected = /* @__PURE__ */ new Set();
|
|
17699
|
+
for (let index = 0; index < selection.length; index += 1) {
|
|
17700
|
+
const entry = selection[index];
|
|
17701
|
+
const credentialIndex = entry?.credentialIndex;
|
|
17702
|
+
if (!Number.isSafeInteger(credentialIndex) || credentialIndex < 0 || credentialIndex >= members.length) {
|
|
17703
|
+
return classificationFailure(
|
|
17704
|
+
"SELECTION_INDEX_OUT_OF_BOUNDS",
|
|
17705
|
+
`selection[${index}].credentialIndex is out of bounds`,
|
|
17706
|
+
["selection", index, "credentialIndex"]
|
|
17707
|
+
);
|
|
17708
|
+
}
|
|
17709
|
+
if (selected.has(credentialIndex)) {
|
|
17710
|
+
return classificationFailure(
|
|
17711
|
+
"SELECTION_INDEX_DUPLICATE",
|
|
17712
|
+
`selection[${index}].credentialIndex is duplicated`,
|
|
17713
|
+
["selection", index, "credentialIndex"]
|
|
17714
|
+
);
|
|
17715
|
+
}
|
|
17716
|
+
selected.add(credentialIndex);
|
|
17717
|
+
selectedIndices.push(credentialIndex);
|
|
17718
|
+
}
|
|
17719
|
+
const classified = new Set(selected);
|
|
17720
|
+
const endorsementIndices = [];
|
|
17721
|
+
for (let index = 0; index < endorsements.length; index += 1) {
|
|
17722
|
+
const entry = endorsements[index];
|
|
17723
|
+
const credentialIndex = entry?.credentialIndex;
|
|
17724
|
+
const targetIndex = entry?.targetCredentialIndex;
|
|
17725
|
+
if (!Number.isSafeInteger(credentialIndex) || credentialIndex < 0 || credentialIndex >= members.length) {
|
|
17726
|
+
return classificationFailure(
|
|
17727
|
+
"ENDORSEMENT_INDEX_OUT_OF_BOUNDS",
|
|
17728
|
+
`endorsements[${index}].credentialIndex is out of bounds`,
|
|
17729
|
+
["endorsements", index, "credentialIndex"]
|
|
17730
|
+
);
|
|
17731
|
+
}
|
|
17732
|
+
if (classified.has(credentialIndex)) {
|
|
17733
|
+
return classificationFailure(
|
|
17734
|
+
"VP_MEMBER_CLASSIFIED_TWICE",
|
|
17735
|
+
`endorsements[${index}].credentialIndex was already classified`,
|
|
17736
|
+
["endorsements", index, "credentialIndex"]
|
|
17737
|
+
);
|
|
17738
|
+
}
|
|
17739
|
+
if (!selected.has(targetIndex)) {
|
|
17740
|
+
return classificationFailure(
|
|
17741
|
+
"ENDORSEMENT_TARGET_NOT_SELECTED",
|
|
17742
|
+
`endorsements[${index}].targetCredentialIndex must reference a selected credential`,
|
|
17743
|
+
["endorsements", index, "targetCredentialIndex"]
|
|
17744
|
+
);
|
|
17745
|
+
}
|
|
17746
|
+
const referenced = readSignedClaimId(members[credentialIndex]);
|
|
17747
|
+
const target = members[targetIndex];
|
|
17748
|
+
const targetId = target !== null && typeof target === "object" ? target.id : void 0;
|
|
17749
|
+
if (typeof referenced !== "string" || typeof targetId !== "string" || referenced !== targetId) {
|
|
17750
|
+
return classificationFailure(
|
|
17751
|
+
"ENDORSEMENT_TARGET_UNBOUND",
|
|
17752
|
+
`endorsements[${index}] claim does not reference the target credential id`,
|
|
17753
|
+
["endorsements", index]
|
|
17754
|
+
);
|
|
17755
|
+
}
|
|
17756
|
+
classified.add(credentialIndex);
|
|
17757
|
+
endorsementIndices.push(credentialIndex);
|
|
17758
|
+
}
|
|
17759
|
+
if (classified.size !== members.length) {
|
|
17760
|
+
return classificationFailure(
|
|
17761
|
+
"UNCLASSIFIED_VP_MEMBER",
|
|
17762
|
+
"every presentation member must be classified exactly once",
|
|
17763
|
+
["presentation", "verifiableCredential"]
|
|
17764
|
+
);
|
|
17765
|
+
}
|
|
17766
|
+
return {
|
|
17767
|
+
ok: true,
|
|
17768
|
+
classification: { selectedIndices, endorsementIndices, memberCount: members.length }
|
|
17769
|
+
};
|
|
17770
|
+
}, "classifyShareManifest");
|
|
17771
|
+
var SharePayloadValidator = SharePayloadValidatorShape.superRefine((payload, ctx) => {
|
|
17772
|
+
const result = classifyShareManifest(payload);
|
|
17773
|
+
if (!result.ok) {
|
|
17177
17774
|
ctx.addIssue({
|
|
17178
17775
|
code: "custom",
|
|
17179
|
-
|
|
17180
|
-
|
|
17776
|
+
message: result.message,
|
|
17777
|
+
path: result.path,
|
|
17778
|
+
params: { shareLinkCode: result.code }
|
|
17181
17779
|
});
|
|
17182
17780
|
}
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
|
|
17781
|
+
});
|
|
17782
|
+
var ShareRecoverySelectionValidator = external_exports.object({
|
|
17783
|
+
ref: external_exports.string().min(1).max(MAX_SHARE_SOURCE_URI_CHARS),
|
|
17784
|
+
order: external_exports.number().int().min(0).max(MAX_SELECTED_CREDENTIALS - 1)
|
|
17785
|
+
}).strict();
|
|
17786
|
+
var ShareRecoveryEndorsementValidator = external_exports.object({ targetRef: external_exports.string().min(1).max(MAX_SHARE_SOURCE_URI_CHARS) }).strict();
|
|
17787
|
+
var ShareRecoveryPlaintextValidator = external_exports.object({
|
|
17788
|
+
protocol: external_exports.literal(SHARE_RECOVERY_PROTOCOL),
|
|
17789
|
+
shareId: ShareLinkIdValidator,
|
|
17790
|
+
ownerProfileId: external_exports.string().min(1).max(128),
|
|
17791
|
+
createdAt: external_exports.iso.datetime(),
|
|
17792
|
+
latest: external_exports.object({ contentVersion: safeVersion, key: ShareContentKeyValidator }).strict(),
|
|
17793
|
+
selection: ShareRecoverySelectionValidator.array().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
17794
|
+
endorsements: ShareRecoveryEndorsementValidator.array().max(MAX_ENDORSEMENTS).default([])
|
|
17795
|
+
}).strict().superRefine((recovery, ctx) => {
|
|
17796
|
+
const orders = /* @__PURE__ */ new Set();
|
|
17797
|
+
recovery.selection.forEach((entry, index) => {
|
|
17798
|
+
if (entry.order >= recovery.selection.length) {
|
|
17192
17799
|
ctx.addIssue({
|
|
17193
17800
|
code: "custom",
|
|
17194
|
-
|
|
17195
|
-
|
|
17801
|
+
message: "order must be within the selection bounds",
|
|
17802
|
+
path: ["selection", index, "order"]
|
|
17196
17803
|
});
|
|
17197
17804
|
}
|
|
17198
|
-
if (
|
|
17805
|
+
if (orders.has(entry.order)) {
|
|
17199
17806
|
ctx.addIssue({
|
|
17200
17807
|
code: "custom",
|
|
17201
|
-
|
|
17202
|
-
|
|
17808
|
+
message: "order must be unique within the selection",
|
|
17809
|
+
path: ["selection", index, "order"]
|
|
17203
17810
|
});
|
|
17204
17811
|
}
|
|
17812
|
+
orders.add(entry.order);
|
|
17813
|
+
});
|
|
17814
|
+
});
|
|
17815
|
+
var ShareOwnerRecoveryValidator = JWEValidator.refine(
|
|
17816
|
+
(value) => utf8ByteLength(JSON.stringify(value)) <= MAX_SHARE_RECOVERY_JWE_BYTES,
|
|
17817
|
+
{ message: `serialized recovery JWE must be at most ${MAX_SHARE_RECOVERY_JWE_BYTES} bytes` }
|
|
17818
|
+
);
|
|
17819
|
+
var ShareLinkStatusValidator = external_exports.enum(["pending", "active", "stopped"]);
|
|
17820
|
+
var ShareContentStateValidator = external_exports.enum(["staging", "finalized", "content_missing"]);
|
|
17821
|
+
var ShareLinkValidator = external_exports.object({
|
|
17822
|
+
id: ShareLinkIdValidator,
|
|
17823
|
+
title: external_exports.string().min(1).max(120),
|
|
17824
|
+
note: external_exports.string().max(500).optional(),
|
|
17825
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
17826
|
+
version: safeVersion,
|
|
17827
|
+
contentVersion: safeVersion,
|
|
17828
|
+
status: ShareLinkStatusValidator,
|
|
17829
|
+
contentState: ShareContentStateValidator,
|
|
17830
|
+
createdAt: external_exports.iso.datetime(),
|
|
17831
|
+
updatedAt: external_exports.iso.datetime(),
|
|
17832
|
+
expiresAt: external_exports.iso.datetime().nullable(),
|
|
17833
|
+
stoppedAt: external_exports.iso.datetime().nullable(),
|
|
17834
|
+
lastViewedAt: external_exports.iso.datetime().nullable(),
|
|
17835
|
+
viewCount: external_exports.number().int().min(0).optional(),
|
|
17836
|
+
passcodeProtected: external_exports.boolean(),
|
|
17837
|
+
notifyOnView: external_exports.boolean(),
|
|
17838
|
+
minorPolicy: external_exports.object({
|
|
17839
|
+
isMinor: external_exports.boolean().nullable(),
|
|
17840
|
+
policyResolved: external_exports.boolean(),
|
|
17841
|
+
defaultExpiryDays: external_exports.union([external_exports.literal(30), external_exports.literal(365)]),
|
|
17842
|
+
viewCountingEnabled: external_exports.boolean()
|
|
17843
|
+
}),
|
|
17844
|
+
/**
|
|
17845
|
+
* Guarded application/API URL for the content. Optional because owner APIs in
|
|
17846
|
+
* D1 have no public resolve/content endpoint yet; it must never be a
|
|
17847
|
+
* LearnCloud object URL or carry a fabricated decryption key.
|
|
17848
|
+
*/
|
|
17849
|
+
contentUrl: external_exports.string().optional()
|
|
17850
|
+
});
|
|
17851
|
+
var clientRequestId = external_exports.string().uuid();
|
|
17852
|
+
var CreateShareLinkInputValidator = external_exports.object({
|
|
17853
|
+
id: ShareLinkIdValidator,
|
|
17854
|
+
clientRequestId,
|
|
17855
|
+
title: external_exports.string().min(1).max(120),
|
|
17856
|
+
note: external_exports.string().max(500).optional(),
|
|
17857
|
+
expiresAt: external_exports.iso.datetime().nullable().optional(),
|
|
17858
|
+
passcode: external_exports.string().min(8).max(64).optional(),
|
|
17859
|
+
notifyOnView: external_exports.boolean().default(false),
|
|
17860
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
17861
|
+
contentVersion: external_exports.literal(1),
|
|
17862
|
+
envelope: ShareEnvelopeValidator,
|
|
17863
|
+
ownerEncryptedRecovery: ShareOwnerRecoveryValidator
|
|
17864
|
+
}).strict();
|
|
17865
|
+
var UpdateShareLinkInputValidator = external_exports.object({
|
|
17866
|
+
id: ShareLinkIdValidator,
|
|
17867
|
+
expectedVersion: safeVersion,
|
|
17868
|
+
clientRequestId,
|
|
17869
|
+
title: external_exports.string().min(1).max(120).optional(),
|
|
17870
|
+
note: external_exports.string().max(500).nullable().optional(),
|
|
17871
|
+
expiresAt: external_exports.iso.datetime().nullable().optional(),
|
|
17872
|
+
/** Omitted preserves the current passcode, null removes it, and a string replaces it. */
|
|
17873
|
+
passcode: external_exports.string().min(8).max(64).nullable().optional(),
|
|
17874
|
+
notifyOnView: external_exports.boolean().optional(),
|
|
17875
|
+
contentVersion: safeVersion.optional(),
|
|
17876
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS).optional(),
|
|
17877
|
+
envelope: ShareEnvelopeValidator.optional(),
|
|
17878
|
+
ownerEncryptedRecovery: ShareOwnerRecoveryValidator.optional()
|
|
17879
|
+
}).strict().superRefine((value, ctx) => {
|
|
17880
|
+
const provided = [
|
|
17881
|
+
value.contentVersion,
|
|
17882
|
+
value.selectedCount,
|
|
17883
|
+
value.envelope,
|
|
17884
|
+
value.ownerEncryptedRecovery
|
|
17885
|
+
].filter((field) => field !== void 0).length;
|
|
17886
|
+
if (provided !== 0 && provided !== 4) {
|
|
17887
|
+
ctx.addIssue({
|
|
17888
|
+
code: "custom",
|
|
17889
|
+
message: "content replacement requires contentVersion, selectedCount, envelope and ownerEncryptedRecovery together"
|
|
17890
|
+
});
|
|
17205
17891
|
}
|
|
17206
17892
|
});
|
|
17207
|
-
var
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
"
|
|
17211
|
-
|
|
17212
|
-
|
|
17893
|
+
var ShareLinkIdInputValidator = external_exports.object({ id: ShareLinkIdValidator }).strict();
|
|
17894
|
+
var ShareLinkOperationKeyInputValidator = external_exports.object({ id: ShareLinkIdValidator, operationId: external_exports.string().uuid() }).strict();
|
|
17895
|
+
var ShareLinkOwnerCommitOutputValidator = external_exports.discriminatedUnion("status", [
|
|
17896
|
+
external_exports.object({ status: external_exports.literal("completed"), share: ShareLinkValidator }).strict(),
|
|
17897
|
+
external_exports.object({
|
|
17898
|
+
status: external_exports.literal("pending"),
|
|
17899
|
+
id: ShareLinkIdValidator,
|
|
17900
|
+
operationId: external_exports.string().uuid()
|
|
17901
|
+
}).strict()
|
|
17213
17902
|
]);
|
|
17214
|
-
var
|
|
17215
|
-
|
|
17216
|
-
|
|
17217
|
-
|
|
17218
|
-
|
|
17219
|
-
|
|
17220
|
-
|
|
17221
|
-
|
|
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
|
|
17903
|
+
var ShareLinkOwnerStatusOutputValidator = external_exports.discriminatedUnion("status", [
|
|
17904
|
+
external_exports.object({ status: external_exports.literal("found"), share: ShareLinkValidator }).strict(),
|
|
17905
|
+
external_exports.object({
|
|
17906
|
+
status: external_exports.literal("pending"),
|
|
17907
|
+
id: ShareLinkIdValidator,
|
|
17908
|
+
operationId: external_exports.string().uuid()
|
|
17909
|
+
}).strict(),
|
|
17910
|
+
external_exports.object({ status: external_exports.literal("not_found"), id: ShareLinkIdValidator }).strict()
|
|
17259
17911
|
]);
|
|
17260
|
-
var
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
|
|
17264
|
-
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
|
|
17268
|
-
|
|
17269
|
-
|
|
17270
|
-
|
|
17271
|
-
|
|
17912
|
+
var ShareLinkOwnerRecoveryOutputValidator = external_exports.object({ recovery: ShareOwnerRecoveryValidator }).strict();
|
|
17913
|
+
var ShareLinkOwnerContentOutputValidator = external_exports.object({
|
|
17914
|
+
id: ShareLinkIdValidator,
|
|
17915
|
+
contentVersion: safeVersion,
|
|
17916
|
+
envelope: ShareEnvelopeValidator
|
|
17917
|
+
}).strict();
|
|
17918
|
+
var ResolveShareLinkInputValidator = external_exports.object({
|
|
17919
|
+
id: ShareLinkIdValidator,
|
|
17920
|
+
/** Sent only in a POST body; it must never be placed in a share URL. */
|
|
17921
|
+
passcode: external_exports.string().min(4).max(64).optional()
|
|
17922
|
+
}).strict();
|
|
17923
|
+
var ShareLinkPublicStateValidator = external_exports.discriminatedUnion("state", [
|
|
17924
|
+
external_exports.object({
|
|
17925
|
+
state: external_exports.literal("passcode_required"),
|
|
17926
|
+
id: ShareLinkIdValidator
|
|
17927
|
+
}).strict(),
|
|
17928
|
+
external_exports.object({ state: external_exports.literal("try_later"), id: ShareLinkIdValidator }).strict(),
|
|
17929
|
+
external_exports.object({
|
|
17930
|
+
state: external_exports.literal("active"),
|
|
17931
|
+
id: ShareLinkIdValidator,
|
|
17932
|
+
title: external_exports.string().max(120),
|
|
17933
|
+
note: external_exports.string().max(500).optional(),
|
|
17934
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
17935
|
+
contentVersion: safeVersion,
|
|
17936
|
+
contentUrl: external_exports.string(),
|
|
17937
|
+
sharer: external_exports.object({
|
|
17938
|
+
displayName: external_exports.string().max(120),
|
|
17939
|
+
avatar: external_exports.string().max(2048).optional()
|
|
17940
|
+
}),
|
|
17941
|
+
createdAt: external_exports.iso.datetime(),
|
|
17942
|
+
updatedAt: external_exports.iso.datetime(),
|
|
17943
|
+
expiresAt: external_exports.iso.datetime().nullable()
|
|
17944
|
+
}).strict(),
|
|
17945
|
+
external_exports.object({
|
|
17946
|
+
state: external_exports.literal("expired"),
|
|
17947
|
+
id: ShareLinkIdValidator,
|
|
17948
|
+
expiresAt: external_exports.iso.datetime()
|
|
17949
|
+
}).strict(),
|
|
17950
|
+
external_exports.object({
|
|
17951
|
+
state: external_exports.literal("stopped"),
|
|
17952
|
+
id: ShareLinkIdValidator,
|
|
17953
|
+
stoppedAt: external_exports.iso.datetime()
|
|
17954
|
+
}).strict(),
|
|
17955
|
+
external_exports.object({ state: external_exports.literal("not_found"), id: ShareLinkIdValidator }).strict()
|
|
17272
17956
|
]);
|
|
17273
|
-
var
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
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()
|
|
17957
|
+
var ListShareLinksInputValidator = external_exports.object({
|
|
17958
|
+
limit: external_exports.number().int().min(1).max(50).default(25),
|
|
17959
|
+
cursor: external_exports.string().max(512).optional()
|
|
17960
|
+
}).strict();
|
|
17961
|
+
var PaginatedShareLinksValidator = PaginationResponseValidator.extend({
|
|
17962
|
+
records: ShareLinkValidator.array()
|
|
17291
17963
|
});
|
|
17292
|
-
var
|
|
17293
|
-
|
|
17294
|
-
|
|
17295
|
-
|
|
17296
|
-
|
|
17297
|
-
|
|
17964
|
+
var AcknowledgeViewInputValidator = external_exports.object({
|
|
17965
|
+
receipt: external_exports.string().min(22).max(128).regex(/^[A-Za-z0-9_-]+$/)
|
|
17966
|
+
}).strict();
|
|
17967
|
+
var AcknowledgeViewOutputValidator = external_exports.object({ ok: external_exports.literal(true) }).strict();
|
|
17968
|
+
var SHARE_VIEW_RECEIPT_TTL_SECONDS = 10 * 60;
|
|
17969
|
+
var ShareLinkPublicContentViewValidator = external_exports.object({
|
|
17970
|
+
id: ShareLinkIdValidator,
|
|
17971
|
+
contentVersion: safeVersion,
|
|
17972
|
+
envelope: ShareEnvelopeValidator,
|
|
17973
|
+
contentUrl: external_exports.string(),
|
|
17974
|
+
receipt: external_exports.string().min(22).max(128).regex(/^[A-Za-z0-9_-]+$/)
|
|
17975
|
+
}).strict();
|
|
17298
17976
|
|
|
17299
17977
|
// src/plugin.ts
|
|
17300
17978
|
var import_helpers = require("@learncard/helpers");
|
|
@@ -17912,27 +18590,40 @@ var issueCredentialWithNetworkStatus = /* @__PURE__ */ __name(async (learnCard,
|
|
|
17912
18590
|
await appendNetworkCredentialStatus(client, credential, statusPurposes)
|
|
17913
18591
|
);
|
|
17914
18592
|
}, "issueCredentialWithNetworkStatus");
|
|
17915
|
-
var
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
|
|
17922
|
-
}
|
|
17923
|
-
};
|
|
17924
|
-
var
|
|
17925
|
-
const
|
|
17926
|
-
const
|
|
17927
|
-
const
|
|
17928
|
-
|
|
17929
|
-
);
|
|
18593
|
+
var injectManagedRefreshService = /* @__PURE__ */ __name((credential, refreshService) => (0, import_helpers.injectManagedRefreshService)(credential, refreshService), "injectManagedRefreshService");
|
|
18594
|
+
var getCredentialSubjectIds = /* @__PURE__ */ __name((vc) => {
|
|
18595
|
+
const subject = vc.credentialSubject;
|
|
18596
|
+
const subjects = Array.isArray(subject) ? subject : subject ? [subject] : [];
|
|
18597
|
+
return subjects.flatMap((entry) => {
|
|
18598
|
+
const id = entry?.id;
|
|
18599
|
+
return typeof id === "string" && id.length > 0 ? [id] : [];
|
|
18600
|
+
});
|
|
18601
|
+
}, "getCredentialSubjectIds");
|
|
18602
|
+
var buildManagedRefreshReceipt = /* @__PURE__ */ __name((vc, allocation, credentialId, fallbackHolderDid, fallbackIssuerDid) => {
|
|
18603
|
+
const issuerDid = (0, import_helpers.getCredentialIssuerId)(vc) ?? fallbackIssuerDid;
|
|
18604
|
+
const holderDid = getCredentialSubjectIds(vc)[0] ?? fallbackHolderDid;
|
|
18605
|
+
const rawStatus = vc.credentialStatus;
|
|
18606
|
+
const hasStatus = rawStatus !== void 0 && rawStatus !== null && !(Array.isArray(rawStatus) && rawStatus.length === 0);
|
|
17930
18607
|
return {
|
|
17931
|
-
|
|
17932
|
-
|
|
17933
|
-
|
|
17934
|
-
|
|
17935
|
-
|
|
18608
|
+
refreshId: allocation.refreshId,
|
|
18609
|
+
refreshService: allocation.refreshService,
|
|
18610
|
+
credentialId: typeof vc.id === "string" && vc.id.length > 0 ? vc.id : credentialId,
|
|
18611
|
+
issuerDid,
|
|
18612
|
+
holderDid,
|
|
18613
|
+
...hasStatus ? {
|
|
18614
|
+
credentialStatus: rawStatus
|
|
18615
|
+
} : {}
|
|
18616
|
+
};
|
|
18617
|
+
}, "buildManagedRefreshReceipt");
|
|
18618
|
+
var ACT_AS_TARGET_NOT_FOUND_MESSAGE = "Act-as target profile not found";
|
|
18619
|
+
var isActAsDenial = /* @__PURE__ */ __name((error51) => {
|
|
18620
|
+
const code = error51?.data?.code;
|
|
18621
|
+
if (code === "FORBIDDEN" || code === "BAD_REQUEST") return true;
|
|
18622
|
+
if (code === "NOT_FOUND") {
|
|
18623
|
+
return error51?.message === ACT_AS_TARGET_NOT_FOUND_MESSAGE;
|
|
18624
|
+
}
|
|
18625
|
+
return false;
|
|
18626
|
+
}, "isActAsDenial");
|
|
17936
18627
|
async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, options) {
|
|
17937
18628
|
const apiToken = typeof apiTokenOrOptions === "string" ? apiTokenOrOptions : void 0;
|
|
17938
18629
|
const resolvedOptions = (typeof apiTokenOrOptions === "object" ? apiTokenOrOptions : options) ?? {};
|
|
@@ -17940,8 +18631,10 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17940
18631
|
guardianApprovalGetter,
|
|
17941
18632
|
extraHeaders,
|
|
17942
18633
|
trustedFederationHosts,
|
|
17943
|
-
allowLocalhostFederation
|
|
18634
|
+
allowLocalhostFederation,
|
|
18635
|
+
actAs
|
|
17944
18636
|
} = resolvedOptions;
|
|
18637
|
+
const mergedExtraHeaders = actAs ? { ...extraHeaders, [ACT_AS_HEADER]: actAs } : extraHeaders;
|
|
17945
18638
|
const serviceUrl = new URL(url2);
|
|
17946
18639
|
const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
|
|
17947
18640
|
const federationConfig = {
|
|
@@ -17959,7 +18652,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17959
18652
|
learnCard?.debug?.("LCN: no local DID available at init; will fetch from profile");
|
|
17960
18653
|
}
|
|
17961
18654
|
learnCard?.debug?.("Adding LearnCardNetwork Plugin");
|
|
17962
|
-
const client = apiToken ? await (0, import_network_brain_client.getApiTokenClient)(url2, apiToken, guardianApprovalGetter,
|
|
18655
|
+
const client = apiToken ? await (0, import_network_brain_client.getApiTokenClient)(url2, apiToken, guardianApprovalGetter, mergedExtraHeaders) : await (0, import_network_brain_client.getClient)(
|
|
17963
18656
|
url2,
|
|
17964
18657
|
async (challenge) => {
|
|
17965
18658
|
const jwt2 = await learnCard.invoke.getDidAuthVp({
|
|
@@ -17970,7 +18663,7 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
17970
18663
|
return jwt2;
|
|
17971
18664
|
},
|
|
17972
18665
|
guardianApprovalGetter,
|
|
17973
|
-
|
|
18666
|
+
mergedExtraHeaders
|
|
17974
18667
|
);
|
|
17975
18668
|
let userData;
|
|
17976
18669
|
learnCard?.debug?.("LCN: initial getProfile query starting", { apiToken: !!apiToken });
|
|
@@ -18173,6 +18866,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18173
18866
|
getManagedProfiles: /* @__PURE__ */ __name(async (_learnCard, options2 = {}) => {
|
|
18174
18867
|
return client.profileManager.getManagedProfiles.query(options2);
|
|
18175
18868
|
}, "getManagedProfiles"),
|
|
18869
|
+
actAs: /* @__PURE__ */ __name(async (_learnCard, profileId) => {
|
|
18870
|
+
const actingOptions = {
|
|
18871
|
+
...resolvedOptions,
|
|
18872
|
+
actAs: profileId
|
|
18873
|
+
};
|
|
18874
|
+
const actingPlugin = apiToken ? await getLearnCardNetworkPlugin(_learnCard, url2, apiToken, actingOptions) : await getLearnCardNetworkPlugin(_learnCard, url2, actingOptions);
|
|
18875
|
+
try {
|
|
18876
|
+
await actingPlugin.methods.getLCNClient(_learnCard).profile.getProfile.query();
|
|
18877
|
+
} catch (error51) {
|
|
18878
|
+
if (isActAsDenial(error51)) {
|
|
18879
|
+
const message = error51 instanceof Error ? error51.message : "Act-as request was denied.";
|
|
18880
|
+
throw new Error(message, { cause: error51 });
|
|
18881
|
+
}
|
|
18882
|
+
_learnCard.debug?.("LCN actAs: getProfile failed (non-fatal)", error51);
|
|
18883
|
+
}
|
|
18884
|
+
return _learnCard.addPlugin(actingPlugin);
|
|
18885
|
+
}, "actAs"),
|
|
18176
18886
|
claimPendingGuardianLinks: /* @__PURE__ */ __name(async () => {
|
|
18177
18887
|
await ensureUser();
|
|
18178
18888
|
return client.inbox.claimPendingGuardianLinks.mutate({});
|
|
@@ -18326,6 +19036,49 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18326
19036
|
await ensureUser();
|
|
18327
19037
|
return client.profile.invalidateInvite.mutate({ challenge });
|
|
18328
19038
|
}, "invalidateInvite"),
|
|
19039
|
+
createShareLink: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
19040
|
+
await ensureUser();
|
|
19041
|
+
return client.shareLinks.create.mutate(input);
|
|
19042
|
+
}, "createShareLink"),
|
|
19043
|
+
updateShareLink: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
19044
|
+
await ensureUser();
|
|
19045
|
+
return client.shareLinks.update.mutate(input);
|
|
19046
|
+
}, "updateShareLink"),
|
|
19047
|
+
revokeShareLink: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
19048
|
+
await ensureUser();
|
|
19049
|
+
return client.shareLinks.revoke.mutate(input);
|
|
19050
|
+
}, "revokeShareLink"),
|
|
19051
|
+
getShareLink: /* @__PURE__ */ __name(async (_learnCard, id) => {
|
|
19052
|
+
await ensureUser();
|
|
19053
|
+
return client.shareLinks.get.query({ id });
|
|
19054
|
+
}, "getShareLink"),
|
|
19055
|
+
getShareLinkOperationStatus: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
19056
|
+
await ensureUser();
|
|
19057
|
+
return client.shareLinks.getOperationStatus.query(input);
|
|
19058
|
+
}, "getShareLinkOperationStatus"),
|
|
19059
|
+
retryShareLinkOperation: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
19060
|
+
await ensureUser();
|
|
19061
|
+
return client.shareLinks.retry.mutate(input);
|
|
19062
|
+
}, "retryShareLinkOperation"),
|
|
19063
|
+
getShareLinkRecovery: /* @__PURE__ */ __name(async (_learnCard, id) => {
|
|
19064
|
+
await ensureUser();
|
|
19065
|
+
return client.shareLinks.getRecovery.query({ id });
|
|
19066
|
+
}, "getShareLinkRecovery"),
|
|
19067
|
+
getShareLinkOwnerContent: /* @__PURE__ */ __name(async (_learnCard, id) => {
|
|
19068
|
+
await ensureUser();
|
|
19069
|
+
return client.shareLinks.getContent.query({ id });
|
|
19070
|
+
}, "getShareLinkOwnerContent"),
|
|
19071
|
+
listShareLinks: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
19072
|
+
await ensureUser();
|
|
19073
|
+
return client.shareLinks.list.query(input);
|
|
19074
|
+
}, "listShareLinks"),
|
|
19075
|
+
// Anonymous public methods: deliberately NO `ensureUser()`. A viewer
|
|
19076
|
+
// has no account and must not need one.
|
|
19077
|
+
// POST keeps an optional passcode in the request body and out of URLs,
|
|
19078
|
+
// access logs, browser history and referrers.
|
|
19079
|
+
resolveShareLink: /* @__PURE__ */ __name(async (_learnCard, id, passcode) => client.publicShareLinks.resolve.mutate({ id, passcode }), "resolveShareLink"),
|
|
19080
|
+
getShareLinkContent: /* @__PURE__ */ __name(async (_learnCard, id, passcode) => client.publicShareLinks.content.mutate({ id, passcode }), "getShareLinkContent"),
|
|
19081
|
+
acknowledgeShareLinkView: /* @__PURE__ */ __name(async (_learnCard, receipt) => client.publicShareLinks.acknowledgeView.mutate({ receipt }), "acknowledgeShareLinkView"),
|
|
18329
19082
|
blockProfile: /* @__PURE__ */ __name(async (_learnCard, profileId) => {
|
|
18330
19083
|
await ensureUser();
|
|
18331
19084
|
return client.profile.blockProfile.mutate({ profileId });
|
|
@@ -18440,12 +19193,15 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18440
19193
|
await ensureUser();
|
|
18441
19194
|
return client.credential.deleteCredential.mutate({ uri });
|
|
18442
19195
|
}, "deleteCredential"),
|
|
18443
|
-
sendPresentation: /* @__PURE__ */ __name(async (_learnCard, profileId, vp, encrypt
|
|
19196
|
+
sendPresentation: /* @__PURE__ */ __name(async (_learnCard, profileId, vp, metadataOrEncrypt, encrypt) => {
|
|
18444
19197
|
await ensureUser();
|
|
18445
|
-
|
|
19198
|
+
const metadata = typeof metadataOrEncrypt === "object" ? metadataOrEncrypt : void 0;
|
|
19199
|
+
const shouldEncrypt = typeof metadataOrEncrypt === "boolean" ? metadataOrEncrypt : encrypt ?? true;
|
|
19200
|
+
if (!shouldEncrypt) {
|
|
18446
19201
|
return client.presentation.sendPresentation.mutate({
|
|
18447
19202
|
profileId,
|
|
18448
|
-
presentation: vp
|
|
19203
|
+
presentation: vp,
|
|
19204
|
+
metadata
|
|
18449
19205
|
});
|
|
18450
19206
|
}
|
|
18451
19207
|
const target = await _learnCard.invoke.getProfile(profileId);
|
|
@@ -18455,7 +19211,11 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18455
19211
|
_learnCard.id.did(),
|
|
18456
19212
|
target.did
|
|
18457
19213
|
]);
|
|
18458
|
-
return client.presentation.sendPresentation.mutate({
|
|
19214
|
+
return client.presentation.sendPresentation.mutate({
|
|
19215
|
+
profileId,
|
|
19216
|
+
presentation,
|
|
19217
|
+
metadata
|
|
19218
|
+
});
|
|
18459
19219
|
}, "sendPresentation"),
|
|
18460
19220
|
acceptPresentation: /* @__PURE__ */ __name(async (_learnCard, uri) => {
|
|
18461
19221
|
await ensureUser();
|
|
@@ -18782,15 +19542,14 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18782
19542
|
boost = options2.overideFn(boost);
|
|
18783
19543
|
}
|
|
18784
19544
|
const enableRefresh = typeof options2 === "object" && options2.enableRefresh === true;
|
|
18785
|
-
let
|
|
19545
|
+
let refreshAllocation;
|
|
18786
19546
|
if (enableRefresh) {
|
|
18787
19547
|
if (!boost.id) boost.id = `urn:uuid:${crypto.randomUUID()}`;
|
|
18788
|
-
|
|
19548
|
+
refreshAllocation = await client.credentialRefresh.allocateCredentialRefresh.mutate({
|
|
18789
19549
|
holder: { profileId, did: targetProfile.did },
|
|
18790
19550
|
credentialId: boost.id
|
|
18791
19551
|
});
|
|
18792
|
-
|
|
18793
|
-
boost = injectManagedRefreshService(boost, allocation.refreshService);
|
|
19552
|
+
boost = injectManagedRefreshService(boost, refreshAllocation.refreshService);
|
|
18794
19553
|
}
|
|
18795
19554
|
const statusPurposes = typeof options2 === "object" ? options2.statusPurposes : void 0;
|
|
18796
19555
|
const vc = await issueCredentialWithNetworkStatus(
|
|
@@ -18799,13 +19558,23 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18799
19558
|
boost,
|
|
18800
19559
|
statusPurposes
|
|
18801
19560
|
);
|
|
18802
|
-
if (
|
|
18803
|
-
|
|
18804
|
-
refreshId:
|
|
19561
|
+
if (refreshAllocation) {
|
|
19562
|
+
const credentialUri = await client.credentialRefresh.sendRefreshableCredential.mutate({
|
|
19563
|
+
refreshId: refreshAllocation.refreshId,
|
|
18805
19564
|
credential: vc,
|
|
18806
19565
|
boostUri,
|
|
18807
19566
|
...typeof options2 === "object" && options2.skipNotification ? { skipNotification: true } : {}
|
|
18808
19567
|
});
|
|
19568
|
+
return {
|
|
19569
|
+
credentialUri,
|
|
19570
|
+
refresh: buildManagedRefreshReceipt(
|
|
19571
|
+
vc,
|
|
19572
|
+
refreshAllocation,
|
|
19573
|
+
boost.id ?? "",
|
|
19574
|
+
targetProfile.did,
|
|
19575
|
+
_learnCard.id.did()
|
|
19576
|
+
)
|
|
19577
|
+
};
|
|
18809
19578
|
}
|
|
18810
19579
|
if (typeof options2 === "object" && !options2.encrypt || !options2) {
|
|
18811
19580
|
return client.boost.sendBoost.mutate({
|
|
@@ -18871,6 +19640,94 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
18871
19640
|
}, "claimBoostWithLink"),
|
|
18872
19641
|
send: /* @__PURE__ */ __name(async (_learnCard, input) => {
|
|
18873
19642
|
await ensureUser();
|
|
19643
|
+
if (input.type === "boost" && input.refresh === true) {
|
|
19644
|
+
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input.recipient);
|
|
19645
|
+
const isPhone = /^\+?[\d\s-]{10,}$/.test(input.recipient.replace(/[\s-]/g, ""));
|
|
19646
|
+
if (isEmail || isPhone) return client.boost.send.mutate(input);
|
|
19647
|
+
const canIssueLocally = "issueCredential" in _learnCard.invoke;
|
|
19648
|
+
if (canIssueLocally && !input.signedCredential && (input.templateUri || input.template)) {
|
|
19649
|
+
let boost;
|
|
19650
|
+
if (input.templateUri) {
|
|
19651
|
+
const result = await getBoostTemplateForIssuance(
|
|
19652
|
+
_learnCard,
|
|
19653
|
+
input.templateUri
|
|
19654
|
+
);
|
|
19655
|
+
const data = await UnsignedVCValidator.spa(result);
|
|
19656
|
+
if (!data.success)
|
|
19657
|
+
throw new Error("Did not get a valid boost from URI");
|
|
19658
|
+
boost = data.data;
|
|
19659
|
+
} else {
|
|
19660
|
+
boost = JSON.parse(
|
|
19661
|
+
JSON.stringify(input.template.credential)
|
|
19662
|
+
);
|
|
19663
|
+
}
|
|
19664
|
+
const prepared = await client.boost.prepareRefreshableSend.mutate({
|
|
19665
|
+
recipient: input.recipient,
|
|
19666
|
+
...input.templateUri ? { templateUri: input.templateUri } : { template: input.template },
|
|
19667
|
+
...input.contractUri ? { contractUri: input.contractUri } : {},
|
|
19668
|
+
...input.templateData ? { templateData: input.templateData } : {},
|
|
19669
|
+
...input.integrationId ? { integrationId: input.integrationId } : {},
|
|
19670
|
+
...boost.id ? { credentialId: boost.id } : {},
|
|
19671
|
+
...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}
|
|
19672
|
+
});
|
|
19673
|
+
if (prepared.completed) return prepared.completed;
|
|
19674
|
+
const boostString = JSON.stringify(boost);
|
|
19675
|
+
const allowAutoAppendEvidence = !hasDynamicEvidenceTemplate(boostString);
|
|
19676
|
+
if (input.templateData && Object.keys(input.templateData).length > 0) {
|
|
19677
|
+
try {
|
|
19678
|
+
const rendered = renderTemplateJson(
|
|
19679
|
+
boostString,
|
|
19680
|
+
input.templateData
|
|
19681
|
+
);
|
|
19682
|
+
boost = JSON.parse(rendered);
|
|
19683
|
+
boost = appendTemplateEvidence(
|
|
19684
|
+
boost,
|
|
19685
|
+
input.templateData,
|
|
19686
|
+
allowAutoAppendEvidence
|
|
19687
|
+
);
|
|
19688
|
+
} catch (error51) {
|
|
19689
|
+
throw new Error(
|
|
19690
|
+
`Failed to apply template data: ${error51 instanceof Error ? error51.message : "Unknown error"}`,
|
|
19691
|
+
{ cause: error51 }
|
|
19692
|
+
);
|
|
19693
|
+
}
|
|
19694
|
+
}
|
|
19695
|
+
if ((0, import_helpers.isVC2Format)(boost)) {
|
|
19696
|
+
boost.validFrom = (/* @__PURE__ */ new Date()).toISOString();
|
|
19697
|
+
} else {
|
|
19698
|
+
boost.issuanceDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
19699
|
+
}
|
|
19700
|
+
boost.issuer = _learnCard.id.did();
|
|
19701
|
+
if (Array.isArray(boost.credentialSubject)) {
|
|
19702
|
+
boost.credentialSubject = boost.credentialSubject.map((subject) => ({
|
|
19703
|
+
...subject,
|
|
19704
|
+
id: prepared.holderDid
|
|
19705
|
+
}));
|
|
19706
|
+
} else {
|
|
19707
|
+
boost.credentialSubject = {
|
|
19708
|
+
...boost.credentialSubject,
|
|
19709
|
+
id: prepared.holderDid
|
|
19710
|
+
};
|
|
19711
|
+
}
|
|
19712
|
+
boost.id = prepared.credentialId;
|
|
19713
|
+
if (boost.type?.includes("BoostCredential"))
|
|
19714
|
+
boost.boostId = prepared.boostUri;
|
|
19715
|
+
boost = injectManagedRefreshService(boost, prepared.refreshService);
|
|
19716
|
+
const signedCredential = await issueCredentialWithNetworkStatus(
|
|
19717
|
+
_learnCard,
|
|
19718
|
+
client,
|
|
19719
|
+
boost
|
|
19720
|
+
);
|
|
19721
|
+
return client.boost.send.mutate({
|
|
19722
|
+
...input,
|
|
19723
|
+
template: void 0,
|
|
19724
|
+
templateUri: prepared.boostUri,
|
|
19725
|
+
signedCredential,
|
|
19726
|
+
refresh: true
|
|
19727
|
+
});
|
|
19728
|
+
}
|
|
19729
|
+
return client.boost.send.mutate(input);
|
|
19730
|
+
}
|
|
18874
19731
|
if (input.type === "boost") {
|
|
18875
19732
|
const recipient = input.recipient;
|
|
18876
19733
|
const isDid = recipient.startsWith("did:");
|
|
@@ -19277,6 +20134,37 @@ async function getLearnCardNetworkPlugin(learnCard, url2, apiTokenOrOptions, opt
|
|
|
19277
20134
|
await ensureUser();
|
|
19278
20135
|
return client.inbox.issue.mutate(issueInboxCredential);
|
|
19279
20136
|
}, "sendCredentialViaInbox"),
|
|
20137
|
+
sendCredentialsViaInbox: /* @__PURE__ */ __name(async (_learnCard, batch) => {
|
|
20138
|
+
await ensureUser();
|
|
20139
|
+
return client.inbox.issueBatch.mutate(batch);
|
|
20140
|
+
}, "sendCredentialsViaInbox"),
|
|
20141
|
+
sendCredentialBatchViaInbox: /* @__PURE__ */ __name(async (_learnCard, batch) => {
|
|
20142
|
+
await ensureUser();
|
|
20143
|
+
return client.inbox.issueBatch.mutate(batch);
|
|
20144
|
+
}, "sendCredentialBatchViaInbox"),
|
|
20145
|
+
waitForInboxCredentialBatch: /* @__PURE__ */ __name(async (_learnCard, batchId, options2) => {
|
|
20146
|
+
await ensureUser();
|
|
20147
|
+
return waitForInboxCredentialBatch(
|
|
20148
|
+
(signal) => client.inbox.getBatch.query({ batchId }, { signal }),
|
|
20149
|
+
options2
|
|
20150
|
+
);
|
|
20151
|
+
}, "waitForInboxCredentialBatch"),
|
|
20152
|
+
sendCredentialsViaInboxAndWait: /* @__PURE__ */ __name(async (_learnCard, batch, options2) => {
|
|
20153
|
+
await ensureUser();
|
|
20154
|
+
if (options2?.signal?.aborted) throw options2.signal.reason;
|
|
20155
|
+
const receipt = await client.inbox.issueBatch.mutate(batch, {
|
|
20156
|
+
signal: options2?.signal
|
|
20157
|
+
});
|
|
20158
|
+
await options2?.onSubmitted?.(receipt);
|
|
20159
|
+
return waitForInboxCredentialBatch(
|
|
20160
|
+
(signal) => client.inbox.getBatch.query({ batchId: receipt.batchId }, { signal }),
|
|
20161
|
+
options2
|
|
20162
|
+
);
|
|
20163
|
+
}, "sendCredentialsViaInboxAndWait"),
|
|
20164
|
+
getInboxCredentialBatch: /* @__PURE__ */ __name(async (_learnCard, batchId) => {
|
|
20165
|
+
await ensureUser();
|
|
20166
|
+
return client.inbox.getBatch.query({ batchId });
|
|
20167
|
+
}, "getInboxCredentialBatch"),
|
|
19280
20168
|
getMySentInboxCredentials: /* @__PURE__ */ __name(async (_learnCard, options2) => {
|
|
19281
20169
|
await ensureUser();
|
|
19282
20170
|
return client.inbox.getMyIssuedCredentials.query(options2);
|