@learncard/credential-library 2.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +30 -1
  2. package/SOURCES.md +63 -0
  3. package/dist/bundles/index.d.ts +5 -0
  4. package/dist/bundles/index.d.ts.map +1 -0
  5. package/dist/bundles/student.d.ts +3 -0
  6. package/dist/bundles/student.d.ts.map +1 -0
  7. package/dist/bundles/types.d.ts +24 -0
  8. package/dist/bundles/types.d.ts.map +1 -0
  9. package/dist/credential-library.cjs.development.js +12244 -713
  10. package/dist/credential-library.cjs.development.js.map +4 -4
  11. package/dist/credential-library.cjs.production.min.js +11 -1
  12. package/dist/credential-library.cjs.production.min.js.map +4 -4
  13. package/dist/credential-library.esm.js +12242 -709
  14. package/dist/credential-library.esm.js.map +4 -4
  15. package/dist/fixtures/clr/achievement-id-associations.d.ts +3 -0
  16. package/dist/fixtures/clr/achievement-id-associations.d.ts.map +1 -0
  17. package/dist/fixtures/clr/employment-record.d.ts +8 -0
  18. package/dist/fixtures/clr/employment-record.d.ts.map +1 -0
  19. package/dist/fixtures/clr/licensing-regulatory-record.d.ts +8 -0
  20. package/dist/fixtures/clr/licensing-regulatory-record.d.ts.map +1 -0
  21. package/dist/fixtures/clr/military-training-record.d.ts +8 -0
  22. package/dist/fixtures/clr/military-training-record.d.ts.map +1 -0
  23. package/dist/fixtures/clr/mixed-career-record.d.ts +8 -0
  24. package/dist/fixtures/clr/mixed-career-record.d.ts.map +1 -0
  25. package/dist/fixtures/clr/mixed-role-portfolio.d.ts +3 -0
  26. package/dist/fixtures/clr/mixed-role-portfolio.d.ts.map +1 -0
  27. package/dist/fixtures/clr/professional-organization-record.d.ts +8 -0
  28. package/dist/fixtures/clr/professional-organization-record.d.ts.map +1 -0
  29. package/dist/fixtures/clr/student-official-academic-transcript.d.ts +3 -0
  30. package/dist/fixtures/clr/student-official-academic-transcript.d.ts.map +1 -0
  31. package/dist/fixtures/clr/training-provider-record.d.ts +8 -0
  32. package/dist/fixtures/clr/training-provider-record.d.ts.map +1 -0
  33. package/dist/fixtures/custom/course-enrollment.d.ts +3 -0
  34. package/dist/fixtures/custom/course-enrollment.d.ts.map +1 -0
  35. package/dist/fixtures/custom/exam-accommodation.d.ts +3 -0
  36. package/dist/fixtures/custom/exam-accommodation.d.ts.map +1 -0
  37. package/dist/fixtures/index.d.ts +25 -1
  38. package/dist/fixtures/index.d.ts.map +1 -1
  39. package/dist/fixtures/obv3/food-allergen-facilitator.d.ts +3 -0
  40. package/dist/fixtures/obv3/food-allergen-facilitator.d.ts.map +1 -0
  41. package/dist/fixtures/obv3/food-allergen-practice-fr.d.ts +3 -0
  42. package/dist/fixtures/obv3/food-allergen-practice-fr.d.ts.map +1 -0
  43. package/dist/fixtures/obv3/food-allergen-practice.d.ts +3 -0
  44. package/dist/fixtures/obv3/food-allergen-practice.d.ts.map +1 -0
  45. package/dist/fixtures/obv3/phishing-transfer.d.ts +3 -0
  46. package/dist/fixtures/obv3/phishing-transfer.d.ts.map +1 -0
  47. package/dist/fixtures/obv3/qualification-apprenticeship.d.ts +3 -0
  48. package/dist/fixtures/obv3/qualification-apprenticeship.d.ts.map +1 -0
  49. package/dist/fixtures/obv3/qualification-badge-override.d.ts +3 -0
  50. package/dist/fixtures/obv3/qualification-badge-override.d.ts.map +1 -0
  51. package/dist/fixtures/obv3/qualification-certification.d.ts +3 -0
  52. package/dist/fixtures/obv3/qualification-certification.d.ts.map +1 -0
  53. package/dist/fixtures/obv3/qualification-expired.d.ts +3 -0
  54. package/dist/fixtures/obv3/qualification-expired.d.ts.map +1 -0
  55. package/dist/fixtures/obv3/qualification-journeyman.d.ts +3 -0
  56. package/dist/fixtures/obv3/qualification-journeyman.d.ts.map +1 -0
  57. package/dist/fixtures/obv3/qualification-license.d.ts +3 -0
  58. package/dist/fixtures/obv3/qualification-license.d.ts.map +1 -0
  59. package/dist/fixtures/obv3/qualification-master.d.ts +3 -0
  60. package/dist/fixtures/obv3/qualification-master.d.ts.map +1 -0
  61. package/dist/fixtures/obv3/student-additional-credentials.d.ts +3 -0
  62. package/dist/fixtures/obv3/student-additional-credentials.d.ts.map +1 -0
  63. package/dist/fixtures/obv3/student-sample-badges.d.ts +586 -0
  64. package/dist/fixtures/obv3/student-sample-badges.d.ts.map +1 -0
  65. package/dist/index.d.ts +1 -0
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/prepare.d.ts.map +1 -1
  68. package/package.json +8 -7
  69. package/src/__tests__/bundles.test.ts +234 -0
  70. package/src/__tests__/clr-non-academic.test.ts +220 -0
  71. package/src/__tests__/curated-examples.test.ts +248 -0
  72. package/src/__tests__/issuance.test.ts +35 -0
  73. package/src/__tests__/registry.test.ts +31 -0
  74. package/src/bundles/index.ts +19 -0
  75. package/src/bundles/student.ts +251 -0
  76. package/src/bundles/types.ts +25 -0
  77. package/src/fixtures/clr/README.md +142 -0
  78. package/src/fixtures/clr/achievement-id-associations.ts +342 -0
  79. package/src/fixtures/clr/employment-record.ts +487 -0
  80. package/src/fixtures/clr/licensing-regulatory-record.ts +388 -0
  81. package/src/fixtures/clr/military-training-record.ts +468 -0
  82. package/src/fixtures/clr/mixed-career-record.ts +814 -0
  83. package/src/fixtures/clr/mixed-role-portfolio.ts +490 -0
  84. package/src/fixtures/clr/professional-organization-record.ts +403 -0
  85. package/src/fixtures/clr/student-official-academic-transcript.ts +3202 -0
  86. package/src/fixtures/clr/training-provider-record.ts +510 -0
  87. package/src/fixtures/custom/course-enrollment.ts +56 -0
  88. package/src/fixtures/custom/exam-accommodation.ts +56 -0
  89. package/src/fixtures/index.ts +87 -0
  90. package/src/fixtures/obv3/food-allergen-facilitator.ts +108 -0
  91. package/src/fixtures/obv3/food-allergen-practice-fr.ts +107 -0
  92. package/src/fixtures/obv3/food-allergen-practice.ts +105 -0
  93. package/src/fixtures/obv3/phishing-transfer.ts +163 -0
  94. package/src/fixtures/obv3/qualification-apprenticeship.ts +58 -0
  95. package/src/fixtures/obv3/qualification-badge-override.ts +64 -0
  96. package/src/fixtures/obv3/qualification-certification.ts +59 -0
  97. package/src/fixtures/obv3/qualification-expired.ts +59 -0
  98. package/src/fixtures/obv3/qualification-journeyman.ts +58 -0
  99. package/src/fixtures/obv3/qualification-license.ts +58 -0
  100. package/src/fixtures/obv3/qualification-master.ts +58 -0
  101. package/src/fixtures/obv3/student-additional-credentials.ts +3912 -0
  102. package/src/fixtures/obv3/student-sample-badges.ts +424 -0
  103. package/src/index.ts +2 -0
  104. package/src/prepare.ts +55 -11
  105. package/dist/__tests__/docs-json.test.d.ts +0 -2
  106. package/dist/__tests__/docs-json.test.d.ts.map +0 -1
  107. package/dist/__tests__/issuance.test.d.ts +0 -2
  108. package/dist/__tests__/issuance.test.d.ts.map +0 -1
  109. package/dist/__tests__/registry.test.d.ts +0 -2
  110. package/dist/__tests__/registry.test.d.ts.map +0 -1
  111. package/dist/__tests__/sd-jwt-vc.test.d.ts +0 -2
  112. package/dist/__tests__/sd-jwt-vc.test.d.ts.map +0 -1
