@tinycloud/sdk-core 3.0.0-beta.0 → 3.0.0-beta.2
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/dist/{credential-admission-C_cO1QqB.d.cts → credential-admission-BVUC6kdw.d.cts} +67 -2
- package/dist/{credential-admission-cvHe-HUC.d.ts → credential-admission-BgvwOTIV.d.ts} +67 -2
- package/dist/delegations/index.cjs +11 -2
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.js +11 -2
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +416 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -3
- package/dist/index.d.ts +92 -3
- package/dist/index.js +416 -3
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +166 -3
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.d.cts +2 -2
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +166 -3
- package/dist/policy/index.js.map +1 -1
- package/package.json +3 -3
package/dist/policy/index.cjs
CHANGED
|
@@ -38,6 +38,8 @@ __export(policy_exports, {
|
|
|
38
38
|
POLICY_ENGINE_RECORD_SCHEMA: () => POLICY_ENGINE_RECORD_SCHEMA,
|
|
39
39
|
POLICY_PRESENTATION_V3_DOMAIN: () => POLICY_PRESENTATION_V3_DOMAIN,
|
|
40
40
|
POLICY_PRESENTATION_V3_SCHEMA: () => POLICY_PRESENTATION_V3_SCHEMA,
|
|
41
|
+
POLICY_PRESENTATION_V4_DOMAIN: () => POLICY_PRESENTATION_V4_DOMAIN,
|
|
42
|
+
POLICY_PRESENTATION_V4_SCHEMA: () => POLICY_PRESENTATION_V4_SCHEMA,
|
|
41
43
|
POLICY_SCHEMA: () => POLICY_SCHEMA,
|
|
42
44
|
POLICY_SESSION_UCAN_V1_PROFILE: () => POLICY_SESSION_UCAN_V1_PROFILE,
|
|
43
45
|
POLICY_STATUS_SCHEMA: () => POLICY_STATUS_SCHEMA,
|
|
@@ -65,7 +67,9 @@ __export(policy_exports, {
|
|
|
65
67
|
UnsupportedSignatureSuiteError: () => UnsupportedSignatureSuiteError,
|
|
66
68
|
W3C_VC_CREDENTIAL_VERIFIER: () => W3C_VC_CREDENTIAL_VERIFIER,
|
|
67
69
|
admitPolicyCredentialV3: () => admitPolicyCredentialV3,
|
|
70
|
+
admitPolicyCredentialV4: () => admitPolicyCredentialV4,
|
|
68
71
|
buildPolicyCredentialPresentationV3: () => buildPolicyCredentialPresentationV3,
|
|
72
|
+
buildPolicyCredentialPresentationV4: () => buildPolicyCredentialPresentationV4,
|
|
69
73
|
canonicalizePolicyCapability: () => canonicalizePolicyCapability,
|
|
70
74
|
canonicalizeSignedObjectUnsigned: () => canonicalizeSignedObjectUnsigned,
|
|
71
75
|
canonicalizeUnifiedPolicyCapability: () => canonicalizeUnifiedPolicyCapability,
|
|
@@ -83,6 +87,7 @@ __export(policy_exports, {
|
|
|
83
87
|
createUnsignedPolicyEngineRecord: () => createUnsignedPolicyEngineRecord,
|
|
84
88
|
deriveSignedObjectMaterial: () => deriveSignedObjectMaterial,
|
|
85
89
|
getPolicyRootStatusV3: () => getPolicyRootStatusV3,
|
|
90
|
+
issuedCredentialEnvelopeFromVerified: () => issuedCredentialEnvelopeFromVerified,
|
|
86
91
|
jcsCanonicalize: () => jcsCanonicalize,
|
|
87
92
|
mintPolicySessionV3: () => mintPolicySessionV3,
|
|
88
93
|
normalizeJson: () => normalizeJson,
|
|
@@ -104,6 +109,7 @@ __export(policy_exports, {
|
|
|
104
109
|
serializeJcsJson: () => serialize,
|
|
105
110
|
signCompactUcanAuthorization: () => signCompactUcanAuthorization,
|
|
106
111
|
signCompactUcanRootAuthorization: () => signCompactUcanRootAuthorization,
|
|
112
|
+
signPolicyCredentialPresentationV4: () => signPolicyCredentialPresentationV4,
|
|
107
113
|
signedObjectIdFor: () => signedObjectIdFor,
|
|
108
114
|
toSignedObjectError: () => toSignedObjectError,
|
|
109
115
|
unifiedNativeProjectionHashHex: () => unifiedNativeProjectionHashHex,
|
|
@@ -3338,6 +3344,7 @@ async function requestPolicyChallengeV3(input) {
|
|
|
3338
3344
|
const response = await fetchFn(new URL("/share/v3/policy/challenges", input.nodeOrigin), {
|
|
3339
3345
|
method: "POST",
|
|
3340
3346
|
redirect: "error",
|
|
3347
|
+
signal: input.signal,
|
|
3341
3348
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3342
3349
|
body: JSON.stringify({ policyCid: input.policyCid, recipientDid: input.recipientDid, requestedCapabilities: input.requestedCapabilities.map(normalizeUnifiedPolicyCapability) })
|
|
3343
3350
|
});
|
|
@@ -3355,6 +3362,7 @@ async function mintPolicySessionV3(input) {
|
|
|
3355
3362
|
const response = await fetchFn(new URL("/share/v3/policy/delegations", input.nodeOrigin), {
|
|
3356
3363
|
method: "POST",
|
|
3357
3364
|
redirect: "error",
|
|
3365
|
+
signal: input.signal,
|
|
3358
3366
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3359
3367
|
body: JSON.stringify({ policyCid: input.policyCid, challengeId: challenge.challengeId, nonce: challenge.nonce, claim: input.claim, presentation: input.presentation })
|
|
3360
3368
|
});
|
|
@@ -3528,6 +3536,11 @@ var POLICY_SESSION_FACT_KEYS = [
|
|
|
3528
3536
|
"issuanceAuditDigestHex",
|
|
3529
3537
|
"remainingRedelegationDepth"
|
|
3530
3538
|
];
|
|
3539
|
+
var POLICY_SESSION_V4_AUDIT_FACT_KEYS = [
|
|
3540
|
+
"credentialIdAuditDigestHex",
|
|
3541
|
+
"presentationJtiAuditDigestHex"
|
|
3542
|
+
];
|
|
3543
|
+
var LOWER_SHA256_HEX = /^[0-9a-f]{64}$/;
|
|
3531
3544
|
var KV_ACTIONS = /* @__PURE__ */ new Set([
|
|
3532
3545
|
"tinycloud.kv/get",
|
|
3533
3546
|
"tinycloud.kv/list",
|
|
@@ -3920,9 +3933,13 @@ function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
|
3920
3933
|
if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
|
|
3921
3934
|
throw new Error("policy session UCAN ordered proofs do not match");
|
|
3922
3935
|
const factKeys = Object.keys(fact);
|
|
3923
|
-
|
|
3936
|
+
const hasLegacyFactShape = factKeys.length === POLICY_SESSION_FACT_KEYS.length && factKeys.every((key) => POLICY_SESSION_FACT_KEYS.includes(key)) && POLICY_SESSION_FACT_KEYS.every((key) => key in fact);
|
|
3937
|
+
const hasV4AuditFactShape = factKeys.length === POLICY_SESSION_FACT_KEYS.length + POLICY_SESSION_V4_AUDIT_FACT_KEYS.length && factKeys.every((key) => POLICY_SESSION_FACT_KEYS.includes(key) || POLICY_SESSION_V4_AUDIT_FACT_KEYS.includes(key)) && POLICY_SESSION_FACT_KEYS.every((key) => key in fact) && POLICY_SESSION_V4_AUDIT_FACT_KEYS.every((key) => key in fact);
|
|
3938
|
+
if (!hasLegacyFactShape && !hasV4AuditFactShape)
|
|
3924
3939
|
throw new Error("policy session UCAN fact is incomplete");
|
|
3925
|
-
if (
|
|
3940
|
+
if (hasV4AuditFactShape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)))
|
|
3941
|
+
throw new Error("policy session UCAN v4 audit facts are invalid");
|
|
3942
|
+
if (fact.profile !== POLICY_SESSION_UCAN_V1_PROFILE || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || parsed.payload.exp - parsed.payload.nbf > 60 || parsed.payload.iss.split("#", 1)[0] !== fact.nodeAudience || parsed.payload.aud !== fact.recipientDid)
|
|
3926
3943
|
throw new Error("policy session UCAN fact is invalid");
|
|
3927
3944
|
return {
|
|
3928
3945
|
authorization,
|
|
@@ -4050,6 +4067,8 @@ var POLICY_V2_DOMAIN = "xyz.tinycloud.policy/policy/v2\0";
|
|
|
4050
4067
|
var POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE = "TinyCloudPolicyCredentialRequirement";
|
|
4051
4068
|
var POLICY_PRESENTATION_V3_SCHEMA = "xyz.tinycloud.policy/presentation/v3";
|
|
4052
4069
|
var POLICY_PRESENTATION_V3_DOMAIN = "xyz.tinycloud.policy/Presentation/v3\0";
|
|
4070
|
+
var POLICY_PRESENTATION_V4_SCHEMA = "xyz.tinycloud.policy/presentation/v4";
|
|
4071
|
+
var POLICY_PRESENTATION_V4_DOMAIN = "xyz.tinycloud.policy/Presentation/v4\0";
|
|
4053
4072
|
function record(value, label) {
|
|
4054
4073
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4055
4074
|
throw new Error(`${label} must be an object`);
|
|
@@ -4224,6 +4243,97 @@ function envelopeFromVerified(verified) {
|
|
|
4224
4243
|
} = verified;
|
|
4225
4244
|
return envelope;
|
|
4226
4245
|
}
|
|
4246
|
+
function issuedCredentialEnvelopeFromVerified(verified) {
|
|
4247
|
+
return envelopeFromVerified(verified);
|
|
4248
|
+
}
|
|
4249
|
+
async function signPolicyCredentialPresentationV4(value, sign) {
|
|
4250
|
+
const item = record(value, "Policy presentation v4");
|
|
4251
|
+
exactKeys2(item, [
|
|
4252
|
+
"schema",
|
|
4253
|
+
"jti",
|
|
4254
|
+
"challengeId",
|
|
4255
|
+
"nonce",
|
|
4256
|
+
"policyCid",
|
|
4257
|
+
"nodeAudience",
|
|
4258
|
+
"holderDid",
|
|
4259
|
+
"subjectDid",
|
|
4260
|
+
"credentialDigest",
|
|
4261
|
+
"requirementDigest",
|
|
4262
|
+
"descriptorDigest",
|
|
4263
|
+
"requestedCapabilities",
|
|
4264
|
+
"issuedAt",
|
|
4265
|
+
"expiresAt"
|
|
4266
|
+
], "Policy presentation v4");
|
|
4267
|
+
if (item.schema !== POLICY_PRESENTATION_V4_SCHEMA || item.holderDid !== item.subjectDid || !Array.isArray(item.requestedCapabilities)) throw new Error("Policy presentation v4 is invalid");
|
|
4268
|
+
const holderDid = nonEmpty(item.holderDid, "Policy presentation v4 holder DID");
|
|
4269
|
+
didKeyBytes(holderDid);
|
|
4270
|
+
const unsigned = Object.freeze({
|
|
4271
|
+
schema: POLICY_PRESENTATION_V4_SCHEMA,
|
|
4272
|
+
jti: nonEmpty(item.jti, "Policy presentation v4 jti"),
|
|
4273
|
+
challengeId: nonEmpty(item.challengeId, "Policy presentation v4 challenge"),
|
|
4274
|
+
nonce: nonEmpty(item.nonce, "Policy presentation v4 nonce"),
|
|
4275
|
+
policyCid: nonEmpty(item.policyCid, "Policy presentation v4 policy CID"),
|
|
4276
|
+
nodeAudience: nonEmpty(item.nodeAudience, "Policy presentation v4 audience"),
|
|
4277
|
+
holderDid,
|
|
4278
|
+
subjectDid: holderDid,
|
|
4279
|
+
credentialDigest: nonEmpty(item.credentialDigest, "Policy presentation v4 credential digest"),
|
|
4280
|
+
requirementDigest: nonEmpty(item.requirementDigest, "Policy presentation v4 requirement digest"),
|
|
4281
|
+
descriptorDigest: nonEmpty(item.descriptorDigest, "Policy presentation v4 descriptor digest"),
|
|
4282
|
+
// The low-level signer preserves the frozen wire bytes exactly. The
|
|
4283
|
+
// policy-aware builder performs capability normalization and containment.
|
|
4284
|
+
requestedCapabilities: Object.freeze(item.requestedCapabilities),
|
|
4285
|
+
issuedAt: date(item.issuedAt, "Policy presentation v4 issuedAt"),
|
|
4286
|
+
expiresAt: date(item.expiresAt, "Policy presentation v4 expiresAt")
|
|
4287
|
+
});
|
|
4288
|
+
const digest2 = (0, import_sha2562.sha256)(new TextEncoder().encode(
|
|
4289
|
+
POLICY_PRESENTATION_V4_DOMAIN + jcsCanonicalize(unsigned)
|
|
4290
|
+
));
|
|
4291
|
+
const signature = await sign(digest2);
|
|
4292
|
+
if (signature.length !== 64 || !import_ed255193.ed25519.verify(signature, digest2, didKeyBytes(holderDid))) throw new Error("policy presentation signature is invalid");
|
|
4293
|
+
return Object.freeze({
|
|
4294
|
+
...unsigned,
|
|
4295
|
+
signature: Object.freeze({
|
|
4296
|
+
suite: "Ed25519",
|
|
4297
|
+
signerDid: holderDid,
|
|
4298
|
+
value: encodeBase64Url2(signature)
|
|
4299
|
+
})
|
|
4300
|
+
});
|
|
4301
|
+
}
|
|
4302
|
+
async function buildPolicyCredentialPresentationV4(input) {
|
|
4303
|
+
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4304
|
+
const requirement = validateCredentialRequirement(input.requirement);
|
|
4305
|
+
const commitment = policy.credentialRequirement;
|
|
4306
|
+
const requirementDigest = await credentialRequirementDigest(requirement);
|
|
4307
|
+
const credentialDigest = await sha256Base64Url(input.credential.credential);
|
|
4308
|
+
if (requirementDigest !== commitment.requirementDigest || input.credential.descriptorDigest !== commitment.descriptorDigest || input.credential.credentialDigest !== credentialDigest || input.credential.issuerDid !== commitment.issuerDid || input.credential.issuerKid !== commitment.issuerKid || jcsCanonicalize(input.credential.profile) !== jcsCanonicalize(commitment.profile) || jcsCanonicalize(input.credential.credentialType) !== jcsCanonicalize(commitment.credentialType)) throw new Error("credential does not match the signed Policy/v2 requirement");
|
|
4309
|
+
const requestedCapabilities = input.requestedCapabilities.map(normalizeUnifiedPolicyCapability);
|
|
4310
|
+
if (requestedCapabilities.length === 0 || requestedCapabilities.some((requested) => !policy.capabilityCeiling.some((authority) => unifiedPolicyCapabilityContains(authority, requested)))) throw new Error("requested capabilities exceed the signed Policy/v2 ceiling");
|
|
4311
|
+
const holderDid = input.credential.holderDid;
|
|
4312
|
+
if (input.challenge.policyCid !== input.policyCid || input.challenge.recipientDid !== holderDid || input.credential.subjectDid !== holderDid || typeof input.challenge.nodeAudience !== "string" || input.challenge.nodeAudience.length === 0 || typeof input.challenge.expiresAt !== "string" || !Number.isFinite(Date.parse(input.challenge.expiresAt))) throw new Error("policy challenge binding is invalid");
|
|
4313
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
4314
|
+
const expiresAtMs = Math.min(
|
|
4315
|
+
now.getTime() + 6e4,
|
|
4316
|
+
Date.parse(input.challenge.expiresAt),
|
|
4317
|
+
Date.parse(input.credential.expiresAt)
|
|
4318
|
+
);
|
|
4319
|
+
if (expiresAtMs <= now.getTime()) throw new Error("policy challenge is expired");
|
|
4320
|
+
return signPolicyCredentialPresentationV4(Object.freeze({
|
|
4321
|
+
schema: POLICY_PRESENTATION_V4_SCHEMA,
|
|
4322
|
+
jti: input.jti ?? encodeBase64Url2(crypto.getRandomValues(new Uint8Array(16))),
|
|
4323
|
+
challengeId: input.challenge.challengeId,
|
|
4324
|
+
nonce: input.challenge.nonce,
|
|
4325
|
+
policyCid: input.policyCid,
|
|
4326
|
+
nodeAudience: input.challenge.nodeAudience,
|
|
4327
|
+
holderDid,
|
|
4328
|
+
subjectDid: holderDid,
|
|
4329
|
+
credentialDigest,
|
|
4330
|
+
requirementDigest,
|
|
4331
|
+
descriptorDigest: input.credential.descriptorDigest,
|
|
4332
|
+
requestedCapabilities: Object.freeze(requestedCapabilities),
|
|
4333
|
+
issuedAt: rfc3339Seconds(now),
|
|
4334
|
+
expiresAt: rfc3339Seconds(new Date(expiresAtMs))
|
|
4335
|
+
}), input.sign);
|
|
4336
|
+
}
|
|
4227
4337
|
async function buildPolicyCredentialPresentationV3(input) {
|
|
4228
4338
|
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4229
4339
|
const requirement = validateCredentialRequirement(input.requirement);
|
|
@@ -4313,7 +4423,8 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4313
4423
|
policyCid: input.policyCid,
|
|
4314
4424
|
recipientDid: input.credential.holderDid,
|
|
4315
4425
|
requestedCapabilities: input.requestedCapabilities,
|
|
4316
|
-
fetch: fetchFn
|
|
4426
|
+
fetch: fetchFn,
|
|
4427
|
+
signal: input.signal
|
|
4317
4428
|
});
|
|
4318
4429
|
const presentation = await buildPolicyCredentialPresentationV3({
|
|
4319
4430
|
...input,
|
|
@@ -4325,6 +4436,7 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4325
4436
|
{
|
|
4326
4437
|
method: "POST",
|
|
4327
4438
|
redirect: "error",
|
|
4439
|
+
signal: input.signal,
|
|
4328
4440
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4329
4441
|
body: JSON.stringify({
|
|
4330
4442
|
policyCid: input.policyCid,
|
|
@@ -4353,6 +4465,57 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4353
4465
|
if (session.cid !== value.sessionCid || session.aud !== input.credential.holderDid || session.fact.policyCid !== input.policyCid || session.fact.recipientDid !== input.credential.holderDid || session.fact.policyDelegationCid !== input.policyRootCid || session.fact.enforcementDelegationCid !== input.enforcementRootCid || jcsCanonicalize(session.att) !== jcsCanonicalize(expectedAttenuation)) {
|
|
4354
4466
|
throw new Error("policy delegation signed binding is invalid");
|
|
4355
4467
|
}
|
|
4468
|
+
input.signal?.throwIfAborted();
|
|
4469
|
+
return Object.freeze({ challenge, presentation, session });
|
|
4470
|
+
}
|
|
4471
|
+
function validatePolicyCredentialAdmissionV4Authority(session, expected) {
|
|
4472
|
+
if (session.iss.split("#", 1)[0] !== expected.nodeAudience || session.fact.nodeAudience !== expected.nodeAudience || session.fact.enforcerDid !== expected.enforcerDid) throw new Error("policy delegation authority binding is invalid");
|
|
4473
|
+
}
|
|
4474
|
+
async function admitPolicyCredentialV4(input) {
|
|
4475
|
+
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4476
|
+
const nodeOrigin = policyNodeOrigin(input.nodeOrigin);
|
|
4477
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
4478
|
+
const challenge = await requestPolicyChallengeV3({
|
|
4479
|
+
nodeOrigin,
|
|
4480
|
+
policyCid: input.policyCid,
|
|
4481
|
+
recipientDid: input.credential.holderDid,
|
|
4482
|
+
requestedCapabilities: input.requestedCapabilities,
|
|
4483
|
+
fetch: fetchFn,
|
|
4484
|
+
signal: input.signal
|
|
4485
|
+
});
|
|
4486
|
+
const presentation = await buildPolicyCredentialPresentationV4({
|
|
4487
|
+
...input,
|
|
4488
|
+
policy,
|
|
4489
|
+
challenge
|
|
4490
|
+
});
|
|
4491
|
+
const response = await fetchFn(new URL("/share/v3/policy/delegations", nodeOrigin), {
|
|
4492
|
+
method: "POST",
|
|
4493
|
+
redirect: "error",
|
|
4494
|
+
signal: input.signal,
|
|
4495
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4496
|
+
body: JSON.stringify({
|
|
4497
|
+
policyCid: input.policyCid,
|
|
4498
|
+
challengeId: challenge.challengeId,
|
|
4499
|
+
nonce: challenge.nonce,
|
|
4500
|
+
requirement: validateCredentialRequirement(input.requirement),
|
|
4501
|
+
credential: envelopeFromVerified(input.credential),
|
|
4502
|
+
presentation
|
|
4503
|
+
})
|
|
4504
|
+
});
|
|
4505
|
+
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
4506
|
+
const value = record(await response.json(), "policy delegation");
|
|
4507
|
+
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") throw new Error("policy delegation response is invalid");
|
|
4508
|
+
const session = parsePolicySessionUcan(value.authorization, [
|
|
4509
|
+
input.policyRootCid,
|
|
4510
|
+
input.enforcementRootCid
|
|
4511
|
+
]);
|
|
4512
|
+
const expectedAttenuation = compactAttenuationForPolicyCapabilities(input.requestedCapabilities);
|
|
4513
|
+
validatePolicyCredentialAdmissionV4Authority(session, {
|
|
4514
|
+
nodeAudience: input.expectedNodeAudience,
|
|
4515
|
+
enforcerDid: input.expectedEnforcerDid
|
|
4516
|
+
});
|
|
4517
|
+
if (session.cid !== value.sessionCid || session.aud !== input.credential.holderDid || session.fact.policyCid !== input.policyCid || session.fact.recipientDid !== input.credential.holderDid || session.fact.policyDelegationCid !== input.policyRootCid || session.fact.enforcementDelegationCid !== input.enforcementRootCid || jcsCanonicalize(session.att) !== jcsCanonicalize(expectedAttenuation)) throw new Error("policy delegation signed binding is invalid");
|
|
4518
|
+
input.signal?.throwIfAborted();
|
|
4356
4519
|
return Object.freeze({ challenge, presentation, session });
|
|
4357
4520
|
}
|
|
4358
4521
|
//# sourceMappingURL=index.cjs.map
|