@lantis Learning Community Library Specifications

@lantis® ALMS Library Database Schema

 

ALMS 1.0 Database Tables

Table Name Description
Raw_Data Simple Storage of Groups of Bits
Members The List of members
User_Meta Meta Data About the members
Beliefs Subjective Statements about reality
Facts Objective Statements about Reality
Arguments Reasons to Believe Something put in “Standard Form”
Lessons Reasons to Believe Something in Long Form
Classes An accumulation of Facts, Arguments, Lessons, and raw data to achieve a learning objective
Dictionary The List of Words and short phrases used by the Community and their meanings and uses
Blockchain Verifactions

ALMS 1.0 Database Schema

Raw Data

Field Type
rd_id bigint(20) unsigned
rd_date bigint(20) unsigned
rd_contributor varchar(250)
rd_blockchain varchar(250)
rd_author varchar(250)
user_id varchar(255)
rd_type varchar(100)
rd_value longtext

Users

Field Type
ID bigint(20) unsigned
user_login varchar(60)
user_pass varchar(64)
user_name varchar(50)
user_email varchar(100)
user_url varchar(100)
user_registered datetime
user_activation_key varchar(60)
user_status int(11)
display_name varchar(250)

Users Metadata

Field Type
umeta_id bigint(20) unsigned
user_id bigint(20) unsigned
meta_key varchar(255)
meta_value longtext

Content

Field Type
ID bigint(20) unsigned
blockchain varchar(200)
content_author bigint(20) unsigned
content_date datetime
content_content longtext
content_title text
content_excerpt text
content_status varchar(20)
content_type varchar(200)
rd_data text
pinged text
content_modified datetime
content_modified_gmt datetime
content_content_filtered longtext
content_parent bigint(20) unsigned
guid varchar(255)
menu_order int(11)
content_type varchar(20)
content_mime_type varchar(100)
comment_count bigint(20)
Indexes
Keyname Type
PRIMARY PRIMARY
content_name INDEX
type_status_date INDEX
content_parent INDEX
content_author INDEX

Valid propositional forms
Modus ponens
One valid argument form is known as modus ponens, not to be mistaken with modus tollens which is another valid argument form that has a like-sounding name and structure. Modus ponens (sometimes abbreviated as MP) says that if one thing is true, then another will be. It then states that the first is true. The conclusion is that the second thing is true.[3] It is shown below in logical form.

If A, then B
A
Therefore B
Before being put into logical form the above statement could have been something like below.

If Kelly does not finish his homework, he will not go to class
Kelly did not finish his homework
Therefore, Kelly will not go to class
The first two statements are the premises while the third is the conclusion derived from them.

Modus tollens
Another form of argument is known as modus tollens (commonly abbreviated MT). In this form, you start with the same first premise as with modus ponens. However, the second part of the premise is denied, leading to the conclusion that the first part of the premise should be denied as well. It is shown below in logical form.

If A, then B
Not B
Therefore not A.[3]
When modus tollens is used with actual content, it looks like below.

If the Saints win the Super Bowl, there will be a party in New Orleans that night
There was no party in New Orleans that night
Therefore, the Saints did not win the Super Bowl
Hypothetical syllogism
Much like modus ponens and modus tollens, hypothetical syllogism (sometimes abbreviated as HS) contains two premises and a conclusion. It is however, slightly more complicated than the first two. In short, it states that if one thing happens, another will as well. If that second thing happens, a third will follow it. Therefore, if the first thing happens, it is inevitable that the third will too.[3] It is shown below in logical form.

If A, then B
If B, then C
Therefore if A, then C
When put into words it looks like below.

If it rains today, I will wear my rain jacket
If I wear my rain jacket, I will keep dry
Therefore if it rains today, I will keep dry
Disjunctive syllogism
Disjunctive syllogism (sometimes abbreviated DS) has one of the same characteristics as modus tollens in that it contains a premise, then in a second premise it denies a statement, leading to the conclusion. In Disjunctive Syllogism, the first premise establishes two options. The second takes one away, so the conclusion states that the remaining one must be true.[3] It is shown below in logical form.