@@ -0,0 +1,424 @@
1
+ import {
2
+ UnsignedAchievementCredentialValidator,
3
+ type Achievement,
4
+ type Evidence,
5
+ } from '@learncard/types';
6
+
7
+ import type { CredentialFixture } from '../../types';
8
+
9
+ type StudentSampleBadgeOptions = {
10
+ fixtureId: string;
11
+ fixtureName: string;
12
+ fixtureDescription: string;
13
+ issuerDid: string;
14
+ validFrom: string;
15
+ achievement: Achievement;
16
+ evidence?: Evidence[];
17
+ };
18
+
19
+ const createStudentSampleBadge = ({
20
+ fixtureId,
21
+ fixtureName,
22
+ fixtureDescription,
23
+ issuerDid,
24
+ validFrom,
25
+ achievement,
26
+ evidence,
27
+ }: StudentSampleBadgeOptions): CredentialFixture => ({
28
+ id: fixtureId,
29
+ name: fixtureName,
30
+ description: fixtureDescription,
31
+ spec: 'obv3',
32
+ profile: 'badge',
33
+ features: ['alignment', 'image', ...(evidence ? (['evidence'] as const) : [])],
34
+ source: 'real-world',
35
+ signed: false,
36
+ validity: 'valid',
37
+ validator: UnsignedAchievementCredentialValidator,
38
+ tags: ['student-persona'],
39
+ credential: {
40
+ '@context': [
41
+ 'https://www.w3.org/ns/credentials/v2',
42
+ 'https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json',
43
+ ],
44
+ type: ['VerifiableCredential', 'OpenBadgeCredential'],
45
+ issuer: { id: issuerDid },
46
+ credentialSubject: {
47
+ id: 'did:example:student',
48
+ achievement,
49
+ type: ['AchievementSubject'],
50
+ },
51
+ name: achievement.name,
52
+ validFrom,
53
+ ...(evidence ? { evidence } : {}),
54
+ },
55
+ });
56
+
57
+ export const obv3StudentAfterschoolProgramMentor = createStudentSampleBadge({
58
+ fixtureId: 'obv3/student-afterschool-program-mentor',
59
+ fixtureName: 'Student Persona — Afterschool Program Mentor',
60
+ fixtureDescription:
61
+ 'A LearnCard social badge recognizing volunteer mentorship in a local afterschool program.',
62
+ issuerDid: 'did:web:network.learncard.com:users:hillvalleyhigh',
63
+ validFrom: '2026-07-06T03:02:55.786Z',
64
+ achievement: {
65
+ achievementType: 'CommunityService',
66
+ tag: ['lc:category:Social Badge', 'lc:subtype:Community Champ', 'lc:displayType:award'],
67
+ alignment: [
68
+ {
69
+ targetCode: '6.6',
70
+ targetDescription:
71
+ 'The ability to consistently act in accordance with a set of values and principles, and be honest and transparent with others.',
72
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
73
+ targetName: 'Personal Integrity',
74
+ targetUrl:
75
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-2dq4yrivs',
76
+ type: ['Alignment'],
77
+ },
78
+ {
79
+ targetCode: '5.1',
80
+ targetDescription:
81
+ 'The ability to understand priorities and apply them to the organization of time, people, and resources to achieve a common goal.',
82
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
83
+ targetName: 'Interpersonal Relationships',
84
+ targetUrl:
85
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-487j1k9l1',
86
+ type: ['Alignment'],
87
+ },
88
+ {
89
+ targetCode: '5.3',
90
+ targetDescription:
91
+ 'The ability to manage time and resource constraints in order to plan for the completion of tasks in a way that maximizes the efficiency of the plan and does not create a burden for those involved in the scheduled events.',
92
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
93
+ targetName: 'Teamwork/Team-Oriented',
94
+ targetUrl:
95
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-bsc9c7cle',
96
+ type: ['Alignment'],
97
+ },
98
+ {
99
+ targetCode: '6.3',
100
+ targetDescription:
101
+ 'The ability to demonstrate honesty, reliability, and ethical behavior during interactions, and consistently follow through on commitments and promises made to others.',
102
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
103
+ targetName: 'Trustworthy',
104
+ targetUrl:
105
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-rcjmkv2qj',
106
+ type: ['Alignment'],
107
+ },
108
+ {
109
+ targetCode: '',
110
+ targetDescription:
111
+ 'The ability to manage time and resource\nconstraints in order to plan for the\ncompletion of tasks in a way that maximizes the efficiency of the plan and does not create a burden for those involved in the scheduled events.',
112
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
113
+ targetName: 'Scheduling',
114
+ targetUrl:
115
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1775837398456-odop6377i',
116
+ type: ['Alignment'],
117
+ },
118
+ ],
119
+ criteria: {
120
+ narrative:
121
+ 'Earn this badge by dedicating your time and energy to support and uplift the youth in an afterschool program, showing your commitment to community service and positive influence.',
122
+ },
123
+ description:
124
+ 'Awarded for dedicated volunteer service in a local afterschool program, demonstrating commitment and positive impact on young minds.',
125
+ id: 'urn:uuid:98c0a926-aa97-4009-a42f-970666931fcb',
126
+ image: 'https://cdn.filestackcontent.com/7hs6fs2Qgurpw2wSjuDx',
127
+ name: 'Afterschool Program Mentor',
128
+ type: ['Achievement'],
129
+ },
130
+ });
131
+
132
+ export const obv3StudentEnvironmentBadge = createStudentSampleBadge({
133
+ fixtureId: 'obv3/student-environment-badge',
134
+ fixtureName: 'Student Persona — Environment Badge',
135
+ fixtureDescription:
136
+ 'A LearnCard badge recognizing completion of the World Scout Environment training course.',
137
+ issuerDid: 'did:web:network.learncard.com:users:scouting2',
138
+ validFrom: '2026-07-06T02:58:48.995Z',
139
+ achievement: {
140
+ achievementType: 'Badge',
141
+ tag: [
142
+ 'lc:category:Social Badge',
143
+ 'lc:subtype:Challenge Maker',
144
+ 'lc:displayType:award',
145
+ 'lc:bgImage:https://cdn.filestackcontent.com/5ZNtFOOZRUeDlYrFBP0f',
146
+ ],
147
+ alignment: [
148
+ {
149
+ targetCode: '6.6',
150
+ targetDescription:
151
+ 'The ability to consistently act in accordance with a set of values and principles, and be honest and transparent with others.',
152
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
153
+ targetName: 'Personal Integrity',
154
+ targetUrl:
155
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-2dq4yrivs',
156
+ type: ['Alignment'],
157
+ },
158
+ {
159
+ targetCode: '8.3',
160
+ targetDescription:
161
+ 'The ability to be eager and open to learning new things, seeking out new information, and asking questions to better understand and solve problems.',
162
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
163
+ targetName: 'Curiosity',
164
+ targetUrl:
165
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-kegwjzu5x',
166
+ type: ['Alignment'],
167
+ },
168
+ {
169
+ targetCode: '2.2',
170
+ targetDescription:
171
+ 'The ability to motivate and guide a group of people toward achieving a common goal or objective.',
172
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
173
+ targetName: 'Leadership',
174
+ targetUrl:
175
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-purc6ulo5',
176
+ type: ['Alignment'],
177
+ },
178
+ {
179
+ targetCode: '7.3',
180
+ targetDescription:
181
+ 'The ability to think beyond the present, and envision and plan for a future state.',
182
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
183
+ targetName: 'Visionary',
184
+ targetUrl:
185
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-waljh6t43',
186
+ type: ['Alignment'],
187
+ },
188
+ ],
189
+ criteria: {
190
+ narrative:
191
+ 'To earn this boost, you need to successfully complete all modules and activities of the World Scout Environment training course, demonstrating a commitment to environmental awareness and stewardship.',
192
+ },
193
+ description: 'Awarded for completing the World Scout Environment Badge training course.',
194
+ id: 'urn:uuid:31b76aa3-8e03-4e41-b58e-5a080584ba60',
195
+ image: 'https://cdn.filestackcontent.com/WjDskz3RZ20cbHoxNKZT',
196
+ name: 'Environment Badge',
197
+ type: ['Achievement'],
198
+ },
199
+ });
200
+
201
+ export const obv3StudentRockClimbingMentor = createStudentSampleBadge({
202
+ fixtureId: 'obv3/student-rock-climbing-mentor',
203
+ fixtureName: 'Student Persona — Rock Climbing Mentor',
204
+ fixtureDescription: 'A LearnCard badge recognizing beginner rock-climbing mentorship.',
205
+ issuerDid: 'did:web:network.learncard.com:users:roycharles2',
206
+ validFrom: '2026-07-06T03:06:03.724Z',
207
+ evidence: [
208
+ {
209
+ id: 'https://cdn.filestackcontent.com/OJBHRYPKS2qY0L94E0uc',
210
+ type: ['Evidence'],
211
+ name: 'Olivia & friends climbing in California',
212
+ description: 'rock climb pic.png · PNG · 1813.1 kB',
213
+ genre: 'photo',
214
+ },
215
+ ],
216
+ achievement: {
217
+ achievementType: 'CommunityService',
218
+ tag: [
219
+ 'lc:category:Social Badge',
220
+ 'lc:subtype:Expert',
221
+ 'lc:displayType:award',
222
+ 'lc:bgImage:https://cdn.filestackcontent.com/PTeHv2CTQmKWboDbWBso',
223
+ ],
224
+ alignment: [
225
+ {
226
+ targetCode: '6.2',
227
+ targetDescription:
228
+ 'The ability to stay driven, focused, and committed to achieving goals and delivering results without the need for constant direction and supervision.',
229
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
230
+ targetName: 'Self-Motivation',
231
+ targetUrl:
232
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-11fyf81e8',
233
+ type: ['Alignment'],
234
+ },
235
+ {
236
+ targetCode: '3.6',
237
+ targetDescription:
238
+ 'The ability to be flexible to changing circumstances and understand the impact of changes to task timelines in order to adjust plans efficiently',
239
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
240
+ targetName: 'Adaptability',
241
+ targetUrl:
242
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-7nubyoxde',
243
+ type: ['Alignment'],
244
+ },
245
+ {
246
+ targetCode: '8.1',
247
+ targetDescription:
248
+ 'The ability to work independently and take initiative to complete tasks without external direction or motivation.',
249
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
250
+ targetName: 'Self-Starter',
251
+ targetUrl:
252
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-86nd9j00d',
253
+ type: ['Alignment'],
254
+ },
255
+ {
256
+ targetCode: '9.4',
257
+ targetDescription:
258
+ 'The ability to understand and share the feelings, perspectives, and experiences of others.',
259
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
260
+ targetName: 'Patience',
261
+ targetUrl:
262
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-frahf8h7k',
263
+ type: ['Alignment'],
264
+ },
265
+ {
266
+ targetCode: '10.1',
267
+ targetDescription:
268
+ 'The ability to respond in the face of adversity in order to successfully recover from unexpected situations and resume or revise a plan to achieve the desired outcome of the original task.',
269
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
270
+ targetName: 'Resilience',
271
+ targetUrl:
272
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-gshg45jlj',
273
+ type: ['Alignment'],
274
+ },
275
+ {
276
+ targetCode: '3.7',
277
+ targetDescription:
278
+ 'The ability to establish clear and achievable objectives and to develop a plan to achieve them.',
279
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
280
+ targetName: 'Goal Setting',
281
+ targetUrl:
282
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-tkv7qhywf',
283
+ type: ['Alignment'],
284
+ },
285
+ {
286
+ targetCode: '10.6',
287
+ targetDescription:
288
+ "The ability to regulate one's actions and emotions in order to stay committed to achieving a goal and keep oneself accountable for their responsibilities",
289
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
290
+ targetName: 'Self-Discipline',
291
+ targetUrl:
292
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-w4yyfkxzt',
293
+ type: ['Alignment'],
294
+ },
295
+ {
296
+ targetCode: '10.4',
297
+ targetDescription:
298
+ 'The ability to stay focused on the process and have unwavering determination when completing a task. The ability to exhibit passion and persistence in the face of adversity',
299
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
300
+ targetName: 'Tenacity',
301
+ targetUrl:
302
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-wq45d7y7r',
303
+ type: ['Alignment'],
304
+ },
305
+ {
306
+ targetCode: '10.7',
307
+ targetDescription:
308
+ 'The ability to stay composed and level-headed when faced with challenging or high-pressure situations.',
309
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
310
+ targetName: 'Calmness Under Pressure',
311
+ targetUrl:
312
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-xniik052a',
313
+ type: ['Alignment'],
314
+ },
315
+ {
316
+ targetCode: '10.8',
317
+ targetDescription:
318
+ "The ability to trust one's abilities and present information with poise. The ability to have realistic confidence in one's judgment while knowing when to ask for assistance.",
319
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
320
+ targetName: 'Self-Confident',
321
+ targetUrl:
322
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-zjgotktn9',
323
+ type: ['Alignment'],
324
+ },
325
+ ],
326
+ criteria: {
327
+ narrative:
328
+ 'You earn this boost by dedicating your time and effort to teach someone the fundamental skills of rock climbing, helping them build confidence and competence on the rock wall.',
329
+ },
330
+ description: 'Awarded for teaching the basics of rock climbing to a beginner.',
331
+ id: 'urn:uuid:758dc921-2350-4861-b346-713f9c99cc92',
332
+ image: 'https://cdn.filestackcontent.com/XqtIkkd3QMqR4ZvyUoWp',
333
+ name: 'Rock Climbing Mentor',
334
+ type: ['Achievement'],
335
+ },
336
+ });
337
+
338
+ export const obv3StudentParkCleanupHelper = createStudentSampleBadge({
339
+ fixtureId: 'obv3/student-park-cleanup-helper',
340
+ fixtureName: 'Student Persona — Park Cleanup Helper',
341
+ fixtureDescription: 'A LearnCard social badge recognizing volunteer park cleanup work.',
342
+ issuerDid: 'did:web:network.learncard.com:users:roycharles2',
343
+ validFrom: '2026-07-06T02:55:59.957Z',
344
+ evidence: [
345
+ {
346
+ id: 'https://cdn.filestackcontent.com/Me0izbIMQNOkv28irNi5',
347
+ type: ['Evidence'],
348
+ name: 'park cleanup helper.webp',
349
+ description: 'park cleanup helper.webp · WEBP · 561.1 kB',
350
+ genre: 'photo',
351
+ },
352
+ ],
353
+ achievement: {
354
+ achievementType: 'CommunityService',
355
+ tag: [
356
+ 'lc:category:Social Badge',
357
+ 'lc:subtype:Park Cleanup Helper',
358
+ 'lc:displayType:award',
359
+ 'lc:bgImage:https://cdn.filestackcontent.com/Ve3UzPtlQOSlRinFlRDI',
360
+ ],
361
+ alignment: [
362
+ {
363
+ targetCode: '5.4',
364
+ targetDescription:
365
+ "The ability to effectively organize a team through actions that contribute to the team's cohesiveness by enhancing relationships, celebrating strengths, acknowledging weaknesses, and actively participating in team experiences and events.",
366
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
367
+ targetName: 'Team-Building',
368
+ targetUrl:
369
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-0vm22kkgh',
370
+ type: ['Alignment'],
371
+ },
372
+ {
373
+ targetCode: '8.1',
374
+ targetDescription:
375
+ 'The ability to work independently and take initiative to complete tasks without external direction or motivation.',
376
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
377
+ targetName: 'Self-Starter',
378
+ targetUrl:
379
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-86nd9j00d',
380
+ type: ['Alignment'],
381
+ },
382
+ {
383
+ targetCode: '5.3',
384
+ targetDescription:
385
+ 'The ability to manage time and resource constraints in order to plan for the completion of tasks in a way that maximizes the efficiency of the plan and does not create a burden for those involved in the scheduled events.',
386
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
387
+ targetName: 'Teamwork/Team-Oriented',
388
+ targetUrl:
389
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-bsc9c7cle',
390
+ type: ['Alignment'],
391
+ },
392
+ {
393
+ targetCode: '5.5',
394
+ targetDescription:
395
+ "The ability to prioritize the common goal of a group over one's personal goals for the benefit of the larger group and be flexible to complete a task being asked of you.",
396
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
397
+ targetName: 'Cooperation',
398
+ targetUrl:
399
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-d89eknulo',
400
+ type: ['Alignment'],
401
+ },
402
+ {
403
+ targetCode: '8.6',
404
+ targetDescription:
405
+ 'The ability to take initiative, set goals, and actively work towards achieving them.',
406
+ targetFramework: 'Pathsmith™ Durable Skills Starter Edition',
407
+ targetName: 'Action-Oriented',
408
+ targetUrl:
409
+ 'https://network.learncard.com/frameworks/fw-1772824300325/skills/skill-1772824804950-fxm6dc0lp',
410
+ type: ['Alignment'],
411
+ },
412
+ ],
413
+ criteria: {
414
+ narrative:
415
+ 'Earn this boost by volunteering in local park cleanup activities, dedicating your time and effort to making our community spaces cleaner and more enjoyable for everyone.',
416
+ },
417
+ description:
418
+ 'Awarded to individuals who contribute to community cleanliness by helping with local park garbage cleanup events.',
419
+ id: 'urn:uuid:241abe36-4bc8-4ab3-86a1-10ad4ed6f866',
420
+ image: 'https://cdn.filestackcontent.com/HhXLRqTTQQGdng7OWcxO',
421
+ name: 'Park Cleanup Helper',
422
+ type: ['Achievement'],
423
+ },
424
+ });
package/src/index.ts CHANGED
@@ -57,6 +57,8 @@ export type {
57
57
  MaterializeSdJwtVcOptions,
58
58
  MaterializedSdJwtVcFixture,
59
59
  } from './materialize-sd-jwt-vc';
