1 Overview
1.1 What is C2E?
C2E is an “Open Document Specification” that enables the Creation and distribution of secure, portable, licensable, and quality-assured digital educational content. C2E is an open-source project that publishes the C2E Document Specification, its APIs and its MIT-licensed reference implementations that support the creation and distribution of secure, portable, licensable, and quality-assured digital educational content maintained by the non-profit Curriki.org.
C2E aims to create an open specification, publish an open API, and drive a vibrant ecosystem that delivers on the promise of high-quality digital educational experiences for all.
1.2 C2E Goals
Portability
Digital educational resources should execute on any device, on any operating system, and on any learning or content management system, known or future. The construct of digital educational resources should be modular in nature so they can be adapted to future devices and technologies:
- C2E’s play on any device or browser.
- C2Es support online and offline consumption.
- C2E technology supports the delivery of content to all the leading learning and content distribution platforms.
Protection
Digital educational resources should be tamper-proof to maintain their academic integrity, as well as their economic value. Their structure should protect and help enforce any of its inherent copyrights and licensing agreements. The model should encourage the creation of digital educational content under the terms of open licenses such as the Creative Commons, but it should not exclude support for commercial and royalty-based licensing:
- C2Es enforces digital media licenses, rights, and security throughout the ecosystem, which reduces the risk of piracy.
- C2Es authenticate the content is unaltered. Easily tells the difference between derivative and original works.
- C2Es protect learner privacy, encourage student agency, and enable student-owned portfolios
Vetted Quality
Digital education resources should be subject to processes that guarantee and verify their quality and accuracy. Automation, Artificial Intelligence, crowd-sourced peer reviews, rating and review systems, and the application of quality control and quality assurance practices should be part and parcel of the digital education resource creation system.
Economic Viability
The digital education resource ecosystem supported by the C2E specification should provide economic incentives to the authors of premium media that augment the quality and enjoyability of educational experiences. The ecosystem should compensate media publishers, authors and creators, and curators of high-quality digital educational content. The authors/creators and curators of high-quality digital education resources are normally marginalized and not compensated equitably for their value in raising human capital on a global scale:
- C2Es enable the accurate collection of payments and royalties from the sale and consumption of the C2E Resources.
- C2Es generate an auditable record of the distribution and usage of C2Es for creators and media owners.
- C2Es reduce the cost of interactive content by removing barriers between media owners, creators, and learners.
1.3 C2E Data Model
The C2E data model is composed of linked data from different data structures shown below. ISCN data is JSON-LD compatible:
- Meta Data: “metadata” attribute are used to define details of the metadata starting with the basic structures, and moving to the more detailed metadata
- C2E Contain: “c2eContain” is a container object that has the following important structures that explains the overall C2E document:
- C2E Resources: “c2ens:c2eResources” is used to list all the resources which are expected to be physical files in the package.
- C2E Models: “c2ens:c2eModels” is used to expand C2E structures that extend Schema’s CreativeWork.
- C2E Source Code: “c2ens:c2eSourceCode” is used to define the script that will execute the C2E.
- Associated C2Es: “c2ens:c2eComponents” is used to define the list of associated C2Es. This gives the ability to include multiple C2Es as components of a C2E.
1.4 C2E Basic CLASS STRUCTURE
C2E defines a distribution and interchange format for digital publications and documents. The C2E Package consists of a special JSON-LD file describing the resources in a Package, with modeling and execution instructions being described by the JSON-LD. The special JSON-LD file is called the C2E Manifest file. The basic architecture of an C2E is reflected in the sample C2E Manifest diagram shown below:
2 C2E Architecture
C2E encompasses an ‘Open Document Specification’ and a set of Open APIs designed to facilitate the synchronization of extensible JSON objects representing various components of a C2E document. Source platforms, such as CurrikiStudio, leverage the C2E Writer SDK to define the content types for a single C2E document. These content types serve as a blueprint for structuring C2E content objects, ensuring seamless integration between the source platforms’ application objects and the corresponding C2E document elements.
Additionally, source platforms like CurrikiStudio can connect to the C2E Wallet application, which houses the C2E Builder. By implementing the ‘Source Search API’ specification, CurrikiStudio, for example, enables the generation of a C2E content index. This index becomes a valuable resource for a C2E Builder, empowering it to efficiently locate and gather the necessary C2E content objects required for constructing a comprehensive C2E document. Through this integration, CurrikiStudio demonstrates how the defined content types, the C2E content index, and the licensing and marketplace capabilities collectively contribute to a seamless connection between its application objects and the corresponding C2E document elements.
Within the C2E ecosystem, elements can contain digital media, which can be licensed, protected, and published to a marketplace. This feature allows for the monetization and distribution of media assets within the C2E framework. For example, source platforms like CurrikiStudio — an authoring platform that includes Projects, Playlists, and Activities as its application objects — enable the addition of licensed media content to C2E elements. By leveraging licensing mechanisms, media assets can be protected and securely integrated into the C2E ecosystem. These licensed media assets can then be published to a marketplace, providing creators with opportunities to showcase and commercialize their content.
2.1 C2E Identity Provider
Identity Access Management (IAM) solutions enable businesses to unlock additional value across all their products and services. C2E leverages these capabilities in modern identity frameworks.
Custom Identity Provider: You can establish a custom identity provider, granting users access to multiple C2E services such as C2E Wallet, Source Platform, C2E Writer, and C2E Player through OAuth2 authentication.
OpenID Connect (OIDC) Provider (Social Login): The C2E architecture also supports the setup of a generic OpenID Connect (OIDC) provider for social logins. This functionality allows integration with and utilization of a third-party OIDC provider for authentication purposes.
Useful Links:
- Creating a custom identity provider: IndyKite Custom Identity Provider Documentation
- Setting up a generic OIDC provider: IndyKite OIDC Provider Setup Documentation
2.1.1 Open API Specification
As a C2E application/service implementing OIDC OAuth2, you will need the following endpoints to receive responses from the authorization server:
- Callback URI: GET /c2e/oauth2/callback
This URI is where the authorization server redirects the user after the authentication and authorization process. During the initial authorization request, your C2E application/service specifies this URI as the callback endpoint. The authorization server includes the authorization code or access token in the query parameters of the redirect URL.
- Token Endpoint (for receiving access tokens): POST /c2e/oauth2/token
This endpoint is used by your C2E application to exchange the authorization code received in the callback for an access token. Your application sends a POST request to this endpoint, including the authorization code in the request parameters or body. The authorization server responds with an access token that your C2E application can use to access protected resources.
These are the primary endpoints that your C2E application needs to handle in the OIDC OAuth2 flow to receive responses from the authorization server. Depending on your specific requirements, you may also need to implement additional endpoints such as token revocation or token refresh, as specified by the OIDC specification or any optional features you wish to support.
Please keep in mind that the actual endpoint URLs may differ based on your implementation and the authorization server you are integrating with. Make sure to consult the documentation provided by your authorization server for the precise endpoint URLs and any additional endpoints required for proper communication.
2.2 C2E Registry Service
The C2E Registry Service is responsible for assigning unique IDs to C2E entities using the pattern c2eid-xxxxx, where ‘xxxxx’ is determined by an algorithm specifically designed for generating unique IDs. This ensures that the Register Service can handle scenarios where there may be collisions or conflicts in generating these IDs. The service implements strategies such as retries, fallback mechanisms, and error handling to effectively address such situations and ensure the uniqueness and integrity of the generated IDs.
2.2.1 Open API Specification
Here are sample API endpoints for a C2E Register Service API using the ‘/c2e/documents/register’ pattern:
- Register a new C2E document: POST /c2e/documents/register
This endpoint is used to register a new C2E document and generate a unique ID for it. The request body should contain the necessary information for the document being registered.
- Get details of a registered C2E document:
GET /c2e/documents/register/{id}
This endpoint retrieves the details of a registered C2E document by its unique ID.
- Update a registered C2E document: PUT /c2e/documents/register/{id}
This endpoint allows updating the details of a registered C2E document identified by its unique ID. The updated document information should be included in the request body.
- Delete a registered C2E document:
DELETE /c2e/documents/register/{id}
This endpoint is used to delete a registered C2E document by its unique ID.
- Generate a unique ID for a C2E document:
GET /c2e/documents/register/generate-id
This endpoint generates a unique ID that can be used for registering a new C2E document. It returns the generated ID as the response.
These are just suggested endpoint paths, and you can modify them to align with your application’s specific naming conventions or requirements. Ensure appropriate error handling and use of status codes in your API implementation.
2.3 C2E Document (package)
It will refer to this “C2E Specification Overview” confluence page.
https://curriki.atlassian.net/l/cp/mf1ui2N1
2.3.1 Open API Specification
2.3.1.1 C2E Metadata
C2E supports CRUD REST API endpoints for given JSON objects, excluding the “@type” and “@id” fields:
METADATA
Create Metadata:
POST /c2e/documents/{c2eid}/metadata
Sample Request:
{
“schemaVersion”: “1.0”
}
Sample Response:
{
“schemaVersion”: “1.0”
}
Read Metadata:
GET /c2e/documents/{c2eid}/metadata
Sample Response:
{
“schemaVersion”: “1.0”
}
Update Metadata:
PUT /c2e/documents/{c2eid}/metadata
Sample Request:
{
“schemaVersion”: “2.0”
}
Sample Response:
{
“schemaVersion”: “2.0”
}
Delete Metadata:
DELETE /c2e/documents/{c2eid}/metadata
Sample Response:
{
“message”: “Metadata deleted successfully.”
}
Please note that you need to replace {c2eid} with the actual ID of the C2E document. The response samples provided are for illustration purposes and may vary based on your implementation.
GENERAL METADATA
Create General Metadata:
POST /c2e/documents/{c2eid}/metadata/general
Sample Request:
{
“title”: “My Sample C2E”,
“description”: “My Sample C2E for Proof of Concept.”,
“keywords”: “c2e, e-learning, learning experience”
}
Sample Response:
{
“title”: “My Sample C2E”,
“description”: “My Sample C2E for Proof of Concept.”,
“keywords”: “c2e, e-learning, learning experience”
}
Read General Metadata:
GET /c2e/documents/{c2eid}/metadata/general
Sample Response:
{
“title”: “My Sample C2E”,
“description”: “My Sample C2E for Proof of Concept.”,
“keywords”: “c2e, e-learning, learning experience”
}
Update General Metadata:
PUT /c2e/documents/{c2eid}/metadata/general
Sample Request:
{
“title”: “Updated Sample C2E”,
“description”: “Updated Sample C2E for Proof of Concept.”,
“keywords”: “c2e, e-learning, learning experience”
}
Sample Response:
{
“title”: “Updated Sample C2E”,
“description”: “Updated Sample C2E for Proof of Concept.”,
“keywords”: “c2e, e-learning, learning experience”
}
Delete General Metadata:
DELETE /c2e/documents/{c2eid}/metadata/general
Sample Response:
{
“message”: “General metadata deleted successfully.”
}
Remember to replace {c2eid} with the actual ID of the C2E document. The provided samples are for illustration purposes and can be modified based on a specific implementation.
AUTHOR
Create Author:
POST /c2e/documents/{c2eid}/metadata/author
Sample Request:
{
“name”: “Waqar Muneer”,
“email”: “waqar@curriki.org”,
“url”: “<https://twitter.com/waqarmnr”>
}
Sample Response:
{
“name”: “Waqar Muneer”,
“email”: “waqar@curriki.org”,
“url”: “<https://twitter.com/waqarmnr”>
}
Read Author:
GET /c2e/documents/{c2eid}/metadata/author
Sample Response:
{
“name”: “Waqar Muneer”,
“email”: “waqar@curriki.org”,
“url”: “<https://twitter.com/waqarmnr”>
}
Update Author:
PUT /c2e/documents/{c2eid}/metadata/author
Sample Request:
{
“name”: “Updated Author”,
“email”: “updated-email@curriki.org”,
“url”: “<https://twitter.com/updated-author”>
}
Sample Response:
{
“name”: “Updated Author”,
“email”: “updated-email@curriki.org”,
“url”: “<https://twitter.com/updated-author”>
}
Delete Author:
DELETE /c2e/documents/{c2eid}/metadata/author
Sample Response:
{
“message”: “Author deleted successfully.”
}
Remember to replace {c2eid} with the actual ID of the C2E document. The provided samples are for illustration purposes and can be modified based on a specific implementation.
PUBLISHER
Create Publisher:
POST /c2e/documents/{c2eid}/metadata/publisher
Sample Request:
{
“name”: “Curriki”,
“email”: “info@curriki.org”,
“url”: “<https://curriki.org”>
}
Sample Response:
{
“name”: “Curriki”,
“email”: “info@curriki.org”,
“url”: “<https://curriki.org”>
}
Read Publisher:
GET /c2e/documents/{c2eid}/metadata/publisher
Sample Response:
{
“name”: “Curriki”,
“email”: “info@curriki.org”,
“url”: “<https://curriki.org”>
}
Update Publisher:
PUT /c2e/documents/{c2eid}/metadata/publisher
Sample Request:
{
“name”: “Updated Publisher”,
“email”: “updated-info@curriki.org”,
“url”: “<https://updated-curriki.org”>
}
Sample Response:
{
“name”: “Updated Publisher”,
“email”: “updated-info@curriki.org”,
“url”: “<https://updated-curriki.org”>
}
Delete Publisher:
DELETE /c2e/documents/{c2eid}/metadata/publisher
Sample Response:
{
“message”: “Publisher deleted successfully.”
}
Remember to replace {c2eid} with the actual ID of the C2E document. The provided samples are for illustration purposes and can be modified based on a specific implementation.
LIFECYCLE
Create Lifecycle:
POST /c2e/documents/{c2eid}/metadata/lifecycle
Sample Request:
{
“version”: “1.10”,
“releaseStatus”: “Beta”
}
Sample Response:
{
“version”: “1.10”,
“releaseStatus”: “Beta”
}
Read Lifecycle:
GET /c2e/documents/{c2eid}/metadata/lifecycle
Sample Response:
{
“version”: “1.10”,
“releaseStatus”: “Beta”
}
Update Lifecycle:
PUT /c2e/documents/{c2eid}/metadata/lifecycle
Sample Request:
{
“version”: “2.0”,
“releaseStatus”: “Stable”
}
Sample Response:
{
“version”: “2.0”,
“releaseStatus”: “Stable”
}
Delete Lifecycle:
DELETE /c2e/documents/{c2eid}/metadata/lifecycle
Sample Response:
{
“message”: “Lifecycle deleted successfully.”
}
Remember to replace {c2eid} with the actual ID of the C2E document. The provided samples are for illustration purposes and can be modified based on a specific implementation.
C2E RECORD (CreativeWork)
Create C2E Record
Endpoint for creating a CreativeWork:
POST /c2e/documents
Sample Input:
{
“id”: “c2ens:c2eid-xxx”,
}
Sample Response:
Status: 201 Created
{
“message”: “CreativeWork created successfully”
}
Endpoint for retrieving a CreativeWork:
GET /c2e/documents/{c2eid}
Sample Response:
Status: 200 OK
{
“@id”: “c2ens:c2eid-xxx”,
“@type”: “c2ens:CreativeWork”
}
Endpoint for updating a CreativeWork:
PUT /c2e/documents/{c2eid}
Sample Input:
{
“@id”: “c2ens:c2eid-xxx”,
“@type”: “c2ens:CreativeWork”
}
Sample Response:
Status: 200 OK
{
“message”: “CreativeWork updated successfully”,
“data”: {
“@id”: “c2ens:c2eid-xxx”,
“@type”: “c2ens:CreativeWork”
}
}
Endpoint for deleting a CreativeWork:
DELETE /c2e/documents/{c2eid}
Sample Response:
Status: 200 OK
{
“message”: “CreativeWork deleted successfully”
}
Please note that {c2eid} represents the unique ID of the CreativeWork. Replace it with the actual ID when making requests to these endpoints.
C2E RESOURCE
Create C2E Resource:
Create C2E Resource:
POST /c2e/documents/{c2eid}/c2eResources
Sample Request:
{
“url”: “/path/to/video.mp4”,
“fileFormat”: “application/json”
}
Sample Response:
{
“url”: “/path/to/video.mp4”,
“fileFormat”: “application/json”
}
Read C2E Resource:
GET /c2e/documents/{c2eid}/c2eResources/{resourceId}
Sample Response:
{
“url”: “/path/to/video.mp4”,
“fileFormat”: “application/json”
}
Update C2E Resource:
PUT /c2e/documents/{c2eid}/c2eResources/{resourceId}
Sample Request:
{
“url”: “/path/to/newvideo.mp4”,
“fileFormat”: “application/json”
}
Sample Response:
{
“url”: “/path/to/newvideo.mp4”,
“fileFormat”: “application/json”
}
Delete C2E Resource:
DELETE /c2e/documents/{c2eid}/c2eResources/{resourceId}
Sample Response:
{
“message”: “C2E Resource deleted successfully.”
}
List C2E Resources:
GET /c2e/documents/{c2eid}/c2eResources
Sample Response:
{
“resources”: [
{
“url”: “/path/to/video.mp4”,
“fileFormat”: “application/json”
},
{
“url”: “/path/to/image.jpg”,
“fileFormat”: “application/text”
}
]
}
Please note that the {c2eid} and {resourceId} placeholders should be replaced with the actual IDs of the C2E document and resource, respectively. The provided samples are for illustration purposes and can be adjusted according to a specific implementation.
C2E CONTENT TYPE
Create C2E Content Type:
POST /c2e/documents/{c2eid}/content-types
Sample Request:
[
{
“name”: “Property1”,
“type”: “string”
},
{
“name”: “Property2”,
“type”: “integer”
}
]
Sample Response:
{
“contentType”: {
“Property1”: {“@type”:”xsd:string”},
“Property2”: {“@type”:”xsd:integer”}
}
}
Read C2E Content Type:
GET /c2e/documents/{c2eid}/content-types/{contentTypeId}
Sample Response:
{
“contentType”: {
“Property1”: {“@type”:”xsd:string”},
“Property2”: {“@type”:”xsd:integer”}
}
}
Update C2E Content Type:
PUT /c2e/documents/{c2eid}/content-types/{contentTypeId}
Sample Request:
[
{
“name”: “Property1”,
“type”: “string”
},
{
“name”: “Property2”,
“type”: “integer”
}
]
Sample Response:
{
“contentType”: {
“Property1”: {“@type”:”xsd:string”},
“Property2”: {“@type”:”xsd:integer”}
}
}
Delete C2E Content Type:
DELETE /c2e/documents/{c2eid}/content-types/{contentTypeId}
Sample Response:
{
“message”: “C2E content type deleted successfully.”
}
List C2E Content Types:
GET /c2e/documents/{c2eid}/content-types
Sample Response:
{
“contentTypes”: [
{
“Property1”: {“@type”:”xsd:string”},
“Property2”: {“@type”:”xsd:integer”}
},
{
“Property1”: {“@type”:”xsd:string”},
“Property2”: {“@type”:”xsd:integer”}
}
]
}
Note: Replace {c2eid} with the actual C2E ID and {contentTypeId} with the ID of the specific C2E content type in the endpoint URLs.
C2E Source Code (Player Plugin)
Create C2E Source Code:
POST /c2e/documents/{c2eid}/source-code
Sample Request:
{
“url”: “/source/index.js”,
“fileFormat”: “application/javascript”
}
Sample Response:
{
“sourceCode”: {
“url”: “/source/index.js”,
“fileFormat”: “application/javascript”
}
}
Read C2E Source Code:
GET /c2e/documents/{c2eid}/source-code/{sourceCodeId}
Sample Response:
{
“sourceCode”: {
“url”: “/source/index.js”,
“fileFormat”: “application/javascript”
}
}
Update C2E Source Code:
PUT /c2e/documents/{c2eid}/source-code/{sourceCodeId}
Sample Request:
{
“url”: “/source/index.js”,
“fileFormat”: “application/javascript”
}
Sample Response:
{
“sourceCode”: {
“url”: “/source/index.js”,
“fileFormat”: “application/javascript”
}
}
Delete C2E Source Code:
DELETE /c2e/documents/{c2eid}/source-code/{sourceCodeId}
Sample Response:
{
“message”: “C2E source code deleted successfully.”
}
List C2E Source Code:
GET /c2e/documents/{c2eid}/source-code
Sample Response:
{
“sourceCode”: [
{
“url”: “/source/index.js”,
“fileFormat”: “application/javascript”
},
{
“url”: “/source/index.html”,
“fileFormat”: “text/html”
}
]
}
Note: Replace {c2eid} with the actual C2E ID and {sourceCodeId} with the ID of the specific C2E source code in the endpoint URLs.
2.5 C2E License
NOTE: C2E is basing its initial licensing model on those that are widely used by the industry, especially the Copyright Clearance Center models, and more specifically, the RightsLink workflow.
2.5.1 Open API Specification
These are sample CRUD REST API endpoints with the “/c2e/documents/{c2eid}” pattern, including “copyright”:
Create License
Endpoint: POST /c2e/documents/{c2eid}/copyright/licenses
Request Body:
{
“licenseNumber”: “C2e-lsc-xxxxx”,
“licenseDate”: “2023-01-01”,
“encodingFormat”: “text/plain or any binary as per need”,
“url”: “/path/to/license.txt”
}
Response Body:
{
“licenseNumber”: “C2e-lsc-xxxxx”,
“licenseDate”: “2023-01-01”,
“encodingFormat”: “text/plain or any binary as per need”,
“url”: “/path/to/license.txt”
}
Retrieve License:
Endpoint: GET /c2e/documents/{c2eid}/copyright/licenses/{licenseId}
Response Body:
{
“licenseNumber”: “C2e-lsc-xxxxx”,
“licenseDate”: “2023-01-01”,
“encodingFormat”: “text/plain or any binary as per need”,
“url”: “/path/to/license.txt”
}
Update License:
Endpoint: PUT /c2e/documents/{c2eid}/copyright/licenses/{licenseId}
Request Body: {
“licenseNumber”: “Updated License Number”,
“licenseDate”: “2023-01-01”,
“encodingFormat”: “text/plain or any binary as per need”,
“url”: “/path/to/license.txt”
}
Response Body:
{
“licenseNumber”: “Updated License Number”,
“licenseDate”: “2023-01-01”,
“encodingFormat”: “text/plain or any binary as per need”,
“url”: “/path/to/license.txt”
}
Delete License:
Endpoint: DELETE /c2e/documents/{c2eid}/copyright/licenses/{licenseId}
Response Body:
{
“message”: “License deleted successfully”
}
Please note that in the above endpoints, {c2eid} and {licenseId} are placeholders for the actual C2E ID and license ID, respectively.
2.6 C2E Protection
Protecting C2E from unauthorized user access, unlicensed user access and shared C2E across multiple users are important to handle the authenticity of utilization of Content and Royalty management.
In order to make C2E protected and accessible to legitimate users only, we following licensing mechanism which is mapped to the identity of the licensor who purchases the C2E and can only be accessible under the terms of the license in Online and Offline mode on a certified C2E Player/Reader.
How to achieve Protection in C2E
This is a core component of the Protection and License management Module which takes care of generating unique license keys which have information related to the content, the identity of the license purchaser, transaction details and validity. All this information together forms a string which is encrypted through the AES algorithm and sealed in the downloadable C2E package along with database entries for log and validation.
When an end user loads the C2E package one a certified C2E Reader/Player, it validates the authenticity by extracting the sealed license key and the details of user who has logged in to the C2E Wallet/Reader, details like content_id like ISBN/UUID by Making API call to a C2E Protection Service with the license and extracted information to check the authenticity. Once approved by the C2E Protection API Service, the end user will be able to consume the content and information can be stored in the device for offline access of the content.
C2E Protection API Service will check the information received as an encrypted API call and data available in the database. If a record matches with values stored in entries, then license will be accepted, otherwise a response will be sent with information like Invalid License Key, Invalid User Information, License expired, etc.
In order to validate/activate the purchased C2E on C2E Wallet or C2E Reader/Player, users will need one time internet connection to check the license information.
How this will safeguard from Intruder/Attacker/Shared Identity
As seen above, the license key has the information related to a user’ s identity, content information, transaction details like timestamp and validity, if other user uploads the same C2E on the C2E Wallet/Reader/Player it will not be authenticated because user information in the license key and user information on the C2E Wallet/Reader will not match and hence they will not able to consume the content.
Diagram 2 explains License Generation and Validation Processes.
Lets Understand this with the help of an example.
License Generation Process/User Journey
As shown in the user journey above,
- Actor / User search the C2E content on Marketplace listing and adds C2E to the Cart and makes checkout call
- The User will be taken to the checkout page where they can provide additional information if required, select the type of License like 1 time view, 3-time views, 1 year validity, etc and make the payment.
- On successful payment, following information will be sent to Protection API which will store the information in a database and generate a license key which will be based on the concatenation of following information and encryption using AES and will get stored in the database.
- User ID
- User Email
- Content ID like ISBN or UUID
- Date of Purchase
- Type of License and Tenure of License
- Validity
- As a payment was successful and an encrypted license key is generated, the user will have an option to download the C2E which will have a sealed license key in the package.
5. User can use the download C2E on Online or Offline C2E Readers
As shown in the user journey above,
- Actor / User search the C2E content on Marketplace listing and adds C2E to the Cart and makes checkout call
- The User will be taken to the checkout page where they can provide additional information if required, select the type of License like 1 time view, 3-time views, 1 year validity, etc and make the payment.
- On successful payment, following information will be sent to Protection API which will store the information in a database and generate a license key which will be based on the concatenation of following information and encryption using AES and will get stored in the database.
- User ID
- User Email
- Content ID like ISBN or UUID
- Date of Purchase
- Type of License and Tenure of License
- Validity
- As a payment was successful and an encrypted license key is generated, the user will have an option to download the C2E which will have a sealed license key in the package.
5. User can use the download C2E on Online or Offline C2E Readers
License Validation Process/User Journey
As shown in the user journey above,
- Actor / User logins to the C2E Reader/Player/Wallet
- Actor / User uploads the downloaded C2E Package on C2E Reader/Player/Wallet
- Application will validate the C2E Package in terms of the structure and extract the sealed encrypted license key and Content information like Content ID like ISB or UUID
- First Online Attempt to activate/validate the license and C2E Package. Application will make API call to C2E Protection Service with following information
- User ID
- User Email
- Content ID like ISBN or UUID
- Encrypted License Key
- Device Id or IP Address if possible (As Apple device does not allow to extract such information)
This information will be validated at server end on Protection Management API with the database and response will be provided with appropriate message and response code for Activation of License, Invalid License Key, Invalid User or License Expired, etc
If the license is validated and activated successfully, information will be stored on local device for future offline access by the user.
If the application is browser-based then encrypted information will be stored in sessions/cookies and if the application is android or ios apps then encrypted information will be stored in the storage area of the application.
Once the above activities are performed as a backend service, users will be able to consume the C2E content.
5. Offline Attempt to activate/validate the license and C2E Package
Application will check for the same information in the local storage and validate the data by decrypting with the details of the user who is logged-in to the application.
If information matches and validity of license is still active based on the expiry date and system date then the user will be able to consume the C2E Content.
2.7 C2E Payments and Ledger
Coming Soon.
2.8 C2E Marketplace
Coming Soon.
3 C2E Specification
3.1 Introduction
C2E defines a distribution and interchange format for digital publications and documents. The C2E format provides a means of representing, packaging and encoding structured and semantically enhanced Web content — including HTML, CSS, SVG and other resources — for distribution in a single-file container.
The expectation is that the C2E format will be utilized for a broad range of content, including educational, professional and scientific publications. This initial release aims to support a wide range of interactive digital requirements, including complex layouts, rich media and interactivity, and global typography features.
C2E is modular in nature: it consists of a family of specifications that define the core features and functionality of the standard. This specification represents the primary entry point to standard, but the specifications listed in Specifications are all a part of C2E. An index to key concepts and definitions defined across these specifications is provided at the end of this specification.
The informative [C2EOverview] provides a general introduction to C2E. A list of technical changes from the previous revision is also available in the informative [C2EChanges].
3.2 C2E Conceptual Model
Figure 2.1 is a conceptual diagram that illustrates the components of the C2E ecosystem.
3.2.1 Major Elements
The C2E Package depicted in Figure 2.1 consists of two major elements: a special JSON-LD file describing the content organization and resources in a Package, and the file resources being described by the JSON-LD. The special JSON-LD file is called the C2E Manifest file, because course content and organization is described in the context of ‘manifests’. Once a Package has been incorporated into a single file for transportation, it is called a Package Interchange File. The relationship of these parts to the content container is described below:
Package
It is a logical directory, which includes a specially named JSON-LD file and contains the actual file resources. The file resources may be organized in sub-directories.
Package Interchange File
It is a single file, (e.g., ‘.zip’, ‘.jar’, ‘.c2e’) which includes a top-level manifest file named “c2e.json” and all other files and directories as identified by the Manifest. A Package Interchange File is a concise Web delivery format, a means of transporting related, structured information. PKZip v2.04g (.zip) is recommended as the default Package Interchange File format. Any ZIP file format MUST conform to RFC1951.
3.2.2 Standard Name for the Manifest File
Content distributed according to the C2E specification must contain an C2E Manifest file. To ensure that the C2E Manifest file is a valid JSON-LD file and can always be found within a Package, it has a pre-defined name and location:
c2e.json
In the absence of this file, the package is not an C2E Package and cannot be processed. It is required that the name be kept, as above, in all lowercase letters.
3.3. JSON-LD
JSON-LD is a lightweight Linked Data format. It is easy for humans to read and write. It is based on the already successful JSON format and provides a way to help JSON data interoperate at Web-scale. JSON-LD is an ideal data format for programming environments, REST Web services, and unstructured databases.
Documentation – https://www.w3.org/TR/json-ld/
3.3.1 Relationship to RDF (Resource Description Framework)
JSON-LD is a concrete RDF syntax. Hence, a JSON-LD document is both an RDF document and a JSON document and correspondingly represents an instance of an RDF data model which is set of triples, each consisting of a subject, a predicate and an object.
3.4. Manifest Elements
A manifest is a description in JSON-LD of the resources comprising meaningful instruction for a C2E. A manifest also contain zero or more static ways of organizing the instructional resources for presentation.
The scope of manifest is elastic. A manifest can describe part of a C2E that can stand by itself outside of the context of a C2E (an instructional object). The decision is given to content developers to describe their content in the way they want it to be considered for aggregation or disaggregation. The general rule is that a Package always contains a single top-level manifest that may contain one or more sub-Manifests. The top-level manifest always describes the Package. Any nested sub-Manifests describe the content at the level to which the sub-Manifest is scoped, such as a course, instructional object, or other.
3.4.1 The Context
One of basic concepts that JSON-LD has is that the Context allows us to define terms that can be used to define the components and resources of the C2E. A context is introduced using an entry with the key @context and may appear within a node object or a value object.
{ “@context”: { } }
Copy
3.4.1.1 Namespaces
Define following namespace prefixes are defined as context terms:
“c2ens”: “https://c2e.curriki.org/”
“sdons”: “https://schema.org/”
“xsd”: “http://www.w3.org/2001/XMLSchema/#”
c2ens namespace prefix is defined to refer to the resources, types and terms by C2E.
sdons namespace prefix is defined to refer to vocabularies by Schema.
xsd namespace prefix defines XML Schema language which is also referred to as XML Schema Definition (XSD).
The context with required namespaces would look like:
3.4.1.2 C2E Mandatory Terms
Following are mandatory terms required to define in the JSON-LD @context
{ “@context”: { “c2ens”: “https://c2e.curriki.org/”, “sdons”: “https://schema.org/”, “xsd”: “http://www.w3.org/2001/XMLSchema/#”, “C2E”: “sdons:CreativeWork”, “c2eType”: {“@id”: “sdons:additionalType”, “@type”:“xsd:string”}, “c2eContain”: {“@id”: “sdons:Collection”, “@container”: [“@graph”, “@index”]}, “c2eResources”: “@graph”, “c2eComponents”: “@graph”, “c2eTerm”: “c2ens:terms/”, “c2eVendor”: {“@id”: “sdons:vendor”, “@type”:“xsd:string”}, “name”: {“@id”: “sdons:name”, “@type”:“xsd:string”}, “url”: {“@id”: “sdons:url”, “@type”:“xsd:string”}, “fileFormat”: {“@id”: “sdons:fileFormat”, “@type”:“xsd:string”}, “@language” : “en” } }
“C2E”: “sdons:CreativeWork” The “C2E” term is used to define primary attribute “@type” of JSON-LD top level object
“c2eType”: {“@id”: “sdons:additionalType”, “@type”:”xsd:string”} The c2eType term is used to define an additional type of the C2E. For example Project, Course, Lesson, Activity, Module
“c2eComponents”: “@graph” The c2eComponents term is use to represent the set of associated components (that can also be a C2E Learning Experiences) of a C2E. It is basically a JSON-LD’s @graph.
“c2eResources”: “@graph” is an important attribute that is used to define the collection of resource files for example an html, text, image, audio, video or scripts. Each resource consists of two main attributes: url and fileFormat.
c2eContain term is used to define a container object that holds to primary structures c2eResources and c2eComponents mentioned above.
“name”: {“@id”: “sdons:name”, “@type”:”xsd:string”} The name term is used to define the name of an object.
c2eTerm is c2ens namespace extension to be used as prefix of C2E specific IRIs in the JSON-LD structure
c2eVendor is used to define the technology vendor who enables the platform to make C2E based on their technology. For example H5P etc.
@language keyword in @context defines the default language of the manifest JSON-LD document.
3.4.1.3 C2E Metadata Terms
Define following terms in the @context which is used to form a metadata object:
“metadata”: “c2eTerm:metadata”, “schemaVersion”: {“@id”: “sdons:schemaVersion”, “@type”:”xsd:string”}, “general”: “c2eTerm:mdGeneral”, “title”: {“@id”: “sdons:headline”, “@type”:”xsd:string”}, “description”: {“@id”: “sdons:description”, “@type”:”xsd:string”}, “keywords”: {“@id”: “sdons:keywords”, “@type”:”xsd:string”}, “author”: {“@id”: “sdons:author”, “@type”:”xsd:string”}, “publisher”: {“@id”: “sdons:publisher”, “@type”:”xsd:string”}, “email”: {“@id”: “sdons:email”, “@type”:”xsd:string”}, “lifecycle”: “c2eTerm:mdLifecycle”, “version”: {“@id”: “sdons:version”, “@type”: “xsd:string”}, “releaseStatus”: {“@id”: “sdons:creativeWorkStatus”, “@type”: “xsd:string”}, “subManifest”: {“@id”: “sdons:url”, “@type”:”xsd:string”}, “copyright”: “c2eTerm:copyright”, “license”: {“@id”: “sdons:license”, “@type”: “xsd:string”}, “encodingFormat”: {“@id”: “sdons:encodingFormat”, “@type”: “xsd:string”}, “copyrightHolder”: {“@id”: “sdons:copyrightHolder”, “@type”: “xsd:string”}, “copyrightNotice”: {“@id”: “sdons:copyrightNotice”, “@type”: “xsd:string”}, “copyrightYear”: {“@id”: “sdons:copyrightYear”, “@type”: “xsd:integer”}
3.4.2 Define C2E JSON-LD Object
3.4.2.1 Define Metadata
Make the following metadata object right after defining all terms in @context structure:
“metadata”: { “@id”: “c2ens:c2eid-xxx/metadata”, “@type”: “sdons:Dataset”, “schemaVersion”: “1.0”, “general”: { “@id”: “c2ens:c2eid-xxx/metadata/general”, “@type”: “sdons:Dataset”, “title”: “My Smaple C2E”, “description”: “My Smaple C2E for Proof of Concept.”, “keywords”: “c2e, e-learning, learning experince” }, “author” : { “@id”: “c2ens:c2eid-xxx/author/id/xxx”, “@type”: “sdons:Person”, “name”: “Waqar Muneer”, “email”: “waqar@curriki.org”, “url”: “https://twitter.com/waqarmnr” }, “publisher” : { “@id”: “c2ens:c2eid-xxx/author/id/xxx”, “@type”: “sdons:Organization”, “name”: “Curriki”, “email”: “info@curriki.org”, “url”: “https://curriki.org” }, “lifecycle”: { “@id”: “c2ens:c2eid-xxx/metadata/lifecycle”, “@type”: “sdons:Code”, “version”: “1.10”, “releaseStatus”: “Beta” }, “copyright”: { “@id”: “c2ens:c2eid-xxx/metadata/copyRight”, “@type”: “sdons:Dataset”, “license”: { “@id”: “c2ens:c2eid-xxx/license/id/xxx”, “@type”: “sdons:DigitalDocument”, “encodingFormat”: “text/plain or any binary as per need”, “url”: “/path/to/license.txt” }, “copyrightHolder”: { “@id”: “c2ens:c2eid-xxx/copyrightHolder/id/xxx”, “@type”: “sdons:Person”, “name”: “Waqar Muneer”, “email”: “waqar@curriki.org”, “url”: “https://twitter.com/waqarmnr” }, “copyrightNotice”: “This C2E has all rights to Waqar Muneer”, “copyrightYear”: “2023” } }
3.4.2.2 Define C2E
C2E consists of “@id”, “@type”, “name” mandatory attributes.
It makes JSON-LD a top level object. For example:
{ “@context”: { “c2ens”: “https://c2e.curriki.org/”, “sdons”: “https://schema.org/”, “xsd”: “http://www.w3.org/2001/XMLSchema/#”, “C2E”: “sdons:CreativeWork” …………………… …………………… }, “metadata”: { “@id”: “c2ens:c2eid-xxx/metadata”, “@type”: “sdons:Dataset”, “schemaVersion”: “1.0” …………………… …………………… }, “@id”: “c2ens:c2eid-xxx”, “@type”: “C2E” }
3.4.2.2.1 C2E Identifier
C2E identifier which is defined as JONS-LD @id is required to have following pattern:
c2ens : c2eid- xxx
which will be translated as:
https://c2e.curriki.org/c2eid-xxx
xxx represents the system generated unique number.
3.4.2.3 Define C2E Resources
Includes references to all of the resources included in the package. At a minimum it should reference all those files that are needed in order to view the content.
In C2E JSON-LD c2eContainer container object, an object is defined with @id and c2eResources attribute which is used to list all resources that are required for a C2E.
“c2eContainer”: [ { “@id”: “c2ens:c2eResources”, “@type”: “sdons:Collection”, “c2eResources” : [ { “@id”: “c2ens:c2eid-xxx/resource/1”, “@type”: “sdons:DigitalDocument”, “url”: “/path/to/file-1.json”, “fileFormat”: “application/json” }, { “@id”: “c2ens:c2eid-xxx/resource/2”, “@type”: “sdons:DigitalDocument”, “url”: “/path/to/readme.txt”, “fileFormat”: “application/text” } ] } ]
3.4.3 Extending C2E Object with “hasPart” attribute (optional)
Since C2E Object is sdons based “CreativeWork, so C2E object is considered to have all of its attributes predefined in it. A C2E Object can be extended by using “hastPart” attribute to associate other “CreativeWork” type of object. CreativeWork’s sub-types such as Article, Blog , LearningResource etc can also be assigned to “hastPart” attribute.
{ “@id”: “c2ens:c2eid-xxx”, “@type”: “C2E”, “hasPart”: { “@id”: “c2ens:c2ePart-xxx”, “@type”: [ “Any specific type of sdons:CreativeWork” ] } }
“hastPart” attribute provide ability to create CreativeWork and its sub-types based on a nested structure.
3.5. Defining C2E Content Types
Since C2E object is a sdons “CreativeWork”, it might be required to construct custom objects that can represent the C2E more than just a sdons “CreativeWork”. C2E has concept of ‘Content Types’ that are used to construct the object models that are used in the C2E implementations.
Content Types are defined in C2E’s object’s “c2eContainer” attribute.
Example
“c2eContainer”: [ { “@id”: “c2ens:c2eContentTypes”, “@type”: “sdons:Collection”, “c2eContentTypes” : [ { “@id”: “c2ens:c2eid-xxx/content-type/SampleContentType”, “@type”: “sdons:CreativeWork”, “Property1”: {“@type”:”xsd:string”}, “Property2”: {“@type”:”xsd:integer”} }, { “@id”: “c2ens:c2eid-xxx/content-type/SampleContentType”, “@type”: “sdons:CreativeWork”, “Property1”: {“@type”:”xsd:string”}, “Property2”: {“@type”:”xsd:integer”} } ] } ]
3.5.1 Define mandatory attributes
In Example mentioned above, an object to define Content Types is constructed with the following three necessary attributes “@id” “@type” and “c2eContentTypes”.
“c2eContentTypes”. attribute would be defined in “@context” as “c2eContentTypes”: “@graph”
3.5.2 Define C2E Content Types
List of Content Types is defined using the “c2eContentTypes” attribute as mentioned in the above example.
3.5.3 Define C2E Content Type Object
{ “@id”: “c2ens:c2eid-xxx/content-type/SampleContentType”, “@type”: “Your Content Type”, “Property1”: {“@type”:”xsd:string”}, “Property2”: {“@type”:”xsd:integer”} }
“@id” is defined following the pattern “c2ens:c2eid-xxx/content-type”.
“@type” should be a valid compact IRI link to define the object type.
3.5.3.1 Define C2E Content Type Object Attributes
First define attributes for example “Property1” or “Property2” as valid compact IRI links in “@context”. For example:
“@context” { ………………… ………………… “Property1”: “c2eTerm:c2eid-xxx/content-type/attribute/Property1” “Property2”: “c2eTerm:c2eid-xxx/content-type/attribute/Property2” ………………… ………………… }
Make sure you do not define the Content Type attribute more than once.
After defining attributes in “@context” now you can define these into the Content Type.
3.5.3.2 Define Data Type for C2E Content Type Object Attribute
It is required to define data type of Content Type Object attribute. Data type could be based on xsd or other data type standards. For example:
“Property1”: {“@type”:”xsd:string”}
It will make Content Type Object like:
{ “@id”: “c2ens:c2eid-xxx/content-type/SampleContentType”, “@type”: “Your Content Type”, “Property1”: {“@type”:”xsd:string”}, “Property2”: {“@type”:”xsd:integer”} }
Following JSON-LD specification link has mentioned namespaces which have valid data types to be used.
3.5.3.3 Define Relationship Between C2E Content Type Objects
To set up relationships between objects. It will be required to introduce the following relationship types in the “@context”.
“@context” { ………………… ………………… “hasOne”: “c2eTerm:hasOne”, “hasMany”: “c2eTerm:hasMany”, “belongsTo”: “c2eTerm:belongsTo” ………………… ………………… }
And then you can define the relationship between the objects as required. For example we can take Content Type objects from example mentioned above and make “hasOne” to “hasMany” relationship as:
“c2eContainer”: [ { “@id”: “c2ens:c2eContentTypes”, “@type”: “sdons:Collection”, “c2eContentTypes” : [ { “@id”: “c2ens:c2eid-xxx/content-type/student”, “@type”: “sdons:CreativeWork”, “Property1”: {“@type”:”xsd:string”}, “Property2”: {“@type”:”xsd:integer”}, “hasMany”: “c2ens:c2eid-xxx/content-type/courses” }, { “@id”: “c2ens:c2eid-xxx/content-type/courses”, “@type”: “sdons:CreativeWork”, “Property1”: {“@type”:”xsd:string”}, “Property2”: {“@type”:”xsd:integer”}, “belongsTo”: “c2ens:c2eid-xxx/content-type/student” } ] } ]
These relationship attributes would require “@id” of related Content Type Objects.
3.6. C2E Contents
C2E contents are defined in c2eContainer as c2eContentCatalog which has Url to /content/contents.js path which lists all the C2E content files.
“c2eContainer”: [ { “@id”: “c2ens:c2eContentCatalog”, “@type”: “sdons:DataCatalog”, “c2eContentCatalog”: { “@id”: “c2ens:c2eid-12345/content/contents.json”, “@type”: “sdons:DigitalDocument”, “url”: “/content/contents.json”, “fileFormate”: “application/json” } } ]
In /content/contents.js file content files would be listed as:
“@id”: “c2ens:c2eContents”, “@type”: “sdons:Collection”, “c2eContents”: [ { “@id”: “c2ens:c2eid-12345/content/my-project-1.json”, “@type”: “sdons:DigitalDocument”, “@index”: “1”, “url”: “/content/my-project-1.json”, “fileFormate”: “application/json”, “learningResourceType”: “Project” }, { “@id”: “c2ens:c2eid-12345/content/my-project-2.json”, “@type”: “sdons:DigitalDocument”, “@index”: “2”, “url”: “/content/my-project-2.json”, “fileFormate”: “application/json”, “learningResourceType”: “Project” } ] }
3.7. Define C2E Source Code
It is required to define the source code path of C2E so that it can provide an entry point to execute.
C2E source code defined in C2E’s object’s “c2eContainer” attribute.
first define “c2eSource” in the context as:
“@context” { ………………… ………………… “c2eSourceCode”: “@graph” ………………… ………………… }
“c2eContainer”: [ { “@id”: “c2ens:c2eSourceCode”, “@type”: “sdons:Collection”, “c2eSourceCode” : [ { “@id”: “c2ens:c2eid-xxx/source/index.js”, “@type”: “sdons:SoftwareSourceCode”, “url”: “/source/index.js”, “fileFormat”: “application/javascript” }, { “@id”: “c2ens:c2eid-xxx/source/index.html”, “@type”: “sdons:SoftwareSourceCode”, “url”: “/source/index.html”, “fileFormat”: “text/html” } ] } ]
It should have 2 objects with attribute “@id” , having “c2eTerm:script” and “c2eTerm:homepageUrl”
“c2eTerm:script” – It would be a script that would be used to execute C2E as code and can be included on HTML documents defined in the “c2eTerm:homepageUrl” object.
“c2eTerm:homepageUrl” – It is an HTML document that will display a C2E document.
3.8. Define Embeded C2Es
In C2E JSON-LD c2eContainer container object, an object is defined with @id and c2eEmbeds attribute which is used to list all associated C2Es that are required for a C2E.
“c2eContainer”: [ { “@id”: “c2ens:c2eEmbeds”, “@type”: “sdons:Collection”, “c2eEmbeds”: [ { “@id”: “c2ens:c2eid-xxx-1”, “@type”: “C2E”, “@index”: “1”, “c2eResources”: [] }, { “@id”: “c2ens:c2eid-xxx-2”, “@type”: “C2E”, “@index”: “2”, “subManifest”: “/path/to/sample-activity/sample-H5P/c2e.json” } ] } ]
3.8.1 Sub-Manifest to define associated C2Es
In cases where complex C2Es are needed then a sub-manifest file c2e.json can be created on the relevant path.
It is defined for objects under c2eEmbeds list as:
“subManifest”: “/path/to/sample-activity/sample-H5P/c2e.json”
Example 4.4 shows the same sub-manifest declaration.
Note that every c2e.json file placed other than the root directory would be considered as sub-manifest and should have association with the main c2e.json manifest file placed on the root directory.
3.9. Licensing
There is a copyright object with license nested object in it which is defined in 4.2.1 Define Metadata section. This copyright object consists of following JSON-LD objects to fulfill the copyrights and licensing needs.
“metadata”: { …….. …….. “copyright”: { “license”: { “@id”: “c2ens:c2eid-xxx/license/id/xxx”, “@type”: “sdons:DigitalDocument”, “licenseNumber”: “C2e-lsc-xxxxx”, “licenseDate”: “2023-01-01”, “encodingFormat”: “text/plain or any binary as per need”, “url”: “/path/to/license.txt” “usageInfo”: { “@id”: “c2ens:c2eid-xxx/license-usage”, “@type”: “sdons:Dataset”, “typeOfUse”: “purchased / rented”, “requestorType”: “Instuctor / Researcher”, “portions”: “tables, slides, video etc”, “numberOfPortions”: “2”, “format”: “printed / electronic / offline / online” } }, “licenseInvoice”: { “accountId” : “xxxxxx” “customer”: { “@type”: “sdons:Person”, “name”: “Jane Doe” }, “paymentDueDate” : “2015-01-30” “totalPaymentDue” : { “@type”: “sdons:PriceSpecification”, “price”: 10.00, “priceCurrency”: “USD” }, “paymentStatus”: “sdons:PaymentComplete”, “referencesOrder” : [ { “@type”: “sdons:Order”, “description”: “furnace”, “orderDate”: “2014-12-01”, “orderNumber”: “123ABC”, “paymentMethod”: “http://purl.org/goodrelations/v1#ByInvoice”, “orderedItem”: { “@type”: “sdons:Product”, “name”: “My C2E”, “productID”: “ABC123” } } ] } } }
3.10. Complete Sample JSON-LD Manifest
Run JSON-LD code in Playground
{ “@context”: { “c2ens”: “https://c2e.curriki.org/”, “sdons”: “https://schema.org/”, “xsd”: “http://www.w3.org/2001/XMLSchema/#”, “C2E”: “sdons:CreativeWork” “c2eContainer”: { “@id”: “sdons:Collection”, “@container”: [ “@graph”, “@index” ] }, “c2eResources”: “@graph”, “c2eContentTypes”: “@graph”, “c2eSourceCode”: “@graph”, “c2eEmbeds