Either A or B
Not A
Therefore B
When used A and B are replaced with real life examples it looks like below.

Either you will see Joe in class today or he will oversleep
You did not see Joe in class today
Therefore Joe overslept
Disjunctive syllogism takes two options and narrows it down to one.

Constructive dilemma
Another valid form of argument is known as constructive dilemma or sometimes just ‘dilemma’. It does not leave the user with one statement alone at the end of the argument, instead, it gives an option of two different statements. The first premise gives an option of two different statements. Then it states that if the first one happens, there will be a particular outcome and if the second happens, there will be a separate outcome. The conclusion is that either the first outcome or the second outcome will happen. The criticism with this form is that it does not give a definitive conclusion; just a statement of possibilities.[3] When it is written in argument form it looks like below.

Either A or B
If A then C
If B then D
Either C or D
When content is inserted in place of the letters, it looks like below.

Bill will either take the stairs or the elevator to his room
If he takes the stairs, he will be tired when he gets to his room
If he takes the elevator, he will miss the start of the football game on TV
Therefore Bill will either be tired when he gets to his room or he will miss the start of the football game
There is a slightly different version of dilemma that uses negation rather than affirming something known as destructive dilemma. When put in argumentative form it looks like below.

If A then C
If B then D
Not C or not D
Therefore not A or not B [4]
References
May, Robert (1993). Logical form: its structure and derivation. Cambridge, Mass: MIT Press.
Stanley, Jason (30 August 2000). “Context and Logical Form”. Linguistics and Philosophy. 23 (4).
Johnson, Robert (2006). A Logic Book: Fundamentals of Reasoning. Cengage Learning.
Elugardo, Reinaldo (1 September 2001). “Logical Form and the Vernacular”. Mind and Language. 16 (4).

Building The Library

 

To build an LRS, you first have to decide if the LRS will be a component of an LMS or a standalone, enterprise LRS. If you decide to build your LRS as part of an LMS, there’s a guide that handles how xAPI content should be imported, launched and how to deal with private access to content. Read more about launching xAPI experiences here.

Below is the bare minimum functionality you will need to implement, no matter which type of LRS you decide to build.

The APIs

The Experience API is really a collection of four RESTful APIs. In talking about xAPI, many focus on statements and transferring them between LRSs, this is the job of the statement API. The Document APIs: State, Activity, and Agent don’t deal with statements, they allow for richer information to be stored (a string, an image, a Word document, a video, etc — the document APIs are about these other pieces of data that don’t belong in a statement). To build an LRS, you have to implement all four APIs.

The statement API is the way to put statements into an LRS and to get statements from an LRS. You can get and put a single statement or multiple statements with this API. This is the API you would use to pull down statements from an LRS to fuel reporting and visualizations.

Statements range in size. Today we often see fairly small statements, but there is potential for very large statements. Adding attachments in 1.0 increases the likelihood of seeing larger statements regularly. An LRS needs to determine how large is too large for a statement, this needs to be carefully decided so it doesn’t limit common use cases for the users. The LRS needs to effectively balance storing and working with large statements while efficiently handling smaller statements.

The state API is generally used by activity providers as a scratch space to support learning activities while they’re in progress. Saving state in this way allows resumption of an activity across sessions and across devices.

Example:
An example for using this API could be a person editing an image as part of a learning activity, that image could be saved (as an image) in the LRS with the state API. The different states of the image could be pulled back by the application at the end to put together a collection that shows the changes in the work over time.

The Activity API stores data about activities in the LRS. There should be a full description of each activity in the LRS that can be referenced through this API. The LRS bears the responsibility for determining the best definition for each unique activity it has received. Part of the LRS’s responsibility for determining an activity’s definition is to attempt to access the activity’s metadata – care should be taken to avoid blocking requests when doing this.

Example:
For team simulations, an activity could store its state under its own profile instead of with the State API. The state API is specific to Agent, the Activity API is not agent specific. Screenshots or pictures of real life training could be stored with this API. It’s a way to store documents that represent people showing their work with the activity.