60
+ // Persona bundles
61
+ export * from './bundles';
60
62
 
61
63
  // Fixtures — importing this module registers all fixtures in the registry
62
64
  export * from './fixtures';
package/src/prepare.ts CHANGED
@@ -41,8 +41,11 @@ const generateUuid = (): string => {
41
41
 
42
42
  const patchIds = (
43
43
  obj: Record<string, unknown>,
44
- idMap: Map<string, string>
44
+ idMap: Map<string, string>,
45
+ preserveSignedCredential = false
45
46
  ): Record<string, unknown> => {
47
+ if (preserveSignedCredential && obj.proof !== undefined) return obj;
48
+
46
49
  const result: Record<string, unknown> = {};
47
50
 
48
51
  for (const [key, value] of Object.entries(obj)) {
@@ -57,11 +60,11 @@ const patchIds = (
57
60
  } else if (Array.isArray(value)) {
58
61
  result[key] = value.map(item =>
59
62
  item && typeof item === 'object' && !Array.isArray(item)
60
- ? patchIds(item as Record<string, unknown>, idMap)
63
+ ? patchIds(item as Record<string, unknown>, idMap, true)
61
64
  : item
62
65
  );
63
66
  } else if (value && typeof value === 'object' && !Array.isArray(value)) {
64
- result[key] = patchIds(value as Record<string, unknown>, idMap);
67
+ result[key] = patchIds(value as Record<string, unknown>, idMap, true);
65
68
  } else {
66
69
  result[key] = value;
67
70
  }
@@ -70,21 +73,28 @@ const patchIds = (
70
73
  return result;
71
74
  };
72
75
 
73
- const remapUuidReferences = (value: unknown, idMap: Map<string, string>): unknown => {
76
+ const remapUuidReferences = (
77
+ value: unknown,
78
+ idMap: Map<string, string>,
79
+ preserveSignedCredential = false
80
+ ): unknown => {
74
81
  if (typeof value === 'string') {
75
82
  // Rewrite explicit references that still point at the original ids.
76
83
  return idMap.get(value) ?? value;
77
84
  }
78
85
 
79
86
  if (Array.isArray(value)) {
80
- return value.map(item => remapUuidReferences(item, idMap));
87
+ return value.map(item => remapUuidReferences(item, idMap, true));
81
88
  }
82
89
 
83
90
  if (value && typeof value === 'object') {
91
+ const record = value as Record<string, unknown>;
92
+ if (preserveSignedCredential && record.proof !== undefined) return record;
93
+
84
94
  return Object.fromEntries(
85
- Object.entries(value as Record<string, unknown>).map(([key, nestedValue]) => [
95
+ Object.entries(record).map(([key, nestedValue]) => [
86
96
  key,
87
- remapUuidReferences(nestedValue, idMap),
97
+ remapUuidReferences(nestedValue, idMap, true),
88
98
  ])
89
99
  );
90
100
  }
@@ -104,16 +114,50 @@ const patchIssuer = (issuer: unknown, issuerDid: string): string | Record<string
104
114
  return issuerDid;
105
115
  };
106
116
 
117
+ const patchCredentialSubject = (credential: unknown, subjectDid: string): unknown => {
118
+ if (!credential || typeof credential !== 'object' || Array.isArray(credential)) {
119
+ return credential;
120
+ }
121
+
122
+ const patchedCredential = { ...(credential as Record<string, unknown>) };
123
+
124
+ if (patchedCredential.proof !== undefined) return patchedCredential;
125
+
126
+ if (patchedCredential.credentialSubject) {
127
+ patchedCredential.credentialSubject = patchSubject(
128
+ patchedCredential.credentialSubject,
129
+ subjectDid
130
+ );
131
+ }
132
+
133
+ return patchedCredential;
134
+ };
135
+
107
136
  const patchSubject = (subject: unknown, subjectDid: string): unknown => {
108
137
  if (Array.isArray(subject)) {
109
- return subject.map(s => patchSubject(s, subjectDid));
138
+ return subject.map(nestedSubject => patchSubject(nestedSubject, subjectDid));
110
139
  }
111
140
 
112
- if (subject && typeof subject === 'object') {
113
- return { ...(subject as Record<string, unknown>), id: subjectDid };
141
+ if (!subject || typeof subject !== 'object') return subject;
142
+
143
+ const patchedSubject: Record<string, unknown> = {
144
+ ...(subject as Record<string, unknown>),
145
+ id: subjectDid,
146
+ };
147
+ const embeddedCredentials = patchedSubject.verifiableCredential;
148
+
149
+ if (Array.isArray(embeddedCredentials)) {
150
+ patchedSubject.verifiableCredential = embeddedCredentials.map(credential =>
151
+ patchCredentialSubject(credential, subjectDid)
152
+ );
153
+ } else if (embeddedCredentials) {
154
+ patchedSubject.verifiableCredential = patchCredentialSubject(
155
+ embeddedCredentials,
156
+ subjectDid
157
+ );
114
158
  }
115
159
 
116
- return subject;
160
+ return patchedSubject;
117
161
  };
118
162
 
119
163
  // ---------------------------------------------------------------------------
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=docs-json.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"docs-json.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/docs-json.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=issuance.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"issuance.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/issuance.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=registry.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/registry.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=sd-jwt-vc.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sd-jwt-vc.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sd-jwt-vc.test.ts"],"names":[],"mappings":""}