Conforms to DI-IPSC-81435A.
Copyright © 2015–2026 Eduworks Corporation and other contributing parties. Licensed under the Apache License, Version 2.0.
AUTHORS
| Name | Role | Department |
|---|---|---|
| Ronald “Fritz” Ray | Lead Architect / Developer | Engineering |
| Mile Divovic | Developer | Engineering |
| Debbie Brown | Developer | Engineering |
| Elaine Kelsey | Developer | Engineering |
| Kari Glover | Developer | Engineering |
| Tyler Landowski | Developer | Engineering |
DOCUMENT HISTORY
| Date | Version | Document Revision Description | Document Author |
|---|---|---|---|
| 2026-06-13 | 1.0 | Initial comprehensive system design document, generated from codebase analysis, cass-npm, cass-editor, and docs.cassproject.org. | Auto-generated |
| 2026-06-14 | 1.1 | Reviewed by lead architect. Removed transient version numbers, converted ASCII diagrams to Mermaid, expanded §3.10 Rules, removed OpenSearch references, corrected LEVR definition, clarified native crypto vs. node-forge fallback. | Ronald “Fritz” Ray |
APPROVALS
| Approval Date | Approved Version | Approver Role | Approver |
|---|---|---|---|
| 2026-06-14 | 1.1 | Lead Architect / Developer | Ronald “Fritz” Ray |
SUPPLEMENTAL DOCUMENTS
| Supplement Date | Supplement Version | Document File Name / Link | Document Name |
|---|---|---|---|
| DI-IPSC-81433A Software Requirements Specification Template.md | Software Requirements Specification | ||
| DI-IPSC-81435 System Design Template.md | System Design Template (blank) | ||
| CONFIGURATION.md | Configuration Guide | ||
| DEPLOYMENT.md | Deployment Guide | ||
| ENVIRONMENT.md | Environment Variable Reference | ||
| FILE.md | File Structure Reference | ||
| DATABASE.md | Database Design Description (DI-IPSC-81437A) |
Table of Contents
| Attribute | Value |
|---|---|
| System Name | Competency and Skills System (CaSS) |
| Project-Unique Identifier | cass |
| Version / Release | Current |
| Repository | https://github.com/cassproject/CASS |
| NPM Package | cassproject |
| License | Apache License 2.0 |
| Organization | Eduworks Corporation |
| Sponsor | Advanced Distributed Learning (ADL) Initiative, U.S. Department of Defense |
CaSS is an open-source, federated infrastructure for the definition, management, exchange, and computation of competency data. It addresses the fundamental challenge of creating a shared, interoperable vocabulary for human capabilities—skills, knowledge, abilities, traits, and learning objectives—across organizational and system boundaries.
Purpose. CaSS enables organizations to:
History. Developed since 2015 under ADL sponsorship, CaSS originated as a Java web application and was re-architected as a Node.js/Express application in the 1.5.x series. The system implements W3C Linked Data principles, using JSON-LD as its native data format with Schema.org and CTDL-compatible type vocabularies.
Operating Sites. CaSS is deployed across DoD training organizations, academic institutions, workforce development programs, and credentialing bodies. It can be operated on-premises, in private clouds, or in containerized environments (Docker, Kubernetes).
This System Design Document (SDD) describes the complete architectural and detailed design of CaSS. It covers system-wide design decisions (Section 3), architectural design including component decomposition and interface design (Section 4), detailed design of each software unit (Section 5), and requirements traceability (Section 6). Section 7 provides a glossary, acronyms, and supplementary notes. Appendixes provide reference tables for environment variables and data schemas.
| Document Name / Link | Version | Comment |
|---|---|---|
| MIL-STD-498 | 1994 (canceled 1998) | Military Standard for Software Development and Documentation; basis for DI-IPSC-81435A |
| DI-IPSC-81435A | A | Data Item Description — System/Subsystem Design Description |
| DI-IPSC-81433A | A | Data Item Description — Software Requirements Specification |
| RFC 8259 — JSON | 2017 | The JavaScript Object Notation Data Interchange Format |
| W3C JSON-LD 1.1 | 2020 | JSON-based Linked Data serialization |
| Schema.org | Current | Shared vocabulary for structured data on the web |
| CTDL — Credential Transparency Description Language | Current | Credential Engine vocabulary for competencies and credentials |
| IMS CASE v1.0 | 1.0 | Competency and Academic Standards Exchange |
| xAPI (Experience API) 1.0.3 | 1.0.3 | Tin Can API for learning activity statements |
| Open Badges 2.0 | 2.0 | Open standard for digital credentials |
| OpenAPI Specification 3.0 | 3.0.3 | REST API description standard |
| FIPS 140-3 | 2019 | Security Requirements for Cryptographic Modules |
| RFC 7519 — JSON Web Token | 2015 | JWT specification |
| OpenID Connect Core 1.0 | 2014 | OIDC specification |
| W3C SKOS | 2009 | Simple Knowledge Organization System |
| Model Context Protocol | Current | Protocol for AI model–tool integration |
| CASS README.md | Current | Installation and getting started |
| CASS CONFIGURATION.md | Current | Server configuration guide |
| CASS DEPLOYMENT.md | Current | Local, Docker, Kubernetes deployment |
| CASS ENVIRONMENT.md | Current | All 80+ environment variables |
| CASS FILE.md | Current | Project file structure reference |
| CASS CHANGELOG.md | Current | Release history |
| OpenAPI Spec (swagger.json) | Current | Machine-readable API specification |
This section documents system-wide design decisions that influence the architecture and implementation of all CaSS components.
busboy.signatureSheet field in request headers or body.@context, @id, and @type fields, and optional @owner, @reader, @signature, and @signatureSha256 security fields.q parameter, with pagination (start, size), sorting (sort), and index hinting (index_hint)./ws/custom to receive real-time change notifications.@id broadcasts of saved objects to all connected WebSocket clients.GET /api/swagger.json and rendered interactively at /api/swagger.GET /api/ping returns server version, SSO state, FIPS mode, banner/MOTD configuration, and server readiness.GET /api/data/{type}/{uid} retrieves an object; POST /api/data/{type}/{uid} creates or updates it. The server validates the signature sheet, checks KBAC permissions, and stores/retrieves from Elasticsearch. Versioned access is available via GET /api/data/{type}/{uid}/{version}.GET/POST /api/sky/repo/search?q=... queries Elasticsearch with sanitized query strings. Results are filtered by KBAC access control before return.POST /api/sky/repo/multiGet, multiPut, multiDelete accept arrays of identifiers or objects for bulk processing.POST /api/sky/id/create generates a key pair; POST /api/sky/id/commit persists identity changes; POST /api/sky/id/login retrieves stored identities.GET /api/profile/latest?frameworkId=...&subject=... triggers a worker-thread-based profile computation. The coordinator checks the cache first; on a miss, it delegates to coprocessor pipeline workers./api/ceasn/*, /api/ims/case/v1p0/*) with import, export, or format-translation semantics.database.afterSave events, the WebSocket module broadcasts the saved object’s @id to all connected clients.database.connected → server.listening → server.ready events via the RxJS event bus, triggering adapter loading and periodic maintenance tasks.SEVERITY.EMERGENCY audit entry, flush logs, and terminate the process with process.exit(1). Container orchestrators (Docker, Kubernetes) restart the process automatically.@signature and @signatureSha256 fields before accepting modifications from non-server actors.FETCH_ALLOW_LIST env var), preventing server-side request forgery (SSRF).CaSS implements a multi-layered security model:
KBAC is the foundational authorization mechanism unique to CaSS:
kbac.js, checking signature validity, timestamp freshness, and expiry.@owner field are public (anyone can read and modify).@owner field restrict write access to listed public key holders; read access remains public.@reader field restrict read access to listed public key holders; data is encrypted at rest.REJECT_SHA1.CaSS supports four mutually exclusive authentication modes (only one active at a time):
| Mode | Implementation | Use Case |
|---|---|---|
| Key-Based (Default) | Built-in PKI identity via skyId.js |
Standalone deployments, no external IdP |
| OIDC/SSO | express-openid-connect (Keycloak, etc.) |
Enterprise SSO integration |
| JWT Bearer Token | express-jwt |
API-to-API authentication |
| Platform One (P1) | Custom JWT middleware with adjective/noun claims | DoD Platform One environments |
HTTP2_SERVER=false).REQUEST_CLIENT_SIDE_CERTIFICATE.CRL_LISTS=true.CASS_IP_ALLOW) with configurable denied-redirect.express-rate-limit.AUTH_ENV_ADMIN_EMAILS).EcEncryptedValue. The subject and agent fields of assertions are individually encrypted with the reader’s public key, ensuring that only authorized parties can determine whom an assertion is about.@reader array with public keys. The object is encrypted at rest in Elasticsearch; only holders of corresponding private keys can decrypt it.@reader field is set, all sensitive fields are encrypted before storage. The server cannot read encrypted data without the appropriate private key.ANONYMIZE_USERS option that obscures user identity in authentication flows.CaSS transitions through the following states during its lifecycle:
stateDiagram-v2
[*] --> Starting
Starting --> DB_Connecting : server.init
DB_Connecting --> Server_Listening : database.connected
Server_Listening --> Adapters_Loading : server.listening
Adapters_Loading --> Ready : adapters loaded
Ready --> Operating : server.ready
Operating --> Operating : periodic 60s ticks
Operating --> Error : uncaught exception
Error --> [*] : process.exit(1)
state Operating {
[*] --> Steady
Steady --> Maintenance : server.periodic
Maintenance --> Steady : cleanup complete
}
| State | RxJS Event | Description |
|---|---|---|
| Starting | server.init |
Express app created, middleware loaded, shims initialized |
| DB Connecting | database.connected |
Elasticsearch connection established, indices verified |
| Server Listening | server.listening |
HTTP/HTTPS/HTTP2 server bound to port, accepting connections |
| Adapters Loading | — | Protocol adapters dynamically loaded via glob from cartridge/adapter/ |
| Ready | server.ready |
All adapters loaded, system fully operational |
| Operating | server.periodic / database.periodic (60s) |
Steady-state; periodic maintenance tasks (ephemeral cleanup, disk checks) |
| Error/Shutdown | — | Uncaught exception triggers alert, log flush, and process.exit(1) |
Degraded Modes:
database.connected and will not start listening.DISABLED_ADAPTERS without affecting core functionality.DISABLED_EDITOR=true, leaving the API fully functional.compression middleware.maxAge cache header.node-worker-threads-pool), preventing CPU-intensive computation from blocking the event loop. Each worker’s memory is configurable via WORKER_MAX_MEMORY (default 1024 MB).PROFILE_TTL, default 30 days).multiGet, multiPut, and multiDelete endpoints reduce HTTP round-trips. MULTIPUT_BATCH_SIZE (default 100) controls per-batch throughput._delete_by_query, avoiding accumulation of stale data.default.js — Matches assertions to competencies via alignment rules.direct.js — Processes direct competency assertions without alignment.conditions.js — Evaluates roll-up rules and framework conditions (graph traversal).timeBounding.js — Filters assertions by date range and temporal validity.explainer.js — Generates human-readable explanations of computation results.template.js — Extensibility template for custom coprocessors.crypto (preferred) with node-forge as a fallback for operations not available natively.EcDirectedGraph and Hypergraph structures.@context, @id, and @type fields. The @id field serves as the globally unique, persistent URL identifier. Writes missing any of these three fields are rejected with HTTP 400.schema.cassproject.org.0.4.Framework, schema.cassproject.org.0.4.Competency, etc. Elasticsearch indices are named by lowercased type namespaces.{"en": "Hello", "es": "Hola"}) are flattened into arrays, and {"@value": "text"} objects are collapsed to their raw string values. This ensures Elasticsearch can full-text-search across all language variants.payload and secret fields are removed from any nested EncryptedValue objects, and all @signature / signature fields are removed. The permanent index retains the full unmodified object.signatureSheet HTTP header or in a signatureSheet multipart form field. Both sources are merged, and each signature is independently validated.EbacSignature types, (b) include a non-null expiry timestamp that has not passed, and (c) pass RSA signature verification against its declared public key. SHA-256 signatures are preferred; SHA-1 signatures are accepted as a fallback unless REJECT_SHA1=true, in which case SHA-1 is rejected with HTTP 451.etc/*.pem) that act as identities for server-side operations (adapter imports, replication, profile computation).skyAdmin2) can read and write any object regardless of @owner restrictions. When AUTH_ALLOW_ENV_ADMINS=true, additional user public keys can be granted admin-equivalent access. Admin overrides are audit-logged.@owner and @reader PEM keys containing newlines are normalized to their canonical single-line form via EcPk.fromPem().toPem().@owner field is set, only the owner(s) can modify or delete the object. Non-owners receive HTTP 401.@reader Filtering. On retrieval, if an object has a non-empty @reader array or is an EncryptedValue type, the system checks whether any proven identity (from the signature sheet) appears in the object’s @owner or @reader list, or is the admin key. If no match, the object is silently removed from results — the client receives no indication that the object exists (it acts as “not found” rather than “forbidden”). In SSO mode, the server additionally attempts to decrypt the object’s secret on behalf of the authenticated user.permanent index; the current version is stored in the type-specific index. Version conflicts (HTTP 409) trigger automatic retry with an incremented version.* (match all). Default page size is 50, default start offset is 0.cartridge/adapter/*.js). Each adapter self-registers its routes using the bindWebService LEVR compatibility function.RekeyRequest object is saved and passes verification, it is added to the EcRemoteLinkedData.forwardingTable, enabling transparent identity migration — subsequent requests for the old identity are forwarded to the new one.global.events.data.{write|delete|found|any}, enabling reactive subscribers (e.g. WebSocket push, adapter side-effects) to act on data changes without polling.@type. Index derivation, KBAC enforcement, dual-write versioning, search indexing, and version history shall apply uniformly to all types.@context/@type combination is stored, the system shall automatically create a new Elasticsearch index named by the lowercased, dot-delimited fully-qualified type URL. No server restart or configuration change is required.Framework, Competency, Relation, Assertion, Level, RollupRule, Directory, Person, Organization, CreativeWork, Concept, ConceptScheme, and EncryptedValue. These types have custom index mappings and participate in higher-level features (profile calculation, adapter exports).ceterms:*), CTDL-ASN types (ceasn:*), the full schema.org vocabulary, SKOS types, and any custom application-defined types — are stored and retrieved identically to official types. They receive CRUD, search, KBAC, and version history support, but do not participate in profile computation or adapter-specific processing unless a dedicated adapter is present.process.on('uncaughtException') catches all unhandled errors, sends an email alert, logs at EMERGENCY severity, and terminates the process.SYSTEM, NETWORK, AUTH, DATA, ADAPTER) and severities (DEBUG, INFO, WARNING, ERROR, EMERGENCY).LOG_FILTERED_CATEGORIES, LOG_FILTERED_SEVERITIES, and LOG_FILTERED_MESSAGES environment variables.httpGet, httpPost, httpPut, httpDelete).schema.cassproject.org.0.4.framework, schema.cassproject.org.0.4.competency).permanent index with external version typing. The current version is also stored in the type-specific index for fast retrieval.ephemeral index with mappings disabled. Periodic cleanup purges expired entries.etc/ directory on the local filesystem. Loss of this directory means loss of all server identity and the ability to modify owned objects.src/main/server/cartridge/adapter/. Adapters are dynamically discovered and loaded at startup. Adapters can be selectively disabled via DISABLED_ADAPTERS.coprocessors/template.js.<iframe>, with CSS inheritance and URL-parameter-based configuration.@id, @type, and @context can be stored, indexed, searched, and retrieved. The Elasticsearch index name is derived automatically from the object’s type, so new types create new indices on first write without code changes. This means CaSS natively supports CTDL (ceterms:Credential, ceterms:LearningOpportunityProfile, etc.), CTDL-ASN (ceasn:CompetencyFramework, ceasn:Competency), the full schema.org vocabulary (~870 types), SKOS taxonomies (Concept, ConceptScheme), and any custom application-specific JSON-LD types. All stored types receive identical treatment: KBAC access control, dual-write versioning, full-text search, and version history apply uniformly.etc/ volume. Multiple server instances can run behind a load balancer.GET /api/ping provides a lightweight health check endpoint used by Kubernetes readiness/liveness probes and Docker health checks.restart: always, and Kubernetes deployments use readiness/liveness probes with automatic pod restart.skyRepo/ (data layer), profile/ (computation), shims/ (runtime infrastructure), cartridge/adapter/ (protocol adapters).swagger-jsdoc and validated at startup, ensuring documentation stays synchronized with code.reindex, purge, and cull operations, protected by admin secret key.etc/ volume. Multiple replicas can serve traffic behind a load balancer.etc/ volume must be a ReadWriteMany (RWX) persistent volume when running multiple replicas.WORKER_MAX_MEMORY (default 1024 MB).--max-old-space-size (development scripts default to 512 MB).ES_JAVA_OPTS (e.g., -Xms512m -Xmx512m in Docker Compose configurations).MAX_CONNECTIONS limits the number of simultaneous connections the server will accept.POST_MAX_SIZE controls maximum request body size for upload-heavy operations.CaSS is composed of four major subsystems, with supporting infrastructure:
graph TB
subgraph Clients["External Clients (Browsers, LMS, LRS, Credential Engines, AI Agents, Partner Systems)"]
end
Clients -- "HTTPS / WebSocket / MCP" --> Server
subgraph Server["CaSS Server (Node.js / Express 5)"]
direction TB
subgraph AppLayer[" "]
direction LR
Editor["CaSS Editor\n(Static SPA, Vue 2)"]
API["REST API — SkyRepo\nCRUD, Search, KBAC Auth,\nIdentity, Batch Ops"]
Adapters["Protocol Adapters\nxAPI, CASE, CTDL-ASN,\nASN, Badges, PNA, SCD,\nOllama, Replication"]
MCP["MCP Server\n(AI Tools)"]
end
Profile["Profile Engine\n(Worker Threads)"]
API --> Profile
subgraph Shims["Runtime Shims Layer"]
direction LR
S1["auth.js"]
S2["event.js"]
S3["levr.js"]
S4["cassproject.js"]
S5["auditLogger.js"]
S6["mailer.js"]
S7["jobs.js"]
S8["ephemeral.js"]
end
API --> Shims
Adapters --> Shims
end
Shims -- "HTTP" --> ES
subgraph ES["Elasticsearch"]
direction TB
TypeIdx["Type-specific indices\n(framework, competency, ...)"]
Perm["permanent (history)"]
Ephem["ephemeral (TTL)"]
end
cassproject npm for data model classes; hosts cass-editor as static files.cassproject npm package. Provides the interoperability layer between client applications and the CaSS repository. All classes are registered as global properties on require(). Used both server-side (by the CaSS server itself) and client-side (by the CaSS editor and third-party integrations).node_modules/cassproject/src/main/webapp/cassproject SDK.cassproject npm (bundled); communicates with CaSS REST API.src/main/webapp/ (pre-built output); source in separate repository.permanent index, and temporary data in an ephemeral index. CaSS communicates with Elasticsearch via its HTTP REST API.docker-compose-oidc.yml)keycloak/.auth.js shim when CASS_OIDC_ENABLED=true.| Resource | Minimum | Recommended |
|---|---|---|
| Runtime | Node.js LTS | Node.js LTS |
| CPU | 2 cores | 4+ cores |
| Memory | 2 GB (1 GB Node.js + 1 GB Elasticsearch) | 8+ GB (4 GB Node.js + 4 GB Elasticsearch) |
| Disk | 10 GB | 50+ GB (depends on data volume) |
| Network | Standard TCP (ports 80, 443, 9200) | Low-latency connection between CaSS and Elasticsearch |
| OS | Any OS supporting Node.js and Docker | Linux (Debian Bookworm, Alpine) |
| Container Runtime | Docker / Kubernetes | Docker / Kubernetes |
| Search Engine | Elasticsearch | Elasticsearch (latest) |
| Resource | Minimum | Recommended |
|---|---|---|
| Browser | Current versions of Chrome, Firefox, Safari, and Edge | Latest Chrome, Firefox, or Edge |
| JavaScript | ES2020 support required | — |
| Network | HTTP(S) connectivity to CaSS server | — |
| Screen | 1024×768 | 1920×1080 |
1. Load audit logger
2. Create Express app with compression, CORS
3. Initialize shims (in order):
event.js → ephemeral.js → jobs.js → mailer.js →
auth.js → levr.js → stjs.js → cassproject.js
4. Load core modules:
util.js → skyRepo.js → skyId.js
5. Serve static editor webapp (unless DISABLED_EDITOR=true)
6. Generate & validate OpenAPI specification (fail hard if invalid)
7. Mount Swagger UI at /api/swagger
8. Set security headers per environment configuration
9. AWAIT: database.connected event
→ Start HTTP/HTTPS/HTTP2 server on configured port
10. AWAIT: server.listening event
→ Dynamically load cartridge adapters via glob
11. EMIT: server.ready
→ System fully operational
12. PERIODIC (60s): server.periodic, database.periodic
→ Ephemeral cleanup, disk space checks
flowchart TD
A["Client Request"] --> B["Express Middleware\n(compression, CORS, headers)"]
B --> C["Auth Middleware\n(OIDC / JWT / P1 / Signature Sheet)"]
C --> D["Route Handler\n(data, search, adapter, etc.)"]
D --> E["KBAC Validation\n(owner/reader permission check)"]
E --> F["Elasticsearch\n(get / put / search / delete)"]
F --> G["Response\n(JSON-LD + compression)"]
The application-wide event bus (global.events) provides reactive, decoupled communication:
| Subject | Events | Subscribers |
|---|---|---|
events.server |
init, listening, ready, periodic (60s) |
All modules |
events.database |
connected, periodic (60s), afterSave |
Data layer, WebSocket, adapters |
events.person |
doPing, arrived, assertionAbout |
Profile engine, identity modules |
events.data |
read, write, delete, found, any |
Adapters, WebSocket, logging |
flowchart LR
Editor["CaSS Editor"] <-- "IF-01: REST/WS" --> Server["CaSS Server"]
IdP["Keycloak (IdP)"] <-- "IF-03: OIDC" --> Server
LRS["LRS"] <-- "IF-04: xAPI" --> Server
Partner["Partner Systems"] <-- "IF-05: REST" --> Server
AIAgent["AI Agent"] <-- "IF-09: MCP" --> Server
Server <-- "IF-02: HTTP" --> ES["Elasticsearch"]
Server -- "IF-06: SMTP" --> Mail["Mail Server"]
Server -- "IF-07: S3 API" --> S3["AWS S3"]
Server <-- "IF-08: REST" --> Peer["Peer CaSS (Replication)"]
| Interface ID | Name | Interfacing Entities | Status |
|---|---|---|---|
| IF-01 | Editor–Server API | CaSS Editor ↔ CaSS Server | Both developing |
| IF-02 | Server–Elasticsearch | CaSS Server ↔ Elasticsearch | Elasticsearch fixed; CaSS adapts |
| IF-03 | Server–OIDC IdP | CaSS Server ↔ Keycloak/OIDC Provider | OIDC standard fixed; CaSS adapts |
| IF-04 | Server–LRS (xAPI) | CaSS Server ↔ Learning Record Store | xAPI spec fixed; CaSS adapts |
| IF-05 | Server–External (Standards) | CaSS Server ↔ Partner Systems | Standards fixed (CASE, CTDL-ASN, etc.) |
| IF-06 | Server–SMTP | CaSS Server → Mail Server | SMTP fixed; CaSS adapts |
| IF-07 | Server–S3 | CaSS Server ↔ AWS S3 | S3 API fixed; CaSS adapts |
| IF-08 | Server–Server (Replication) | CaSS Server ↔ Peer CaSS Server | CaSS protocol; both sides developing |
| IF-09 | Server–MCP (AI) | CaSS Server ↔ AI Agent | MCP standard fixed; CaSS adapts |
Type: Real-time data transfer via HTTPS REST and WebSocket.
Communication Protocol:
/ws/custom for change notificationsKey Data Elements:
| Element | Type | Format | Description |
|---|---|---|---|
@id |
string (URI) | https://{host}/api/data/{type}/{uid}/{version} |
Globally unique persistent identifier |
@type |
string | Dotted namespace (e.g., schema.cassproject.org.0.4.Framework) |
JSON-LD type |
@context |
string (URI) | https://schema.cassproject.org/0.4/ |
JSON-LD context |
@owner |
string[] | PEM-encoded RSA public keys | Write-access holders |
@reader |
string[] | PEM-encoded RSA public keys | Read-access holders (data encrypted) |
@signature |
string | Base64-encoded RSA signature | SHA-1 integrity signature |
@signatureSha256 |
string | Base64-encoded RSA signature | SHA-256 integrity signature |
signatureSheet |
string[] | Array of signed tokens | Authentication tokens per request |
Endpoints (Core):
| Method | Path | Purpose |
|---|---|---|
GET |
/api/ping |
Health check, version, SSO state |
GET/POST |
/api/data/{type}/{uid} |
Object CRUD |
GET/POST |
/api/data/{type}/{uid}/{version} |
Versioned object access |
GET/POST |
/api/sky/repo/search |
Full-text search |
POST |
/api/sky/repo/multiGet |
Batch retrieval |
POST |
/api/sky/repo/multiPut |
Batch storage |
POST |
/api/sky/repo/multiDelete |
Batch deletion |
POST |
/api/sky/id/create |
Create identity |
POST |
/api/sky/id/commit |
Commit identity changes |
POST |
/api/sky/id/login |
Login |
GET |
/api/sky/admin |
Admin public keys |
GET |
/api/profile/latest |
Compute learner profile |
WS |
/ws/custom |
Real-time change notifications |
Type: Storage-and-retrieval of data via HTTP REST.
Communication Protocol:
http://elasticsearch:9200)ELASTICSEARCH_AUTHORIZATION headerKey Operations:
| Operation | ES API | CaSS Wrapper |
|---|---|---|
| Store object | PUT /{index}/_doc/{id}?version={v}&version_type=external |
skyrepoPut() |
| Retrieve object | GET /{index}/_doc/{id} |
skyrepoGet() |
| Delete object | DELETE /{index}/_doc/{id} |
skyrepoDelete() |
| Search | POST /{index}/_search (Simple Query String) |
skyrepoSearch() |
| Index management | PUT /{index}, GET /_cat/indices |
util.js |
| Bulk delete (ephemeral) | POST /ephemeral/_delete_by_query |
ephemeral.js |
Each standards adapter exposes its own REST endpoint namespace:
| Adapter | Endpoint Prefix | Standard | Direction |
|---|---|---|---|
| CTDL-ASN | /api/ceasn/*, /api/ctdlasn/* |
CTDL-ASN JSON-LD | Import + Export |
| IMS CASE | /api/ims/case/v1p0/* |
IMS CASE v1.0 | Read API (11 endpoints) + Harvest |
| ASN | /api/asn/* |
Achievement Standards Network | Import + Export |
| Open Badges | /api/badge/* |
Open Badges 2.0 | Read API |
| xAPI | /api/xapi/* |
Experience API 1.0.3 | Statement ingest |
| PNA | /api/ce/pna/* |
Portable Native Assertions | Read + Write |
| SCD | /api/scd/* |
Service Component Documentation | Read |
| Ollama | /api/ollama/framework |
— | AI generation |
| Replication | (internal) | CaSS protocol | Bidirectional |
Type: AI tool integration via Streamable HTTP.
Endpoint: POST /api/mcp
Description: The MCP server auto-generates tool definitions from the CaSS OpenAPI specification. AI agents connecting via MCP can invoke CaSS API operations as “tools,” enabling natural-language-driven competency management.
Implementation: The MCP adapter (mcp.js) uses the MCP TypeScript SDK v2 (@modelcontextprotocol/server + @modelcontextprotocol/node) with OpenAPI-to-tools conversion (openapi-to-tools.js) and JSON Schema to Zod validation (json-schema-to-zod.js).
Project-unique identifier: CASS-SRV-CORE
Source: src/main/server.js (539 lines)
Language: JavaScript (Node.js, Express 5)
server.js creates the Express application and configures middleware (compression, CORS, body parsing).database.connected, the HTTP/HTTPS/HTTP2 server starts listening.server.listening, adapter cartridges are loaded dynamically via glob.server.ready, the system enters steady-state operation with 60-second periodic ticks.| Environment Variable | Purpose |
|---|---|
PORT |
Listen port (default 80/443) |
CASS_LOOPBACK |
Self-referencing URL |
ELASTICSEARCH_ENDPOINT |
Database URL |
HTTPS / HTTP2_SERVER |
Transport mode |
CASS_BASE |
URL prefix |
process.exit(1).WARNING with FetchBlocked message.Project-unique identifier: CASS-SRV-SKYREPO
Source: src/main/server/skyRepo/ (15 files)
Language: JavaScript
SkyRepo is the data persistence layer—a JSON-LD object store backed by Elasticsearch with KBAC-enforced access control, versioning, and full-text search.
| File | Identifier | Purpose |
|---|---|---|
data.js |
SKYREPO-DATA |
Express route handler for GET/POST /api/data/*. Routes requests to get, put, or delete operations based on HTTP method and body content. |
get.js |
SKYREPO-GET |
Retrieves a JSON-LD object from Elasticsearch by type, UID, and optional version. Falls back to the permanent index for historical versions. |
put.js |
SKYREPO-PUT |
Stores a JSON-LD object in its type-specific index and the permanent index. Uses external versioning (version_type=external). Emits database.afterSave events. |
delete.js |
SKYREPO-DEL |
Deletes an object from its type-specific index (version history is preserved in permanent). |
search.js |
SKYREPO-SEARCH |
Proxies search queries to Elasticsearch using Simple Query String, with KBAC filtering of results. |
searchUtil.js |
SKYREPO-SEARCHUTIL |
Query sanitization, special character escaping, index hint resolution. |
multiget.js |
SKYREPO-MULTIGET |
Batch retrieval by array of partial identifiers. |
multiput.js |
SKYREPO-MULTIPUT |
Batch storage with configurable batch size (MULTIPUT_BATCH_SIZE). |
multidelete.js |
SKYREPO-MULTIDEL |
Batch deletion by array of identifiers. |
kbac.js |
SKYREPO-KBAC |
Key-Based Access Control. Validates signature sheets, checks @owner/@reader permissions, enforces write-access restrictions. Central to the security model. ~250 lines. |
history.js |
SKYREPO-HISTORY |
Retrieves version history of an object from the permanent index. |
ping.js |
SKYREPO-PING |
GET /api/ping handler returning server version, SSO state, FIPS mode, banner/MOTD, plugins, and endpoint information. |
admin.js |
SKYREPO-ADMIN |
GET /api/sky/admin returning admin public keys. |
langs.js |
SKYREPO-LANGS |
ISO language code lookup table for internationalization. |
util.js |
SKYREPO-UTIL |
Elasticsearch HTTP helper functions (httpGet, httpPost, httpPut, httpDelete), index management, backup/restore utilities. |
flowchart TD
Input["Request with signature sheet + target object"] --> Extract["Extract signature sheets\nfrom request headers/body"]
Extract --> Verify["For each signature:\nVerify RSA signature (SHA-256, fallback SHA-1)\nCheck timestamp freshness\nAdd verified key to proven identities"]
Verify --> HasOwner{"Object has @owner?"}
HasOwner -- Yes --> OwnerMatch{"Any proven identity\nmatches an @owner?"}
OwnerMatch -- Yes --> AllowWrite["Allow write"]
OwnerMatch -- No --> DenyWrite["Deny write (401)"]
HasOwner -- No --> HasReader{"Object has @reader?"}
HasReader -- Yes --> ReaderMatch{"Any proven identity\nmatches a @reader?"}
ReaderMatch -- Yes --> AllowRead["Allow read"]
ReaderMatch -- No --> ServerMatch{"Server identity\nmatches?"}
ServerMatch -- Yes --> AllowRead
ServerMatch -- No --> Encrypted["Return encrypted\n(unreadable) object"]
HasReader -- No --> PublicAccess["Public access (allow all)"]
Project-unique identifier: CASS-SRV-PROFILE
Source: src/main/server/profile/ (6+ files)
Language: JavaScript
The profile engine computes a learner’s competency attainment by aggregating assertions against a framework’s competency structure, using a pluggable coprocessor pipeline executed in worker threads.
| File | Identifier | Purpose |
|---|---|---|
controller.js |
PROF-CTRL |
Express route handler for GET /api/profile/latest. Parses parameters (frameworkId, subject, flushCache, cache, targetDateTime), delegates to coordinator. |
coordinator.js |
PROF-COORD |
Orchestrates profile computation across frameworks. Manages the cache layer (checks cache TTL, stores results). Spawns worker threads when needed. |
calculator.js |
PROF-CALC |
Core assertion-to-competency calculation logic (~18 KB). Resolves assertions to competencies, evaluates alignment matches, and produces raw profile data. |
worker.js |
PROF-WORKER |
Worker thread entry point (~12 KB). Each worker loads cassproject, creates its own EcRepository, and executes the coprocessor pipeline. Configurable memory via WORKER_MAX_MEMORY. |
util.js |
PROF-UTIL |
Utility functions for profile processing, confidence thresholds. |
Coprocessors are pluggable computation modules in profile/coprocessors/:
| File | Stage | Description |
|---|---|---|
default.js |
Assertion Matching | Matches assertions to competencies using alignment rules (source → target mapping) |
direct.js |
Direct Assertions | Handles assertions that directly reference competencies without alignment indirection |
conditions.js |
Roll-up Evaluation | Evaluates roll-up rules—graph traversal of framework conditions to determine derived mastery |
timeBounding.js |
Temporal Filtering | Filters assertions by targetDateTime, removing expired or not-yet-valid evidence |
explainer.js |
Explanation Generation | Produces human-readable narrative explanations of how each competency’s status was determined |
template.js |
Extension Point | Template for implementing custom coprocessors |
flowchart TD
Req["GET /api/profile/latest\n?frameworkId=...&subject="] --> Ctrl["controller.js\nParse parameters"]
Ctrl --> Coord["coordinator.js\nCheck cache (PROFILE_TTL)"]
Coord -- "Cache HIT" --> Return["Return cached result"]
Coord -- "Cache MISS" --> Worker["Spawn worker.js\n(node-worker-threads-pool)"]
Worker --> Load["Worker loads cassproject\nFetches framework, competencies, assertions"]
Load --> P1["default.js"]
P1 --> P2["direct.js"]
P2 --> P3["conditions.js"]
P3 --> P4["timeBounding.js"]
P4 --> P5["explainer.js"]
P5 --> Cache["Store in cache if enabled"]
Cache --> Resp["JSON response to client"]
Return --> Resp
Project-unique identifier: CASS-SRV-SHIMS
Source: src/main/server/shims/ (10 files + util/)
Language: JavaScript
Shims provide cross-cutting runtime infrastructure: authentication, event bus, backward compatibility, cryptographic identity, logging, email, and background job scheduling.
| File | Identifier | Lines | Purpose |
|---|---|---|---|
auth.js |
SHIM-AUTH |
~858 | Central authentication middleware. Implements four auth modes (KBAC signature sheets, OIDC/SSO via express-openid-connect, JWT via express-jwt, Platform One). Only one mode active at a time; selection based on environment variables. Manages admin cache and identity resolution. |
event.js |
SHIM-EVENT |
— | RxJS-based event bus. Creates global.events with Subjects for server, database, person, data event categories. Enables decoupled, reactive module communication. |
levr.js |
SHIM-LEVR |
~679 | LEVR compatibility layer. Provides bindWebService() for adapter route registration, httpGet/Post/Put/Delete helpers, file I/O operations, and request body parsing. Bridges legacy LEVR API to Express 5. |
cassproject.js |
SHIM-CASS |
— | SDK import shim. Imports key classes from the cassproject npm package (EcIdentity, EcPpk, EcPk, EcRepository, etc.) and makes them available as globals. |
auditLogger.js |
SHIM-AUDIT |
— | Structured audit logging. Provides report(category, severity, source, message) with filterable categories (SYSTEM, NETWORK, AUTH, DATA, ADAPTER) and severities (DEBUG through EMERGENCY). Supports flush and file-based logging in production mode. |
ephemeral.js |
SHIM-EPHEM |
— | Ephemeral data store. Stores TTL-based temporary data in an Elasticsearch ephemeral index. Periodic cleanup via _delete_by_query on expired entries. Used for signature sheet caches and transient computation state. |
jobs.js |
SHIM-JOBS |
— | Background job scheduler. Manages periodic tasks (disk space monitoring) with cron-style scheduling. |
mailer.js |
SHIM-MAIL |
— | SMTP email. Uses nodemailer to send alerts for uncaught exceptions, disk warnings, and administrative events. Configurable via SMTP_* environment variables. |
http2compat.js |
SHIM-H2 |
— | HTTP/2 compatibility shim. Bridges HTTP/2 push-stream behavior for environments that require HTTP/1.1 compatibility. |
stjs.js |
SHIM-STJS |
— | Schema.org type utilities. Provides type-checking and type-resolution functions for JSON-LD objects. |
util/sharedAdminCache.js |
SHIM-ADMCACHE |
— | Admin key cache. Caches admin public keys for fast KBAC checks, reducing repeated Elasticsearch lookups. |
Project-unique identifier: CASS-SRV-ADAPTERS
Source: src/main/server/cartridge/adapter/ (13 files)
Language: JavaScript
Protocol adapters enable CaSS to import from, export to, and interoperate with external standards-based systems. Each adapter is a self-contained module that registers its own Express routes using bindWebService().
Adapters follow a cartridge pattern:
.js file in the cartridge/adapter/ directory.server.js uses glob to discover and require() all adapter files.bindWebService() (from levr.js) to register its HTTP routes.DISABLED_ADAPTERS environment variable (comma-separated list of adapter names).| File | Identifier | Size | Endpoints | Description |
|---|---|---|---|---|
ceasn.js |
ADAPT-CEASN |
~89 KB | /api/ceasn/*, /api/ctdlasn/* |
CTDL-ASN adapter. The largest adapter. Imports and exports competency frameworks in Credential Transparency Description Language format. Handles complex JSON-LD context mapping, property translation, and CTDL vocabulary conformance. |
caseAdapter.js |
ADAPT-CASE |
— | /api/ims/case/v1p0/* |
IMS CASE v1.0 read API. Implements 11 endpoints (CFDocuments, CFItems, CFAssociations, CFPackages, CFSubjects, etc.) for standards-compliant CASE data access. |
caseIngest.js |
ADAPT-CASEIN |
— | POST /api/ims/case/harvest |
CASE bulk import. Harvests competency frameworks from external CASE-compliant servers. |
asn.js |
ADAPT-ASN |
— | /api/asn/* |
ASN adapter. Imports/exports Achievement Standards Network XML and JSON formats. Uses @xmldom/xmldom for XML parsing. |
openbadges.js |
ADAPT-BADGES |
— | /api/badge/* |
Open Badges 2.0. Exposes badge profile, class, and assertion endpoints in OBv2 format. |
xapi.js |
ADAPT-XAPI |
— | /api/xapi/* |
xAPI adapter. Fetches Experience API statements from configured LRS endpoints, converts them to CaSS assertions. Supports OIDC client authentication for LRS access. |
pna.js |
ADAPT-PNA |
— | /api/ce/pna/* |
Portable Native Assertions. Reads/writes assertion data to local filesystem or AWS S3 buckets. Configurable via PNA_* environment variables. |
scd.js |
ADAPT-SCD |
— | /api/scd/* |
Service Component Documentation. Read-only adapter for SCD data. |
ollama.js |
ADAPT-OLLAMA |
— | POST /api/ollama/framework |
AI-assisted framework generation. Uses Ollama (local LLM) to generate competency frameworks from natural language prompts. |
replicate.js |
ADAPT-REPL |
— | (internal) | Server-to-server replication. Enables data synchronization between CaSS instances. Uses dedicated replication key pair (CASS_REPLICATION_PPK). |
jsonLd.js |
ADAPT-JSONLD |
— | POST /api/jsonld |
JSON-LD context resolution. Resolves JSON-LD @context references. |
mcp.js |
ADAPT-MCP |
— | /api/mcp |
Model Context Protocol. Auto-generates MCP tools from OpenAPI spec; serves AI agent tool invocations. |
profile.js |
ADAPT-PROFILE |
— | /api/profile/* |
Profile bridge. Routes profile calculation requests to the profile engine subsystem. |
Project-unique identifier: CASS-LIB
Source: node_modules/cassproject/ (installed), GitHub
Version: Current
Language: JavaScript
The cassproject npm package is the official JavaScript SDK. It provides typed data model classes, CRUD operations, cryptographic identity management, and import/export utilities. It is used both server-side (by CaSS itself) and client-side (bundled into the CaSS editor).
classDiagram
EcLinkedData <|-- EcRemoteLinkedData
EcRemoteLinkedData <|-- Competency
EcRemoteLinkedData <|-- Framework
EcRemoteLinkedData <|-- Assertion
EcRemoteLinkedData <|-- Relation
EcRemoteLinkedData <|-- Level
EcRemoteLinkedData <|-- RollupRule
EcRemoteLinkedData <|-- Directory
EcRemoteLinkedData <|-- GeneralFile
EcRemoteLinkedData <|-- Concept
EcRemoteLinkedData <|-- ConceptScheme
EcRemoteLinkedData <|-- EncryptedValue
Competency <|-- EcCompetency
Framework <|-- EcFramework
Assertion <|-- EcAssertion
Relation <|-- EcAlignment
Level <|-- EcLevel
RollupRule <|-- EcRollupRule
Directory <|-- EcDirectory
GeneralFile <|-- EcFile
Concept <|-- EcConcept
ConceptScheme <|-- EcConceptScheme
EncryptedValue <|-- EcEncryptedValue
class EcCompetency { CRUD + alignment/level management }
class EcFramework { CRUD + competency/relation management }
class EcAssertion { encrypted subject/agent }
class EcAlignment { source → target with type }
class EcLevel { proficiency levels }
class EcRollupRule { aggregation rules }
class EcEncryptedValue { encrypted object wrapper }
note for EcRemoteLinkedData "Also includes 180+ schema.org types,\n40+ Credential Engine types, S3000L types"
| Class | Purpose | Key Methods |
|---|---|---|
EcRepository |
Primary CRUD interface (~2,042 lines) | .get(id), .search(query), .save(obj), ._delete(obj), .getAs(id, type), .searchAs(query, type) |
EcIdentityManager |
Manages owned identities and contacts | .addIdentity(identity), .getSignatureSheet(server), .getPpk(pk) |
EcIdentity |
Single identity (key pair + display name) | .ppk, .displayName |
EcPpk |
Private key wrapper | .fromPem(pem), .sign(data), .decrypt(data) |
EcPk |
Public key wrapper | .fromPem(pem), .verify(data, signature), .encrypt(data) |
EcEncryptedValue |
Encrypted data wrapper | .encryptValue(data, id, owner, reader), .decryptIntoObject(ev) |
EcRemote |
Low-level HTTP wrapper | .postExpectingString(url, formData), .getExpectingObject(url) |
EcLinkedData |
Base JSON-LD object | .toJson(), .copyFrom(obj), .isA(type), .getFullType() |
EcRemoteLinkedData |
Remote-storable object | .owner[], .reader[], .signature[], .addOwner(pk), .addReader(pk) |
On require("cassproject"), all classes are registered as global.* properties (via exports.js, 1,536 lines). No destructuring or module imports needed—classes are available globally throughout the CaSS server codebase.
| Class | Format | Direction |
|---|---|---|
ASNImport |
ASN XML/JSON | Import |
CSVImport / CSVExport |
CSV | Import / Export |
CTDLASNCSVImport |
CTDL-ASN CSV | Import |
CTDLASNCSVConceptImport |
CTDL-ASN concept taxonomy CSV | Import |
MedbiqImport |
MedBiquitous XML | Import |
FrameworkImport |
Generic JSON-LD | Import |
TabStructuredImport |
Tab-indented text | Import |
| Package | Purpose |
|---|---|
node-forge |
RSA/AES cryptography (fallback; native crypto preferred) |
jsonld |
JSON-LD processing |
papaparse |
CSV parsing |
base64-arraybuffer |
Base64 encoding |
web-worker / promise-worker |
Web Worker polyfill |
Project-unique identifier: CASS-UI-EDITOR
Source: src/main/webapp/ (pre-built output), GitHub (source)
Technology: Vue.js 2, Vue CLI, Webpack
Language: JavaScript
The CaSS editor is the primary user-facing web application for authoring, browsing, importing, exporting, and managing competency frameworks. It is a single-page application (SPA) served as static files by the CaSS server.
The Express server mounts the editor at both / and /cass-editor/ as static files with 24-hour cache:
app.use(baseUrl, express.static('src/main/webapp/', { maxAge: 24*60*60*1000 }));
app.use(baseUrl + "cass-editor/", express.static('src/main/webapp/', { maxAge: 24*60*60*1000 }));
Can be disabled via DISABLED_EDITOR=true.
The editor uses Webpack code-splitting to lazy-load route-level components:
| Route/Feature | Purpose | Description |
|---|---|---|
| Framework | Core editor | Create, edit, browse, delete competency frameworks with rich metadata editing |
| Crosswalk | Alignment tool | Align competencies across different frameworks with drag-and-drop mapping |
| Concepts / Concept Scheme | Taxonomy management | SKOS-compliant concept and taxonomy authoring |
| Progression Model | Progression authoring | Learning progression sequence modeling |
| Directory | Framework browser | Browse, search, and organize published frameworks |
| Import | Data ingestion | Import from CSV, MedBiquitous XML, JSON-LD, IMS CASE, CTDL-ASN (~2.1 MB chunk) |
| Login | Authentication | Login UI for key-based, OIDC, or SSO authentication |
| Configuration Editor | Settings manager | Customize editor properties, relationship types, resource types |
| User Group Editor | Permissions | Manage readers, authors, admins per framework |
| Organizations / Organization | Org management | Organizational structure management |
| Plugin Manager / Plugin Container | Extensibility | Plugin lifecycle management with iframe isolation |
| Timeline | Version history | Browse object version history |
| Welcome / About | Information | Landing page and system information |
cassproject SDK bundled into the client handles all API communication, signature sheet generation, and cryptographic operations.cassproject SDK, which prefers the native Web Crypto API / Node.js crypto module and falls back to node-forge for operations not available natively (e.g., certain RSA-OAEP and AES modes).The editor is designed to be embedded in third-party applications via <iframe>:
X-Frame-Options: SAMEORIGIN header is controllable via INCLUDE_SAMEORIGIN_IFRAME_HEADER.Project-unique identifier: CASS-SRV-MCP
Source: src/main/server/mcp/ + src/main/server/cartridge/adapter/mcp.js
Language: JavaScript
The MCP (Model Context Protocol) server enables AI agents to interact with CaSS using natural-language tool invocation. It auto-generates MCP tool definitions from the CaSS OpenAPI specification.
| File | Purpose |
|---|---|
lib/openapi-to-tools.js |
Converts OpenAPI 3.0 endpoint definitions to MCP tool definitions (name, description, input schema) |
lib/json-schema-to-zod.js |
Converts JSON Schema definitions to Zod validation schemas for runtime parameter validation |
lib/http-client.js |
HTTP client wrapper for executing MCP tool calls against the CaSS REST API |
adapter/mcp.js |
Express route handler mounting MCP at /api/mcp using the MCP SDK v2 (@modelcontextprotocol/server + @modelcontextprotocol/node) Streamable HTTP transport |
flowchart LR
Agent["AI Agent"] --> Client["MCP Client"]
Client -- "POST /api/mcp\n(Streamable HTTP)" --> SDK["MCP SDK\nRoute to tool handler"]
SDK --> Map["openapi-to-tools\nMap tool name to API endpoint"]
Map --> Validate["json-schema-to-zod\nValidate parameters"]
Validate --> Call["http-client\nExecute internal API call"]
Call --> Response["MCP tool response"]
The following table maps key system requirements to the CaSS components that implement them. Requirements are derived from the system’s stated purpose, referenced standards, and the DI-IPSC-81433A Software Requirements Specification Template.
| Requirement | Description | Implementing Component(s) |
|---|---|---|
| REQ-DATA-01 | Store and retrieve competency frameworks as JSON-LD linked data | CASS-SRV-SKYREPO (data.js, get.js, put.js), CASS-LIB (EcFramework, EcCompetency) |
| REQ-DATA-02 | Full-text search across all stored objects | CASS-SRV-SKYREPO (search.js, searchUtil.js) |
| REQ-DATA-03 | Version history for all objects | CASS-SRV-SKYREPO (history.js, put.js — permanent index) |
| REQ-DATA-04 | Batch CRUD operations | CASS-SRV-SKYREPO (multiget.js, multiput.js, multidelete.js) |
| REQ-SEC-01 | Key-Based Access Control (KBAC) for all data operations | CASS-SRV-SKYREPO (kbac.js), CASS-LIB (EcIdentityManager, EcPpk, EcPk) |
| REQ-SEC-02 | Object-level encryption for privacy-sensitive data | CASS-LIB (EcEncryptedValue), CASS-SRV-SKYREPO (kbac.js — reader check) |
| REQ-SEC-03 | FIPS 140-3 cryptographic compliance | Docker images (OpenSSL), CASS-LIB (native crypto with node-forge fallback), CASS-SRV-SKYREPO (kbac.js — SHA-256) |
| REQ-SEC-04 | OIDC/SSO authentication | CASS-SRV-SHIMS (auth.js — express-openid-connect) |
| REQ-SEC-05 | TLS/HTTPS with HTTP/2 support | CASS-SRV-CORE (server.js — https, http2compat) |
| REQ-SEC-06 | Audit logging | CASS-SRV-SHIMS (auditLogger.js) |
| REQ-PROFILE-01 | Compute learner profiles from assertions against frameworks | CASS-SRV-PROFILE (controller.js, coordinator.js, calculator.js, worker.js) |
| REQ-PROFILE-02 | Pluggable profile calculation coprocessors | CASS-SRV-PROFILE (coprocessors/*.js) |
| REQ-PROFILE-03 | Profile caching with configurable TTL | CASS-SRV-PROFILE (coordinator.js — PROFILE_TTL, PROFILE_CACHE) |
| REQ-INTEROP-01 | CTDL-ASN import/export | CASS-SRV-ADAPTERS (ceasn.js) |
| REQ-INTEROP-02 | IMS CASE v1.0 read API compliance | CASS-SRV-ADAPTERS (caseAdapter.js — 11 endpoints) |
| REQ-INTEROP-03 | xAPI statement ingestion | CASS-SRV-ADAPTERS (xapi.js) |
| REQ-INTEROP-04 | Open Badges 2.0 endpoints | CASS-SRV-ADAPTERS (openbadges.js) |
| REQ-INTEROP-05 | ASN import/export | CASS-SRV-ADAPTERS (asn.js) |
| REQ-INTEROP-06 | Server-to-server data replication | CASS-SRV-ADAPTERS (replicate.js) |
| REQ-INTEROP-07 | MCP (AI agent) integration | CASS-SRV-MCP (mcp.js, openapi-to-tools.js) |
| REQ-UI-01 | Web-based framework authoring and management | CASS-UI-EDITOR (Framework, Crosswalk, Import routes) |
| REQ-UI-02 | Framework import from CSV, XML, JSON-LD formats | CASS-UI-EDITOR (Import route), CASS-LIB (importers) |
| REQ-UI-03 | SKOS concept/taxonomy management | CASS-UI-EDITOR (Concepts, ConceptScheme routes) |
| REQ-UI-04 | User/group permission management | CASS-UI-EDITOR (UserGroupEditor route) |
| REQ-UI-05 | Embeddable via iframe | CASS-UI-EDITOR (iframe mode, URL parameter config) |
| REQ-DEPLOY-01 | Docker containerized deployment | Docker images (4 variants), Docker Compose (7 configs) |
| REQ-DEPLOY-02 | Kubernetes deployment | K8s manifests (StatefulSet, Deployment, PVC, Ingress) |
| REQ-DEPLOY-03 | Environment-variable-based configuration | CASS-SRV-CORE (80+ env vars per ENVIRONMENT.md) |
| REQ-API-01 | OpenAPI 3.0 documented REST API | CASS-SRV-CORE (swagger.json, swagger-jsdoc), /api/swagger |
| REQ-API-02 | WebSocket real-time change notifications | CASS-SRV-CORE (websocket.js — /ws/custom) |
| REQ-AVAIL-01 | Health check endpoint | CASS-SRV-SKYREPO (ping.js — GET /api/ping) |
| REQ-AVAIL-02 | Horizontal scalability | Stateless server + shared Elasticsearch + shared etc/ volume |
This document was generated from automated analysis of the CaSS codebase, the cassproject npm package, the pre-built CaSS editor output, and publicly available documentation at docs.cassproject.org and devs.cassproject.org.
The system was originally developed in Java and was re-architectured to Node.js in the 1.5.x series. Some design patterns (e.g., the levr.js compatibility shim, the bindWebService function, and the class inheritance hierarchy in cassproject) reflect this heritage.
| Acronym | Meaning |
|---|---|
| ADL | Advanced Distributed Learning Initiative |
| AES | Advanced Encryption Standard |
| ASN | Achievement Standards Network |
| CASE | Competency and Academic Standards Exchange |
| CaSS | Competency and Skills System |
| CORS | Cross-Origin Resource Sharing |
| CRL | Certificate Revocation List |
| CRUD | Create, Read, Update, Delete |
| CSCI | Computer Software Configuration Item |
| CTDL | Credential Transparency Description Language |
| CTDL-ASN | CTDL — Achievement Standards Network extension |
| DID | Data Item Description |
| ECK | Elastic Cloud on Kubernetes |
| ES | Elasticsearch |
| FIPS | Federal Information Processing Standards |
| HSTS | HTTP Strict Transport Security |
| HTTP/2 | Hypertext Transfer Protocol version 2 |
| HWCI | Hardware Configuration Item |
| IDD | Interface Design Description |
| IdP | Identity Provider |
| JSON-LD | JavaScript Object Notation for Linked Data |
| JWT | JSON Web Token |
| KBAC | Key-Based Access Control |
| K8s | Kubernetes |
| LEVR | A functional, JSON-centric programming language (legacy platform) |
| LMS | Learning Management System |
| LRS | Learning Record Store |
| MCP | Model Context Protocol |
| mTLS | Mutual TLS (client certificate authentication) |
| OBv2 | Open Badges version 2.0 |
| OIDC | OpenID Connect |
| P1 | Platform One (DoD DevSecOps platform) |
| PEM | Privacy-Enhanced Mail (key encoding format) |
| PII | Personally Identifiable Information |
| PKI | Public Key Infrastructure |
| PNA | Portable Native Assertions |
| PVC | Persistent Volume Claim (Kubernetes) |
| REST | Representational State Transfer |
| RSA | Rivest–Shamir–Adleman (asymmetric cryptosystem) |
| RSA-OAEP | RSA Optimal Asymmetric Encryption Padding |
| RWX | ReadWriteMany (Kubernetes volume access mode) |
| RxJS | Reactive Extensions for JavaScript |
| S3 | Amazon Simple Storage Service |
| SCD | Service Component Documentation |
| SKOS | Simple Knowledge Organization System |
| SPA | Single-Page Application |
| SPDY | HTTP/2 predecessor protocol |
| SRS | Software Requirements Specification |
| SSDD | System/Subsystem Design Description |
| SSO | Single Sign-On |
| TLS | Transport Layer Security |
| TTL | Time-To-Live |
| URI | Uniform Resource Identifier |
| W3C | World Wide Web Consortium |
| WS | WebSocket |
| xAPI | Experience API (Tin Can API) |
| Term | Definition |
|---|---|
| Assertion | A claim or piece of evidence about an individual’s attainment of a competency at a certain performance level. Assertions can be encrypted to protect privacy. |
| Cartridge | A dynamically-loadable protocol adapter module placed in the cartridge/adapter/ directory. |
| Competency | A human-readable and machine-actionable object representing a skill, knowledge area, ability, trait, or learning outcome. |
| Competency Framework | A structured collection of competencies organized as a directed graph, with relationships (edges) and metadata. |
| Coprocessor | A pluggable computation module in the profile calculation pipeline that processes assertions to determine competency attainment. |
| Crosswalk | An alignment mapping between competencies in different frameworks, establishing equivalency or hierarchical relationships. |
| Ephemeral Store | A TTL-based temporary data store backed by a dedicated Elasticsearch index, used for transient computation state. |
| Framework | See Competency Framework. |
| Identity | An RSA key pair (public + private key) that represents an actor in the CaSS system. Identities sign requests and own objects. |
| JSON-LD | JavaScript Object Notation for Linked Data; the native data serialization format for all CaSS objects. |
| KBAC | Key-Based Access Control; CaSS’s foundational authorization mechanism based on RSA cryptographic signatures rather than traditional role-based access. |
| Level | A performance or proficiency level associated with a competency (e.g., “Novice,” “Proficient,” “Expert”). |
| Profile | A computed summary of an individual’s competency attainment across a framework, derived from aggregated assertions. |
| Relation | A typed, directed link between two competencies (e.g., “narrows,” “requires,” “isEquivalentTo”). |
| Roll-up Rule | A rule that defines how mastery of one competency is computed from mastery of related competencies (graph-based aggregation). |
| Signature Sheet | A time-limited, RSA-signed token array that proves key ownership. Attached to each authenticated CaSS request. |
| SkyRepo | The internal name for CaSS’s data persistence layer (JSON-LD object store over Elasticsearch). |
See ENVIRONMENT.md for the complete reference of 80+ environment variables, organized by functional category:
| Index Name Pattern | Content | Versioning |
|---|---|---|
schema.cassproject.org.0.4.framework |
Current version of Framework objects | External (timestamp-based) |
schema.cassproject.org.0.4.competency |
Current version of Competency objects | External |
schema.cassproject.org.0.4.assertion |
Current version of Assertion objects | External |
schema.cassproject.org.kbac.0.2.encryptedvalue |
Encrypted value wrappers | External |
schema.org.person |
Person objects | External |
permanent |
All historical versions of all objects | External |
ephemeral |
TTL-based temporary data (mappings disabled) | Internal |
Index names are derived by lowercasing and dot-delimiting the JSON-LD @type value.
| Variant | Base Image | Dockerfile | Compose File | Notes |
|---|---|---|---|---|
| Default | node:lts-slim (Debian) |
docker/standalone/node/Dockerfile |
docker-compose.yml |
FIPS OpenSSL; recommended for production |
| Alpine | node:lts-alpine |
DockerfileAlpine |
docker-compose-alpine.yml |
~40% smaller image |
| Distroless | gcr.io/distroless/nodejs-debian |
DockerfileDistroless |
docker-compose-distroless.yml |
Minimal attack surface; no shell |
| OIDC | Same as default | Same as default | docker-compose-oidc.yml |
Includes Keycloak for SSO |
| Platform One | Iron Bank nodejs16 |
DockerfileP1 |
— | DoD Iron Bank hardened image |
The complete, machine-readable OpenAPI 3.0 specification is maintained at src/main/swagger.json and served live at GET /api/swagger.json. Interactive documentation is available at /api/swagger/.
The specification covers validated endpoints across the API surface, tested by the automated test suite (4.swagger.test.js, 4.swagger.schema.test.js).
| Test File | Scope | Description |
|---|---|---|
0.harness.test.js |
Infrastructure | Starts server, waits for readiness |
1.skyRepo.test.js |
Data Layer | SkyRepo CRUD operations |
1.skyrepo.admin.test.js |
Data Layer | Admin endpoint tests |
2.EcRepository.l0.test.js |
SDK + Security | EcRepository at security level 0 (public) |
2.EcRepository.l1.test.js |
SDK + Security | EcRepository at level 1 (owned) |
2.EcRepository.l2.test.js |
SDK + Security | EcRepository at level 2 (encrypted) |
2.EcRepository.sso.l0.test.js |
SDK + SSO | EcRepository SSO variant, level 0 |
2.EcRepository.sso.l1.test.js |
SDK + SSO | EcRepository SSO variant, level 1 |
2.EcRepository.sso.l2.test.js |
SDK + SSO | EcRepository SSO variant, level 2 |
3.profile.test.js |
Profile Engine | Profile calculation tests |
3.xapi.test.js |
Adapter | xAPI adapter integration |
4.swagger.test.js |
API Compliance | OpenAPI endpoint validation |
4.swagger.schema.test.js |
API Compliance | Response schema validation (Ajv) |
5.mcp.*.test.js |
MCP | JSON-schema-to-zod + openapi-to-tools |
8.asn.test.js |
Adapter | ASN import/export |
8.case.test.js |
Adapter | IMS CASE adapter |
8.ceasn.test.js |
Adapter | CTDL-ASN adapter |
9.restore.test.js |
Admin | Backup/restore functionality |