Another example, in our Tetris prototype you will see a call to store high scores across the users in the LRS as a document for the activity with the Activity API. This populates a leaderboard much more quickly than by deriving high scores across all of the statements for the Tetris activity each time the user requests to see the leaderboard.

The Agent API is similar to the State and Activity APIs, but it’s focused on adding additional data about agents to the LRS. The Agent API is a way to connect the different ways a person has been identified across an LRS by adding the different IDs and credentials to the Agent.

Example:
An avatar that represents the person could be added to their profile in the LRS through the Agent API. An avatar image is not something that would be sent with a statement. When other permissed systems queried the LRS for the profile, they could pull in this image file to populate for the person in their system.

Security and Authentication: Permissions and OAuth

An LRS has to support authentication, and the most common two authentication mechanisms are HTTP basic authentication and oAuth. If an LRS is going to support oAuth, then it has to implement the various requirements listed below. oAuth is a commonly used specification for authentication on the web. For example, this image illustrates a music site and Facebook connecting with oAuth. In most of the Experience API world, the consumer would be an application and the provider would be the LRS. LRSs can also connect to each other. Once connected they can use the Statement API to share statements.

There are five scenarios in the xAPI spec:

  • The application is a known oAuth consumer and the person is known
  • The application is a known oAuth consumer and the person is not known
  • The application is not a known oAuth consumer but the person is known
  • There is no application and the person is known
  • There is no authentication – blank credentials are used for testing purposes only.

In the authorization process, the Experience API spec has specific ways that tokens, authorizations, and temporary credentials need to work with endpoints.

If an oAuth connection is made, the scope of the data that can be shared through the statement API is defined. An LRS has to support the scopes defined in oAuth 2.0.

The LRS is responsible for populating (or validating) the authority portion of the statement, based on the credentials used to send the statement. There are specific requirements for constructing an authority based on each type of authentication.

Statement Transfer: Retrieval

Retrieving a collection of statements from an LRS and storing them locally to support reports or visualizations is the best way to work with the data. Constantly querying the LRS is less effective because it’s a big load. Pulling down the data also allows you to do more in-depth queries of the data because the statement API doesn’t query on all statement parameters (extensions, for example, can not be queried with the statement API). See Reporting for more details.

An LRS will need to carefully index data because efficiently serving the queries can be complex. One challenge is efficiently handling relationships between statements. An example of this would be if a search for certain conditions that match statement C must return statement A. Then if A targets B which targets C, all three must be returned, as described in filter conditions for statement refs. Statement references are ways to point to another statement as important to the referencing statement.

When a query for statements is made to the LRS, it returns a number of statement results and generates a URL, which has to remain active for 24 hours to allow for more statements to be pulled down. There are also guidelines about the length of URLs and storage of query data, that’s all in the spec too.

Data Quality

The LRS has specific responsibilities when it comes to voided statements. This is because xAPI statements are immutable. They cannot be deleted. A false or inaccurate statement can only be voided. The burden is on the LRS to make sure that the original flawed statement is dealt with appropriately so it doesn’t mire reports and other ways that the data may be used.

The LRS needs to store all ‘voiding’ statements, and when returning statement results the LRS must filter out any statements which have been voided. The LRS should check to see if that statement made any changes to the activity or agent definitions and roll the changes that the statement made back. Read more about handling voided statements in the spec.

The LRS checks for syntax. It has to validate all of the pieces of a statement to make sure that data is formatted properly, required fields are present, and that the JSON values match the requirements of the spec. The semantics of a statement and meaning of the data within the statement is the responsibility of the activity provider.

Considering the volume of data that is flowing in and out of an LRS, concurrency is a major concern. The specification has many rules and checks that an LRS must do to make sure that the data in the LRS is not being degraded by putting old data into the LRS.

Signed statements have a special case in the LRS. They can be validated by the authority signing the statement without trusting the system that the statement originated in. In order for an LRS to validate signed statements, the LRS must check specific algorithms and properties in the JSON Web Signature (JWS) format. The implementor of the LRS needs to understand specification for JWS as well as the specific rules outlined in the xAPI specification.

