@learncard/credential-library 2.0.2 → 2.0.4
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 +2 -1
- package/dist/credential-library.cjs.development.js +139 -20
- package/dist/credential-library.cjs.development.js.map +4 -4
- package/dist/credential-library.cjs.production.min.js +1 -1
- package/dist/credential-library.cjs.production.min.js.map +4 -4
- package/dist/credential-library.esm.js +127 -8
- package/dist/credential-library.esm.js.map +4 -4
- package/dist/fixtures/clr/provisional-transcript.d.ts +7 -1
- package/dist/fixtures/clr/provisional-transcript.d.ts.map +1 -1
- package/dist/fixtures/index.d.ts +2 -1
- package/dist/fixtures/index.d.ts.map +1 -1
- package/dist/fixtures/obv3/rubric-aligned-badge.d.ts +3 -0
- package/dist/fixtures/obv3/rubric-aligned-badge.d.ts.map +1 -0
- package/dist/prepare.d.ts +0 -18
- package/dist/prepare.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/__tests__/registry.test.ts +43 -0
- package/src/fixtures/clr/provisional-transcript.ts +16 -3
- package/src/fixtures/index.ts +3 -0
- package/src/fixtures/obv3/rubric-aligned-badge.ts +105 -0
- package/src/prepare.ts +15 -0
package/README.md
CHANGED
|
@@ -251,7 +251,7 @@ See the [Credential Viewer README](../../examples/credential-viewer/README.md) f
|
|
|
251
251
|
- `vc-v2/membership-credential` — Professional association membership
|
|
252
252
|
- `vc-v2/license-credential` — Professional nursing license
|
|
253
253
|
|
|
254
|
-
### Open Badges v3 (
|
|
254
|
+
### Open Badges v3 (12)
|
|
255
255
|
|
|
256
256
|
- `obv3/minimal-badge` — Minimal OBv3 achievement credential
|
|
257
257
|
- `obv3/full-badge` — Full-featured badge with image, evidence, alignment, results, expiration
|
|
@@ -264,6 +264,7 @@ See the [Credential Viewer README](../../examples/credential-viewer/README.md) f
|
|
|
264
264
|
- `obv3/course-completion` — Introduction to Machine Learning course completion
|
|
265
265
|
- `obv3/k12-diploma` — High school diploma
|
|
266
266
|
- `obv3/endorsement-credential` — Program accreditation endorsement
|
|
267
|
+
- `obv3/rubric-aligned-badge` — Open Skills Alignment result with rubric levels and CTDL alignment
|
|
267
268
|
|
|
268
269
|
### CLR v2 (4)
|
|
269
270
|
|
|
@@ -68,6 +68,7 @@ __export(index_exports, {
|
|
|
68
68
|
obv3OneedtechFull: () => obv3OneedtechFull,
|
|
69
69
|
obv3PlugfestJff2: () => obv3PlugfestJff2,
|
|
70
70
|
obv3ProfessionalCert: () => obv3ProfessionalCert,
|
|
71
|
+
obv3RubricAlignedBadge: () => obv3RubricAlignedBadge,
|
|
71
72
|
obv3StandaloneFullCourse: () => obv3StandaloneFullCourse,
|
|
72
73
|
obv3WithAlignment: () => obv3WithAlignment,
|
|
73
74
|
obv3WithEndorsement: () => obv3WithEndorsement,
|
|
@@ -1585,8 +1586,107 @@ var obv3EndorsementCredential = {
|
|
|
1585
1586
|
}
|
|
1586
1587
|
};
|
|
1587
1588
|
|
|
1588
|
-
// src/fixtures/
|
|
1589
|
+
// src/fixtures/obv3/rubric-aligned-badge.ts
|
|
1589
1590
|
var import_types13 = require("@learncard/types");
|
|
1591
|
+
var RESULT_DESCRIPTION_ID = "urn:uuid:7cc1519e-87f4-4cae-b7a5-786ec15db769";
|
|
1592
|
+
var PROFICIENT_LEVEL_ID = "urn:uuid:eb753d86-9277-478d-b9c4-3d589c82aff8";
|
|
1593
|
+
var obv3RubricAlignedBadge = {
|
|
1594
|
+
id: "obv3/rubric-aligned-badge",
|
|
1595
|
+
name: "Rubric-Aligned OBv3 Badge",
|
|
1596
|
+
description: "Open Badges v3 credential with rubric levels, an achieved level, and a CTDL result alignment",
|
|
1597
|
+
spec: "obv3",
|
|
1598
|
+
profile: "badge",
|
|
1599
|
+
features: ["alignment", "results"],
|
|
1600
|
+
source: "synthetic",
|
|
1601
|
+
signed: false,
|
|
1602
|
+
validity: "valid",
|
|
1603
|
+
validator: import_types13.UnsignedAchievementCredentialValidator,
|
|
1604
|
+
tags: ["rubric", "open-skill-alignment"],
|
|
1605
|
+
credential: {
|
|
1606
|
+
"@context": [
|
|
1607
|
+
"https://www.w3.org/ns/credentials/v2",
|
|
1608
|
+
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
|
1609
|
+
],
|
|
1610
|
+
id: "urn:uuid:b3e5babd-f68e-4095-979d-3e910a444e73",
|
|
1611
|
+
type: ["VerifiableCredential", "OpenBadgeCredential"],
|
|
1612
|
+
name: "Applied Data Analysis",
|
|
1613
|
+
description: "Recognizes applied data analysis at the proficient rubric level.",
|
|
1614
|
+
issuer: {
|
|
1615
|
+
id: "did:example:issuer123",
|
|
1616
|
+
type: ["Profile"],
|
|
1617
|
+
name: "Example Skills Institute",
|
|
1618
|
+
url: "https://example.org"
|
|
1619
|
+
},
|
|
1620
|
+
validFrom: "2026-01-15T00:00:00Z",
|
|
1621
|
+
credentialSubject: {
|
|
1622
|
+
id: "did:example:learner456",
|
|
1623
|
+
type: ["AchievementSubject"],
|
|
1624
|
+
achievement: {
|
|
1625
|
+
id: "urn:uuid:e736a10c-aa36-466f-99af-e52440f32d8e",
|
|
1626
|
+
type: ["Achievement"],
|
|
1627
|
+
achievementType: "Badge",
|
|
1628
|
+
name: "Applied Data Analysis",
|
|
1629
|
+
description: "Analyze a real-world dataset and communicate supported conclusions.",
|
|
1630
|
+
criteria: {
|
|
1631
|
+
narrative: "Submit an analysis that meets at least the proficient rubric level."
|
|
1632
|
+
},
|
|
1633
|
+
resultDescription: [
|
|
1634
|
+
{
|
|
1635
|
+
id: RESULT_DESCRIPTION_ID,
|
|
1636
|
+
type: ["ResultDescription"],
|
|
1637
|
+
name: "Data Analysis Rubric",
|
|
1638
|
+
resultType: "RubricCriterionLevel",
|
|
1639
|
+
valueMin: "1",
|
|
1640
|
+
valueMax: "4",
|
|
1641
|
+
rubricCriterionLevel: [
|
|
1642
|
+
{
|
|
1643
|
+
id: "urn:uuid:a4993932-d453-4417-b5aa-52b1bc1ea80e",
|
|
1644
|
+
type: ["RubricCriterionLevel"],
|
|
1645
|
+
name: "Developing",
|
|
1646
|
+
level: "2",
|
|
1647
|
+
points: "2"
|
|
1648
|
+
},
|
|
1649
|
+
{
|
|
1650
|
+
id: PROFICIENT_LEVEL_ID,
|
|
1651
|
+
type: ["RubricCriterionLevel"],
|
|
1652
|
+
name: "Proficient",
|
|
1653
|
+
level: "3",
|
|
1654
|
+
points: "3"
|
|
1655
|
+
},
|
|
1656
|
+
{
|
|
1657
|
+
id: "urn:uuid:217fc04f-383b-48a0-a2e5-1cf1b016f7d4",
|
|
1658
|
+
type: ["RubricCriterionLevel"],
|
|
1659
|
+
name: "Advanced",
|
|
1660
|
+
level: "4",
|
|
1661
|
+
points: "4"
|
|
1662
|
+
}
|
|
1663
|
+
],
|
|
1664
|
+
alignment: [
|
|
1665
|
+
{
|
|
1666
|
+
type: ["Alignment"],
|
|
1667
|
+
targetName: "Analyze data using appropriate methods",
|
|
1668
|
+
targetUrl: "https://credentialengineregistry.org/resources/ce-2f5dce8d-29ad-40cb-a9e1-5a5517ff79a7",
|
|
1669
|
+
targetType: "CTDL",
|
|
1670
|
+
targetFramework: "Credential Engine Registry"
|
|
1671
|
+
}
|
|
1672
|
+
]
|
|
1673
|
+
}
|
|
1674
|
+
]
|
|
1675
|
+
},
|
|
1676
|
+
result: [
|
|
1677
|
+
{
|
|
1678
|
+
type: ["Result"],
|
|
1679
|
+
resultDescription: RESULT_DESCRIPTION_ID,
|
|
1680
|
+
value: "3",
|
|
1681
|
+
achievedLevel: PROFICIENT_LEVEL_ID
|
|
1682
|
+
}
|
|
1683
|
+
]
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
|
|
1688
|
+
// src/fixtures/clr/minimal.ts
|
|
1689
|
+
var import_types14 = require("@learncard/types");
|
|
1590
1690
|
var clrMinimal = {
|
|
1591
1691
|
id: "clr/minimal",
|
|
1592
1692
|
name: "Minimal CLR v2 Credential",
|
|
@@ -1597,7 +1697,7 @@ var clrMinimal = {
|
|
|
1597
1697
|
source: "spec-example",
|
|
1598
1698
|
signed: false,
|
|
1599
1699
|
validity: "valid",
|
|
1600
|
-
validator:
|
|
1700
|
+
validator: import_types14.UnsignedClrCredentialValidator,
|
|
1601
1701
|
credential: {
|
|
1602
1702
|
"@context": [
|
|
1603
1703
|
"https://www.w3.org/ns/credentials/v2",
|
|
@@ -1636,7 +1736,7 @@ var clrMinimal = {
|
|
|
1636
1736
|
};
|
|
1637
1737
|
|
|
1638
1738
|
// src/fixtures/clr/multi-achievement.ts
|
|
1639
|
-
var
|
|
1739
|
+
var import_types15 = require("@learncard/types");
|
|
1640
1740
|
var clrMultiAchievement = {
|
|
1641
1741
|
id: "clr/multi-achievement",
|
|
1642
1742
|
name: "CLR v2 with Multiple Achievements and Associations",
|
|
@@ -1647,7 +1747,7 @@ var clrMultiAchievement = {
|
|
|
1647
1747
|
source: "synthetic",
|
|
1648
1748
|
signed: false,
|
|
1649
1749
|
validity: "valid",
|
|
1650
|
-
validator:
|
|
1750
|
+
validator: import_types15.UnsignedClrCredentialValidator,
|
|
1651
1751
|
tags: ["comprehensive"],
|
|
1652
1752
|
credential: {
|
|
1653
1753
|
"@context": [
|
|
@@ -2082,7 +2182,7 @@ var clrUniversityTranscript = {
|
|
|
2082
2182
|
};
|
|
2083
2183
|
|
|
2084
2184
|
// src/fixtures/boost/basic.ts
|
|
2085
|
-
var
|
|
2185
|
+
var import_types16 = require("@learncard/types");
|
|
2086
2186
|
var boostBasic = {
|
|
2087
2187
|
id: "boost/basic",
|
|
2088
2188
|
name: "Basic LearnCard Boost",
|
|
@@ -2093,7 +2193,7 @@ var boostBasic = {
|
|
|
2093
2193
|
source: "synthetic",
|
|
2094
2194
|
signed: false,
|
|
2095
2195
|
validity: "valid",
|
|
2096
|
-
validator:
|
|
2196
|
+
validator: import_types16.UnsignedAchievementCredentialValidator,
|
|
2097
2197
|
tags: ["learncard", "boost"],
|
|
2098
2198
|
credential: {
|
|
2099
2199
|
"@context": [
|
|
@@ -2129,7 +2229,7 @@ var boostBasic = {
|
|
|
2129
2229
|
};
|
|
2130
2230
|
|
|
2131
2231
|
// src/fixtures/boost/boost-id.ts
|
|
2132
|
-
var
|
|
2232
|
+
var import_types17 = require("@learncard/types");
|
|
2133
2233
|
var boostId = {
|
|
2134
2234
|
id: "boost/boost-id",
|
|
2135
2235
|
name: "LearnCard Boost ID",
|
|
@@ -2140,7 +2240,7 @@ var boostId = {
|
|
|
2140
2240
|
source: "synthetic",
|
|
2141
2241
|
signed: false,
|
|
2142
2242
|
validity: "valid",
|
|
2143
|
-
validator:
|
|
2243
|
+
validator: import_types17.UnsignedAchievementCredentialValidator,
|
|
2144
2244
|
tags: ["learncard", "boost", "id"],
|
|
2145
2245
|
credential: {
|
|
2146
2246
|
"@context": [
|
|
@@ -2185,7 +2285,7 @@ var boostId = {
|
|
|
2185
2285
|
};
|
|
2186
2286
|
|
|
2187
2287
|
// src/fixtures/boost/with-skills.ts
|
|
2188
|
-
var
|
|
2288
|
+
var import_types18 = require("@learncard/types");
|
|
2189
2289
|
var boostWithSkills = {
|
|
2190
2290
|
id: "boost/with-skills",
|
|
2191
2291
|
name: "LearnCard Boost with Skills",
|
|
@@ -2196,7 +2296,7 @@ var boostWithSkills = {
|
|
|
2196
2296
|
source: "synthetic",
|
|
2197
2297
|
signed: false,
|
|
2198
2298
|
validity: "valid",
|
|
2199
|
-
validator:
|
|
2299
|
+
validator: import_types18.UnsignedAchievementCredentialValidator,
|
|
2200
2300
|
tags: ["learncard", "boost", "skills"],
|
|
2201
2301
|
credential: {
|
|
2202
2302
|
"@context": [
|
|
@@ -2406,7 +2506,7 @@ var boostDelegate = {
|
|
|
2406
2506
|
};
|
|
2407
2507
|
|
|
2408
2508
|
// src/fixtures/invalid/missing-context.ts
|
|
2409
|
-
var
|
|
2509
|
+
var import_types19 = require("@learncard/types");
|
|
2410
2510
|
var invalidMissingContext = {
|
|
2411
2511
|
id: "invalid/missing-context",
|
|
2412
2512
|
name: "Missing @context",
|
|
@@ -2417,7 +2517,7 @@ var invalidMissingContext = {
|
|
|
2417
2517
|
source: "synthetic",
|
|
2418
2518
|
signed: false,
|
|
2419
2519
|
validity: "invalid",
|
|
2420
|
-
validator:
|
|
2520
|
+
validator: import_types19.UnsignedVCValidator,
|
|
2421
2521
|
tags: ["negative-test"],
|
|
2422
2522
|
credential: {
|
|
2423
2523
|
// Intentionally missing '@context'
|
|
@@ -2430,7 +2530,7 @@ var invalidMissingContext = {
|
|
|
2430
2530
|
};
|
|
2431
2531
|
|
|
2432
2532
|
// src/fixtures/invalid/empty-type.ts
|
|
2433
|
-
var
|
|
2533
|
+
var import_types20 = require("@learncard/types");
|
|
2434
2534
|
var invalidEmptyType = {
|
|
2435
2535
|
id: "invalid/empty-type",
|
|
2436
2536
|
name: "Empty type Array",
|
|
@@ -2441,7 +2541,7 @@ var invalidEmptyType = {
|
|
|
2441
2541
|
source: "synthetic",
|
|
2442
2542
|
signed: false,
|
|
2443
2543
|
validity: "invalid",
|
|
2444
|
-
validator:
|
|
2544
|
+
validator: import_types20.UnsignedVCValidator,
|
|
2445
2545
|
tags: ["negative-test"],
|
|
2446
2546
|
credential: {
|
|
2447
2547
|
"@context": ["https://www.w3.org/ns/credentials/v2"],
|
|
@@ -2454,7 +2554,7 @@ var invalidEmptyType = {
|
|
|
2454
2554
|
};
|
|
2455
2555
|
|
|
2456
2556
|
// src/fixtures/invalid/missing-issuer.ts
|
|
2457
|
-
var
|
|
2557
|
+
var import_types21 = require("@learncard/types");
|
|
2458
2558
|
var invalidMissingIssuer = {
|
|
2459
2559
|
id: "invalid/missing-issuer",
|
|
2460
2560
|
name: "Missing Issuer",
|
|
@@ -2465,7 +2565,7 @@ var invalidMissingIssuer = {
|
|
|
2465
2565
|
source: "synthetic",
|
|
2466
2566
|
signed: false,
|
|
2467
2567
|
validity: "invalid",
|
|
2468
|
-
validator:
|
|
2568
|
+
validator: import_types21.UnsignedVCValidator,
|
|
2469
2569
|
tags: ["negative-test"],
|
|
2470
2570
|
credential: {
|
|
2471
2571
|
"@context": ["https://www.w3.org/ns/credentials/v2"],
|
|
@@ -14330,8 +14430,9 @@ var clrCompetencyAligned = {
|
|
|
14330
14430
|
};
|
|
14331
14431
|
|
|
14332
14432
|
// src/fixtures/clr/provisional-transcript.ts
|
|
14333
|
-
var
|
|
14433
|
+
var import_types22 = require("@learncard/types");
|
|
14334
14434
|
var REFRESH_SERVICE_INLINE_CONTEXT = {
|
|
14435
|
+
partial: "https://purl.imsglobal.org/spec/clr/v2p0#partial",
|
|
14335
14436
|
"LearnCardCredentialRefresh2026": "https://learncard.com/refresh#LearnCardCredentialRefresh2026",
|
|
14336
14437
|
authorization: {
|
|
14337
14438
|
"@id": "https://purl.imsglobal.org/spec/ob/v3p0#authorization",
|
|
@@ -14355,7 +14456,7 @@ var clrProvisionalTranscript = {
|
|
|
14355
14456
|
source: "synthetic",
|
|
14356
14457
|
signed: false,
|
|
14357
14458
|
validity: "valid",
|
|
14358
|
-
validator:
|
|
14459
|
+
validator: import_types22.UnsignedClrCredentialValidator,
|
|
14359
14460
|
tags: ["transcript", "provisional", "refresh", "clr", "managed-refresh"],
|
|
14360
14461
|
credential: {
|
|
14361
14462
|
"@context": [
|
|
@@ -14374,6 +14475,8 @@ var clrProvisionalTranscript = {
|
|
|
14374
14475
|
name: "Ridgeview Community College \u2014 Office of the Registrar"
|
|
14375
14476
|
},
|
|
14376
14477
|
validFrom: "2026-01-15T00:00:00Z",
|
|
14478
|
+
validUntil: "2026-05-31T00:00:00Z",
|
|
14479
|
+
partial: true,
|
|
14377
14480
|
refreshService: PLACEHOLDER_REFRESH_SERVICE,
|
|
14378
14481
|
credentialSubject: {
|
|
14379
14482
|
id: "did:example:student-ridgeview-042",
|
|
@@ -14394,7 +14497,8 @@ var clrProvisionalTranscript = {
|
|
|
14394
14497
|
id: "urn:uuid:7d2e9f41-3c58-4e21-9b6a-1f0c5d8e2a49",
|
|
14395
14498
|
type: ["ResultDescription"],
|
|
14396
14499
|
name: "Course Status",
|
|
14397
|
-
resultType: "
|
|
14500
|
+
resultType: "Status",
|
|
14501
|
+
allowedValue: ["InProgress", "Provisional", "Completed"]
|
|
14398
14502
|
}
|
|
14399
14503
|
]
|
|
14400
14504
|
}
|
|
@@ -14448,6 +14552,8 @@ var buildFinalTranscriptVariant = /* @__PURE__ */ __name((provisional, options =
|
|
|
14448
14552
|
final.name = "Final Official Transcript \u2014 Ridgeview Community College";
|
|
14449
14553
|
final.description = "Final official transcript certified by the registrar. Supersedes the provisional record.";
|
|
14450
14554
|
if (options.validFrom) final.validFrom = options.validFrom;
|
|
14555
|
+
delete final.validUntil;
|
|
14556
|
+
delete final.partial;
|
|
14451
14557
|
const subject = final.credentialSubject;
|
|
14452
14558
|
if (isRecord(subject) && Array.isArray(subject.verifiableCredential)) {
|
|
14453
14559
|
subject.verifiableCredential = subject.verifiableCredential.map((nested) => {
|
|
@@ -14460,7 +14566,7 @@ var buildFinalTranscriptVariant = /* @__PURE__ */ __name((provisional, options =
|
|
|
14460
14566
|
next.credentialSubject = {
|
|
14461
14567
|
...next.credentialSubject,
|
|
14462
14568
|
result: next.credentialSubject.result.map(
|
|
14463
|
-
(result) => isRecord(result) ? { ...result, status: "Completed", value: "
|
|
14569
|
+
(result) => isRecord(result) ? { ...result, status: "Completed", value: "Completed" } : result
|
|
14464
14570
|
)
|
|
14465
14571
|
};
|
|
14466
14572
|
}
|
|
@@ -23024,6 +23130,7 @@ var ALL_FIXTURES = [
|
|
|
23024
23130
|
obv3StandaloneFullCourse,
|
|
23025
23131
|
obv3K12Diploma,
|
|
23026
23132
|
obv3EndorsementCredential,
|
|
23133
|
+
obv3RubricAlignedBadge,
|
|
23027
23134
|
// CLR v2
|
|
23028
23135
|
clrMinimal,
|
|
23029
23136
|
clrMultiAchievement,
|
|
@@ -23274,6 +23381,7 @@ var patchSubject = /* @__PURE__ */ __name((subject, subjectDid) => {
|
|
|
23274
23381
|
}
|
|
23275
23382
|
return subject;
|
|
23276
23383
|
}, "patchSubject");
|
|
23384
|
+
var FIXTURE_VALIDITY_MS = 180 * 24 * 60 * 60 * 1e3;
|
|
23277
23385
|
var prepareFixture = /* @__PURE__ */ __name((fixture, options) => {
|
|
23278
23386
|
if (isSdJwtVcFixture(fixture)) {
|
|
23279
23387
|
throw new Error(
|
|
@@ -23310,6 +23418,17 @@ var prepareFixture = /* @__PURE__ */ __name((fixture, options) => {
|
|
|
23310
23418
|
} else {
|
|
23311
23419
|
credential.validUntil = validUntil;
|
|
23312
23420
|
}
|
|
23421
|
+
} else {
|
|
23422
|
+
const from = new Date(
|
|
23423
|
+
credential.validFrom ?? credential.issuanceDate
|
|
23424
|
+
).getTime();
|
|
23425
|
+
const baseline = Math.max(from, Date.now());
|
|
23426
|
+
for (const field of ["validUntil", "expirationDate"]) {
|
|
23427
|
+
const expiry = credential[field];
|
|
23428
|
+
if (typeof expiry === "string" && new Date(expiry).getTime() <= baseline) {
|
|
23429
|
+
credential[field] = new Date(baseline + FIXTURE_VALIDITY_MS).toISOString();
|
|
23430
|
+
}
|
|
23431
|
+
}
|
|
23313
23432
|
}
|
|
23314
23433
|
return credential;
|
|
23315
23434
|
}, "prepareFixture");
|