Changelog¶
Changelog¶
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
[0.6.4] - 2026-06-01¶
Fixed¶
- Validators / CLI: component-lesson bundle check in preview and
--lessonkitvalidate/preview paths (parity withlxpack build) - Runtime / flow:
any/allflow rules withoutfromapply on all inferrable source activities, not just the first nested branch - Runtime: Next button disabled when no reachable next step in a branching course
- Runtime: warn when flow
gototarget is not in the current nav list - Validators: flow cycle detection for
interaction.donealigned with runtime (specific lesson id) - Validators: HTML interactions using
parent.lxpackBridgeno longer warn incorrectly - API:
packageLessonkit()resolves relative output againstconfigDirby default - CLI: reject relative paths in
--spa-lesson
[0.6.3] - 2026-05-30¶
Added¶
- Flow: optional
fromon flow rules limits when a rule is evaluated (activity id the learner is on);interaction.doneandassessment.passedrules inferfromwhen omitted - Validators: warn when
variable.eqflow rules omitfrom(migration hint)
Fixed¶
- Runtime: position-aware flow navigation — persistent variables no longer redirect learners on unrelated steps; branching-demo basic path skips
component_lesson - Runtime: sidebar disabled state matches click reachability; Prev/Next buttons disabled when flow blocks the target
- CLI:
lxpack preview --lessonkitfails on invalidlxpack.config.json(parity with validate/build) - CLI: malformed
--spa-lessonvalues exit with a clear error instead of an uncaught exception - CLI:
findCourseDirand unexpected build errors print friendly messages and exit 1
[0.6.2] - 2026-05-30¶
Fixed¶
- Runtime: clear content area when navigating so stale async renders no longer leave the previous lesson visible; delayed iframe
track()resolves html/spa lessons by interaction id (with fallback for sub-step ids on the current lesson) - CLI:
lxpack init --forceremoves stalelessonkit.jsonandlxpack.import.json - Validators:
lessonkit.json/lxpack.import.jsonno longer trigger false “included in export” warnings - API:
packageLessonkit()accepts optionalconfigDirand resolvestarget/outputBaseDirfromlxpack.config.jsonwhen omitted (CLI parity)
Changed¶
- Node.js: all
@lxpack/*packages and the CLI now support Node.js 18 and 20 (engines.nodeis>=18). CI runs lint, build, typecheck, test, examples, conformance, and coverage on both versions. - Validators: markdown validation warns on
vbscript:anddata:text/htmlURIs (aligned with runtime sanitizer)
[0.6.1] - 2026-05-29¶
Fixed¶
- Runtime: assessment UI no longer renders into the wrong activity after fast navigation (
isStaleguard on assessment load) - SCORM packaging:
lessonkit.jsonandlxpack.import.jsonare omitted from LMS export ZIPs (parity with preview) - cmi5:
fetchCmi5AuthTokenalways uses POST even whenRequestInit.methodis overridden - CLI:
--lessonkitbuild/validate/preview loadlxpack.config.jsonfrom the interchange file’s directory, not onlyprocess.cwd() - API / exports:
readRuntimeBundlemerges@lxpack/componentsCSS like preview (loadLearnerStylesshared with CLI) - xAPI: preserve
Bearerauthorization headers; terminal flush retries after an in-flight flush completes - SCORM bridges: honor LMS
Initialize/Commit/Finishfailures; skip persist/restore when the session is not ready - SCORM 2004:
Scorm2004Adapterblocks Get/Set afterTerminate(matches SCORM 1.2 adapter behavior) - CLI:
lxpack init --forceremoves stalecourse.yaml,lxpack.config.json,.lxpack/, and.gitignoreat the project root
[0.6.0] - 2026-05-29¶
Added¶
@lxpack/spa-bridge— typed child SDK (getLxpackBridge), score normalization,createLxpackBridgeHostfor the runtime@lxpack/tracking-schema—mapLessonkitTelemetryToLxpack/mapLessonkitTelemetryToBridgeActionfor LessonKit event names (includingcourse_completed→completeCourse)- Theme presets —
runtime.themePresetin interchange (lessonkit:default,lessonkit:brand) resolves tocssVariables - CLI —
lxpack preview --lessonkitandlxpack validate --lessonkitwith--spa-lesson/--spa-dist @lxpack/conformance— shared export-target matrix runner for CI@lxpack/lessonkit— meta-package re-exporting package, bridge, interchange, and telemetry APIs- Docs — SPA bridge, SCORM SPA recipes, API stability
Changed¶
- Runtime bridge host uses
@lxpack/spa-bridge;completeCourse()onlxpackBridge.v1marks in-scope lessons, passes assessments, and sets html/spa interaction suspend keys - Interchange
tracking.xapisupported inlessonkit.jsonv1 - SPA validators warn when
index.htmlomitslxpackBridgereferences packageLessonkit: drops temp staging after successful build unlessdebugor explicitcourseDir; resolves output paths against project cwd viaoutputAnchorDir
Fixed¶
- Runtime / SPA bridge: bridge
trackuses the same wrapper aswindow.lxpack(flow + interaction completion); bridge completions refresh nav/progress;completeCourse()respects SCORM 2004 per-SCO launch scope - SPA bridge: score normalization when
maxScoreis set but values are already 0–1; non-finite scores rejected; optionalpassedhonored onsubmitAssessment - LessonKit: validate SPA destination paths before copy (path escape); interchange warnings on build/preview/API when assessments are injected; preview
--lessonkitrespectslxpack.config.jsondefault export target; mergecourse.titlefrom interchange - LessonKit schema: reject invalid SPA paths, duplicate lesson ids, and
path/build.outputDirconflicts at parse time; warn on unknownthemePreset - CLI: reject unknown or missing
--spa-lessonids up front - Preview: guard async markdown renders against stale navigation
[0.5.0] - 2026-05-29¶
Added¶
packageLessonkit()(@lxpack/api) — materializecourse.yaml, copy SPA build folders with path containment, and build LMS packages without a hand-authored project tree- LessonKit interchange schema (v1) — Zod-validated
lessonkit.json(format: lessonkit,version: 1);parseLessonkitInterchange,interchangeToManifest,materializeLessonkitProjectin@lxpack/validators - Interchange-only validation —
validateCourseWithInterchangeaccepts courses with interchange but nocourse.yaml - CLI —
lxpack build --lessonkit <path> --spa-lesson id=/abs/dist(and--spa-distfor single-SPA courses) - Docs — lessonkit.json interchange reference
- Example —
examples/lessonkit-spa/scripts/package-via-api.mjs
Changed¶
- Interchange files must declare
format: "lessonkit"andversion: "1"(invalid interchange fails with path-qualified Zod errors) mergeInterchangeIntoManifestmergesruntime.cssVariablesand interchange assessment refs
[0.4.0] - 2026-05-27¶
Added¶
type: spalessons — package built web app folders (path/index.html) across all export targets; parent bridge APIwindow.parent.lxpackBridge.v1for completion, assessments, and tracking@lxpack/api— programmaticvalidateCourseandbuildCoursewith typed results, optional injected assessments, and interchange merge@lxpack/tracking-schema— shared track event types for runtime and adapterslessonkit.json/lxpack.import.json— optional interchange metadata merged at validate/build (CLI and API)- Example —
examples/lessonkit-spa/demonstrating SPA + markdown in one course
Changed¶
- CLI validate/build/preview merge
lessonkit.jsonvia shared@lxpack/validatorsinterchange module (parity with@lxpack/api) - Documentation and library skills updated for v0.4.0 LessonKit interoperability
Fixed¶
- SCORM 1.2:
imsmanifest.xmlnow listslxpack-components.jswhen a components bundle is shipped - SCORM 2004: removed duplicate
<file>entries forlxpack-runtime.js/lxpack-components.jsinshared_assets - Interchange validation:
validateCourseWithInterchangeno longer returns stale pre-merge errors afterlessonkit.jsonfixes the manifest; preview failure diagnostics use interchange merge (same as validate/build) - Runtime navigation: Prev button no longer linear-back into flow-skipped lessons; numeric flow conditions reject non-finite values (
NaN) - SPA lessons:
interaction.doneparity with HTML lessons in runtime, validators, and docs - Preview security: block
lessonkit.json,lxpack.import.json, andnode_modules/under/course/; interchange files validated with packagable-path rules (symlink escape blocked) - CLI:
validateandpreviewdefault export target aligned withbuild(scorm12);buildprints validation issues on failure; component lessons fail validation when@lxpack/componentsbundle is unavailable
[0.3.6] - 2026-05-26¶
Fixed¶
- SCORM/LMS: browser client bundle inlines validators subset instead of bare
@lxpack/validatorsimport (#3)
[0.3.5] - 2026-05-26¶
Fixed¶
- Runtime client bundle: SCORM/LMS launch no longer throws
ReferenceError: process is not defined(Vitest bootstrap guard) - Flow: sidebar navigation respects branching rules when
flowis defined - Flow:
interaction.doneuses the same explicit completion rules as HTML auto-complete - Flow: Prev button respects branching reachability (cannot linear-back into skipped activities)
- Flow: boolean variable equality is strict (
true/falseonly;0/1no longer match) - Progress: empty compact
{}suspend_data restores without corrupt-data warnings - SCORM 2004 / 1.2: zero-progress sessions set
incompleteCMI instead of leaving stale LMS status - cmi5: AU session bootstrap via
fetchlaunch URL (POST +auth-token; cached insessionStoragefor refresh)
Security¶
- Validate
assessments[].filemust live underassessments/; exports and preview block manifest paths - Preview: case-insensitive blocks, manifest-driven denylist, backslash-normalized URLs; block URL aliases to sensitive realpaths
- Harden
course.yamlandlxpack.config.jsonload against symlink escapes - Reject symlinks and hard links on markdown lessons, assessments, and packaged files; reject in-tree aliases to
assessments/or manifest paths - Reject hard links under
interactions/and symlinks/hard links on component overrides - Markdown lesson paths use safe relative-path rules
- Packaging requires an assessment bundle when the course defines assessments
- Packaging skips
assessments/case-insensitively (aligned with preview)
Changed¶
validatewarns onjavascript:URIs in markdown lesson links/imagesvalidatenormalizes backslashes in HTML interaction paths- Preview validation failures print
[warning]/[error]labels likelxpack validate
Notes¶
- HTML interaction iframes still use
allow-same-origin(trusted author content)
[0.3.4] - 2026-05-25¶
Fixed¶
- SCORM 2004: per-SCO completion/CMI when launched with
activityId - Preview: decode and normalize
%-encoded/course/paths before blocklist - Components: quote-safe HTML escaping in builtin widgets
- SCORM 1.2:
incompletewhen progress exists at 0% score; trimsuspend_dataon directLMSSetValue - Progress: empty compact
{}suspend_data no longer resets state - Build: missing xAPI IRI throws
CoursePackagingError - Learner shell: graceful error when config JSON is invalid
Changed¶
validate/previewrespectlxpack.config.jsondefaultTargetlikebuild;previewgains--target- Validate output distinguishes warnings vs errors
- Validator warning for cmi5
fetchlimitation; preview warns on non-loopback host
Security¶
safeJsonForHtmlalso escapes>- Markdown links/images: block
javascript:URIs
Notes¶
- HTML interaction iframes still use
allow-same-origin(trusted author content); cmi5fetchAU bootstrap remains future work
[0.3.3] - 2026-05-27¶
Fixed¶
- SCORM minimal/trim suspend_data preserves flow
interaction_*andv:*keys lxpack validateapplies xapi/cmi5 rules fromlxpack.config.jsondefaultTarget- HTML interaction auto-complete only on explicit completion (aligns with flow
interaction.done) - SCORM 2004: failed assessments no longer set
completion_statustocompleted - xAPI launch params: merge query string and hash (hash wins on duplicates)
examples/xapi-awarenessandexamples/cmi5-demodefaultTargetmatch demo purpose
Changed¶
scripts/validate-examples.shchecksscorm12/scorm2004targets for linear and branching demos
[0.3.2] - 2026-05-26¶
Fixed¶
- Branching demo
choose-pathinteraction useswindow.parent.lxpackso variable branching works inside iframe labs (preview and SCORM) - Restored
@lxpack/clicoverage thresholds with tests forloadLearnerStyles()and preview xAPI/cmi5 validation paths
Changed¶
- Default learner UI: expanded markdown typography, quiz layout, dark-theme shell polish, and built-in component styling in preview and exports
- Preview and SCORM builds embed full learner styles via
loadLearnerStyles()(runtime + component CSS when needed) lxpack initand example HTML interactions use a consistent modern lab theme inside interaction framesvalidatewarns when HTML interactionindex.htmlcallswindow.lxpackinstead ofwindow.parent.lxpack
[0.3.1] - 2026-05-25¶
Fixed¶
- Flow
interaction.donenow recognizes html lesson completion when interactions calltrack()with an event id different from the lesson id (init and examples used mismatched ids). The preview runtime mirrors completion onto the lesson id without duplicate xAPI statements - HTML interaction
track({ data: false })no longer marks the lesson done for flowinteraction.done isInteractionDonetreats only truthy values as done (not0or"")- Preview server blocks normalized path traversal (
..,//,./) tocourse.yaml,lxpack.config.json, assessments,.lxpack/, dotfiles, andlxpack.config.ts - Preview and packaging reject course paths that escape the course directory via symlinks
collectFilesrejects symlinks; blocks.envand.gitfrom export packagesoutput.dirandbuild -opaths resolve withrealpathcontainment- SCORM suspend pruning preserves
interaction_*keys referenced in manifestflow - xAPI statement queue uses
fetchkeepaliveon terminate for best-effort LRS delivery - Corrupt SCORM
suspend_datalogs a warning instead of failing silently validateCourseruns xAPI tracking checks whentracking.xapiis set or export target is xapi/cmi5- HTML interaction directories validated for nested symlink escapes
lxpack init --forceclears priorassessments/andinteractions/content before rescaffoldingbuild/previewloadlxpack.config.jsonafter resolving export target validation needs
Changed¶
lxpack initand example phishing labs use the lesson id intrack()for consistency withinteraction.doneexamples/xapi-awareness: correct course title andactivityIrimetadataexamples/cmi5-demo: correct course title metadata- Documentation: security notes reflect DOMPurify markdown sanitization (shipped in 0.3.0); preview blocking, export TOC order, SCORM 2004 completion semantics, cmi5
fetchlimitation
Notes¶
- cmi5
fetchlaunch parameter is parsed but AU session bootstrap viafetchis not implemented in v0.3.1 (runtime warns when present)
[0.3.0] - 2026-05-24¶
Added¶
- DOMPurify-based markdown sanitization in the browser runtime
installScorm2004API()for preview SCORM 2004 simulation
Changed¶
lxpack.config.jsonexports.defaultTargetmay bexapiorcmi5- Runtime client build externalizes
@lxpack/validators(type-only imports) to keep the browser bundle Node-free lxpack validate --targetrejects unknown export targets (same asbuild)- Preview server blocks
/course/course.yaml,/course/lxpack.config.json, and/course/.lxpack/* - HTML interaction paths validated for safe characters; iframe
srcescaped - Flow
variable.eqrespects manifest variabletypewhen comparing values - Runtime applies
lxpack-theme-{theme}class fromcourse.yamlruntime.theme - CI runs
pnpm test:coveragewith per-package thresholds
Fixed¶
- cmi5 launch
fetchquery param no longer used as the xAPI LRSendpoint - LRS transport re-queues statements after a failed POST instead of dropping them
- Preview xAPI
onStatementcallback no longer fires twice per statement - Browser client passes
activityIriandxapiconfig through toLxpackRuntime lxpack validatechecks xAPI tracking when--target xapi|cmi5ortracking.xapiis present- Preview YAML assessment fetch includes
maxAttempts,shuffleChoices, andshowFeedback - SCORM minimal suspend snapshot preserves
assessment_attempts_*keys when scores exist interaction.doneflow conditions require a truthy interaction value- xAPI
buildInteractedavoids duplicate simulation keys in statement extensions - Activity lists for xAPI analytics delegate to
enumerateActivitiesfrom@lxpack/validators - Preview can use SCORM 1.2 / 2004 simulators via config (default remains
local/ localStorage) - Documentation synced for Phase 3 (shipped) and preview SCORM behavior
Notes¶
- cmi5
fetchlaunch parameter is parsed but session bootstrap viafetchis not implemented in v0.3.0 (runtime warns when present)
0.2.2 - 2026-05-24¶
Fixed¶
- Flow cycle detection now analyzes real flow-jump graphs (context-aware for
assessment.passedandinteraction.done); replaces broken rule-index heuristic submitAssessmentandtrack({ type: "assessment" })enforcemaxAttemptsand ignore submissions after pass- Quiz UI shows correct attempts remaining, blocks exhausted forms, and prevents double-submit
- SCORM suspend pruning preserves
assessment_attempts_*andassessment_passing_*keys - SCORM 2004 single-SCO mode restricts sidebar navigation to the launch activity
- Flow navigation falls back to linear next/prev when
gototarget is invalid - SCORM 2004
suspend_datatrimmed to 4096 characters (parity with SCORM 1.2) - Duplicate assessment IDs no longer parse the second file; empty
all/anyconditions rejected - Activity IDs restricted to safe characters for SCORM paths; duplicate question/choice IDs rejected
interaction.doneflow conditions must reference html interaction lessons only
Changed¶
- Root
pnpm testrunspnpm buildfirst viapretestto avoid staledist/failures
0.2.1 - 2026-05-24¶
Fixed¶
- Quiz
maxAttemptsnow persists across submits and navigation - SCORM status no longer marks the course failed while quiz retries remain
- SCORM 2004 SCO pages use correct asset
baseUrland honoractivityIdon first launch - SCORM 2004 exports no longer embed all answer keys in every SCO; manifest omits missing
lxpack-components.js - SCORM 2004 lesson SCOs no longer embed quiz questions, feedback, or configs (assessment content only on assessment launch pages)
- SCORM
suspend_dataserialization uses a parse-safe minimal snapshot instead of byte-truncating JSON - Exported packages error clearly when an assessment is missing from embedded config (no silent YAML fetch)
- Preview reuses validated assessment bundle from a single
validateCoursepass (same as build) lxpack build --dir --target scorm2004produces a valid multi-SCO tree; directory builds include the components bundle when used- Flow cycles, duplicate lesson/assessment IDs, and invalid flow references fail validation
- Preview blocks direct access to
assessments/*.yamlsource files - Flow navigation race after “Mark complete” corrected; manifest variables restored after suspend data load
0.2.0 - 2026-05-23¶
Added¶
- Manifest
variablesandflowwith a small condition AST (variable.eq,assessment.passed,interaction.done,all/any) - Flow-aware navigation in
@lxpack/runtime(linear fallback whenflowis omitted) - Quiz engine upgrades:
maxAttempts,shuffleChoices,showFeedback(immediate | end | never) @lxpack/components— built-in widgets (callout,image-card,checklist), registry, and browser bundle- Lesson type
componentwith optionalprops - SCORM 2004 multi-SCO export (
lxpack build --target scorm2004) with per-activity launch pages and IMS Simple Sequencing subset - SCORM 2004 Run-Time API adapter (
API_1484_11) and preview simulator - Example course at
examples/branching-demo
Changed¶
- Assessment configs and feedback text are embedded in runtime config at build time (author YAML still excluded from ZIPs)
lxpack initscaffolds acomponents/directory and documents optionalvariables/flowkeys
Notes¶
- Completes Phase 2 (runtime expansion). Phase 3+ covers xAPI, cmi5, themes, hot reload, and plugins.
- SCORM 2004 sequencing uses a supported rule subset; validate packages in SCORM Cloud or Moodle before production rollout.
0.1.1 - 2026-05-23¶
Fixed¶
- Escape
<in embedded JSON config (preview + export) to prevent script-breakout - Stop shipping assessment answer keys as fetchable YAML; embed sanitized assessments in runtime config
- Path containment for
lxpack init --dirandlxpack.config.jsonoutput directory - Symlink path traversal in course validation
- SCORM progress: compact suspend data, safe truncation,
lesson_locationfallback - SCORM status committed after assessment submission
- Assessment
track()parity, navigation race guard, doubleLMSFinish - Stricter assessment sub-schemas; preview fails on validation errors like build
- SCORM manifest identifier collisions; build reuses validated manifest
Security¶
- Markdown sanitization remains basic; only use trusted author content until DOMPurify support lands
0.1.0 - 2026-05-23¶
Added¶
@lxpack/cli—init,preview,validate, andbuildcommands@lxpack/validators— strict Zod schemas, path containment, assessment validation@lxpack/runtime— browser client with markdown lessons, HTML interactions, MCQ assessments, progress tracking@lxpack/scorm— SCORM 1.2 and standalone HTML ZIP/directory export- Real SCORM 1.2 LMS API discovery with preview simulator fallback
lxpack.config.jsonfor default export target and output directory- Example course at
examples/security-awareness - CI checks (lint, build, typecheck, test) and release workflow with pre-publish gates
Notes¶
- Completes Phase 1 (MVP). Phase 2 shipped in v0.2.0 — see Roadmap.
- Phase 3+ covers xAPI, cmi5, themes, hot reload, and plugins.
- The runtime browser bundle is ESM (
client.js); legacy LMS environments without module support are not targeted in this release.