An LRS returns only meta information only to HTTP headers, not the full documents in the LRS. A request can be made to find out if there is a newer version of a document without downloading the full document. This is a less load intensive way of checking to see if documents need to be downloaded from the LRS to support an application or report.

Future Proofing: API versioning and resource requests

Version headers are required in every response from an LRS to make it clear what versions of the xAPI specification the LRS supports. The version headers use semantic versioning. An LRS needs to provide an ‘about’ resource that returns JSON that identifies the versions of the specification that the LRS supports.

Handling the Past

There are three versions of the Experience API specification that are in use by different activity providers currently. The specification doesn’t require that an LRS support pre-release versions, but many LRS do. If the LRS does support version 0.9 and 0.95 of the spec, it needs to up-convert older versions to the most recent version of the specification so that they are able to be understood by all clients. This means that the older statements must be preserved in their original state and an updated version should be stored according to this appendix to the spec, appendix D.

Credential Management

An LRS is not required by the specification to do user management and permission management, but in order to be usable it will need to. This includes building ways for applications to register as OAuth consumers, managing user credentials, and managing basic authorization combos. Managing who can talk with the LRS is one part, the next step is to give controls for how much they can access which comes with a much more complicated set of decisions to be made about security and permissions.

Test your LRS with the Test Suite

There’s a basic xAPI conformance test suite that you can use to test how well your LRS conforms to the spec. It’s not complete, but it will test a wide range of things related to xAPI conformance. There’s no official “conformance certification” yet, so passing the test suite is the closest thing to an official certification. You can find the xAPI conformance test suite here.

Dealing with IE: Cross Origin Requests

The specification enables cross domain tracking, but the method for doing this does not allow HTTP headers to be set. This is a problem in using IE8 and IE9. There is a specific workaround for this in the specification that LRSs must support.

Beyond the basic, spec required LRS functionality:

Now, all of that said, if you want to build an LRS that is a standalone enterprise system it will need a lot more functionality. These are some of the things the LRS should do:

  • Permissions management
  • Push-pull statement synchronization with other lrs
  • Data extraction, viewing and analysis
  • Authentication management
  • Actor merging, supported by the Agent API

Incorporating The Atlantis Learning Library into the ALMS API

Atlantis Learning Library (ALL).

Since ALL is meant to be a component with limited but well-defined capabilities, we expect that in many cases it will be desirable to integrate ALL into a third-party Learning Management System (LMS).

This document was created to define those expected behaviors.

 

Packaging

Content, activity definitions, and activity provider definitions may be packaged for ALMS.

The primary object being packaged is always activity definitions.

It is valid to create a package that contains only activity definitions, however, content and activity provider definitions may only be packaged with an associated activity definition.

An ALMS package must always include an ALMS metadata file, this is a file named “ALMS.xml”, conforming to the ALMS schema. If not including content, this file itself may be used as the ALMS package. If the content is to be included, then this file must be placed into a zip file with the content.

An ALMS package must contain exactly one “ALMS.xml” file. The location of the “ALMS.xml” file is considered the “root” of the package. All files within the package should be under the root. So, it is valid for ALMS.xml to be in a nested directory structure within the zip, but only if every directory above it contains nothing but a single sub-directory.

If HTML files are included in the content package, they may link to each other, or other resources within the package, using relative paths based on the package structure. They may also link to external resources using absolute paths.

Activity Definition

The activity definition section of ALMS.xml maps to the activity definition defined in the ALMS API document, with the exception of “launch” and “resource”.

Launch is an absolute or relative path to a document which can be launched by the LMS in a web browser in order to “deliver” this activity.

Resource is an absolute or relative path to something that a person can either read or download which will enable them to experience this activity, for example: an application to run, a video to view, or directions to a physical location for an event.

Only one activity definition within a package may contain launch or resource elements. This limitation should be lifted in future ALMS versions but the implementation consequences of multiple launchable activities per package need more thought first.

NOTE: Activities do not have a hierarchy, and are declared as a flat list. Any hierarchical context must be reported by the activity provider, using the “context” portion of each statement. (if that context is to be preserved). If emulating a traditional SCORM package using ALMS, consider adding a “grouping” activity to each statement, which corresponds to your “root of the activity tree”, and also a “parent” activity.

Activity Provider Definition, activity groups.

The ALMS.xml file includes one or more groups of activities. The reason for breaking up activities into groups is to enable defining different authorized activity providers for each group. Each group of activities has a “provider” section, which MAY be used to declare to the LMS/ALL what applications (activity providers) should be allowed to report statements about each group of activities. The elements in this section reflect the information that must be registered during the OAuth application registration process, and provide a way to get this information into an LMS without the administrator having to go through a registration UI.

The schema for ALMS.xml is: http://projectALMS.com/ALMS.xsd

ALMS.xml doesn’t have to have all activity IDs that will be used in it, what it should have is:

  1. The activity ID that is considered the root activity for this package, along with a launch link, so the LMS knows what to launch.
  2. Any activity details (such as activity descriptions) that should be available to reporting systems, but will not be (or may not be) sent by the activity provider when reporting statements. That is, ALMS.xml may be used to describe activities to the ALL, as an alternative to doing that description at runtime.

Import

When importing an ALMS package, all the content, activity definitions, and activity provider definitions in the package will be imported.

If any activity definitions are loaded then all the files within the package starting from the “root”, and excluding the file “ALMS.xml”, must be placed in an accessible location by the LMS. For any activity definitions that have “launch” or “resource” defined, the LMS will store those values as activity profile entries in its associated ALL. Any relative URLs will be transformed into absolute URLs based on the location the ALL stored the content.

Language / Internationalization

Many of the entries in the ALMS schema have an xml:lang attribute. Where the language of the associated entry is known, it should be declared. Where an entry is available in multiple languages, it should be repeated for each language. If the language is unknown, then the attribute should be left blank.

### Launch

ALMS APs(?) do not need to be launched from an LMS, however, it is still an option. When an LMS launches an ALMS AP, it will provide the necessary information for that AP to track back to the ALL (endpoint, learner information, credentials, and optionally registration, activity ID, platform, language, and grouping). The format of the launch URL will be as follows:

<AP URL>/?endpoint=<ALLendpoint>&auth=<token>&actor=<learner>[&registration=<registration>][&activity_id=<activity ID>[&activity_platform=<platform>][&Accept-Language=<acceptlanguage>][&grouping=<grouping activity ID>]

Note that some of the parameter values include reserved characters and even other URLS, and therefore must be URL encoded.

Example launch link (shown without URL encoding and with line breaks for readability):

http://example.scorm.com/TCActivityProvider/  

?endpoint=http://example.scorm.com/ALL/  

&auth=OjFjMGY4NTYxNzUwOGI4YWY0NjFkNzU5MWUxMzE1ZGQ1  

&actor={ “name” : [“Project ALMS”], “mbox” : [“mailto:ALMS@scorm.com”] }  

&registration=760e3480-ba55-4991-94b0-01820dbd23a2  

&activity_id=http://example.scorm.com/ALMS/example/simplestatement  

Partial launch information may also be provided by an LMS in the form of a launch link, which may consist of only endpoint information, or may include learner information but not credentials. In this case, the AP would have to have been configured with or prompt for the necessary information.

The LMS should specify Accept-Language, if it knows the learner’s language preferences. Except for its location in the query string instead of the header, Accept-Language should be constructed and interpreted according to RFC 2616(HTTP 1.1).

The LMS should specify a grouping activity if the activity being launched is considered, by the LMS, to be part of a larger group of activities for reporting purposes. The grouping activity specified should then be added to the context of each statement the activity being launch reports, so that these statements can later be identified as all being related to the grouping activity.

The LMS should specify a registration on a launch link if the launch is logically part of an LMS “registration”. The Activity Provider will then store the specified registration in context when reporting statements.

Any parameters that are not defined here which are passed on a launch link should be echoed back to the ALL when reporting statements associated with that launch. This allows an LMS that is integrated with ALL to pass through additional context information.

If no launch information is provided, then the AP must minimally be configured with the ALL endpoint it should track to. The AP may also be configured with credentials from the ALL, in which case credentials need not be obtained for each learner.

If launch refers to an activity with associated protected content, the launch link will include additional parameters to support access to that protected content. (see Private Content Access and ALMS

OAuth

If the activity being launched has an associated registered OAuth application with the LMS, the LMS should not include an “auth” parameter in the launch link. The Activity Provider / OAuth application is expected to authenticate using OAuth, which may involve asking the learner to re-authenticate.

Other Scenarios

The process of getting launch information from an LMS to an AP in a manner other than a launch link (URL) is not defined. Although it is a goal of the ALMS API to support out of browser scenarios, this is supported by allowing the AP to pass information to a ALL about learners and activities that have not been previously defined in the ALL. That is, out of browser scenarios are supported by removing the requirement for the ALL to launch the activity. Minimally, the AP must be configured with the ALL endpoint, and usually will also need authentication credentials.

### Private Content Access and ALMS

This section describes a companion specification to the ALMS API for the purpose of gaining access to content that is stored on an LMS, but which requires authentication to retrieve. This is needed since even though ALMS allows tracking of experiences for which the content is not stored on an LMS, or for which there is no traditional content, the LMS is still a convenient place to store the content associated with a learning experience. Since ALMS does not require an active browser session, the content may no longer be retrieved by relying on that session.

Since the problem is accessing content which is stored on an LMS, and to avoid the need for a complex permissions scheme, this access method will apply only to content that has been uploaded in a ALMS package, and only where the accessor of that content has been launched using a ALMS launch link.

In addition to the launch link parameters described in the launch section, the following parameters will be provided as needed:

  • content_token: The authorization token to be included on requests to the content endpoint. If missing, the content is not protected and must be accessed directly.
  • content_endpoint: the absolute URL to use to access protected content. If content token is specified, but the endpoint is not, the TCAPI endpoint, with the postfix “content/” is to be used as the content endpoint.

When a client application needs to access a protected resource, it will first determine the path to the protected resource based on the content endpoint, and the relative path of the protected resource within the ALMS package.

For example, in the Golf Example ALMS package, there is a resource ‘Etiquette/distracting.jpg’. If the content endpoint is:https://example.com/TCAPI/content/, then the following path would be built to access this protected resource, and the specified content_token is added to that URL. It should not be necessary to merge the content token with other query string parameters, as even though content may use query string parameters when loaded to determine how to behave, they should not be necessary for retrieving a resource from the server. Note that this methodology works for retrieving 1 resource at a time, an HTML document loaded in this way which includes relative paths would have broken links.

https://example.com/TCAPI/content/Etiquette/distracting.jpg?content_token=b50607fb-956e- 429f-b89e-388c43dbbbcf

The client may then issue an HTTP GET to this URL to access the resource.

In order to retrieve an entire content package, the content endpoint would be combined with the content token, with no additional path information. So the following URL would retrieve the entire content package, in zip format:https://example.com/TCAPI/content/?content_token=b50607fb-956e-429f-b89e-388c43dbbbcf

The server will not enforce any authentication scheme on the content endpoint, except validation of the content token. The content token will serve both the validate the request, and look up what ALMS package the request is associated with. The content token will remain valid as long as the ‘auth’ parameter sent in the launch link remains valid.

Upon receiving a request on the content endpoint, and validating the content token, it is recommended that the server issue a 301 redirect to the URL on the LMS where the content may be accessed, and include on the URL a signature that the LMS will recognize to allow access to the content.

If the above behavior is not practical, the server must instead handle GET, HEAD (should this be READ?), and OPTIONS requests according to the HTTP 1.1 specification, as if the server was hosting the content at the specified URL. Note that this includes properly supporting headers such as ETag, Range, if-*, etc.

The behavior described above is intended to allow clients to access individual protected resources without implementing any ALMS behavior. For example, this is important in order to enable handing off a URL to a video player, that player needs only support HTTP, it does not need to have any ALMS specific logic. It will be still be necessary for the ALMS client application to generate the correct URL for each protected resource. So a resource which when loaded then refers to other resources (such as a web page), must be loaded by a client with additional logic to fix those links.